#define SIZEOF_DOUBLE   (FP_D_Size())
 #define SIZEOF_PTR      2
 
+/* Bit sizes */
+#define CHAR_BITS       (8 * SIZEOF_CHAR)
+#define SHORT_BITS      (8 * SIZEOF_SHORT)
+#define INT_BITS        (8 * SIZEOF_INT)
+#define LONG_BITS       (8 * SIZEOF_LONG)
+#define LONGLONG_BITS   (8 * SIZEOF_LONGLONG)
+#define FLOAT_BITS      (8 * SIZEOF_FLOAT)
+#define DOUBLE_BITS     (8 * SIZEOF_DOUBLE)
+#define PTR_BITS        (8 * SIZEOF_PTR)
+
 /* Predefined type strings */
 extern Type type_schar[];
 extern Type type_uchar[];
 
 
 
 
+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;
+
+    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_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* ParseStructDecl (const char* Name, TypeCode StructType)
 /* Parse a struct/union declaration. */
 {
 
     unsigned  StructSize;
     unsigned  FieldSize;
-    unsigned  Offs;
     int       FlexibleMember;
+    unsigned  Offs;
+    int       BitOffs;          /* Bit offset for bit-fields */
+    int       FieldWidth;       /* Width in bits, -1 if not a bit-field */
     SymTable* FieldTab;
     SymEntry* Entry;
 
     /* Parse struct fields */
     FlexibleMember = 0;
     StructSize     = 0;
+    BitOffs        = 0;
     while (CurTok.Tok != TOK_RCURLY) {
 
        /* Get the type of the entry */
             }
 
            /* Get type and name of the struct field */
-           ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
+           ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
+
+            /* Check for a bit-field declaration */
+            FieldWidth = ParseFieldWidth (&Decl);
 
-            /* Get the offset of this field */
-            Offs = (StructType == T_STRUCT)? StructSize : 0;
+            /* A non bit-field without a name is legal but useless */
+            if (FieldWidth < 0 && Decl.Ident[0] == '\0') {
+                Warning ("Declaration does not declare anything");
+                goto NextMember;
+            }
+
+            /* 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
+             */
+            if (BitOffs > 0) {
+                if (FieldWidth <= 0 || (BitOffs + FieldWidth) > INT_BITS) {
+                    /* BitOffs > 0, so this can only be a struct */
+                    StructSize += SIZEOF_INT;
+                    BitOffs = 0;
+                }
+            }
+
+            /* Apart from the above, a bit field with width 0 is not processed
+             * further. An unnamed bit field will just increase the bit offset.
+             */
+            if (FieldWidth == 0) {
+                goto NextMember;
+            } else if (FieldWidth > 0 && Decl.Ident[0] == '\0') {
+                if (StructType == T_STRUCT) {
+                    BitOffs += FieldWidth;
+                }
+                goto NextMember;
+            }
 
             /* 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.
+                /* It's a struct. Offset of this member is the current struct
+                 * size plus any full bytes from the bit offset in case of
+                 * bit-fields.
+                 */
+                Offs = StructSize + (BitOffs >> 3);
+
+                /* 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 */
                     FlexibleMember = 1;
                     /* Assume zero for size calculations */
                     SetElementCount (Decl.Type, FLEXIBLE);
-                } else {
+                } else if (FieldWidth < 0) {
                     StructSize += CheckedSizeOf (Decl.Type);
                 }
 
-           } else {
+                /* Add a field entry to the table */
+                if (FieldWidth > 0) {
+                    AddBitField (Decl.Ident, Offs, BitOffs & 0x07, FieldWidth);
+                    BitOffs += FieldWidth;
+                } else {
+                    AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
+                }
+
+           } else {
 
-                /* It's a union */
+                /* It's a union. Offset of this member is always zero */
+                Offs = 0;
                 FieldSize = CheckedSizeOf (Decl.Type);
-               if (FieldSize > StructSize) {
-                   StructSize = FieldSize;
-               }
-           }
+               if (FieldSize > StructSize) {
+                   StructSize = FieldSize;
+               }
 
-           /* Add a field entry to the table */
-           AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
+                /* Add a field entry to the table */
+                if (FieldWidth > 0) {
+                    AddBitField (Decl.Ident, 0, 0, FieldWidth);
+                } else {
+                    AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
+                }
+           }
 
-           if (CurTok.Tok != TOK_COMMA) {
-               break;
+NextMember: if (CurTok.Tok != TOK_COMMA) {
+               break;
             }
-           NextToken ();
-       }
-       ConsumeSemi ();
+           NextToken ();
+       }
+       ConsumeSemi ();
     }
 
     /* Skip the closing brace */
 
        Error ("Struct/union has no field named `%s'", Ident);
                Expr->Type = type_int;
        return;
+    }       
+    if ((Field->Flags & SC_BITFIELD) == SC_BITFIELD) {
+        Error ("Bit-fields are currently unsupported - sorry");
+        Expr->Type = type_int;
+        return;
     }
 
     /* If we have a struct pointer that is an lvalue and not already in the
 
        /* Check for const operands */
        if (ED_IsConstAbs (Expr) && rconst) {
-             
-            /* If the result is constant, this is suspicious when not in 
+
+            /* If the result is constant, this is suspicious when not in
              * preprocessor mode.
              */
             if (!Preprocessing) {
 
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2006 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2000-2009, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
     } Flags [] = {
        /* Beware: Order is important! */
        { "SC_TYPEDEF",     SC_TYPEDEF          },
+        { "SC_BITFIELD",    SC_BITFIELD         },
                { "SC_STRUCTFIELD", SC_STRUCTFIELD      },
        { "SC_STRUCT",      SC_STRUCT           },
        { "SC_AUTO",        SC_AUTO             },
 
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2008 Ullrich von Bassewitz                                       */
+/* (C) 2000-2009 Ullrich von Bassewitz                                       */
 /*               Roemerstrasse 52                                            */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 #define SC_TYPE                0x4000U /* This is a type, struct, typedef, etc. */
 #define SC_STRUCT              0x4001U /* Struct or union */
 #define SC_STRUCTFIELD  0x4002U        /* Struct or union field */
-#define SC_TYPEDEF             0x4003U /* A typedef */
+#define SC_BITFIELD     0x4004U /* A bit-field inside a struct or union */
+#define SC_TYPEDEF             0x4008U /* A typedef */
 
 #define SC_ZEROPAGE    0x8000U /* Symbol marked as zeropage */
 
            unsigned            Size;     /* Size of the union/struct */
        } S;
 
+        /* Data for bit fields */
+        struct {
+            unsigned            Offs;     /* Byte offset into struct */
+            unsigned            BitOffs;  /* Bit offset into last byte */
+            unsigned            Width;    /* Width in bits */
+        } B;
+
        /* Data for functions */
        struct {
            struct FuncDesc*    Func;     /* Function descriptor */
 
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2006 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2000-2009, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
     /* Non-structs do not have any struct fields... */
     if (IsClassStruct (T)) {
 
-       const SymTable* Tab;
-
        /* Get a pointer to the struct/union type */
        const SymEntry* Struct = GetSymEntry (T);
        CHECK (Struct != 0);
 
-       /* Get the field symbol table from the struct entry.
-        * Beware: The table may not exist.
+       /* Now search in the struct symbol table. Beware: The table may not
+         * exist.
         */
-       Tab = Struct->V.S.SymTab;
-
-       /* Now search in the struct symbol table */
-       if (Tab) {
+       if (Struct->V.S.SymTab) {
                    Field = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name));
        }
     }
 
 
 
+SymEntry* AddBitField (const char* Name, unsigned Offs, unsigned BitOffs, unsigned Width)
+/* Add a bit field to the local symbol table and return the symbol entry */
+{
+    /* Do we have an entry with this name already? */
+    SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
+    if (Entry) {
+
+       /* We have a symbol with this name already */
+       Error ("Multiple definition for `%s'", Name);
+
+    } else {
+
+       /* Create a new entry */
+       Entry = NewSymEntry (Name, SC_BITFIELD);
+
+       /* Set the symbol attributes. Bit-fields are always of type unsigned */
+       Entry->Type        = type_uint;
+        Entry->V.B.Offs    = Offs;
+        Entry->V.B.BitOffs = BitOffs;
+        Entry->V.B.Width   = Width;
+
+       /* Add the entry to the symbol table */
+       AddSymEntry (SymTab, Entry);
+
+    }
+
+    /* Return the entry */
+    return Entry;
+}
+
+
+
 SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val)
 /* Add an constant symbol to the symbol table and return it */
 {
 
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000     Ullrich von Bassewitz                                        */
-/*              Wacholderweg 14                                              */
-/*              D-70597 Stuttgart                                            */
-/* EMail:       uz@musoftware.de                                             */
+/* (C) 2000-2009, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 SymEntry* AddStructSym (const char* Name, unsigned Size, SymTable* Tab);
 /* Add a struct/union entry and return it */
 
+SymEntry* AddBitField (const char* Name, unsigned Offs, unsigned BitOffs, unsigned Width);
+/* Add a bit field to the local symbol table and return the symbol entry */
+
 SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val);
 /* Add an constant symbol to the symbol table and return it */