At 13:54 +0200 29/6/05, Frank Heckenbach wrote:
Adriaan van Os wrote:
The same (and probably a lot of other weird stuff) can be achieved We support `absolute' for BP compatibility, but IMHO then we should restrict it to what BP requires, i.e. really absolute addresses, or the address of entire variables or parameters.
I am not enthousiastic about this one because GPC
- is very restrictive in what typecasts are allowed
I agree entirely with the for loop case. I would hope that the absolute case is not removed though. For example, I use this quite cleanly in my program:
function SFTPProducer( parameter: UnivPtr ): OSStatus; var transfer: TransferDataPtr absolute parameter; taskinfo: TaskInformationPtr = @transfer^.producer; extra: SFTPExtraStoragePtr absolute taskinfo^.extra_storage;
I have many similar producer and consumer threads. The threads must take a defined parameter (and GPC will not allow me to cast the procedure to a compatible one taking a different pointer). The thread data has pointers for storage, and the absolute method allows specifying a specific type for each different thread.
Yes, I agree that it could all be done with multiple variables, casting and assignments, but that clutters the code, adds warnings which have to be disabled, and adds real code that may or may not be optimized away later.
Via pointers you can cast basically everything, i.e. `PNewType (@OldVar)^'. (Sure, you must be able to take the address, i.e. lvalues, and you may get warnings about alignment, and on strict alignment machines it may actually crash, but all of this is also true for absolute variables. In fact, internally absolute variables do just cast pointers.)
You cannot case function pointers to/from pointers, so that would not work for at least that case. You cannot even cast function pointers between reasonably compatible cases (like parameters with differing pointer types).
- typecastst with $R+ cause range-check errors.
Which kinds of typecasts? Can you give an example?
It is traditional to use a UserData field of UInt32 or SInt32 or Pointer to store arbitrary user data in various interfaces on the Mac. Casting between them can generate range check errors. So for example, a library that uses SInt32 as the UserData field, where you wish to have the UserData store an arbitrary UInt32 can cause a range check error when you pass it as SInt32(mydata).
Traditional use of casting between SInt32 and UInt32 on the Mac is a binary four byte cast.
The problem of course is that as a developer you might never catch this range check until after you deploy the application (disabling range checking when deploying the application is a possibility but might lead to security issues such as buffer overflows).
Anyway, summary:
for loops as only local variables - I fully support this change.
removing absolute - I would not make this change. I can live with it if you do, but it is a useful feature which can be used reasonably cleanly. If you support univ instead, or function casting between reasonably compatible functions, or function casting to/from pointers, then all of those would provide alternate solutions. I would really love to see univ implemented for pointer parameters, I even started doing it myself, but got a bit stuck when I hit pascal_type_variant...
Casting range checks - it is not what I expect, I expect cast to be a strict change of type with no interpretation on the contents, but I can understand and accept the reasoning for it (for example EnumeratedType(myinteger) is obviously bogus if myinteger is not within range).
Enjoy, Peter.