]> git.sur5r.net Git - cc65/commitdiff
Allow any number of optional braces around all initializers as required by the standard
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 16 Mar 2003 14:31:48 +0000 (14:31 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 16 Mar 2003 14:31:48 +0000 (14:31 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@2024 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/declare.c

index 6d0c47f5e87e552a18b14222d235fe80a9253131..049e4b6161f96d24013d7ecfc9dd73f021f9a5aa 100644 (file)
@@ -1008,74 +1008,173 @@ void CheckEmptyDecl (const DeclSpec* D)
 
 
 
-static unsigned ParseVoidInit (void)
-/* Parse an initialization of a void variable (special cc65 extension).
- * Return the number of bytes initialized.
+static void SkipInitializer (unsigned BracesExpected)
+/* Skip the remainder of an initializer in case of errors. Try to be somewhat
+ * smart so we don't have too many following errors.
  */
 {
-    ExprDesc lval;
-    unsigned Size;
+    while (CurTok.Tok != TOK_CEOF && CurTok.Tok != TOK_SEMI && BracesExpected > 0) {
+        switch (CurTok.Tok) {
+            case TOK_RCURLY:    --BracesExpected;   break;
+            case TOK_LCURLY:    ++BracesExpected;   break;
+            default:                                break;
+        }
+        NextToken ();
+    }
+}
 
-    ConsumeLCurly ();
 
-    /* Allow an arbitrary list of values */
-    Size = 0;
-    do {
-       ConstExpr (&lval);
-       switch (UnqualifiedType (lval.Type[0])) {
 
-           case T_SCHAR:
-           case T_UCHAR:
-               if ((lval.Flags & E_MCTYPE) == E_TCONST) {
-                   /* Make it byte sized */
-                   lval.ConstVal &= 0xFF;
-               }
-               DefineData (&lval);
-                Size += SIZEOF_CHAR;
-                break;
+static unsigned OpeningCurlyBraces (unsigned BracesNeeded)
+/* Accept any number of opening curly braces around an initialization, skip
+ * them and return the number. If the number of curly braces is less than
+ * BracesNeeded, issue a warning.
+ */
+{
+    unsigned BraceCount = 0;
+    while (CurTok.Tok == TOK_LCURLY) {
+        ++BraceCount;
+        NextToken ();
+    }
+    if (BraceCount < BracesNeeded) {
+        Error ("`{' expected");
+    }
+    return BraceCount;
+}
 
-           case T_SHORT:
-           case T_USHORT:
-           case T_INT:
-           case T_UINT:
-           case T_PTR:
-           case T_ARRAY:
-               if ((lval.Flags & E_MCTYPE) == E_TCONST) {
-                   /* Make it word sized */
-                   lval.ConstVal &= 0xFFFF;
-               }
-               DefineData (&lval);
-               Size += SIZEOF_INT;
-                break;
 
-           case T_LONG:
-           case T_ULONG:
-               DefineData (&lval);
-               Size += SIZEOF_LONG;
-                break;
 
-           default:
-               Error ("Illegal type in initialization");
-               break;
+static void ClosingCurlyBraces (unsigned BracesExpected)
+/* Accept and skip the given number of closing curly braces together with
+ * an optional comma. Output an error messages, if the input does not contain
+ * the expected number of braces.
+ */
+{
+    while (BracesExpected) {
+        if (CurTok.Tok == TOK_RCURLY) {
+            NextToken ();
+        } else if (CurTok.Tok == TOK_COMMA && NextTok.Tok == TOK_RCURLY) {
+            NextToken ();
+            NextToken ();
+        } else {
+            Error ("`}' expected");
+            return;
+        }
+        --BracesExpected;
+    }
+}
 
-       }
 
-       if (CurTok.Tok != TOK_COMMA) {
-           break;
-       }
-       NextToken ();
 
-    } while (CurTok.Tok != TOK_RCURLY);
+static unsigned ParseSimpleInit (type* T)
+/* Parse initializaton for simple data types. Return the number of data bytes. */
+{
+    static const unsigned long Masks[] = {
+        0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL
+    };
+    ExprDesc ED;
+
+    /* Optional opening brace */
+    unsigned BraceCount = OpeningCurlyBraces (0);
+
+    /* Get the size of the expected type */
+    unsigned Size = SizeOf (T);
+    CHECK (Size > 0 && Size <= sizeof(Masks)/sizeof(Masks[0]));
+
+    /* Expression */
+    ConstExpr (&ED);
+    if ((ED.Flags & E_MCTYPE) == E_TCONST) {
+        /* Make the const value the correct size */
+        ED.ConstVal &= Masks[Size-1];
+    }
+    assignadjust (T, &ED);
 
-    /* Closing brace */
-    ConsumeRCurly ();
+    /* Output the data */
+    DefineData (&ED);
 
-    /* Return the number of bytes initialized */
+    /* Close eventually opening braces */
+    ClosingCurlyBraces (BraceCount);
+
+    /* Done */
     return Size;
 }
 
 
 
+static unsigned ParseArrayInit (type* T, int AllowFlexibleMembers)
+/* Parse initializaton for arrays. Return the number of data bytes. */
+{
+    int Count;
+
+    /* Get the array data */
+    type* ElementType    = GetElementType (T);
+    unsigned ElementSize = CheckedSizeOf (ElementType);
+    long ElementCount    = GetElementCount (T);
+
+    /* Special handling for a character array initialized by a literal */
+    if (IsTypeChar (ElementType) && CurTok.Tok == TOK_SCONST) {
+
+        /* Optional curly braces */
+        unsigned BraceCount = OpeningCurlyBraces (0);
+
+        /* Char array initialized by string constant */
+        const char* Str = GetLiteral (CurTok.IVal);
+        Count = GetLiteralPoolOffs () - CurTok.IVal;
+
+        /* Translate into target charset */
+        TranslateLiteralPool (CurTok.IVal);
+        g_defbytes (Str, Count);
+
+        /* Remove string from pool */
+        ResetLiteralPoolOffs (CurTok.IVal);
+        NextToken ();
+
+        /* Closing curly braces (if we had any opening ones) */
+        ClosingCurlyBraces (BraceCount);
+
+    } else {
+
+        /* Optional curly braces */
+        unsigned BraceCount = OpeningCurlyBraces (1);
+
+        /* Initialize the array members */
+        Count = 0;
+        while (CurTok.Tok != TOK_RCURLY) {
+            /* Flexible array members may not be initialized within
+             * an array (because the size of each element may differ
+             * otherwise).
+             */
+            ParseInitInternal (ElementType, 0);
+            ++Count;
+            if (CurTok.Tok != TOK_COMMA)
+                break;
+            NextToken ();
+        }
+
+        /* Closing curly braces (if we had any opening ones) */
+        ClosingCurlyBraces (BraceCount);
+    }
+
+
+    if (ElementCount == UNSPECIFIED) {
+        /* Number of elements determined by initializer */
+        Encode (T + 1, Count);
+        ElementCount = Count;
+    } else if (ElementCount == FLEXIBLE && AllowFlexibleMembers) {
+        /* In non ANSI mode, allow initialization of flexible array
+         * members.
+         */
+        ElementCount = Count;
+    } else if (Count < ElementCount) {
+        g_zerobytes ((ElementCount - Count) * ElementSize);
+    } else if (Count > ElementCount) {
+        Error ("Too many initializers");
+    }
+    return ElementCount * ElementSize;
+}
+
+
+
 static unsigned ParseStructInit (type* Type, int AllowFlexibleMembers)
 /* Parse initialization of a struct or union. Return the number of data bytes. */
 {
@@ -1084,11 +1183,9 @@ static unsigned ParseStructInit (type* Type, int AllowFlexibleMembers)
     unsigned  StructSize;
     unsigned  Size;
 
-    static const token_t EndTokens[] = { TOK_RCURLY, TOK_SEMI };
-
 
     /* Consume the opening curly brace */
-    ConsumeLCurly ();
+    unsigned BraceCount = OpeningCurlyBraces (1);
 
     /* Get a pointer to the struct entry from the type */
     Entry = DecodePtr (Type + 1);
@@ -1103,10 +1200,7 @@ static unsigned ParseStructInit (type* Type, int AllowFlexibleMembers)
     if (Tab == 0) {
        Error ("Cannot initialize variables with incomplete type");
         /* Try error recovery */
-        SkipTokens (EndTokens, sizeof(EndTokens)/sizeof(EndTokens[0]));
-        if (CurTok.Tok == TOK_RCURLY) {
-            NextToken ();
-        }
+        SkipInitializer (BraceCount);
        /* Nothing initialized */
        return 0;
     }
@@ -1119,6 +1213,7 @@ static unsigned ParseStructInit (type* Type, int AllowFlexibleMembers)
     while (CurTok.Tok != TOK_RCURLY) {
        if (Entry == 0) {
            Error ("Too many initializers");
+            SkipInitializer (BraceCount);
            return Size;
        }
         /* Parse initialization of one field. Flexible array members may
@@ -1133,7 +1228,7 @@ static unsigned ParseStructInit (type* Type, int AllowFlexibleMembers)
     }
 
     /* Consume the closing curly brace */
-    ConsumeRCurly ();
+    ClosingCurlyBraces (BraceCount);
 
     /* If there are struct fields left, reserve additional storage */
     if (Size < StructSize) {
@@ -1150,99 +1245,93 @@ static unsigned ParseStructInit (type* Type, int AllowFlexibleMembers)
 
 
 
+static unsigned ParseVoidInit (void)
+/* Parse an initialization of a void variable (special cc65 extension).
+ * Return the number of bytes initialized.
+ */
+{
+    ExprDesc lval;
+    unsigned Size;
+
+    /* Opening brace */
+    unsigned BraceCount = OpeningCurlyBraces (1);
+
+    /* Allow an arbitrary list of values */
+    Size = 0;
+    do {
+       ConstExpr (&lval);
+       switch (UnqualifiedType (lval.Type[0])) {
+
+           case T_SCHAR:
+           case T_UCHAR:
+               if ((lval.Flags & E_MCTYPE) == E_TCONST) {
+                   /* Make it byte sized */
+                   lval.ConstVal &= 0xFF;
+               }
+               DefineData (&lval);
+                Size += SIZEOF_CHAR;
+                break;
+
+           case T_SHORT:
+           case T_USHORT:
+           case T_INT:
+           case T_UINT:
+           case T_PTR:
+           case T_ARRAY:
+               if ((lval.Flags & E_MCTYPE) == E_TCONST) {
+                   /* Make it word sized */
+                   lval.ConstVal &= 0xFFFF;
+               }
+               DefineData (&lval);
+               Size += SIZEOF_INT;
+                break;
+
+           case T_LONG:
+           case T_ULONG:
+               DefineData (&lval);
+               Size += SIZEOF_LONG;
+                break;
+
+           default:
+               Error ("Illegal type in initialization");
+               break;
+
+       }
+
+       if (CurTok.Tok != TOK_COMMA) {
+           break;
+       }
+       NextToken ();
+
+    } while (CurTok.Tok != TOK_RCURLY);
+
+    /* Closing brace */
+    ClosingCurlyBraces (BraceCount);
+
+    /* Return the number of bytes initialized */
+    return Size;
+}
+
+
+
 static unsigned ParseInitInternal (type* T, int AllowFlexibleMembers)
 /* Parse initialization of variables. Return the number of data bytes. */
 {
-    ExprDesc    lval;
-    const char* str;
-    int         Count;
-    type*       ElementType;
-    unsigned    ElementSize;
-    long        ElementCount;
-
     switch (UnqualifiedType (*T)) {
 
        case T_SCHAR:
        case T_UCHAR:
-           ConstExpr (&lval);
-           if ((lval.Flags & E_MCTYPE) == E_TCONST) {
-               /* Make it byte sized */
-               lval.ConstVal &= 0xFF;
-           }
-           assignadjust (T, &lval);
-           DefineData (&lval);
-           return SIZEOF_CHAR;
-
        case T_SHORT:
        case T_USHORT:
        case T_INT:
        case T_UINT:
        case T_PTR:
-           ConstExpr (&lval);
-           if ((lval.Flags & E_MCTYPE) == E_TCONST) {
-               /* Make it word sized */
-               lval.ConstVal &= 0xFFFF;
-           }
-           assignadjust (T, &lval);
-           DefineData (&lval);
-           return SIZEOF_INT;
-
        case T_LONG:
        case T_ULONG:
-           ConstExpr (&lval);
-           if ((lval.Flags & E_MCTYPE) == E_TCONST) {
-               /* Make it long sized */
-               lval.ConstVal &= 0xFFFFFFFF;
-           }
-           assignadjust (T, &lval);
-           DefineData (&lval);
-           return SIZEOF_LONG;
+            return ParseSimpleInit (T);
 
        case T_ARRAY:
-            ElementType  = GetElementType (T);
-            ElementSize  = CheckedSizeOf (ElementType);
-           ElementCount = GetElementCount (T);
-                   if (IsTypeChar (ElementType) && CurTok.Tok == TOK_SCONST) {
-                /* Char array initialized by string constant */
-               str = GetLiteral (CurTok.IVal);
-               Count = GetLiteralPoolOffs () - CurTok.IVal;
-                /* Translate into target charset */
-               TranslateLiteralPool (CurTok.IVal);
-               g_defbytes (str, Count);
-                /* Remove string from pool */
-               ResetLiteralPoolOffs (CurTok.IVal);
-               NextToken ();
-           } else {
-               ConsumeLCurly ();
-               Count = 0;
-               while (CurTok.Tok != TOK_RCURLY) {
-                    /* Flexible array members may not be initialized within
-                     * an array (because the size of each element may differ
-                     * otherwise).
-                     */
-                   ParseInitInternal (ElementType, 0);
-                   ++Count;
-                   if (CurTok.Tok != TOK_COMMA)
-                       break;
-                   NextToken ();
-               }
-               ConsumeRCurly ();
-           }
-           if (ElementCount == UNSPECIFIED) {
-                /* Number of elements determined by initializer */
-               Encode (T + 1, Count);
-                ElementCount = Count;
-            } else if (ElementCount == FLEXIBLE && AllowFlexibleMembers) {
-                /* In non ANSI mode, allow initialization of flexible array
-                 * members.
-                 */
-                ElementCount = Count;
-           } else if (Count < ElementCount) {
-               g_zerobytes ((ElementCount - Count) * ElementSize);
-           } else if (Count > ElementCount) {
-               Error ("Too many initializers");
-           }
-            return ElementCount * ElementSize;
+            return ParseArrayInit (T, AllowFlexibleMembers);
 
         case T_STRUCT:
         case T_UNION: