]> git.sur5r.net Git - cc65/blobdiff - src/cc65/declare.c
Added a new option --dep-target to the compiler. This option allows to set the
[cc65] / src / cc65 / declare.c
index c15cc53a3e12f0547d740cf39cd1fac6cfb22595..587d7ce74b34a2ab84cf0fb83ae0e1d4b2069dbe 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2005 Ullrich von Bassewitz                                       */
-/*               Römerstraße 52                                              */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 1998-2010, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 
 
 /*****************************************************************************/
-/*                                Forwards                                  */
+/*                                   Data                                    */
+/*****************************************************************************/
+
+
+
+typedef struct StructInitData StructInitData;
+struct StructInitData {
+    unsigned    Size;                   /* Size of struct */
+    unsigned    Offs;                   /* Current offset in struct */
+    unsigned    BitVal;                 /* Summed up bit-field value */
+    unsigned    ValBits;                /* Valid bits in Val */
+};
+
+
+
+/*****************************************************************************/
+/*                                Forwards                                  */
 /*****************************************************************************/
 
 
@@ -77,41 +93,111 @@ static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers);
 
 
 /*****************************************************************************/
-/*                           internal functions                             */
+/*                           Internal functions                             */
 /*****************************************************************************/
 
 
 
-static TypeCode OptionalQualifiers (TypeCode Q)
-/* Read type qualifiers if we have any */
+static void DuplicateQualifier (const char* Name)
+/* Print an error message */
 {
-    while (TokIsTypeQual (&CurTok)) {
+    Warning ("Duplicate qualifier: `%s'", Name);
+}
 
-       switch (CurTok.Tok) {
 
-           case TOK_CONST:
-               if (Q & T_QUAL_CONST) {
-                   Error ("Duplicate qualifier: `const'");
-               }
-               Q |= T_QUAL_CONST;
-               break;
+
+static TypeCode OptionalQualifiers (TypeCode Allowed)
+/* Read type qualifiers if we have any. Allowed specifies the allowed
+ * qualifiers.
+ */
+{
+    /* We start without any qualifiers */
+    TypeCode Q = T_QUAL_NONE;
+
+    /* Check for more qualifiers */
+    while (1) {
+
+       switch (CurTok.Tok) {
+
+           case TOK_CONST:
+                if (Allowed & T_QUAL_CONST) {
+                    if (Q & T_QUAL_CONST) {
+                        DuplicateQualifier ("const");
+                    }
+                    Q |= T_QUAL_CONST;
+                } else {
+                    goto Done;
+                }
+                break;
 
            case TOK_VOLATILE:
-               if (Q & T_QUAL_VOLATILE) {
-                   Error ("Duplicate qualifier: `volatile'");
-               }
-               Q |= T_QUAL_VOLATILE;
-               break;
+                if (Allowed & T_QUAL_VOLATILE) {
+                    if (Q & T_QUAL_VOLATILE) {
+                        DuplicateQualifier ("volatile");
+                    }
+                    Q |= T_QUAL_VOLATILE;
+                } else {
+                    goto Done;
+                }
+               break;
 
             case TOK_RESTRICT:
-                if (Q & T_QUAL_RESTRICT) {
-                    Error ("Duplicate qualifier: `restrict'");
+                if (Allowed & T_QUAL_RESTRICT) {
+                    if (Q & T_QUAL_RESTRICT) {
+                        DuplicateQualifier ("restrict");
+                    }
+                    Q |= T_QUAL_RESTRICT;
+                } else {
+                    goto Done;
+                }
+                break;
+
+            case TOK_NEAR:
+                if (Allowed & T_QUAL_NEAR) {
+                    if (Q & T_QUAL_NEAR) {
+                        DuplicateQualifier ("near");
+                    }
+                    Q |= T_QUAL_NEAR;
+                } else {
+                    goto Done;
+                }
+                break;
+
+            case TOK_FAR:
+                if (Allowed & T_QUAL_FAR) {
+                    if (Q & T_QUAL_FAR) {
+                        DuplicateQualifier ("far");
+                    }
+                    Q |= T_QUAL_FAR;
+                } else {
+                    goto Done;
+                }
+                break;
+
+            case TOK_FASTCALL:
+                if (Allowed & T_QUAL_FASTCALL) {
+                    if (Q & T_QUAL_FASTCALL) {
+                        DuplicateQualifier ("fastcall");
+                    }
+                    Q |= T_QUAL_FASTCALL;
+                } else {
+                    goto Done;
+                }
+                break;
+
+            case TOK_CDECL:
+                if (Allowed & T_QUAL_CDECL) {
+                    if (Q & T_QUAL_CDECL) {
+                        DuplicateQualifier ("cdecl");
+                    }
+                    Q |= T_QUAL_CDECL;
+                } else {
+                    goto Done;
                 }
-                Q |= T_QUAL_RESTRICT;
                 break;
 
            default:
-               Internal ("Unexpected type qualifier token: %d", CurTok.Tok);
+               goto Done;
 
        }
 
@@ -119,6 +205,33 @@ static TypeCode OptionalQualifiers (TypeCode Q)
        NextToken ();
     }
 
+Done:
+    /* We cannot have more than one address size far qualifier */
+    switch (Q & T_QUAL_ADDRSIZE) {
+
+        case T_QUAL_NONE:
+        case T_QUAL_NEAR:
+        case T_QUAL_FAR:
+            break;
+
+        default:
+            Error ("Cannot specify more than one address size qualifier");
+            Q &= ~T_QUAL_ADDRSIZE;
+    }
+
+    /* We cannot have more than one calling convention specifier */
+    switch (Q & T_QUAL_CCONV) {
+
+        case T_QUAL_NONE:
+        case T_QUAL_FASTCALL:
+        case T_QUAL_CDECL:
+            break;
+
+        default:
+            Error ("Cannot specify more than one calling convention qualifier");
+            Q &= ~T_QUAL_CCONV;
+    }
+
     /* Return the qualifiers read */
     return Q;
 }
@@ -160,9 +273,10 @@ static void InitDeclSpec (DeclSpec* D)
 static void InitDeclaration (Declaration* D)
 /* Initialize the Declaration struct for use */
 {
-    D->Ident[0]  = '\0';
-    D->Type[0].C = T_END;
-    D->Index     = 0;
+    D->Ident[0]   = '\0';
+    D->Type[0].C  = T_END;
+    D->Index      = 0;
+    D->Attributes = 0;
 }
 
 
@@ -190,39 +304,22 @@ static void AddTypeToDeclaration (Declaration* D, TypeCode T)
 
 
 
-static void AddFuncTypeToDeclaration (Declaration* D, FuncDesc* F)
-/* Add a function type plus function descriptor to the type of a declaration */
+static void FixQualifiers (Type* DataType)
+/* Apply several fixes to qualifiers */
 {
-    NeedTypeSpace (D, 1);
-    D->Type[D->Index].C = T_FUNC;
-    SetFuncDesc (D->Type + D->Index, F);
-    ++D->Index;
-}
-
-
+    Type*    T;
+    TypeCode Q;
 
-static void AddArrayToDeclaration (Declaration* D, long Size)
-/* Add an array type plus size to the type of a declaration */
-{
-    NeedTypeSpace (D, 1);
-    D->Type[D->Index].C = T_ARRAY;
-    D->Type[D->Index].A.L = Size;
-    ++D->Index;
-}
-
-
-
-static void FixArrayQualifiers (Type* T)
-/* Using typedefs, it is possible to generate declarations that have
- * type qualifiers attached to an array, not the element type. Go and
- * fix these here.
- */
-{
-    TypeCode Q = T_QUAL_NONE;
+    /* Using typedefs, it is possible to generate declarations that have
+     * type qualifiers attached to an array, not the element type. Go and
+     * fix these here.
+     */
+    T = DataType;
+    Q = T_QUAL_NONE;
     while (T->C != T_END) {
         if (IsTypeArray (T)) {
             /* Extract any type qualifiers */
-            Q |= T->C & T_MASK_QUAL;
+            Q |= GetQualifier (T);
             T->C = UnqualifiedType (T->C);
         } else {
             /* Add extracted type qualifiers here */
@@ -231,9 +328,69 @@ static void FixArrayQualifiers (Type* T)
         }
         ++T;
     }
-
     /* Q must be empty now */
     CHECK (Q == T_QUAL_NONE);
+
+    /* Do some fixes on pointers and functions. */
+    T = DataType;
+    while (T->C != T_END) {
+        if (IsTypePtr (T)) {
+
+            /* Fastcall qualifier on the pointer? */
+            if (IsQualFastcall (T)) {
+                /* Pointer to function which is not fastcall? */
+                if (IsTypeFunc (T+1) && !IsQualFastcall (T+1)) {
+                    /* Move the fastcall qualifier from the pointer to
+                     * the function.
+                     */
+                    T[0].C &= ~T_QUAL_FASTCALL;
+                    T[1].C |= T_QUAL_FASTCALL;
+                } else {
+                    Error ("Invalid `_fastcall__' qualifier for pointer");
+                }
+            }
+
+            /* Apply the default far and near qualifiers if none are given */
+            Q = (T[0].C & T_QUAL_ADDRSIZE);
+            if (Q == T_QUAL_NONE) {
+                /* No address size qualifiers specified */
+                if (IsTypeFunc (T+1)) {
+                    /* Pointer to function. Use the qualifier from the function
+                     * or the default if the function don't has one.
+                     */
+                    Q = (T[1].C & T_QUAL_ADDRSIZE);
+                    if (Q == T_QUAL_NONE) {
+                        Q = CodeAddrSizeQualifier ();
+                    }
+                } else {
+                    Q = DataAddrSizeQualifier ();
+                }
+                T[0].C |= Q;
+            } else {
+                /* We have address size qualifiers. If followed by a function,
+                 * apply these also to the function.
+                 */
+                if (IsTypeFunc (T+1)) {
+                    TypeCode FQ = (T[1].C & T_QUAL_ADDRSIZE);
+                    if (FQ == T_QUAL_NONE) {
+                        T[1].C |= Q;
+                    } else if (FQ != Q) {
+                        Error ("Address size qualifier mismatch");
+                        T[1].C = (T[1].C & ~T_QUAL_ADDRSIZE) | Q;
+                    }
+                }
+            }
+
+        } else if (IsTypeFunc (T)) {
+
+            /* Apply the default far and near qualifiers if none are given */
+            if ((T[0].C & T_QUAL_ADDRSIZE) == 0) {
+                T[0].C |= CodeAddrSizeQualifier ();
+            }
+
+        }
+        ++T;
+    }
 }
 
 
@@ -331,31 +488,169 @@ static void ParseEnumDecl (void)
 
 
 
-static SymEntry* ParseStructDecl (const char* Name, TypeCode StructType)
-/* Parse a struct/union declaration. */
+static int ParseFieldWidth (Declaration* Decl)
+/* Parse an optional field width. Returns -1 if no field width is speficied,
+ * otherwise the width of the field.
+ */
 {
+    ExprDesc Expr;
 
-    unsigned  StructSize;
+    if (CurTok.Tok != TOK_COLON) {
+        /* No bit-field declaration */
+        return -1;
+    }
+
+    /* Read the width */
+    NextToken ();
+    ConstAbsIntExpr (hie1, &Expr);
+    if (Expr.IVal < 0) {
+        Error ("Negative width in bit-field");
+        return -1;
+    }
+    if (Expr.IVal > (int) INT_BITS) {
+        Error ("Width of bit-field exceeds its type");
+        return -1;
+    }
+    if (Expr.IVal == 0 && Decl->Ident[0] != '\0') {
+        Error ("Zero width for named bit-field");
+        return -1;
+    }
+    if (!IsTypeInt (Decl->Type)) {
+        /* Only integer types may be used for bit-fields */
+        Error ("Bit-field has invalid type");
+        return -1;
+    }
+
+    /* Return the field width */
+    return (int) Expr.IVal;
+}
+
+
+
+static SymEntry* StructOrUnionForwardDecl (const char* Name)
+/* Handle a struct or union forward decl */
+{
+    /* Try to find a struct with the given name. If there is none,
+     * insert a forward declaration into the current lexical level.
+     */
+    SymEntry* Entry = FindTagSym (Name);
+    if (Entry == 0) {
+        Entry = AddStructSym (Name, 0, 0);
+    } else if (SymIsLocal (Entry) && (Entry->Flags & SC_STRUCT) != SC_STRUCT) {
+        /* Already defined in the level, but no struct */
+        Error ("Symbol `%s' is already different kind", Name);
+    }
+    return Entry;
+}
+
+
+
+static SymEntry* ParseUnionDecl (const char* Name)
+/* Parse a union declaration. */
+{
+
+    unsigned  UnionSize;
     unsigned  FieldSize;
-    unsigned  Offs;
+    int       FieldWidth;       /* Width in bits, -1 if not a bit-field */
+    SymTable* FieldTab;
+    SymEntry* Entry;
+
+
+    if (CurTok.Tok != TOK_LCURLY) {
+       /* Just a forward declaration. */
+       return StructOrUnionForwardDecl (Name);
+    }
+
+    /* Add a forward declaration for the struct in the current lexical level */
+    Entry = AddStructSym (Name, 0, 0);
+
+    /* Skip the curly brace */
+    NextToken ();
+
+    /* Enter a new lexical level for the struct */
+    EnterStructLevel ();
+
+    /* Parse union fields */
+    UnionSize      = 0;
+    while (CurTok.Tok != TOK_RCURLY) {
+
+       /* Get the type of the entry */
+       DeclSpec Spec;
+       InitDeclSpec (&Spec);
+       ParseTypeSpec (&Spec, -1, T_QUAL_NONE);
+
+       /* Read fields with this type */
+       while (1) {
+
+           Declaration Decl;
+
+           /* Get type and name of the struct field */
+           ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
+
+            /* Check for a bit-field declaration */
+            FieldWidth = ParseFieldWidth (&Decl);
+
+            /* Ignore zero sized bit fields in a union */
+            if (FieldWidth == 0) {
+                goto NextMember;
+            }
+
+            /* Check for fields without a name */
+            if (Decl.Ident[0] == '\0') {
+                /* Any field without a name is legal but useless in a union */
+                Warning ("Declaration does not declare anything");
+                goto NextMember;
+            }
+
+            /* Handle sizes */
+            FieldSize = CheckedSizeOf (Decl.Type);
+            if (FieldSize > UnionSize) {
+                UnionSize = FieldSize;
+            }
+
+            /* Add a field entry to the table. */
+            if (FieldWidth > 0) {
+                AddBitField (Decl.Ident, 0, 0, FieldWidth);
+            } else {
+                AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, 0);
+            }
+
+NextMember: if (CurTok.Tok != TOK_COMMA) {
+               break;
+            }
+           NextToken ();
+       }
+       ConsumeSemi ();
+    }
+
+    /* Skip the closing brace */
+    NextToken ();
+
+    /* Remember the symbol table and leave the struct level */
+    FieldTab = GetSymTab ();
+    LeaveStructLevel ();
+
+    /* Make a real entry from the forward decl and return it */
+    return AddStructSym (Name, UnionSize, FieldTab);
+}
+
+
+
+static SymEntry* ParseStructDecl (const char* Name)
+/* Parse a struct declaration. */
+{
+
+    unsigned  StructSize;
     int       FlexibleMember;
+    int       BitOffs;          /* Bit offset for bit-fields */
+    int       FieldWidth;       /* Width in bits, -1 if not a bit-field */
     SymTable* FieldTab;
     SymEntry* Entry;
 
 
     if (CurTok.Tok != TOK_LCURLY) {
-       /* Just a forward declaration. Try to find a struct with the given
-        * name. If there is none, insert a forward declaration into the
-        * current lexical level.
-        */
-       Entry = FindTagSym (Name);
-               if (Entry == 0) {
-           Entry = AddStructSym (Name, 0, 0);
-       } else if (SymIsLocal (Entry) && (Entry->Flags & SC_STRUCT) == 0) {
-           /* Already defined in the level but no struct */
-           Error ("Symbol `%s' is already different kind", Name);
-       }
-       return Entry;
+       /* Just a forward declaration. */
+       return StructOrUnionForwardDecl (Name);
     }
 
     /* Add a forward declaration for the struct in the current lexical level */
@@ -370,6 +665,7 @@ static SymEntry* ParseStructDecl (const char* Name, TypeCode StructType)
     /* Parse struct fields */
     FlexibleMember = 0;
     StructSize     = 0;
+    BitOffs        = 0;
     while (CurTok.Tok != TOK_RCURLY) {
 
        /* Get the type of the entry */
@@ -381,6 +677,7 @@ static SymEntry* ParseStructDecl (const char* Name, TypeCode StructType)
        while (1) {
 
            Declaration Decl;
+            ident       Ident;
 
             /* If we had a flexible array member before, no other fields can
              * follow.
@@ -391,47 +688,97 @@ static SymEntry* ParseStructDecl (const char* Name, TypeCode StructType)
             }
 
            /* Get type and name of the struct field */
-           ParseDecl (&Spec, &Decl, 0);
+           ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
 
-            /* Get the offset of this field */
-            Offs = (StructType == T_STRUCT)? StructSize : 0;
+            /* Check for a bit-field declaration */
+            FieldWidth = ParseFieldWidth (&Decl);
 
-            /* Calculate the sizes, handle flexible array members */
-            if (StructType == T_STRUCT) {
+            /* If this is not a bit field, or the bit field is too large for
+             * the remainder of the current member, or we have a bit field
+             * with width zero, align the struct to the next member by adding
+             * a member with an anonymous name.
+             */
+            if (BitOffs > 0) {
+                if (FieldWidth <= 0 || (BitOffs + FieldWidth) > (int) INT_BITS) {
 
-                /* 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 */
-                    SetElementCount (Decl.Type, FLEXIBLE);
-                } else {
-                    StructSize += CheckedSizeOf (Decl.Type);
+                    /* We need an anonymous name */
+                    AnonName (Ident, "bit-field");
+
+                    /* Add an anonymous bit-field that aligns to the next
+                     * storage unit.
+                     */
+                    AddBitField (Ident, StructSize, BitOffs, INT_BITS - BitOffs);
+
+                    /* No bits left */
+                    StructSize += SIZEOF_INT;
+                    BitOffs = 0;
                 }
+            }
 
-           } else {
+            /* Apart from the above, a bit field with width 0 is not processed
+             * further.
+             */
+            if (FieldWidth == 0) {
+                goto NextMember;
+            }
 
-                /* It's a union */
-                FieldSize = CheckedSizeOf (Decl.Type);
-               if (FieldSize > StructSize) {
-                   StructSize = FieldSize;
-               }
-           }
+            /* Check for fields without names */
+            if (Decl.Ident[0] == '\0') {
+                if (FieldWidth < 0) {
+                    /* A non bit-field without a name is legal but useless */
+                    Warning ("Declaration does not declare anything");
+                    goto NextMember;
+                } else {
+                    /* A bit-field without a name will get an anonymous one */
+                    AnonName (Decl.Ident, "bit-field");
+                }
+            }
 
-           /* Add a field entry to the table */
-           AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
+            /* 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 */
+                SetElementCount (Decl.Type, FLEXIBLE);
+            }
 
-           if (CurTok.Tok != TOK_COMMA) {
-               break;
+            /* Add a field entry to the table */
+            if (FieldWidth > 0) {
+                /* Add full byte from the bit offset to the variable offset.
+                 * This simplifies handling he bit-field as a char type
+                 * in expressions.
+                 */
+                unsigned Offs = StructSize + (BitOffs / CHAR_BITS);
+                AddBitField (Decl.Ident, Offs, BitOffs % CHAR_BITS, FieldWidth);
+                BitOffs += FieldWidth;
+                CHECK (BitOffs <= (int) INT_BITS);
+                if (BitOffs == INT_BITS) {
+                    StructSize += SIZEOF_INT;
+                    BitOffs = 0;
+                }
+            } else {
+                AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, StructSize);
+                if (!FlexibleMember) {
+                    StructSize += CheckedSizeOf (Decl.Type);
+                }
             }
-           NextToken ();
-       }
-       ConsumeSemi ();
+
+NextMember: if (CurTok.Tok != TOK_COMMA) {
+               break;
+            }
+           NextToken ();
+       }
+       ConsumeSemi ();
+    }
+
+    /* If we have bits from bit-fields left, add them to the size. */
+    if (BitOffs > 0) {
+        StructSize += ((BitOffs + CHAR_BITS - 1) / CHAR_BITS);
     }
 
     /* Skip the closing brace */
@@ -452,13 +799,12 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
 {
     ident      Ident;
     SymEntry*  Entry;
-    TypeCode    StructType;
 
     /* Assume we have an explicit type */
     D->Flags &= ~DS_DEF_TYPE;
 
     /* Read type qualifiers if we have any */
-    Qualifiers = OptionalQualifiers (Qualifiers);
+    Qualifiers |= OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE);
 
     /* Look at the data type */
     switch (CurTok.Tok) {
@@ -593,23 +939,40 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
            D->Type[1].C = T_END;
            break;
 
-       case TOK_STRUCT:
        case TOK_UNION:
-           StructType = (CurTok.Tok == TOK_STRUCT)? T_STRUCT : T_UNION;
            NextToken ();
            /* */
            if (CurTok.Tok == TOK_IDENT) {
                strcpy (Ident, CurTok.Ident);
                NextToken ();
            } else {
-               AnonName (Ident, (StructType == T_STRUCT)? "struct" : "union");
+                       AnonName (Ident, "union");
+           }
+           /* Remember we have an extra type decl */
+           D->Flags |= DS_EXTRA_TYPE;
+           /* Declare the union in the current scope */
+           Entry = ParseUnionDecl (Ident);
+                   /* Encode the union entry into the type */
+           D->Type[0].C = T_UNION;
+           SetSymEntry (D->Type, Entry);
+           D->Type[1].C = T_END;
+           break;
+
+       case TOK_STRUCT:
+           NextToken ();
+           /* */
+           if (CurTok.Tok == TOK_IDENT) {
+               strcpy (Ident, CurTok.Ident);
+               NextToken ();
+           } else {
+                       AnonName (Ident, "struct");
            }
            /* Remember we have an extra type decl */
            D->Flags |= DS_EXTRA_TYPE;
            /* Declare the struct in the current scope */
-           Entry = ParseStructDecl (Ident, StructType);
+           Entry = ParseStructDecl (Ident);
                    /* Encode the struct entry into the type */
-           D->Type[0].C = StructType;
+           D->Type[0].C = T_STRUCT;
            SetSymEntry (D->Type, Entry);
            D->Type[1].C = T_END;
            break;
@@ -647,7 +1010,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
            if (Entry && SymIsTypeDef (Entry)) {
                        /* It's a typedef */
                NextToken ();
-               TypeCpy (D->Type, Entry->Type);
+               TypeCopy (D->Type, Entry->Type);
                break;
            }
            /* FALL THROUGH */
@@ -666,7 +1029,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
     }
 
     /* There may also be qualifiers *after* the initial type */
-    D->Type[0].C |= OptionalQualifiers (Qualifiers);
+    D->Type[0].C |= (Qualifiers | OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE));
 }
 
 
@@ -696,7 +1059,7 @@ static void ParseOldStyleParamList (FuncDesc* F)
        }
 
        /* Create a symbol table entry with type int */
-       AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF, 0);
+       AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF | SC_DEFTYPE, 0);
 
        /* Count arguments */
                ++F->ParamCount;
@@ -736,7 +1099,7 @@ static void ParseOldStyleParamList (FuncDesc* F)
        /* Parse a comma separated variable list */
        while (1) {
 
-           Declaration         Decl;
+           Declaration         Decl;
 
            /* Read the parameter */
            ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
@@ -745,8 +1108,18 @@ static void ParseOldStyleParamList (FuncDesc* F)
                /* We have a name given. Search for the symbol */
                SymEntry* Sym = FindLocalSym (Decl.Ident);
                if (Sym) {
-                   /* Found it, change the default type to the one given */
-                   ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
+                    /* Check if we already changed the type for this
+                     * parameter
+                     */
+                    if (Sym->Flags & SC_DEFTYPE) {
+                        /* Found it, change the default type to the one given */
+                        ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
+                        /* Reset the "default type" flag */
+                        Sym->Flags &= ~SC_DEFTYPE;
+                    } else {
+                        /* Type has already been changed */
+                        Error ("Redefinition for parameter `%s'", Sym->Name);
+                    }
                } else {
                    Error ("Unknown identifier: `%s'", Decl.Ident);
                }
@@ -775,7 +1148,7 @@ static void ParseAnsiParamList (FuncDesc* F)
 
        DeclSpec        Spec;
        Declaration     Decl;
-       DeclAttr        Attr;
+        SymEntry*       Sym;
 
        /* Allow an ellipsis as last parameter */
        if (CurTok.Tok == TOK_ELLIPSIS) {
@@ -810,14 +1183,24 @@ static void ParseAnsiParamList (FuncDesc* F)
            F->Flags |= FD_UNNAMED_PARAMS;
 
            /* Clear defined bit on nonames */
-           Spec.StorageClass &= ~SC_DEF;
+           Decl.StorageClass &= ~SC_DEF;
        }
 
-       /* Parse an attribute ### */
-       ParseAttribute (&Decl, &Attr);
+       /* Parse attributes for this parameter */
+       ParseAttribute (&Decl);
 
        /* Create a symbol table entry */
-       AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Spec.StorageClass, 0);
+        Sym = AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Decl.StorageClass, 0);
+
+        /* Add attributes if we have any */
+        SymUseAttr (Sym, &Decl);
+
+        /* If the parameter is a struct or union, emit a warning */
+        if (IsClassStruct (Decl.Type)) {
+            if (IS_Get (&WarnStructParam)) {
+                Warning ("Passing struct by value for parameter `%s'", Decl.Ident);
+            }
+        }
 
        /* Count arguments */
                ++F->ParamCount;
@@ -834,17 +1217,6 @@ static void ParseAnsiParamList (FuncDesc* F)
      * the breaks above bail out without checking.
      */
     ConsumeRParen ();
-
-    /* Check if this is a function definition */
-    if (CurTok.Tok == TOK_LCURLY) {
-       /* Print an error if we have unnamed parameters and cc65 extensions
-         * are disabled.
-        */
-               if (IS_Get (&Standard) != STD_CC65 &&
-            (F->Flags & FD_UNNAMED_PARAMS) != 0) {
-           Error ("Parameter name omitted");
-       }
-    }
 }
 
 
@@ -883,8 +1255,10 @@ static FuncDesc* ParseFuncDecl (void)
 
     /* Parse params */
     if ((F->Flags & FD_OLDSTYLE) == 0) {
+
        /* New style function */
        ParseAnsiParamList (F);
+
     } else {
        /* Old style function */
        ParseOldStyleParamList (F);
@@ -914,13 +1288,6 @@ static FuncDesc* ParseFuncDecl (void)
        Sym = Sym->PrevSym;
     }
 
-    /* Add the default address size for the function */
-    if (CodeAddrSize == ADDR_SIZE_FAR) {
-        F->Flags |= FD_FAR;
-    } else {
-        F->Flags |= FD_NEAR;
-    }
-
     /* Leave the lexical level remembering the symbol tables */
     RememberFunctionLevel (F);
 
@@ -930,114 +1297,37 @@ static FuncDesc* ParseFuncDecl (void)
 
 
 
-static unsigned FunctionModifierFlags (void)
-/* Parse __fastcall__, __near__ and __far__ and return the matching FD_ flags */
-{
-    /* Read the flags */
-    unsigned Flags = FD_NONE;
-    while (CurTok.Tok == TOK_FASTCALL || CurTok.Tok == TOK_NEAR || CurTok.Tok == TOK_FAR) {
-
-        /* Get the flag bit for the next token */
-        unsigned F = FD_NONE;
-        switch (CurTok.Tok) {
-            case TOK_FASTCALL:  F = FD_FASTCALL; break;
-            case TOK_NEAR:             F = FD_NEAR;     break;
-            case TOK_FAR:      F = FD_FAR;      break;
-            default:            Internal ("Unexpected token: %d", CurTok.Tok);
-        }
-
-        /* Remember the flag for this modifier */
-        if (Flags & F) {
-            Error ("Duplicate modifier");
-        }
-        Flags |= F;
-
-        /* Skip the token */
-        NextToken ();
-    }
-
-    /* Sanity check */
-    if ((Flags & (FD_NEAR | FD_FAR)) == (FD_NEAR | FD_FAR)) {
-        Error ("Cannot specify both, `__near__' and `__far__' modifiers");
-        Flags &= ~(FD_NEAR | FD_FAR);
-    }
-
-    /* Return the flags read */
-    return Flags;
-}
-
-
-
-static void ApplyFunctionModifiers (Type* T, unsigned Flags)
-/* Apply a set of function modifier flags to a function */
-{
-    /* Get the function descriptor */
-    FuncDesc* F = GetFuncDesc (T);
-
-    /* Special check for __fastcall__ */
-    if ((Flags & FD_FASTCALL) != 0 && IsVariadicFunc (T)) {
-        Error ("Cannot apply `__fastcall__' to functions with "
-               "variable parameter list");
-        Flags &= ~FD_FASTCALL;
-    }
-
-    /* Remove the default function address size modifiers */
-    F->Flags &= ~(FD_NEAR | FD_FAR);
-
-    /* Add the new modifers */
-    F->Flags |= Flags;
-}
-
-
-
-static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
+static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
 /* Recursively process declarators. Build a type array in reverse order. */
 {
+    /* Read optional function or pointer qualifiers. These modify the
+     * identifier or token to the right. For convenience, we allow the fastcall
+     * qualifier also for pointers here. If it is a pointer-to-function, the
+     * qualifier will later be transfered to the function itself. If it's a
+     * pointer to something else, it will be flagged as an error.
+     */
+    TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_FASTCALL);
+
     /* Pointer to something */
     if (CurTok.Tok == TOK_STAR) {
 
-       TypeCode C;
-
         /* Skip the star */
                NextToken ();
 
-       /* Allow optional const or volatile qualifiers */
-               C = T_PTR | OptionalQualifiers (T_QUAL_NONE);
+       /* Allow const, restrict and volatile qualifiers */
+        Qualifiers |= OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE | T_QUAL_RESTRICT);
 
         /* Parse the type, the pointer points to */
-               Decl (Spec, D, Mode);
+               Declarator (Spec, D, Mode);
 
        /* Add the type */
-       AddTypeToDeclaration (D, C);
+       AddTypeToDeclaration (D, T_PTR | Qualifiers);
                return;
     }
 
-    /* Function modifiers */
-    if (CurTok.Tok == TOK_FASTCALL || CurTok.Tok == TOK_NEAR || CurTok.Tok == TOK_FAR) {
-
-       /* Remember the current type pointer */
-       Type* T = D->Type + D->Index;
-
-       /* Read the flags */
-       unsigned Flags = FunctionModifierFlags ();
-
-       /* Parse the function */
-       Decl (Spec, D, Mode);
-
-       /* Check that we have a function */
-       if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) {
-           Error ("Function modifier applied to non function");
-       } else {
-            ApplyFunctionModifiers (T, Flags);
-        }
-
-       /* Done */
-       return;
-    }
-
     if (CurTok.Tok == TOK_LPAREN) {
                NextToken ();
-               Decl (Spec, D, Mode);
+               Declarator (Spec, D, Mode);
                ConsumeRParen ();
     } else {
        /* Things depend on Mode now:
@@ -1068,17 +1358,41 @@ static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
 
                    /* Function declaration */
            FuncDesc* F;
+
+            /* Skip the opening paren */
                    NextToken ();
 
            /* Parse the function declaration */
                    F = ParseFuncDecl ();
 
+            /* We cannot specify fastcall for variadic functions */
+            if ((F->Flags & FD_VARIADIC) && (Qualifiers & T_QUAL_FASTCALL)) {
+                Error ("Variadic functions cannot be `__fastcall'");
+                Qualifiers &= ~T_QUAL_FASTCALL;
+            }
+
            /* Add the function type. Be sure to bounds check the type buffer */
-           AddFuncTypeToDeclaration (D, F);
+            NeedTypeSpace (D, 1);
+            D->Type[D->Index].C = T_FUNC | Qualifiers;
+            D->Type[D->Index].A.P = F;
+            ++D->Index;
+
+            /* Qualifiers now used */
+            Qualifiers = T_QUAL_NONE;
+
                } else {
-           /* Array declaration */
+           /* Array declaration. */
                    long Size = UNSPECIFIED;
+
+            /* We cannot have any qualifiers for an array */
+            if (Qualifiers != T_QUAL_NONE) {
+                Error ("Invalid qualifiers for array");
+                Qualifiers = T_QUAL_NONE;
+            }
+
+            /* Skip the left bracket */
                    NextToken ();
+
            /* Read the size if it is given */
                    if (CurTok.Tok != TOK_RBRACK) {
                ExprDesc Expr;
@@ -1093,12 +1407,31 @@ static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
                 }
                        Size = Expr.IVal;
                    }
+
+            /* Skip the right bracket */
                    ConsumeRBrack ();
 
-           /* Add the array type with the size */
-           AddArrayToDeclaration (D, Size);
+           /* Add the array type with the size to the type */
+            NeedTypeSpace (D, 1);
+            D->Type[D->Index].C = T_ARRAY;
+            D->Type[D->Index].A.L = Size;
+            ++D->Index;
                }
     }
+
+    /* If we have remaining qualifiers, flag them as invalid */
+    if (Qualifiers & T_QUAL_NEAR) {
+        Error ("Invalid `__near__' qualifier");
+    }
+    if (Qualifiers & T_QUAL_FAR) {
+        Error ("Invalid `__far__' qualifier");
+    }
+    if (Qualifiers & T_QUAL_FASTCALL) {
+        Error ("Invalid `__fastcall__' qualifier");
+    }
+    if (Qualifiers & T_QUAL_CDECL) {
+        Error ("Invalid `__cdecl__' qualifier");
+    }
 }
 
 
@@ -1123,7 +1456,7 @@ Type* ParseType (Type* T)
     ParseDecl (&Spec, &Decl, DM_NO_IDENT);
 
     /* Copy the type to the target buffer */
-    TypeCpy (T, Decl.Type);
+    TypeCopy (T, Decl.Type);
 
     /* Return a pointer to the target buffer */
     return T;
@@ -1131,21 +1464,32 @@ Type* ParseType (Type* T)
 
 
 
-void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
+void ParseDecl (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
 /* Parse a variable, type or function declaration */
 {
     /* Initialize the Declaration struct */
     InitDeclaration (D);
 
     /* Get additional declarators and the identifier */
-    Decl (Spec, D, Mode);
+    Declarator (Spec, D, Mode);
 
     /* Add the base type. */
     NeedTypeSpace (D, TypeLen (Spec->Type) + 1);       /* Bounds check */
-    TypeCpy (D->Type + D->Index, Spec->Type);
+    TypeCopy (D->Type + D->Index, Spec->Type);
 
-    /* Fix any type qualifiers attached to an array type */
-    FixArrayQualifiers (D->Type);
+    /* Use the storage class from the declspec */
+    D->StorageClass = Spec->StorageClass;
+
+    /* Do several fixes on qualifiers */
+    FixQualifiers (D->Type);
+
+    /* If we have a function, add a special storage class */
+    if (IsTypeFunc (D->Type)) {
+        D->StorageClass |= SC_FUNC;
+    }
+
+    /* Parse attributes for this declaration */
+    ParseAttribute (D);
 
     /* Check several things for function or function pointer types */
     if (IsTypeFunc (D->Type) || IsTypeFuncPtr (D->Type)) {
@@ -1187,6 +1531,19 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
 
     }
 
+    /* For anthing that is not a function or typedef, check for an implicit
+     * int declaration.
+     */
+    if ((D->StorageClass & SC_FUNC) != SC_FUNC &&
+        (D->StorageClass & SC_TYPEDEF) != SC_TYPEDEF) {
+        /* If the standard was not set explicitly to C89, print a warning
+         * for variables with implicit int type.
+         */
+        if ((Spec->Flags & DS_DEF_TYPE) != 0 && IS_Get (&Standard) >= STD_C99) {
+            Warning ("Implicit `int' is an obsolete feature");
+        }
+    }
+
     /* Check the size of the generated type */
     if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type)) {
         unsigned Size = SizeOf (D->Type);
@@ -1212,7 +1569,7 @@ void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, long DefType)
     InitDeclSpec (D);
 
     /* There may be qualifiers *before* the storage class specifier */
-    Qualifiers = OptionalQualifiers (T_QUAL_NONE);
+    Qualifiers = OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE);
 
     /* Now get the storage class specifier for this declaration */
     ParseStorageClass (D, DefStorage);
@@ -1338,11 +1695,29 @@ static void DefineData (ExprDesc* Expr)
 
 
 
-static unsigned ParseScalarInit (Type* T)
-/* Parse initializaton for scalar data types. Return the number of data bytes. */
+static void OutputBitFieldData (StructInitData* SI)
+/* Output bit field data */
 {
-    ExprDesc ED;
+    /* Ignore if we have no data */
+    if (SI->ValBits > 0) {
+
+        /* Output the data */
+        g_defdata (CF_INT | CF_UNSIGNED | CF_CONST, SI->BitVal, 0);
 
+        /* Clear the data from SI and account for the size */
+        SI->BitVal  = 0;
+        SI->ValBits = 0;
+        SI->Offs   += SIZEOF_INT;
+    }
+}
+
+
+
+static void ParseScalarInitInternal (Type* T, ExprDesc* ED)
+/* Parse initializaton for scalar data types. This function will not output the
+ * data but return it in ED.
+ */
+{
     /* Optional opening brace */
     unsigned BraceCount = OpeningCurlyBraces (0);
 
@@ -1354,14 +1729,25 @@ static unsigned ParseScalarInit (Type* T)
     }
 
     /* Get the expression and convert it to the target type */
-    ConstExpr (hie1, &ED);
-    TypeConversion (&ED, T);
-
-    /* Output the data */
-    DefineData (&ED);
+    ConstExpr (hie1, ED);
+    TypeConversion (ED, T);
 
     /* Close eventually opening braces */
     ClosingCurlyBraces (BraceCount);
+}
+
+
+
+static unsigned ParseScalarInit (Type* T)
+/* Parse initializaton for scalar data types. Return the number of data bytes. */
+{
+    ExprDesc ED;
+
+    /* Parse initialization */
+    ParseScalarInitInternal (T, &ED);
+
+    /* Output the data */
+    DefineData (&ED);
 
     /* Done */
     return SizeOf (T);
@@ -1404,12 +1790,12 @@ static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers)
 
     /* Special handling for a character array initialized by a literal */
     if (IsTypeChar (ElementType) &&
-        (CurTok.Tok == TOK_SCONST ||
-        (CurTok.Tok == TOK_LCURLY && NextTok.Tok == TOK_SCONST))) {
+        (CurTok.Tok == TOK_SCONST || CurTok.Tok == TOK_WCSCONST ||
+        (CurTok.Tok == TOK_LCURLY &&
+         (NextTok.Tok == TOK_SCONST || NextTok.Tok == TOK_WCSCONST)))) {
 
         /* Char array initialized by string constant */
         int NeedParen;
-        const char* Str;
 
         /* If we initializer is enclosed in brackets, remember this fact and
          * skip the opening bracket.
@@ -1419,16 +1805,13 @@ static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers)
             NextToken ();
         }
 
-        /* Get the initializer string and its size */
-        Str = GetLiteral (CurTok.IVal);
-        Count = GetLiteralPoolOffs () - CurTok.IVal;
-
         /* Translate into target charset */
-        TranslateLiteralPool (CurTok.IVal);
+        TranslateLiteral (CurTok.SVal);
 
         /* If the array is one too small for the string literal, omit the
          * trailing zero.
          */
+        Count = GetLiteralSize (CurTok.SVal);
         if (ElementCount != UNSPECIFIED &&
             ElementCount != FLEXIBLE    &&
             Count        == ElementCount + 1) {
@@ -1437,10 +1820,9 @@ static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers)
         }
 
         /* Output the data */
-        g_defbytes (Str, Count);
+        g_defbytes (GetLiteralStr (CurTok.SVal), Count);
 
-        /* Remove string from pool */
-        ResetLiteralPoolOffs (CurTok.IVal);
+        /* Skip the string */
         NextToken ();
 
         /* If the initializer was enclosed in curly braces, we need a closing
@@ -1495,10 +1877,9 @@ static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers)
 static unsigned ParseStructInit (Type* T, int AllowFlexibleMembers)
 /* Parse initialization of a struct or union. Return the number of data bytes. */
 {
-    SymEntry* Entry;
-    SymTable* Tab;
-    unsigned  StructSize;
-    unsigned  Size;
+    SymEntry*       Entry;
+    SymTable*       Tab;
+    StructInitData  SI;
 
 
     /* Consume the opening curly brace */
@@ -1508,56 +1889,139 @@ static unsigned ParseStructInit (Type* T, int AllowFlexibleMembers)
     Entry = GetSymEntry (T);
 
     /* Get the size of the struct from the symbol table entry */
-    StructSize = Entry->V.S.Size;
+    SI.Size = 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");
+       Error ("Cannot initialize variables with incomplete type");
         /* Try error recovery */
         SkipInitializer (1);
-       /* Nothing initialized */
-       return 0;
+       /* Nothing initialized */
+       return 0;
     }
 
     /* Get a pointer to the list of symbols */
     Entry = Tab->SymHead;
 
     /* Initialize fields */
-    Size = 0;
+    SI.Offs    = 0;
+    SI.BitVal  = 0;
+    SI.ValBits = 0;
     while (CurTok.Tok != TOK_RCURLY) {
-       if (Entry == 0) {
-           Error ("Too many initializers");
+
+        /* */
+       if (Entry == 0) {
+           Error ("Too many initializers");
             SkipInitializer (1);
-           return Size;
+           return SI.Offs;
        }
-        /* Parse initialization of one field. Flexible array members may
-         * only be initialized if they are the last field (or part of the
-         * last struct field).
+
+        /* Parse initialization of one field. Bit-fields need a special
+         * handling.
          */
-       Size += ParseInitInternal (Entry->Type, AllowFlexibleMembers && Entry->NextSym == 0);
-       Entry = Entry->NextSym;
-       if (CurTok.Tok != TOK_COMMA)
+        if (SymIsBitField (Entry)) {
+
+            ExprDesc ED;
+            unsigned Val;
+            unsigned Shift;
+
+            /* Calculate the bitmask from the bit-field data */
+            unsigned Mask = (1U << Entry->V.B.BitWidth) - 1U;
+
+            /* Safety ... */
+            CHECK (Entry->V.B.Offs * CHAR_BITS + Entry->V.B.BitOffs ==
+                   SI.Offs         * CHAR_BITS + SI.ValBits);
+
+            /* This may be an anonymous bit-field, in which case it doesn't
+             * have an initializer.
+             */
+            if (IsAnonName (Entry->Name)) {
+                /* Account for the data and output it if we have a full word */
+                SI.ValBits += Entry->V.B.BitWidth;
+                CHECK (SI.ValBits <= INT_BITS);
+                if (SI.ValBits == INT_BITS) {
+                    OutputBitFieldData (&SI);
+                }
+                goto NextMember;
+            } else {
+                /* Read the data, check for a constant integer, do a range
+                 * check.
+                 */
+                ParseScalarInitInternal (type_uint, &ED);
+                if (!ED_IsConstAbsInt (&ED)) {
+                    Error ("Constant initializer expected");
+                    ED_MakeConstAbsInt (&ED, 1);
+                }
+                if (ED.IVal > (long) Mask) {
+                    Warning ("Truncating value in bit-field initializer");
+                    ED.IVal &= (long) Mask;
+                }
+                Val = (unsigned) ED.IVal;
+            }
+
+            /* Add the value to the currently stored bit-field value */
+            Shift = (Entry->V.B.Offs - SI.Offs) * CHAR_BITS + Entry->V.B.BitOffs;
+            SI.BitVal |= (Val << Shift);
+
+            /* Account for the data and output it if we have a full word */
+            SI.ValBits += Entry->V.B.BitWidth;
+            CHECK (SI.ValBits <= INT_BITS);
+            if (SI.ValBits == INT_BITS) {
+                OutputBitFieldData (&SI);
+            }
+
+        } else {
+
+            /* Standard member. We should never have stuff from a
+             * bit-field left
+             */
+            CHECK (SI.ValBits == 0);
+
+            /* Flexible array members may only be initialized if they are
+             * the last field (or part of the last struct field).
+             */
+            SI.Offs += ParseInitInternal (Entry->Type, AllowFlexibleMembers && Entry->NextSym == 0);
+        }
+
+        /* More initializers? */
+               if (CurTok.Tok != TOK_COMMA) {
            break;
-       NextToken ();
+        }
+
+        /* Skip the comma */
+        NextToken ();
+
+NextMember:
+        /* Next member. For unions, only the first one can be initialized */
+        if (IsTypeUnion (T)) {
+            /* Union */
+            Entry = 0;
+        } else {
+            /* Struct */
+            Entry = Entry->NextSym;
+        }
     }
 
     /* Consume the closing curly brace */
     ConsumeRCurly ();
 
+    /* If we have data from a bit-field left, output it now */
+    OutputBitFieldData (&SI);
+
     /* If there are struct fields left, reserve additional storage */
-    if (Size < StructSize) {
-       g_zerobytes (StructSize - Size);
-        Size = StructSize;
+    if (SI.Offs < SI.Size) {
+       g_zerobytes (SI.Size - SI.Offs);
+        SI.Offs = SI.Size;
     }
 
     /* Return the actual number of bytes initialized. This number may be
-     * larger than StructSize if flexible array members are present and were
-     * initialized (possible in non ANSI mode).
+     * larger than sizeof (Struct) if flexible array members are present and
+     * were initialized (possible in non ANSI mode).
      */
-    return Size;
+    return SI.Offs;
 }
 
 
@@ -1581,11 +2045,11 @@ static unsigned ParseVoidInit (void)
 
            case T_SCHAR:
            case T_UCHAR:
-               if (ED_IsConstAbsInt (&Expr)) {
-                   /* Make it byte sized */
-                   Expr.IVal &= 0xFF;
-               }
-               DefineData (&Expr);
+               if (ED_IsConstAbsInt (&Expr)) {
+                   /* Make it byte sized */
+                   Expr.IVal &= 0xFF;
+               }
+               DefineData (&Expr);
                 Size += SIZEOF_CHAR;
                 break;
 
@@ -1595,26 +2059,26 @@ static unsigned ParseVoidInit (void)
            case T_UINT:
            case T_PTR:
            case T_ARRAY:
-               if (ED_IsConstAbsInt (&Expr)) {
+               if (ED_IsConstAbsInt (&Expr)) {
                    /* Make it word sized */
-                   Expr.IVal &= 0xFFFF;
-               }
-               DefineData (&Expr);
-               Size += SIZEOF_INT;
+                   Expr.IVal &= 0xFFFF;
+               }
+               DefineData (&Expr);
+               Size += SIZEOF_INT;
                 break;
 
            case T_LONG:
            case T_ULONG:
-               if (ED_IsConstAbsInt (&Expr)) {
+               if (ED_IsConstAbsInt (&Expr)) {
                    /* Make it dword sized */
-                   Expr.IVal &= 0xFFFFFFFF;
-               }
-               DefineData (&Expr);
-               Size += SIZEOF_LONG;
+                   Expr.IVal &= 0xFFFFFFFF;
+               }
+               DefineData (&Expr);
+               Size += SIZEOF_LONG;
                 break;
 
            default:
-               Error ("Illegal type in initialization");
+               Error ("Illegal type in initialization");
                break;
 
        }
@@ -1648,6 +2112,8 @@ static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers)
        case T_UINT:
        case T_LONG:
        case T_ULONG:
+        case T_FLOAT:
+        case T_DOUBLE:
             return ParseScalarInit (T);
 
        case T_PTR: