]> git.sur5r.net Git - cc65/commitdiff
Added flexible array members for structs
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 3 Feb 2003 22:14:20 +0000 (22:14 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 3 Feb 2003 22:14:20 +0000 (22:14 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@1925 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codegen.c
src/cc65/codegen.h
src/cc65/datatype.c
src/cc65/datatype.h
src/cc65/declare.c
src/cc65/declare.h
src/cc65/symtab.c
src/cc65/typecmp.c

index a9f5dd6947854c8519492cc2b5f5697bb05e5117..f3a556fb21b0d18496d3bb1ac1d39e7c2e621921 100644 (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);
+    }
 }
 
 
index 17dfcd513c0537de1fb1dc8c5564cadd30b8327a..ff9b1830651c99980fe8334214f351f64412771e 100644 (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 */
index e323f20ecea453adc13ae14acc3493a6b78311db..781470b651de5c71e9a20721730004b52714602f 100644 (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);
+}
+
+
+
index c5a93dc4d34ca616d1e886aa8425bc8c6c3d734d..2cbebedef7738e1b153729adeb31633ed2cfe7dc 100644 (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 */
index 16e76a591bcda3aacd4bc2d04ba0022929bbcf43..20db1f6afcee378ba13087ad002a092ab631ee4d 100644 (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;
 
-    /* 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;
 
     }
 }
 
 
 
+
index c079a1a0d28f4a9c55bab97a3671b66355b7384b..5195456c38f5812692cca947337661cee4ee18e8 100644 (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.
+ */
 
 
 
index cc8dcc10604d9a2168bb95181231e1bb42d5c44c..2c50775d797ffe9e96eaa1993fcc71d5f0141596 100644 (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);
                }
index 3a101011c5a8272663ee87a9d87f4bc44e350799..5b2be8500acace006370c70264b71f1eab8118ea 100644 (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;