From c123666d24e5dda1e7242b0c31b90c8cea769f82 Mon Sep 17 00:00:00 2001 From: cuz Date: Mon, 3 Feb 2003 22:14:20 +0000 Subject: [PATCH] Added flexible array members for structs git-svn-id: svn://svn.cc65.org/cc65/trunk@1925 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codegen.c | 14 ++-- src/cc65/codegen.h | 10 +-- src/cc65/datatype.c | 34 ++++++-- src/cc65/datatype.h | 10 ++- src/cc65/declare.c | 190 ++++++++++++++++++++++++++++---------------- src/cc65/declare.h | 14 ++-- src/cc65/symtab.c | 14 ++-- src/cc65/typecmp.c | 20 ++--- 8 files changed, 194 insertions(+), 112 deletions(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index a9f5dd694..f3a556fb2 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -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); + } } diff --git a/src/cc65/codegen.h b/src/cc65/codegen.h index 17dfcd513..ff9b18306 100644 --- a/src/cc65/codegen.h +++ b/src/cc65/codegen.h @@ -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 */ diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index e323f20ec..781470b65 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -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); +} + + + diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index c5a93dc4d..2cbebedef 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -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 */ diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 16e76a591..20db1f6af 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -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; - /* Allow an arbitrary list of values */ ConsumeLCurly (); + + /* Allow an arbitrary list of values */ + 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; } } + diff --git a/src/cc65/declare.h b/src/cc65/declare.h index c079a1a0d..5195456c3 100644 --- a/src/cc65/declare.h +++ b/src/cc65/declare.h @@ -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. + */ diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index cc8dcc106..2c50775d7 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -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); } diff --git a/src/cc65/typecmp.c b/src/cc65/typecmp.c index 3a101011c..5b2be8500 100644 --- a/src/cc65/typecmp.c +++ b/src/cc65/typecmp.c @@ -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; -- 2.39.5