mirror of
https://github.com/byteworksinc/ORCA-C.git
synced 2025-01-01 13:29:32 +00:00
Merge branch 'designated-initializers'
This implements designated initializers as specified by C99 and later. It also fixes a few initialization-related bugs.
This commit is contained in:
commit
935bb6c04e
11
CCommon.pas
11
CCommon.pas
@ -321,14 +321,17 @@ type
|
||||
initializerPtr = ^initializerRecord; {initializers}
|
||||
initializerRecord = record
|
||||
next: initializerPtr; {next record in the chain}
|
||||
count: integer; {# of duplicate records}
|
||||
disp: longint; {disp within overall object being initialized}
|
||||
count: integer; {# of duplicate records (>1 for bytes only)}
|
||||
bitdisp: integer; {disp in byte (field lists only)}
|
||||
bitsize: integer; {width in bits; 0 for byte sizes}
|
||||
isStructOrUnion: boolean; {is this a struct or union initializer?}
|
||||
case isConstant: boolean of {is this a constant initializer?}
|
||||
false: (iTree: tokenPtr);
|
||||
false: (
|
||||
iType: typePtr; {type being initialized}
|
||||
iTree: tokenPtr; {initializer expression}
|
||||
);
|
||||
true : ( {Note: qVal.lo must overlap iVal}
|
||||
case itype: baseTypeEnum of
|
||||
case basetype: baseTypeEnum of
|
||||
cgByte,
|
||||
cgUByte,
|
||||
cgWord,
|
||||
|
40
CGI.pas
40
CGI.pas
@ -279,7 +279,11 @@ type
|
||||
cgDouble,
|
||||
cgComp,
|
||||
cgExtended : (rval: extended);
|
||||
cgString : (str: longStringPtr);
|
||||
cgString : (
|
||||
case isByteSeq: boolean of
|
||||
false : (str: longStringPtr);
|
||||
true : (data: ptr; len: longint);
|
||||
);
|
||||
cgVoid,
|
||||
ccPointer : (pval: longint; pstr: longStringPtr);
|
||||
end;
|
||||
@ -574,6 +578,16 @@ procedure GenS (fop: pcodes; str: longstringPtr);
|
||||
{ str - pointer to string }
|
||||
|
||||
|
||||
procedure GenBS (fop: pcodes; data: ptr; len: longint);
|
||||
|
||||
{ generate an instruction that uses a byte sequence operand }
|
||||
{ }
|
||||
{ parameters: }
|
||||
{ fop - operation code }
|
||||
{ data - pointer to data }
|
||||
{ data - length of data }
|
||||
|
||||
|
||||
procedure GenL1 (fop: pcodes; lval: longint; fp1: integer);
|
||||
|
||||
{ generate an instruction that uses a longint and an int }
|
||||
@ -1230,6 +1244,30 @@ if codeGeneration then begin
|
||||
end; {GenS}
|
||||
|
||||
|
||||
procedure GenBS {fop: pcodes; data: ptr; len: longint};
|
||||
|
||||
{ generate an instruction that uses a byte sequence operand }
|
||||
{ }
|
||||
{ parameters: }
|
||||
{ fop - operation code }
|
||||
{ data - pointer to data }
|
||||
{ len - length of data }
|
||||
|
||||
var
|
||||
lcode: icptr; {local copy of code}
|
||||
|
||||
begin {GenBS}
|
||||
if codeGeneration then begin
|
||||
lcode := code;
|
||||
lcode^.optype := cgString;
|
||||
lcode^.isByteSeq := true;
|
||||
lcode^.data := data;
|
||||
lcode^.len := len;
|
||||
Gen0(fop);
|
||||
end; {if}
|
||||
end; {GenBS}
|
||||
|
||||
|
||||
procedure GenL1 {fop: pcodes; lval: longint; fp1: integer};
|
||||
|
||||
{ generate an instruction that uses a longint and an int }
|
||||
|
3
DAG.pas
3
DAG.pas
@ -202,7 +202,8 @@ else if (op1 <> nil) and (op2 <> nil) then
|
||||
or fastMath then
|
||||
CodesMatch := true;
|
||||
cgString:
|
||||
CodesMatch := LongStrCmp(op1^.str, op2^.str);
|
||||
if not (op1^.isByteSeq or op1^.isByteSeq) then
|
||||
CodesMatch := LongStrCmp(op1^.str, op2^.str);
|
||||
cgVoid, ccPointer:
|
||||
if op1^.pval = op2^.pval then
|
||||
CodesMatch := LongStrCmp(op1^.str, op2^.str);
|
||||
|
28
MM.pas
28
MM.pas
@ -23,6 +23,7 @@
|
||||
{ GCalloc - allocate & clear memory from the global pool }
|
||||
{ GInit - initialize a global pool }
|
||||
{ GMalloc - allocate memory from the global pool }
|
||||
{ GLongMalloc - allocate global memory }
|
||||
{ LInit - initialize a local pool }
|
||||
{ LMalloc - allocate memory from the local pool }
|
||||
{ Malloc - allocate memory }
|
||||
@ -73,6 +74,15 @@ procedure GInit;
|
||||
{ Initialize a global pool }
|
||||
|
||||
|
||||
function GLongMalloc (bytes: longint): ptr;
|
||||
|
||||
{ Allocate a potentially large amount of global memory. }
|
||||
{ }
|
||||
{ Parameters: }
|
||||
{ bytes - number of bytes to allocate }
|
||||
{ ptr - points to the first byte of the allocated memory }
|
||||
|
||||
|
||||
function GMalloc (bytes: integer): ptr;
|
||||
|
||||
{ Allocate memory from the global pool. }
|
||||
@ -182,6 +192,24 @@ globalPtr := pointer(ord4(globalPtr) + bytes);
|
||||
end; {GMalloc}
|
||||
|
||||
|
||||
function GLongMalloc {bytes: longint): ptr};
|
||||
|
||||
{ Allocate a potentially large amount of global memory. }
|
||||
{ }
|
||||
{ Parameters: }
|
||||
{ bytes - number of bytes to allocate }
|
||||
{ ptr - points to the first byte of the allocated memory }
|
||||
|
||||
var
|
||||
myhandle: handle; {for dereferencing the block}
|
||||
|
||||
begin {GLongMalloc}
|
||||
myhandle := NewHandle(bytes, globalID, $C000, nil);
|
||||
if ToolError <> 0 then TermError(5);
|
||||
GLongMalloc := myhandle^;
|
||||
end; {GLongMalloc}
|
||||
|
||||
|
||||
procedure LInit;
|
||||
|
||||
{ Initialize a local pool }
|
||||
|
18
Native.pas
18
Native.pas
@ -361,6 +361,7 @@ type
|
||||
rkind = (k1,k2,k3,k4); {cnv record types}
|
||||
|
||||
var
|
||||
bp: ^byte; {byte pointer}
|
||||
ch: char; {temp storage for string constants}
|
||||
cns: realRec; {for converting reals to bytes}
|
||||
cnv: record {for converting double, real to bytes}
|
||||
@ -672,9 +673,20 @@ case mode of
|
||||
CnOut(cns.inSANE[j]);
|
||||
end;
|
||||
cgString : begin
|
||||
sptr := icptr(name)^.str;
|
||||
for j := 1 to sptr^.length do
|
||||
CnOut(ord(sPtr^.str[j]));
|
||||
if not icptr(name)^.isByteSeq then begin
|
||||
sptr := icptr(name)^.str;
|
||||
for j := 1 to sptr^.length do
|
||||
CnOut(ord(sPtr^.str[j]));
|
||||
end {if}
|
||||
else begin
|
||||
lval := 0;
|
||||
while lval < icptr(name)^.len do begin
|
||||
bp := pointer(
|
||||
ord4(icptr(name)^.data) + lval);
|
||||
CnOut(bp^);
|
||||
lval := lval + 1;
|
||||
end;
|
||||
end; {else}
|
||||
end;
|
||||
ccPointer : begin
|
||||
if icptr(name)^.lab <> nil then begin
|
||||
|
1043
Parser.pas
1043
Parser.pas
File diff suppressed because it is too large
Load Diff
42
Scanner.pas
42
Scanner.pas
@ -49,6 +49,7 @@ type
|
||||
next: tokenListRecordPtr; {next element in list}
|
||||
token: tokenType; {token}
|
||||
expandEnabled: boolean; {can this token be macro expanded?}
|
||||
suppressPrint: boolean; {suppress printing with #pragma expand?}
|
||||
tokenStart,tokenEnd: ptr; {token start/end markers}
|
||||
end;
|
||||
macroRecordPtr = ^macroRecord;
|
||||
@ -153,13 +154,15 @@ procedure NextToken;
|
||||
{ Read the next token from the file. }
|
||||
|
||||
|
||||
procedure PutBackToken (var token: tokenType; expandEnabled: boolean);
|
||||
procedure PutBackToken (var token: tokenType; expandEnabled: boolean;
|
||||
suppressPrint: boolean);
|
||||
|
||||
{ place a token into the token stream }
|
||||
{ }
|
||||
{ parameters: }
|
||||
{ token - token to put back into the token stream }
|
||||
{ expandEnabled - can macro expansion be performed? }
|
||||
{ suppressPrint - suppress printing with #pragma expand? }
|
||||
|
||||
|
||||
procedure TermScanner;
|
||||
@ -510,13 +513,15 @@ macroFound := mPtr;
|
||||
end; {IsDefined}
|
||||
|
||||
|
||||
procedure PutBackToken {var token: tokenType; expandEnabled: boolean};
|
||||
procedure PutBackToken {var token: tokenType; expandEnabled: boolean;
|
||||
suppressPrint: boolean};
|
||||
|
||||
{ place a token into the token stream }
|
||||
{ }
|
||||
{ parameters: }
|
||||
{ token - token to put back into the token stream }
|
||||
{ expandEnabled - can macro expansion be performed? }
|
||||
{ suppressPrint - suppress printing with #pragma expand? }
|
||||
|
||||
var
|
||||
tPtr: tokenListRecordPtr; {work pointer}
|
||||
@ -527,6 +532,7 @@ tPtr^.next := tokenList;
|
||||
tokenList := tPtr;
|
||||
tPtr^.token := token;
|
||||
tPtr^.expandEnabled := expandEnabled;
|
||||
tPtr^.suppressPrint := suppressPrint;
|
||||
tPtr^.tokenStart := tokenStart;
|
||||
tPtr^.tokenEnd := tokenEnd;
|
||||
end; {PutBackToken}
|
||||
@ -777,6 +783,8 @@ if list or (numErr <> 0) then begin
|
||||
179: msg := @'_Pragma requires one string literal argument';
|
||||
180: msg := @'decimal digit sequence expected';
|
||||
181: msg := @'''main'' may not have any function specifiers';
|
||||
182: msg := @'''='' expected';
|
||||
183: msg := @'array index out of bounds';
|
||||
otherwise: Error(57);
|
||||
end; {case}
|
||||
writeln(msg^);
|
||||
@ -1626,7 +1634,7 @@ else
|
||||
end; {for}
|
||||
token.sval^.str[len+1] := chr(0);
|
||||
token.sval^.length := len+1;
|
||||
PutBackToken(token, true);
|
||||
PutBackToken(token, true, false);
|
||||
end; {BuildStringToken}
|
||||
|
||||
|
||||
@ -1915,7 +1923,7 @@ if macro^.parameters >= 0 then begin {find the values of the parameters}
|
||||
Error(14);
|
||||
if token.kind <> rparench then begin {insist on a closing ')'}
|
||||
if not gettingFileName then {put back the source stream token}
|
||||
PutBackToken(token, true);
|
||||
PutBackToken(token, true, false);
|
||||
Error(12);
|
||||
end; {if}
|
||||
preprocessing := lPreprocessing;
|
||||
@ -1923,7 +1931,7 @@ if macro^.parameters >= 0 then begin {find the values of the parameters}
|
||||
else begin
|
||||
Error(13);
|
||||
if not gettingFileName then {put back the source stream token}
|
||||
PutBackToken(token, true);
|
||||
PutBackToken(token, true, false);
|
||||
end; {else}
|
||||
end; {if}
|
||||
if macro^.readOnly then begin {handle special macros}
|
||||
@ -2038,7 +2046,7 @@ if macro^.readOnly then begin {handle special macros}
|
||||
|
||||
end; {case}
|
||||
if macro^.algorithm <> 8 then {if not _Pragma}
|
||||
PutBackToken(token, true);
|
||||
PutBackToken(token, true, false);
|
||||
end {if}
|
||||
else begin
|
||||
|
||||
@ -2126,11 +2134,11 @@ else begin
|
||||
if expandEnabled then
|
||||
if tcPtr^.token.name^ = macro^.name^ then
|
||||
expandEnabled := false;
|
||||
PutBackToken(tcPtr^.token, expandEnabled);
|
||||
PutBackToken(tcPtr^.token, expandEnabled, false);
|
||||
end; {else}
|
||||
end {if}
|
||||
else
|
||||
PutBackToken(tcPtr^.token, true);
|
||||
PutBackToken(tcPtr^.token, true, false);
|
||||
tcPtr := tcPtr^.next;
|
||||
end; {while}
|
||||
end; {else}
|
||||
@ -2145,7 +2153,7 @@ else begin
|
||||
expandEnabled := false;
|
||||
tokenStart := tlPtr^.tokenStart;
|
||||
tokenEnd := tlPtr^.tokenEnd;
|
||||
PutBackToken(tlPtr^.token, expandEnabled);
|
||||
PutBackToken(tlPtr^.token, expandEnabled, false);
|
||||
end; {else}
|
||||
lastPtr := tlPtr;
|
||||
tlPtr := tlPtr^.next;
|
||||
@ -3436,7 +3444,7 @@ if ch in ['a','d','e','i','l','p','u','w'] then begin
|
||||
end; {if}
|
||||
if token.name^ <> 'STDC' then begin
|
||||
{Allow macro expansion, other than for STDC }
|
||||
PutBackToken(token, true);
|
||||
PutBackToken(token, true, false);
|
||||
NextToken;
|
||||
end; {if}
|
||||
if token.name^ = 'keep' then
|
||||
@ -4901,6 +4909,7 @@ var
|
||||
tPtr: tokenListRecordPtr; {for removing tokens from putback buffer}
|
||||
tToken: tokenType; {for merging tokens}
|
||||
sPtr,tsPtr: gstringPtr; {for forming string constants}
|
||||
suppressPrint: boolean; {suppress printing the token?}
|
||||
lLastWasReturn: boolean; {local copy of lastWasReturn}
|
||||
codePoint: longint; {Unicode character value}
|
||||
chFromUCN: integer; {character given by UCN (converted)}
|
||||
@ -5164,6 +5173,7 @@ if tokenList <> nil then begin {get a token put back by a macro}
|
||||
tokenList := tPtr^.next;
|
||||
expandEnabled := tPtr^.expandEnabled;
|
||||
tokenExpandEnabled := expandEnabled;
|
||||
suppressPrint := tPtr^.suppressPrint;
|
||||
token := tPtr^.token;
|
||||
tokenStart := tPtr^.tokenStart;
|
||||
tokenEnd := tPtr^.tokenEnd;
|
||||
@ -5224,7 +5234,9 @@ if tokenList <> nil then begin {get a token put back by a macro}
|
||||
expandMacros := lExpandMacros;
|
||||
end; {if}
|
||||
goto 2;
|
||||
end; {if}
|
||||
end {if}
|
||||
else
|
||||
suppressPrint := false;
|
||||
5: {skip white space}
|
||||
while charKinds[ord(ch)] in [illegal,ch_white,ch_eol,ch_pound] do begin
|
||||
if charKinds[ord(ch)] = ch_pound then begin
|
||||
@ -5738,7 +5750,7 @@ if (token.kind = stringconst) and not mergingStrings {handle adjacent strings}
|
||||
done := false;
|
||||
end {if}
|
||||
else begin
|
||||
PutBackToken(token, tokenExpandEnabled);
|
||||
PutBackToken(token, tokenExpandEnabled, false);
|
||||
done := true;
|
||||
end; {else}
|
||||
token := tToken;
|
||||
@ -5753,8 +5765,10 @@ if doingPPExpression then begin
|
||||
if token.kind = typedef then
|
||||
token.kind := ident;
|
||||
end; {if}
|
||||
if printMacroExpansions and not suppressMacroExpansions then
|
||||
PrintToken(token); {print the token stream}
|
||||
if printMacroExpansions then
|
||||
if not suppressMacroExpansions then
|
||||
if not suppressPrint then
|
||||
PrintToken(token); {print the token stream}
|
||||
if token.kind = otherch then
|
||||
if not (skipping or preprocessing or suppressMacroExpansions)
|
||||
or doingPPExpression then
|
||||
|
16
Symbol.asm
16
Symbol.asm
@ -22,3 +22,19 @@ lb1 sta [table],Y
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
****************************************************************
|
||||
*
|
||||
* SaveBF - save a value to a bit-field
|
||||
*
|
||||
* Inputs:
|
||||
* addr - address to copy to
|
||||
* bitdisp - displacement past the address
|
||||
* bitsize - number of bits
|
||||
* val - value to copy
|
||||
*
|
||||
****************************************************************
|
||||
*
|
||||
SaveBF private cc
|
||||
jml ~SaveBF call ~SaveBF in ORCALib
|
||||
end
|
||||
|
282
Symbol.pas
282
Symbol.pas
@ -295,6 +295,14 @@ function StringType(prefix: charStrPrefixEnum): typePtr;
|
||||
|
||||
implementation
|
||||
|
||||
type
|
||||
{From CGC.pas}
|
||||
realrec = record {used to convert from real to in-SANE}
|
||||
itsReal: extended;
|
||||
inSANE: packed array[1..10] of byte;
|
||||
inCOMP: packed array[1..8] of byte;
|
||||
end;
|
||||
|
||||
var
|
||||
staticNum: packed array[1..6] of char; {static variable number}
|
||||
|
||||
@ -325,6 +333,17 @@ function UsualUnaryConversions: baseTypeEnum; extern;
|
||||
{ outputs: }
|
||||
{ expressionType - set to result type }
|
||||
|
||||
|
||||
{- Imported from CGC.pas ---------------------------------------}
|
||||
|
||||
procedure CnvSC (rec: realrec); extern;
|
||||
|
||||
{ convert a real number to SANE comp format }
|
||||
{ }
|
||||
{ parameters: }
|
||||
{ rec - record containing the value to convert; also }
|
||||
{ has space for the result }
|
||||
|
||||
{---------------------------------------------------------------}
|
||||
|
||||
procedure CnOut (i: integer); extern;
|
||||
@ -396,6 +415,16 @@ procedure ClearTable (table: symbolTable); extern;
|
||||
|
||||
{ clear the symbol table to all zeros }
|
||||
|
||||
procedure SaveBF (addr: ptr; bitdisp, bitsize: integer; val: longint); extern;
|
||||
|
||||
{ save a value to a bit-field }
|
||||
{ }
|
||||
{ parameters: }
|
||||
{ addr - address to copy to }
|
||||
{ bitdisp - displacement past the address }
|
||||
{ bitsize - number of bits }
|
||||
{ val - value to copy }
|
||||
|
||||
{---------------------------------------------------------------}
|
||||
|
||||
|
||||
@ -663,6 +692,218 @@ procedure DoGlobals;
|
||||
{ declare the ~globals and ~arrays segments }
|
||||
|
||||
|
||||
procedure StaticInit (variable: identPtr);
|
||||
|
||||
{ statically initialize a variable }
|
||||
|
||||
type
|
||||
{record of pointer initializers}
|
||||
relocPtr = ^relocationRecord;
|
||||
relocationRecord = record
|
||||
next: relocPtr; {next record}
|
||||
initializer: initializerPtr; {the initializer}
|
||||
disp: longint; {disp in overall data structure}
|
||||
end;
|
||||
|
||||
{pointers to each type}
|
||||
bytePtr = ^byte;
|
||||
wordPtr = ^integer;
|
||||
longPtr = ^longint;
|
||||
quadPtr = ^longlong;
|
||||
realPtr = ^real;
|
||||
doublePtr = ^double;
|
||||
extendedPtr = ^extended;
|
||||
|
||||
var
|
||||
buffPtr: ptr; {pointer to data buffer}
|
||||
count: integer; {# of duplicate records}
|
||||
disp: longint; {disp into buffer (for output)}
|
||||
endDisp: longint; {ending disp for current chunk}
|
||||
i: integer; {loop counter}
|
||||
ip: initializerPtr; {used to trace initializer lists}
|
||||
lastReloc, nextReloc: relocPtr; {for reversing relocs list}
|
||||
realVal: realRec; {used for extended-to-comp conversion}
|
||||
relocs: relocPtr; {list of records needing relocation}
|
||||
|
||||
{pointers used to write data}
|
||||
bp: bytePtr;
|
||||
wp: wordPtr;
|
||||
lp: longPtr;
|
||||
qp: quadPtr;
|
||||
rp: realPtr;
|
||||
dp: doublePtr;
|
||||
ep: extendedPtr;
|
||||
|
||||
|
||||
procedure UpdateRelocs;
|
||||
|
||||
{ update relocation records to account for an initializer }
|
||||
|
||||
var
|
||||
disp: longint; {disp of current initializer}
|
||||
done: boolean; {done with loop?}
|
||||
endDisp: longint; {disp at end of current initializer}
|
||||
last: ^relocPtr; {the pointer referring to rp}
|
||||
rp: relocPtr; {reloc record being processed}
|
||||
|
||||
begin {UpdateRelocs}
|
||||
disp := ip^.disp;
|
||||
if ip^.bitsize <> 0 then begin
|
||||
endDisp := disp + (ip^.bitdisp + ip^.bitsize + 7) div 8;
|
||||
disp := disp + ip^.bitdisp div 8;
|
||||
end {if}
|
||||
else if ip^.basetype = cgString then
|
||||
endDisp := disp + ip^.sVal^.length
|
||||
else
|
||||
endDisp := disp + TypeSize(ip^.baseType);
|
||||
last := @relocs;
|
||||
rp := relocs;
|
||||
done := false;
|
||||
while (rp <> nil) and not done do begin
|
||||
if rp^.disp + cgPointerSize <= disp then begin
|
||||
{initializer is entirely after this reloc: no conflicts}
|
||||
done := true;
|
||||
end {if}
|
||||
else if endDisp <= rp^.disp then begin
|
||||
{initializer is entirely before this reloc}
|
||||
last := @rp^.next;
|
||||
rp := rp^.next;
|
||||
end {else if}
|
||||
else begin
|
||||
{conflict: remove the conflicting reloc record}
|
||||
last^ := rp^.next;
|
||||
lp := pointer(ord4(buffPtr) + rp^.disp);
|
||||
lp^ := 0;
|
||||
dispose(rp);
|
||||
rp := last^;
|
||||
end; {else}
|
||||
end; {while}
|
||||
if ip^.basetype = ccPointer then begin
|
||||
new(rp);
|
||||
rp^.next := last^;
|
||||
last^ := rp;
|
||||
rp^.disp := ip^.disp;
|
||||
rp^.initializer := ip;
|
||||
end; {if}
|
||||
end; {UpdateRelocs}
|
||||
|
||||
begin {StaticInit}
|
||||
{allocate buffer}
|
||||
{(+3 for possible bitfield overhang)}
|
||||
buffPtr := GLongMalloc(variable^.itype^.size+3);
|
||||
|
||||
relocs := nil; {evaluate initializers}
|
||||
ip := variable^.iPtr;
|
||||
while ip <> nil do begin
|
||||
count := 0;
|
||||
while count < ip^.count do begin
|
||||
UpdateRelocs;
|
||||
if ip^.bitsize <> 0 then begin
|
||||
bp := pointer(ord4(buffPtr) + ip^.disp + count);
|
||||
SaveBF(bp, ip^.bitdisp, ip^.bitsize, ip^.iVal);
|
||||
end {if}
|
||||
else
|
||||
case ip^.basetype of
|
||||
cgByte,cgUByte: begin
|
||||
bp := pointer(ord4(buffPtr) + ip^.disp + count);
|
||||
bp^ := ord(ip^.iVal) & $ff;
|
||||
end;
|
||||
|
||||
cgWord,cgUWord: begin
|
||||
wp := pointer(ord4(buffPtr) + ip^.disp + count);
|
||||
wp^ := ord(ip^.iVal);
|
||||
end;
|
||||
|
||||
cgLong,cgULong: begin
|
||||
lp := pointer(ord4(buffPtr) + ip^.disp + count);
|
||||
lp^ := ip^.iVal;
|
||||
end;
|
||||
|
||||
cgQuad,cgUQuad: begin
|
||||
qp := pointer(ord4(buffPtr) + ip^.disp + count);
|
||||
qp^ := ip^.qVal;
|
||||
end;
|
||||
|
||||
cgReal: begin
|
||||
rp := pointer(ord4(buffPtr) + ip^.disp + count);
|
||||
rp^ := ip^.rVal;
|
||||
end;
|
||||
|
||||
cgDouble: begin
|
||||
dp := pointer(ord4(buffPtr) + ip^.disp + count);
|
||||
dp^ := ip^.rVal;
|
||||
end;
|
||||
|
||||
cgExtended: begin
|
||||
ep := pointer(ord4(buffPtr) + ip^.disp + count);
|
||||
ep^ := ip^.rVal;
|
||||
end;
|
||||
|
||||
cgComp: begin
|
||||
realVal.itsReal := ip^.rVal;
|
||||
CnvSC(realVal);
|
||||
for i := 1 to 8 do begin
|
||||
bp := pointer(ord4(buffPtr) + ip^.disp + count + i-1);
|
||||
bp^ := realVal.inCOMP[i];
|
||||
end; {for}
|
||||
end;
|
||||
|
||||
cgString: begin
|
||||
for i := 1 to ip^.sVal^.length do begin
|
||||
bp := pointer(ord4(buffPtr) + ip^.disp + count + i-1);
|
||||
bp^ := ord(ip^.sVal^.str[i]);
|
||||
end; {for}
|
||||
end;
|
||||
|
||||
ccPointer: ; {handled by UpdateRelocs}
|
||||
|
||||
cgVoid: Error(57);
|
||||
end; {case}
|
||||
count := count + 1; {assumes count > 1 only for bytes}
|
||||
end; {while}
|
||||
ip := ip^.next;
|
||||
end; {while}
|
||||
|
||||
lastReloc := nil; {reverse the relocs list}
|
||||
while relocs <> nil do begin
|
||||
nextReloc := relocs^.next;
|
||||
relocs^.next := lastReloc;
|
||||
lastReloc := relocs;
|
||||
relocs := nextReloc;
|
||||
end; {while}
|
||||
relocs := lastReloc;
|
||||
|
||||
disp := 0; {generate the initialization data}
|
||||
while disp < variable^.itype^.size do begin
|
||||
if relocs = nil then
|
||||
endDisp := variable^.itype^.size
|
||||
else
|
||||
endDisp := relocs^.disp;
|
||||
if disp <> endDisp then begin
|
||||
GenBS(dc_cns, pointer(ord4(buffPtr) + disp), endDisp - disp);
|
||||
disp := endDisp;
|
||||
end; {if}
|
||||
if relocs <> nil then begin
|
||||
code^.optype := ccPointer;
|
||||
code^.r := ord(relocs^.initializer^.pPlus);
|
||||
code^.q := 1;
|
||||
code^.pVal := relocs^.initializer^.pVal;
|
||||
if relocs^.initializer^.isName then begin
|
||||
code^.lab := relocs^.initializer^.pName;
|
||||
code^.pstr := nil;
|
||||
end {if}
|
||||
else
|
||||
code^.pstr := relocs^.initializer^.pstr;
|
||||
Gen0(dc_cns);
|
||||
lastReloc := relocs;
|
||||
relocs := relocs^.next;
|
||||
dispose(lastReloc);
|
||||
disp := disp + cgPointerSize;
|
||||
end; {if}
|
||||
end; {while}
|
||||
end; {StaticInit}
|
||||
|
||||
|
||||
procedure GenArrays;
|
||||
|
||||
{ define global arrays }
|
||||
@ -697,38 +938,7 @@ procedure DoGlobals;
|
||||
end; {if}
|
||||
if sp^.state = initialized then begin
|
||||
Gen2Name(dc_glb, 0, ord(sp^.storage = private), sp^.name);
|
||||
ip := sp^.iPtr;
|
||||
while ip <> nil do begin
|
||||
case ip^.itype of
|
||||
cgByte,cgUByte,cgWord,cgUWord: begin
|
||||
lval := ip^.ival;
|
||||
Gen2t(dc_cns, long(lval).lsw, ip^.count, ip^.itype);
|
||||
end;
|
||||
cgLong,cgULong:
|
||||
GenL1(dc_cns, ip^.ival, ip^.count);
|
||||
cgQuad,cgUQuad:
|
||||
GenQ1(dc_cns, ip^.qval, ip^.count);
|
||||
cgReal,cgDouble,cgComp,cgExtended:
|
||||
GenR1t(dc_cns, ip^.rval, ip^.count, ip^.itype);
|
||||
cgString:
|
||||
GenS(dc_cns, ip^.sval);
|
||||
ccPointer: begin
|
||||
code^.optype := ccPointer;
|
||||
code^.r := ord(ip^.pPlus);
|
||||
code^.q := ip^.count;
|
||||
code^.pVal := ip^.pVal;
|
||||
if ip^.isName then begin
|
||||
code^.lab := ip^.pName;
|
||||
code^.pstr := nil;
|
||||
end {if}
|
||||
else
|
||||
code^.pstr := ip^.pstr;
|
||||
Gen0(dc_cns);
|
||||
end;
|
||||
otherwise: Error(57);
|
||||
end; {case}
|
||||
ip := ip^.next;
|
||||
end; {while}
|
||||
StaticInit(sp);
|
||||
end {if}
|
||||
else begin
|
||||
size := sp^.itype^.size;
|
||||
@ -790,17 +1000,17 @@ procedure DoGlobals;
|
||||
if sp^.state = initialized then begin
|
||||
Gen2Name(dc_glb, 0, ord(sp^.storage = private), sp^.name);
|
||||
ip := sp^.iPtr;
|
||||
case ip^.itype of
|
||||
case ip^.basetype of
|
||||
cgByte,cgUByte,cgWord,cgUWord: begin
|
||||
lval := ip^.ival;
|
||||
Gen2t(dc_cns, long(lval).lsw, 1, ip^.itype);
|
||||
Gen2t(dc_cns, long(lval).lsw, 1, ip^.basetype);
|
||||
end;
|
||||
cgLong,cgULong:
|
||||
GenL1(dc_cns, ip^.ival, 1);
|
||||
cgQuad,cgUQuad:
|
||||
GenQ1(dc_cns, ip^.qval, 1);
|
||||
cgReal,cgDouble,cgComp,cgExtended:
|
||||
GenR1t(dc_cns, ip^.rval, 1, ip^.itype);
|
||||
GenR1t(dc_cns, ip^.rval, 1, ip^.basetype);
|
||||
cgString:
|
||||
GenS(dc_cns, ip^.sval);
|
||||
ccPointer: begin
|
||||
@ -1287,7 +1497,7 @@ var
|
||||
if ip = nil then ip := defaultStruct^.fieldList;
|
||||
|
||||
while ip <> nil do begin
|
||||
if ip^.name^ <> '~anonymous' then
|
||||
if ip^.name^[1] <> '~' then
|
||||
GenSymbol(ip, none);
|
||||
ip := ip^.next;
|
||||
end; {while}
|
||||
|
@ -24,6 +24,7 @@
|
||||
{1} c99tgmath.c
|
||||
{1} c99pragma.c
|
||||
{1} c99inline.c
|
||||
{1} c99desinit.c
|
||||
{1} c11generic.c
|
||||
{1} c11align.c
|
||||
{1} c11noret.c
|
||||
|
@ -55,6 +55,22 @@ int main(void) {
|
||||
if (s2p->d != 123.5)
|
||||
goto Fail;
|
||||
|
||||
struct S s3 = {.b = 10, 20, .a=30};
|
||||
|
||||
if (s3.a != 30)
|
||||
goto Fail;
|
||||
if (s3.b != 10)
|
||||
goto Fail;
|
||||
if (s3.c != 20)
|
||||
goto Fail;
|
||||
|
||||
struct S s4 = {.a=30, 10, 20.5, .d = 123.5};
|
||||
|
||||
if (s4.a != 30)
|
||||
goto Fail;
|
||||
if (s4.d != 123.5)
|
||||
goto Fail;
|
||||
|
||||
if (sizeof(struct S) != sizeof(struct T))
|
||||
goto Fail;
|
||||
|
||||
|
@ -85,6 +85,16 @@ int main(void) {
|
||||
|
||||
if (s.a || !s.b)
|
||||
goto Fail;
|
||||
|
||||
_Bool b1 = 123;
|
||||
_Bool b2 = -123.5;
|
||||
_Bool b3 = 0.0;
|
||||
static _Bool b4 = 0x100000000;
|
||||
static _Bool b5 = 0.0001;
|
||||
static _Bool b6 = -0.0;
|
||||
|
||||
if (b1 != 1 || b2 != 1 || b3 != 0 || b4 != 1 || b5 != 1 || b6 != 0)
|
||||
goto Fail;
|
||||
|
||||
printf ("Passed Conformance Test c99bool\n");
|
||||
return 0;
|
||||
|
208
Tests/Conformance/c99desinit.c
Normal file
208
Tests/Conformance/c99desinit.c
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Test of designated initializers (C99).
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef __ORCAC__
|
||||
typedef long long comp;
|
||||
#endif
|
||||
|
||||
struct S1 {
|
||||
int i;
|
||||
union {
|
||||
long x;
|
||||
char y;
|
||||
} u;
|
||||
short a[3];
|
||||
} s1 = {8, .a[0] = 9, .u.y = 'F', .i = 50, .a = {[1]=1,2}, .a[1] = 10};
|
||||
|
||||
struct S2 {
|
||||
char c;
|
||||
unsigned char uc;
|
||||
signed char sc;
|
||||
short s;
|
||||
unsigned short us;
|
||||
int i;
|
||||
unsigned int ui;
|
||||
long l;
|
||||
unsigned long ul;
|
||||
long long ll;
|
||||
unsigned long long ull;
|
||||
_Bool b;
|
||||
float f;
|
||||
double d;
|
||||
long double ld;
|
||||
comp cp;
|
||||
void *p;
|
||||
} s2 = {.p = &s2, .i = 123.4, .ui = 70, -123456, 123456, .c = 'd', 'e', 'f',
|
||||
.us = 78, .s = 40.1, .ll = 1234567890, 0x800000001, 123, 123.5,
|
||||
.cp = 9876543210, .d = -456.5, -789.5,
|
||||
};
|
||||
|
||||
struct S3 {
|
||||
float f;
|
||||
double d;
|
||||
long double ld;
|
||||
} s3 = {-123456LL, 3000000000U, 12345678900ULL};
|
||||
|
||||
char s4[] = {{123}, [3] = {'x'}};
|
||||
|
||||
struct S5 {
|
||||
int :16;
|
||||
signed int a:4;
|
||||
signed int b:6;
|
||||
signed int c:6;
|
||||
int :0;
|
||||
unsigned d:9;
|
||||
int :12;
|
||||
unsigned e:4;
|
||||
unsigned f:16;
|
||||
long g;
|
||||
int :15;
|
||||
} s5 = {-4, -5, 3, .g = 123456789, .d = 455, 8, 42345};
|
||||
|
||||
char *s6[4] = {s4, s4+1, [0]=0, [1]=s4+2, &s4[3], s4+4};
|
||||
|
||||
union U9 {
|
||||
union U9 *p;
|
||||
char s[6];
|
||||
} s9 = {&s9, .s = {"abcde"}, .s[1] = 'x'};
|
||||
|
||||
union U9 s10 = {&s9, .s = {"abcde"}, .s[1] = 'x', .p = &s10};
|
||||
|
||||
union U9 s11 = {&s9, .s[1] = 'x'};
|
||||
|
||||
struct S13 {
|
||||
struct S13a {
|
||||
struct S13b {
|
||||
struct S13c {
|
||||
int a;
|
||||
int b;
|
||||
} z;
|
||||
} y;
|
||||
} x;
|
||||
} s13 = {13, .x.y.z = {.b = 14}};
|
||||
|
||||
int f1(int i) {return i * 2 + 1;}
|
||||
|
||||
int main(void) {
|
||||
struct S1 a1 =
|
||||
{8, .a[0] = 9, .u.y = 'F', .i = 50, .a = {[1]=1,2}, .a[1] = 10};
|
||||
|
||||
struct S2 a2 =
|
||||
{.p = &s2, .i = 123.4, .ui = 70, -123456, 123456, .c = 'd', 'e', 'f',
|
||||
.us = 78, .s = 40.1, .ll = 1234567890, 0x800000001, 123, 123.5,
|
||||
.cp = 9876543210, .d = -456.5, -789.5,
|
||||
};
|
||||
|
||||
struct S3 a3 = {-123456LL, 3000000000U, 12345678900ULL};
|
||||
|
||||
char a4[] = {{123}, [3] = {'x'}};
|
||||
|
||||
struct S5 a5 = {-4, -5, 3, .g = 123456789, .d = 455, 8, 42345};
|
||||
|
||||
char *a6[4] = {s4, s4+1, [0]=0, [1]=s4+2, &s4[3], s4+4};
|
||||
|
||||
char a7[] = {"foo"[0], [1] = "foo"[2], "foo"[3]};
|
||||
|
||||
char a8[] = {"foo" != 0, [1] = "foo" == 0};
|
||||
|
||||
union U9 a9 = {&s9, .s = {"abcde"}, .s[1] = 'x'};
|
||||
|
||||
union U9 a10 = {&s9, .s = {"abcde"}, .s[1] = 'x', .p = &s10};
|
||||
|
||||
union U9 a11 = {&s9, .s[1] = 'x'};
|
||||
|
||||
struct S3 a12 = {.ld = f1(1)-8, .f = f1(2)*7, f1(3)+10};
|
||||
|
||||
struct S13 a13 = {s13.x.y};
|
||||
|
||||
if (s1.i!=50 || s1.u.y!='F' || s1.a[0]!=0 || s1.a[1]!=10 || s1.a[2]!=2)
|
||||
goto Fail;
|
||||
|
||||
if (a1.i!=50 || a1.u.y!='F' || a1.a[0]!=0 || a1.a[1]!=10 || a1.a[2]!=2)
|
||||
goto Fail;
|
||||
|
||||
if (s2.c != 'd' || s2.uc != 'e' || s2.sc != 'f' || s2.s != 40
|
||||
|| s2.us != 78 || s2.i != 123 || s2.ui != 70 || s2.l != -123456
|
||||
|| s2.ul != 123456 || s2.ll != 1234567890
|
||||
|| s2.ull != 0x800000001 || s2.b != 1 || s2.f != 123.5
|
||||
|| s2.d != -456.5 || s2.ld != -789.5 || s2.cp != 9876543210
|
||||
|| s2.p != &s2)
|
||||
goto Fail;
|
||||
|
||||
if (a2.c != 'd' || a2.uc != 'e' || a2.sc != 'f' || a2.s != 40
|
||||
|| a2.us != 78 || a2.i != 123 || a2.ui != 70 || a2.l != -123456
|
||||
|| a2.ul != 123456 || a2.ll != 1234567890
|
||||
|| a2.ull != 0x800000001 || a2.b != 1 || a2.f != 123.5
|
||||
|| a2.d != -456.5 || a2.ld != -789.5 || a2.cp != 9876543210
|
||||
|| a2.p != &s2)
|
||||
goto Fail;
|
||||
|
||||
if (s3.f != -123456.0 || s3.d != 3000000000.0 || s3.ld != 12345678900.0)
|
||||
goto Fail;
|
||||
|
||||
if (a3.f != -123456.0 || a3.d != 3000000000.0 || a3.ld != 12345678900.0)
|
||||
goto Fail;
|
||||
|
||||
if (sizeof(s4) != 4 || s4[0] != 123 || s4[1] != 0 || s4[2] != 0
|
||||
|| s4[3] != 'x')
|
||||
goto Fail;
|
||||
|
||||
if (sizeof(a4) != 4 || a4[0] != 123 || a4[1] != 0 || a4[2] != 0
|
||||
|| a4[3] != 'x')
|
||||
goto Fail;
|
||||
|
||||
if (s5.a != -4 || s5.b != -5 || s5.c != 3 || s5.d != 455 || s5.e != 8
|
||||
|| s5.f != 42345 || s5.g != 123456789)
|
||||
goto Fail;
|
||||
|
||||
if (a5.a != -4 || a5.b != -5 || a5.c != 3 || a5.d != 455 || a5.e != 8
|
||||
|| a5.f != 42345 || a5.g != 123456789)
|
||||
goto Fail;
|
||||
|
||||
if (s6[0] != 0 || s6[1] != &s4[2] || s6[2] != &s4[3] || s6[3] != s4+4)
|
||||
goto Fail;
|
||||
|
||||
if (a6[0] != 0 || a6[1] != &s4[2] || a6[2] != &s4[3] || a6[3] != s4+4)
|
||||
goto Fail;
|
||||
|
||||
if (sizeof(a7) != 3 || a7[0] != 'f' || a7[1] != 'o' || a7[2] != 0)
|
||||
goto Fail;
|
||||
|
||||
if (sizeof(a8) != 2 || a8[0] != 1 || a8[1] != 0)
|
||||
goto Fail;
|
||||
|
||||
if (strcmp(s9.s, "axcde") != 0)
|
||||
goto Fail;
|
||||
|
||||
if (strcmp(a9.s, "axcde") != 0)
|
||||
goto Fail;
|
||||
|
||||
if (s10.p != &s10)
|
||||
goto Fail;
|
||||
|
||||
if (a10.p != &s10)
|
||||
goto Fail;
|
||||
|
||||
if (s11.s[1] != 'x')
|
||||
goto Fail;
|
||||
|
||||
if (a11.s[1] != 'x')
|
||||
goto Fail;
|
||||
|
||||
if (a12.f != 35 || a12.d != 17 || a12.ld != -5)
|
||||
goto Fail;
|
||||
|
||||
if (a13.x.y.z.a != 0 || a13.x.y.z.b != 14)
|
||||
goto Fail;
|
||||
|
||||
printf ("Passed Conformance Test c99desinit\n");
|
||||
return 0;
|
||||
|
||||
Fail:
|
||||
printf ("Failed Conformance Test c99desinit\n");
|
||||
}
|
37
cc.notes
37
cc.notes
@ -603,6 +603,37 @@ is equivalent to the directive
|
||||
|
||||
The _Pragma("...") token sequence may be formed using preprocessor macros.
|
||||
|
||||
30. (C99) ORCA/C now supports designated initializers, which let you explicitly specify the array element or struct/union member that should be initialized by an expression within a braced initializer list. They have the form:
|
||||
|
||||
designator-list = expression
|
||||
|
||||
Designators may be of the form
|
||||
|
||||
[ constant-expression ]
|
||||
|
||||
to designate an element of an array, or
|
||||
|
||||
. identifier
|
||||
|
||||
to designate a specific field of a structure or union. A designator list may consist of one or more designators; successive designators correspond to successive levels of a nested data structure.
|
||||
|
||||
Designated and non-designated initializers may be mixed within an initializer list. If a non-designated initializer follows a designated one, it applies to the next subobject after the designated one, and initialization continues forward in the usual order until it is complete or another designator is encountered. If a braced initializer list does not include initializers for all the elements of an array or all the named members of a structure, the other ones are initialized to 0 (the same as when not using designated initializers).
|
||||
|
||||
Designated initializers make it possible to initialize subobjects in any order, and to initialize later subobjects without having to write an explicit initializer for earlier ones. Designated initializers also allow union members other than the first one to be initialized. It is also possible to initialize the same subobject multiple times, but in that case the initializer appearing latest in the initializer list will override any earlier ones.
|
||||
|
||||
As an example, the declaration
|
||||
|
||||
struct {
|
||||
int i;
|
||||
union {
|
||||
long x;
|
||||
char y;
|
||||
} u;
|
||||
short a[3];
|
||||
} s = {20, .a[0] = 9, .u.y = 'F', .i = 50, .a = {[1]=1,2}, .a[1] = 10};
|
||||
|
||||
sets s.i to 50, s.u.y to 'F', s.a[0] to 0, s.a[1] to 10, and s.a[2] to 2.
|
||||
|
||||
|
||||
Multi-Character Character Constants
|
||||
-----------------------------------
|
||||
@ -1976,6 +2007,12 @@ int foo(int[42]);
|
||||
|
||||
220. In certain cases where a header starts or ends in the middle of a declaration, it would not be represented correctly in the .sym file. This could cause errors or misbehavior on subsequent compiles.
|
||||
|
||||
221. Structures with unnamed bit-fields were sometimes initialized incorrectly.
|
||||
|
||||
222. If an expression of type unsigned long and value greater than LONG_MAX was used in the initializer for a floating-point variable with static storage duration, the wrong value would be produced.
|
||||
|
||||
223. Expressions of floating-point type could not be used in initializers for integer variables with static storage duration. This should be allowed, with a conversion performed as in the case of assignment.
|
||||
|
||||
-- Bugs from C 2.1.0 that have been fixed -----------------------------------
|
||||
|
||||
1. In some situations, fread() reread the first 1K or so of the file.
|
||||
|
Loading…
Reference in New Issue
Block a user