1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-25 13:29:41 +00:00

Added flexible array members for structs

git-svn-id: svn://svn.cc65.org/cc65/trunk@1925 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2003-02-03 22:14:20 +00:00
parent d5481ff95b
commit c123666d24
8 changed files with 194 additions and 112 deletions

View File

@ -6,9 +6,9 @@
/* */
/* */
/* */
/* (C) 1998-2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* (C) 1998-2003 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
@ -4013,10 +4013,12 @@ void g_defbytes (const void* Bytes, unsigned Count)
void g_zerobytes (unsigned n)
/* Output n bytes of data initialized with zero */
void g_zerobytes (unsigned Count)
/* Output Count bytes of data initialized with zero */
{
AddDataLine ("\t.res\t%u,$00", n);
if (Count > 0) {
AddDataLine ("\t.res\t%u,$00", Count);
}
}

View File

@ -6,9 +6,9 @@
/* */
/* */
/* */
/* (C) 1998-2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* (C) 1998-2003 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
@ -432,8 +432,8 @@ void g_defdata (unsigned flags, unsigned long val, long offs);
void g_defbytes (const void* bytes, unsigned count);
/* Output a row of bytes as a constant */
void g_zerobytes (unsigned n);
/* Output n bytes of data initialized with zero */
void g_zerobytes (unsigned Count);
/* Output Count bytes of data initialized with zero */
void g_initregister (unsigned Label, unsigned Reg, unsigned Size);
/* Initialize a register variable from static initialization data */

View File

@ -6,9 +6,9 @@
/* */
/* */
/* */
/* (C) 1998-2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* (C) 1998-2003 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@musoftware.de */
/* */
/* */
@ -368,7 +368,7 @@ void PrintRawType (FILE* F, const type* Type)
void Encode (type* Type, unsigned long Val)
/* Encode p[0] and p[1] so that neither p[0] nore p[1] is zero */
/* Encode Val into the given type string */
{
int I;
for (I = 0; I < DECODE_SIZE; ++I) {
@ -429,6 +429,7 @@ unsigned SizeOf (const type* T)
/* Compute size of object represented by type array. */
{
SymEntry* Entry;
long ElementCount;
switch (UnqualifiedType (T[0])) {
@ -470,11 +471,17 @@ unsigned SizeOf (const type* T)
case T_STRUCT:
case T_UNION:
Entry = (SymEntry*) DecodePtr (T+1);
Entry = DecodePtr (T+1);
return Entry->V.S.Size;
case T_ARRAY:
return (Decode (T+ 1) * SizeOf (T + DECODE_SIZE + 1));
ElementCount = GetElementCount (T);
if (ElementCount < 0) {
/* Array with unspecified size */
return 0;
} else {
return ElementCount * SizeOf (T + DECODE_SIZE + 1);
}
default:
Internal ("Unknown type in SizeOf: %04X", *T);
@ -564,7 +571,7 @@ unsigned TypeOf (const type* T)
return CF_LONG | CF_UNSIGNED;
case T_FUNC:
F = (FuncDesc*) DecodePtr (T+1);
F = DecodePtr (T+1);
return (F->Flags & FD_VARIADIC)? 0 : CF_FIXARGC;
case T_STRUCT:
@ -714,7 +721,7 @@ FuncDesc* GetFuncDesc (const type* T)
CHECK (T[0] == T_FUNC);
/* Decode the function descriptor and return it */
return (FuncDesc*) DecodePtr (T+1);
return DecodePtr (T+1);
}
@ -737,3 +744,14 @@ type* GetFuncReturn (type* T)
long GetElementCount (const type* T)
/* Get the element count of the array specified in T (which must be of
* array type).
*/
{
CHECK (IsTypeArray (T));
return (unsigned) Decode (T+1);
}

View File

@ -144,6 +144,9 @@ typedef unsigned short type;
/* Type elements needed for Encode/Decode */
#define DECODE_SIZE 5
/* Unspecified size for the element count of an array */
#define UNSPECIFIED -1L
/* Sizes */
#define SIZEOF_CHAR 1
#define SIZEOF_SHORT 2
@ -218,7 +221,7 @@ void PrintFuncSig (FILE* F, const char* Name, type* Type);
/* Print a function signature. */
void Encode (type* Type, unsigned long Val);
/* Encode an unsigned long into a type array */
/* Encode Val into the given type string */
void EncodePtr (type* Type, void* P);
/* Encode a pointer into a type array */
@ -474,6 +477,11 @@ FuncDesc* GetFuncDesc (const type* T) attribute ((const));
type* GetFuncReturn (type* T) attribute ((const));
/* Return a pointer to the return type of a function or pointer-to-function type */
long GetElementCount (const type* T);
/* Get the element count of the array specified in T (which must be of
* array type).
*/
/* End of datatype.h */

View File

@ -9,7 +9,7 @@
/* (C) 1998-2003 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@musoftware.de */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -236,7 +236,7 @@ static void ParseEnumDecl (void)
/* Add an entry to the symbol table */
AddConstSym (Ident, type_int, SC_ENUM, EnumVal++);
/* Check for end of definition */
if (CurTok.Tok != TOK_COMMA)
break;
@ -251,9 +251,10 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType)
/* Parse a struct/union declaration. */
{
unsigned StructSize;
unsigned FieldSize;
unsigned Offs;
unsigned StructSize;
unsigned FieldSize;
unsigned Offs;
int FlexibleMember;
SymTable* FieldTab;
SymEntry* Entry;
@ -283,7 +284,8 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType)
EnterStructLevel ();
/* Parse struct fields */
StructSize = 0;
FlexibleMember = 0;
StructSize = 0;
while (CurTok.Tok != TOK_RCURLY) {
/* Get the type of the entry */
@ -294,30 +296,55 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType)
/* Read fields with this type */
while (1) {
/* Get type and name of the struct field */
Declaration Decl;
/* If we had a flexible array member before, no other fields can
* follow.
*/
if (FlexibleMember) {
Error ("Flexible array member must be last field");
FlexibleMember = 0; /* Avoid further errors */
}
/* Get type and name of the struct field */
ParseDecl (&Spec, &Decl, 0);
/* Get the offset of this field */
Offs = (StructType == T_STRUCT)? StructSize : 0;
/* Add a field entry to the table */
AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
/* Calculate the sizes, handle flexible array members */
if (StructType == T_STRUCT) {
/* It's a struct. Check if this field is a flexible array
* member, and calculate the size of the field.
*/
if (IsTypeArray (Decl.Type) && GetElementCount (Decl.Type) == UNSPECIFIED) {
/* Array with unspecified size */
if (StructSize == 0) {
Error ("Flexible array member cannot be first struct field");
}
FlexibleMember = 1;
/* Assume zero for size calculations */
Encode (Decl.Type + 1, 0);
} else {
StructSize += CheckedSizeOf (Decl.Type);
}
/* Calculate offset of next field/size of the union */
FieldSize = CheckedSizeOf (Decl.Type);
if (StructType == T_STRUCT) {
/* It's a struct */
StructSize += FieldSize;
} else {
/* It's a union */
FieldSize = CheckedSizeOf (Decl.Type);
if (FieldSize > StructSize) {
StructSize = FieldSize;
}
}
if (CurTok.Tok != TOK_COMMA)
/* Add a field entry to the table */
AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
if (CurTok.Tok != TOK_COMMA) {
break;
}
NextToken ();
}
ConsumeSemi ();
@ -871,17 +898,17 @@ static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
D->T += DECODE_SIZE;
} else {
/* Array declaration */
unsigned long Size = 0;
long Size = UNSPECIFIED;
NextToken ();
/* Read the size if it is given */
if (CurTok.Tok != TOK_RBRACK) {
ExprDesc lval;
ConstExpr (&lval);
if (lval.ConstVal < 0) {
if (lval.ConstVal <= 0) {
if (D->Ident[0] != '\0') {
Error ("Size of array `%s' is negative", D->Ident);
Error ("Size of array `%s' is invalid", D->Ident);
} else {
Error ("Size of array is negative");
Error ("Size of array is invalid");
}
lval.ConstVal = 1;
}
@ -978,16 +1005,21 @@ void CheckEmptyDecl (const DeclSpec* D)
static void ParseVoidInit (void)
/* Parse an initialization of a void variable (special cc65 extension) */
static unsigned ParseVoidInit (void)
/* Parse an initialization of a void variable (special cc65 extension).
* Return the number of bytes initialized.
*/
{
ExprDesc lval;
unsigned Size;
ConsumeLCurly ();
/* Allow an arbitrary list of values */
ConsumeLCurly ();
Size = 0;
do {
ConstExpr (&lval);
switch (lval.Type[0]) {
switch (UnqualifiedType (lval.Type[0])) {
case T_SCHAR:
case T_UCHAR:
@ -996,7 +1028,8 @@ static void ParseVoidInit (void)
lval.ConstVal &= 0xFF;
}
DefineData (&lval);
break;
Size += SIZEOF_CHAR;
break;
case T_SHORT:
case T_USHORT:
@ -1009,42 +1042,53 @@ static void ParseVoidInit (void)
lval.ConstVal &= 0xFFFF;
}
DefineData (&lval);
break;
Size += SIZEOF_INT;
break;
case T_LONG:
case T_ULONG:
DefineData (&lval);
break;
Size += SIZEOF_LONG;
break;
default:
Error ("Illegal type in initialization");
break;
}
}
if (CurTok.Tok != TOK_COMMA) {
break;
}
NextToken ();
if (CurTok.Tok != TOK_COMMA) {
break;
}
NextToken ();
} while (CurTok.Tok != TOK_RCURLY);
/* Closing brace */
ConsumeRCurly ();
/* Return the number of bytes initialized */
return Size;
}
static void ParseStructInit (type* Type)
/* Parse initialization of a struct or union */
static unsigned ParseStructInit (type* Type)
/* Parse initialization of a struct or union. Return the number of data bytes. */
{
SymEntry* Entry;
SymTable* Tab;
unsigned StructSize;
unsigned Size;
/* Consume the opening curly brace */
ConsumeLCurly ();
/* Get a pointer to the struct entry from the type */
Entry = (SymEntry*) Decode (Type + 1);
Entry = DecodePtr (Type + 1);
/* Get the size of the struct from the symbol table entry */
StructSize = Entry->V.S.Size;
/* Check if this struct definition has a field table. If it doesn't, it
* is an incomplete definition.
@ -1052,44 +1096,50 @@ static void ParseStructInit (type* Type)
Tab = Entry->V.S.SymTab;
if (Tab == 0) {
Error ("Cannot initialize variables with incomplete type");
/* Returning here will cause lots of errors, but recovery is difficult */
return;
/* Returning here will cause lots of errors, but recovery is difficult */
return 0;
}
/* Get a pointer to the list of symbols */
Entry = Tab->SymHead;
/* Initialize fields */
Size = 0;
while (CurTok.Tok != TOK_RCURLY) {
if (Entry == 0) {
Error ("Too many initializers");
return;
}
ParseInit (Entry->Type);
Entry = Entry->NextSym;
if (CurTok.Tok != TOK_COMMA)
break;
NextToken ();
if (Entry == 0) {
Error ("Too many initializers");
return Size;
}
Size += ParseInit (Entry->Type);
Entry = Entry->NextSym;
if (CurTok.Tok != TOK_COMMA)
break;
NextToken ();
}
/* Consume the closing curly brace */
ConsumeRCurly ();
/* If there are struct fields left, reserve additional storage */
while (Entry) {
g_zerobytes (CheckedSizeOf (Entry->Type));
Entry = Entry->NextSym;
if (Size < StructSize) {
g_zerobytes (StructSize - Size);
}
/* Return the number of bytes initialized */
return StructSize;
}
void ParseInit (type* T)
/* Parse initialization of variables. */
unsigned ParseInit (type* T)
/* Parse initialization of variables. Return the number of data bytes. */
{
ExprDesc lval;
type* t;
ExprDesc lval;
type* t;
const char* str;
int Count;
int Size;
int Count;
long ElementCount;
unsigned ElementSize;
switch (UnqualifiedType (*T)) {
@ -1102,7 +1152,7 @@ void ParseInit (type* T)
}
assignadjust (T, &lval);
DefineData (&lval);
break;
return SIZEOF_CHAR;
case T_SHORT:
case T_USHORT:
@ -1116,7 +1166,7 @@ void ParseInit (type* T)
}
assignadjust (T, &lval);
DefineData (&lval);
break;
return SIZEOF_INT;
case T_LONG:
case T_ULONG:
@ -1127,14 +1177,15 @@ void ParseInit (type* T)
}
assignadjust (T, &lval);
DefineData (&lval);
break;
return SIZEOF_LONG;
case T_ARRAY:
Size = Decode (T + 1);
ElementCount = GetElementCount (T);
ElementSize = CheckedSizeOf (T + DECODE_SIZE + 1);
t = T + DECODE_SIZE + 1;
if (IsTypeChar(t) && CurTok.Tok == TOK_SCONST) {
if (IsTypeChar (t) && CurTok.Tok == TOK_SCONST) {
str = GetLiteral (CurTok.IVal);
Count = strlen (str) + 1;
Count = GetLiteralPoolOffs () - CurTok.IVal;
TranslateLiteralPool (CurTok.IVal); /* Translate into target charset */
g_defbytes (str, Count);
ResetLiteralPoolOffs (CurTok.IVal); /* Remove string from pool */
@ -1151,34 +1202,33 @@ void ParseInit (type* T)
}
ConsumeRCurly ();
}
if (Size == 0) {
if (ElementCount == UNSPECIFIED) {
Encode (T + 1, Count);
} else if (Count < Size) {
g_zerobytes ((Size - Count) * CheckedSizeOf (T + DECODE_SIZE + 1));
} else if (Count > Size) {
} else if (Count < ElementCount) {
g_zerobytes ((ElementCount - Count) * ElementSize);
} else if (Count > ElementCount) {
Error ("Too many initializers");
}
break;
return ElementCount * ElementSize;
case T_STRUCT:
case T_UNION:
ParseStructInit (T);
break;
return ParseStructInit (T);
case T_VOID:
if (!ANSI) {
/* Special cc65 extension in non ANSI mode */
ParseVoidInit ();
break;
return ParseVoidInit ();
}
/* FALLTHROUGH */
default:
Error ("Illegal type");
break;
return SIZEOF_CHAR;
}
}

View File

@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 1998-2001 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* (C) 1998-2003 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -101,8 +101,10 @@ void CheckEmptyDecl (const DeclSpec* D);
* warning if not.
*/
void ParseInit (type* T);
/* Parse initialization of variables. */
unsigned ParseInit (type* T);
/* Parse initialization of variables. Return the number of initialized data
* bytes.
*/

View File

@ -6,9 +6,9 @@
/* */
/* */
/* */
/* (C) 2000-2001 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* (C) 2000-2003 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
@ -717,17 +717,17 @@ SymEntry* AddGlobalSym (const char* Name, const type* Type, unsigned Flags)
if (IsTypeArray (Type) && IsTypeArray (EType)) {
/* Get the array sizes */
unsigned Size = Decode (Type + 1);
unsigned ESize = Decode (EType + 1);
long Size = GetElementCount (Type);
long ESize = GetElementCount (EType);
if ((Size != 0 && ESize != 0 && Size != ESize) ||
if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) ||
TypeCmp (Type+DECODE_SIZE+1, EType+DECODE_SIZE+1) < TC_EQUAL) {
/* Types not identical: Conflicting types */
Error ("Conflicting types for `%s'", Name);
return Entry;
} else {
/* Check if we have a size in the existing definition */
if (ESize == 0) {
if (ESize == UNSPECIFIED) {
/* Existing, size not given, use size from new def */
Encode (EType + 1, Size);
}

View File

@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* (C) 1998-2003 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -107,7 +107,7 @@ static int EqualSymTables (SymTable* Tab1, SymTable* Tab2)
return 0;
}
}
/* Compare the types of this field */
if (TypeCmp (Sym1->Type, Sym2->Type) < TC_EQUAL) {
/* Field types not equal */
@ -149,7 +149,7 @@ static void DoCompare (const type* lhs, const type* rhs, typecmp_t* Result)
type LeftType, RightType;
type LeftSign, RightSign;
type LeftQual, RightQual;
unsigned LeftCount, RightCount;
long LeftCount, RightCount;
/* Check if the end of the type string is reached */
if (*rhs == T_END) {
@ -274,9 +274,11 @@ static void DoCompare (const type* lhs, const type* rhs, typecmp_t* Result)
case T_TYPE_ARRAY:
/* Check member count */
LeftCount = Decode (lhs+1);
RightCount = Decode (rhs+1);
if (LeftCount != 0 && RightCount != 0 && LeftCount != RightCount) {
LeftCount = GetElementCount (lhs);
RightCount = GetElementCount (rhs);
if (LeftCount != UNSPECIFIED &&
RightCount != UNSPECIFIED &&
LeftCount != RightCount) {
/* Member count given but different */
SetResult (Result, TC_INCOMPATIBLE);
return;