This was not sent to the list, but it was intended to ... I realized while reading the last message of Franck on the subject
-------- Message d'origine -------- Objet: Re: Bug? Identifier Integer sometimes fails Date: Fri, 20 Dec 2002 19:23:13 +0100 De: Maurice Lombardi Maurice.Lombardi@ujf-grenoble.fr A: cbfalconer@worldnet.att.net Références: 3E018128.27241.258BB6@localhost 3E01B718.1040507@ujf-grenoble.fr 3E01CF33.32301.1072E43@localhost 200212192052.VAA26157@goedel.fjf.gnu.de 3E032F09.9080500@ujf-grenoble.fr 3E0338E3.E2F21BFE@yahoo.com
CBFalconer a écrit:
Maurice Lombardi wrote:
... snip ...
The only problem I see is the restriction by pascal to only one case variant in a record. I suppose C has no restriction on the number of union inside a struct. This can be solved only by some extra types.
Is this really so? There is the requirement that fixed components precede variant components, but AFAIK there is no limitation on nesting.
Isn't the following legal?
TYPE x = RECORD a : integer; CASE b : char OF 'B': (b1 : fubar); 'C': CASE c1 : char OF 'c': (c2 : foo); END; (* CASE c1 *) 'D': CASE d1 : char OF 'd': (d2 : bar); END; (* CASE d1 *) END; (* CASE b *) (* e : integer; WOULD BE ILLEGAL here *) END; (* RECORD x *)
The names have to be distinct, and the compiler must be able to infer a fixed offset for any component name.
This does not work. But nested record are possible to solve this problem. In fact the proper equivalent of
union { .. ; .. } HighWord;
is
Highword: packed record case integer of '1': ( .. ); '2': ( .. ) end;
(I missed previously the enclosing record, which was however written in the example ...)
You can check on the following C and pascal more complex examples functionally equivalents to the original one
-------------------------------------------------------------------- #include <stdio.h>
#define WORD unsigned short #define BYTE char #define DWORD unsigned
typedef struct _LDT_ENTRY { WORD LimitLow; WORD BaseLow; union { struct { BYTE BaseMid; BYTE Flags1; } Bytes; struct { DWORD BaseMid:8; DWORD Type:5; DWORD Dpl:2; DWORD Pres:1; } Bits; } HighWord; union { struct { BYTE Flags2; BYTE BaseHi; } Bytes; struct { DWORD LimitHi:4; DWORD Sys:1; DWORD Reserved_0:1; DWORD Default_Big:1; DWORD Granularity:1; DWORD BaseHi:8; } Bits; } HigherWord; } LDT_ENTRY,*PLDT_ENTRY,*LPLDT_ENTRY;
int main(void) { // struct _LDT_ENTRY ldt; LDT_ENTRY ldt; // equivalent declarations
ldt.HighWord.Bytes.BaseMid = 0xDE; ldt.HighWord.Bytes.Flags1 = 0xAD; ldt.HigherWord.Bytes.Flags2 = 0xBE; ldt.HigherWord.Bytes.BaseHi = 0xEF;
printf("%d %d %d %d %d %d %d %d %d %d\n", ldt.HighWord.Bits.BaseMid, ldt.HighWord.Bits.Type, ldt.HighWord.Bits.Dpl, ldt.HighWord.Bits.Pres, ldt.HigherWord.Bits.LimitHi, ldt.HigherWord.Bits.Sys, ldt.HigherWord.Bits.Reserved_0, ldt.HigherWord.Bits.Default_Big, ldt.HigherWord.Bits.Granularity, ldt.HigherWord.Bits.BaseHi);
return 0; }
---------------------------------------------------------------------
-------------------------------------------------------------------- program teststruc;
{$define DWORD cardinal}
type LDT_ENTRY = packed record LimitLow: WORD; BaseLow: WORD; HighWord: packed record case integer of 1: (Bytes: packed record BaseMid: BYTE; Flags1: BYTE; end); 2: (Bits: packed record BaseMid: DWORD(8); C_Type: DWORD(5); Dpl: DWORD(2); Pres: DWORD(1); end) end; HigherWord: packed record case integer of 1: (Bytes: packed record Flags2: BYTE; BaseHi: BYTE end); 2: (Bits: packed record LimitHi: DWORD(4); Sys: DWORD(1); Reserved_0: DWORD(1); Default_Big: DWORD(1); Granularity: DWORD(1); BaseHi: DWORD(8) end) end; end;
type PLDT_ENTRY = ^LDT_ENTRY; LPLDT_ENTRY = PLDT_ENTRY;
var ldt:LDT_ENTRY;
begin with ldt do begin with HighWord.Bytes do begin BaseMid:=$DE; Flags1 :=$AD; end; with HigherWord.Bytes do begin Flags2 :=$BE; BaseHi :=$EF; end; with HighWord.Bits do write (BaseMid,' ', C_Type,' ', Dpl,' ', Pres,' '); with HigherWord.Bits do writeln(LimitHi,' ', Sys,' ', Reserved_0,' ', Default_Big,' ', Granularity,' ', BaseHi); end; readln end. ---------------------------------------------------------------------
Al this seems amenable to automatic translation.
Maurice
Maurice Lombardi wrote:
This was not sent to the list, but it was intended to ... I realized while reading the last message of Franck on the subject
-------- Message d'origine -------- Objet: Re: Bug? Identifier Integer sometimes fails Date: Fri, 20 Dec 2002 19:23:13 +0100 De: Maurice Lombardi Maurice.Lombardi@ujf-grenoble.fr A: cbfalconer@worldnet.att.net Références: 3E018128.27241.258BB6@localhost 3E01B718.1040507@ujf-grenoble.fr 3E01CF33.32301.1072E43@localhost 200212192052.VAA26157@goedel.fjf.gnu.de 3E032F09.9080500@ujf-grenoble.fr 3E0338E3.E2F21BFE@yahoo.com
CBFalconer a écrit:
Maurice Lombardi wrote:
... snip ...
The only problem I see is the restriction by pascal to only one case variant in a record. I suppose C has no restriction on the number of union inside a struct. This can be solved only by some extra types.
Is this really so? There is the requirement that fixed components precede variant components, but AFAIK there is no limitation on nesting.
Isn't the following legal?
TYPE
... snip fouled declaration ...
The names have to be distinct, and the compiler must be able to infer a fixed offset for any component name.
This does not work. But nested record are possible to solve this problem. In fact the proper equivalent of
Herewith a corrected and compilable version of that RECORD
CONST maxindex = 5;
TYPE fubar = real; bar = 1 .. maxindex; foo = ARRAY[bar] OF integer;
x = RECORD a : integer; CASE b : char OF 'B': ( b1 : fubar); 'C': ( CASE c1 : char OF 'c': (c2 : foo) ); (* end CASE c1 *) 'D': ( CASE d1 : char OF 'd': (d2 : bar); ); (* end CASE d1 *) (* end CASE b *) (* e : integer; WOULD BE ILLEGAL here *) END; (* RECORD x *)
It compiles with both PascalP and gpc --standard-pascal.