/* */
/* */
/* */
-/* (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 */
/* */
/* */
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) {
/* Compute size of object represented by type array. */
{
SymEntry* Entry;
+ long ElementCount;
switch (UnqualifiedType (T[0])) {
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);
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:
CHECK (T[0] == T_FUNC);
/* Decode the function descriptor and return it */
- return (FuncDesc*) DecodePtr (T+1);
+ return DecodePtr (T+1);
}
+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);
+}
+
+
+
/* (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 */
/* 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;
/* Parse a struct/union declaration. */
{
- unsigned StructSize;
- unsigned FieldSize;
- unsigned Offs;
+ unsigned StructSize;
+ unsigned FieldSize;
+ unsigned Offs;
+ int FlexibleMember;
SymTable* FieldTab;
SymEntry* Entry;
EnterStructLevel ();
/* Parse struct fields */
- StructSize = 0;
+ FlexibleMember = 0;
+ StructSize = 0;
while (CurTok.Tok != TOK_RCURLY) {
/* Get the type of the entry */
/* 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 ();
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;
}
-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:
lval.ConstVal &= 0xFF;
}
DefineData (&lval);
- break;
+ Size += SIZEOF_CHAR;
+ break;
case T_SHORT:
case T_USHORT:
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.
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)) {
}
assignadjust (T, &lval);
DefineData (&lval);
- break;
+ return SIZEOF_CHAR;
case T_SHORT:
case T_USHORT:
}
assignadjust (T, &lval);
DefineData (&lval);
- break;
+ return SIZEOF_INT;
case T_LONG:
case T_ULONG:
}
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 */
}
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;
}
}
+
/* */
/* */
/* */
-/* (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 */
return 0;
}
}
-
+
/* Compare the types of this field */
if (TypeCmp (Sym1->Type, Sym2->Type) < TC_EQUAL) {
/* Field types not equal */
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) {
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;