Peter N Lewis wrote:
In the Mac OS, we have a concept of a FourCharCode, which is essentially a UInt32 except that it often has values that are made up of four characters. In Mac OS compilers then, the UNSIGNEDLONG (Cardinal attribute( size = 32 ))is compatible as a special case with constant strings of four characters.
To be more precise, type FourCharCode is treated in a special way, but there are suble differences even between CodeWarrior Pascal, Think Pascal and MPW Pascal (not to mention the CodeWarrior 80x86 cross compiler).
In GPC, we've implemented FourCharCode = packed array[0..3] of char which works for most things, but it is not possible to do a case statement of this type, nor is it possible to cast between UInt32 and FourCharCode (which would provide a workaround, as the case statement could case the value and constants to UInt32 (except GPC does not allow casting in the case constants part, but even that can be worked around).
In fact, casting does work in GPC in nearly all cases. Consider the following test program:
program cast; type word32 = word attribute ( size = 32); word16 = word attribute ( size = 16); rec32 = record r1: word16; r2: word16 end; arr32 = array[ 1..2] of word16; fourcharcode = array[ 1..4] of char; var i: word32; r: rec32; a: arr32; f: fourcharcode; const k1: fourcharcode = 'wxyz'; k2: fourcharcode = 'pqrs'; k3 = 'klmn'; begin i:= 2 + 1 * $10000; writeln( 'i = ', i); r:= rec32( i); writeln( 'r.r1 = ', r.r1, ' r.r2 = ', r.r2); a:= arr32( i); writeln( 'a[ 1 ] = ', a[ 1], ' a[ 2] = ', a[ 2]); writeln;
i:= 4 + 3 * $10000; writeln( 'i = ', i); word32( r):= i; writeln( 'r.r1 = ', r.r1, ' r.r2 = ', r.r2); word32( a):= i; writeln( 'a[ 1 ] = ', a[ 1], ' a[ 2] = ', a[ 2]); writeln;
i:= ORD( 'a') * $1000000 + ORD( 'b') * $10000 + ORD( 'c') * $100 + ORD( 'd') * $1; writeln( 'i = ', i); f:= fourcharcode( i); writeln( 'f = ', f); writeln;
i:= ORD( 'e') * $1000000 + ORD( 'f') * $10000 + ORD( 'g') * $100 + ORD( 'h') * $1; writeln( 'i = ', i); word32( f):= i; writeln( 'f = ', f); writeln;
f:= 'abcd'; writeln( 'f = ', f); i:= word32( f); writeln( 'i = ', i); writeln;
f:= 'efgh'; writeln( 'f = ', f); fourcharcode( i):= f; writeln( 'i = ', i); writeln;
// i:= word32( 'abcd'); not allowed by GPC
fourcharcode( i):= 'abcd'; writeln( 'i = ', i, ' (''abcd'')');
i:= word32( k1); writeln( 'i = ', i, ' (''', k1, ''')'); fourcharcode( i):= k2; writeln( 'i = ', i, ' (''', k2, ''')');
// i:= word32( k3); not allowed by GPC
fourcharcode( i):= k3; writeln( 'i = ', i, ' (''', k3, ''')'); end.
So, all of these type casts work, except the value type cast i:=word32( 'abcd'). This can be worked around by:
- using a variable type cast instead of a value type cast, e.g. fourcharcode( i ):= 'abcd' - declaring a typed constant for the fourcharcode (which is not a bad idea anyway), e.g. i:=word32( k1)
It would be nice if GPC were to allow i:=word32( 'abcd') also (e.g. in --macpascal mode), but this is not a necessity.
So basically, I'm looking for recommendations as to the best way to implement compatibility with this inside GPC, and/or the best extensions to GPC to allow compatibility with this sort of code.
A typical example might be:
const typeBoolean = 'bool'; typeChar = 'TEXT'; typeSInt16 = 'shor'; typeSInt32 = 'long'; typeUInt32 = 'magn'; etc
So it ends up being used as an extensible enumerated type if you like. Anyway, this concept is used all over the Mac OS API, so it is important to have reasonable compatibility for writin Mac OS applications.
Ok, so can anyone think of the best way to get this functionality?
I would recommend:
const typeBoolean : FourCharCode = 'bool'; typeChar : FourCharCode = 'TEXT'; typeSInt16 : FourCharCode = 'shor'; typeSInt32 : FourCharCode = 'long'; typeUInt32 : FourCharCode = 'magn'; etc
Changing FourCharCode = UInt32 is probably better since the concept behind it is as a fixed size low cost use, and it is essentially never used as a string as such.
I am not convinced that changing FourCharCode to UInt32 is a good idea.
Regards,
Adriaan van Os