From: cuz Date: Sun, 16 Mar 2003 14:31:48 +0000 (+0000) Subject: Allow any number of optional braces around all initializers as required by the standard X-Git-Tag: V2.12.0~1668 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=6f52726647096c873b3be3cbbd048295c44e8019;p=cc65 Allow any number of optional braces around all initializers as required by the standard git-svn-id: svn://svn.cc65.org/cc65/trunk@2024 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 6d0c47f5e..049e4b616 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -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: