- int sum = 0, usum = 0;
- int bitOffset = 0;
- symbol *loop;
-
- /* for the identifiers */
- loop = sdef->fields;
- while (loop) {
-
- /* create the internal name for this variable */
- SNPRINTF (loop->rname, sizeof(loop->rname), "_%s", loop->name);
- if (su == UNION) {
- sum = 0;
- bitOffset = 0;
- }
- SPEC_VOLATILE (loop->etype) |= (su == UNION ? 1 : 0);
-
- /* if this is a bit field */
- if (loop->bitVar) {
-
- /* change it to a unsigned bit */
- SPEC_NOUN (loop->etype) = V_BITFIELD;
- SPEC_USIGN (loop->etype) = 1;
- SPEC_BLEN (loop->etype) = loop->bitVar;
-
- if (loop->bitVar == BITVAR_PAD) {
- /* A zero length bitfield forces padding */
- SPEC_BSTR (loop->etype) = bitOffset;
- SPEC_BLEN (loop->etype) = 0;
- bitOffset = 8;
- loop->offset = sum;
- }
- else {
- if (bitOffset == 8) {
- bitOffset = 0;
- sum++;
- }
- /* check if this fit into the remaining */
- /* bits of this byte else align it to the */
- /* next byte boundary */
- if (loop->bitVar <= (8 - bitOffset)) {
- /* fits into current byte */
- loop->offset = sum;
- SPEC_BSTR (loop->etype) = bitOffset;
- bitOffset += loop->bitVar;
- }
- else if (!bitOffset) {
- /* does not fit, but is already byte aligned */
- loop->offset = sum;
- SPEC_BSTR (loop->etype) = bitOffset;
- bitOffset += loop->bitVar;
- }
- else {
- /* does not fit; need to realign first */
- sum++;
- loop->offset = (su == UNION ? sum = 0 : sum);
- bitOffset = 0;
- SPEC_BSTR (loop->etype) = bitOffset;
- bitOffset += loop->bitVar;
- }
- while (bitOffset>8) {
- bitOffset -= 8;
- sum++;
- }
- }
- }
- else {
- /* This is a non-bit field. Make sure we are */
- /* byte aligned first */
- if (bitOffset) {
- sum++;
- loop->offset = (su == UNION ? sum = 0 : sum);
- bitOffset = 0;
- }
- loop->offset = sum;
- checkDecl (loop, 1);
- sum += getSize (loop->type);
- }
-
- loop = loop->next;
-
- /* if union then size = sizeof larget field */
- if (su == UNION) {
- /* For UNION, round up after each field */
- sum += ((bitOffset+7)/8);
- usum = max (usum, sum);
- }
-
- }
-
- /* For STRUCT, round up after all fields processed */
- if (su != UNION)
- sum += ((bitOffset+7)/8);
-
- return (su == UNION ? usum : sum);
+ int sum = 0, usum = 0;
+ int bitOffset = 0;
+ symbol *loop;
+
+ /* for the identifiers */
+ loop = sdef->fields;
+ while (loop) {
+
+ /* create the internal name for this variable */
+ SNPRINTF (loop->rname, sizeof(loop->rname), "_%s", loop->name);
+ if (su == UNION) {
+ sum = 0;
+ bitOffset = 0;
+ }
+ SPEC_VOLATILE (loop->etype) |= (su == UNION ? 1 : 0);
+
+ /* if this is a bit field */
+ if (loop->bitVar) {
+
+ SPEC_BUNNAMED (loop->etype) = loop->bitUnnamed;
+
+ /* change it to a unsigned bit */
+ SPEC_NOUN (loop->etype) = V_BITFIELD;
+ /* ISO/IEC 9899 J.3.9 implementation defined behaviour: */
+ /* a "plain" int bitfield is unsigned */
+ if (!loop->etype->select.s.b_signed)
+ SPEC_USIGN(loop->etype) = 1;
+
+ if (loop->bitVar == BITVAR_PAD) {
+ /* A zero length bitfield forces padding */
+ SPEC_BLEN (loop->etype) = 0;
+ SPEC_BSTR (loop->etype) = bitOffset;
+ if (bitOffset > 0)
+ bitOffset = 8; /* padding is not needed when at bit 0 */
+ loop->offset = sum;
+ }
+ else {
+ SPEC_BLEN (loop->etype) = loop->bitVar;
+
+ if (bitOffset == 8) {
+ bitOffset = 0;
+ sum++;
+ }
+ /* check if this fit into the remaining */
+ /* bits of this byte else align it to the */
+ /* next byte boundary */
+ if (loop->bitVar <= (8 - bitOffset)) {
+ /* fits into current byte */
+ loop->offset = sum;
+ SPEC_BSTR (loop->etype) = bitOffset;
+ bitOffset += loop->bitVar;
+ }
+ else if (!bitOffset) {
+ /* does not fit, but is already byte aligned */
+ loop->offset = sum;
+ SPEC_BSTR (loop->etype) = bitOffset;
+ bitOffset += loop->bitVar;
+ }
+ else {
+ if( TARGET_IS_PIC16 && getenv("PIC16_PACKED_BITFIELDS") ) {
+ /* if PIC16 && enviroment variable is set, then
+ * tightly pack bitfields, this means that when a
+ * bitfield goes beyond byte alignment, do not
+ * automatically start allocatint from next byte,
+ * but also use the available bits first */
+ fprintf(stderr, ": packing bitfields in structures\n");
+ SPEC_BSTR (loop->etype) = bitOffset;
+ bitOffset += loop->bitVar;
+ loop->offset = (su == UNION ? sum = 0 : sum);
+ } else {
+ /* does not fit; need to realign first */
+ sum++;
+ loop->offset = (su == UNION ? sum = 0 : sum);
+ bitOffset = 0;
+ SPEC_BSTR (loop->etype) = bitOffset;
+ bitOffset += loop->bitVar;
+ }
+ }
+ while (bitOffset>8) {
+ bitOffset -= 8;
+ sum++;
+ }
+ }
+ }
+ else {
+ /* This is a non-bit field. Make sure we are */
+ /* byte aligned first */
+ if (bitOffset) {
+ sum++;
+ loop->offset = (su == UNION ? sum = 0 : sum);
+ bitOffset = 0;
+ }
+ loop->offset = sum;
+ checkDecl (loop, 1);
+ sum += getSize (loop->type);
+
+ /* search for "flexibel array members" */
+ /* and do some syntax checks */
+ if ( su == STRUCT
+ && checkStructFlexArray (loop, loop->type))
+ {
+ /* found a "flexible array member" */
+ sdef->b_flexArrayMember = TRUE;
+ /* is another struct-member following? */
+ if (loop->next)
+ werror (E_FLEXARRAY_NOTATEND);
+ /* is it the first struct-member? */
+ else if (loop == sdef->fields)
+ werror (E_FLEXARRAY_INEMPTYSTRCT);
+ }
+ }
+
+ loop = loop->next;
+
+ /* if union then size = sizeof largest field */
+ if (su == UNION) {
+ /* For UNION, round up after each field */
+ sum += ((bitOffset+7)/8);
+ usum = max (usum, sum);
+ }
+
+ }
+
+ /* For STRUCT, round up after all fields processed */
+ if (su != UNION)
+ sum += ((bitOffset+7)/8);
+
+ return (su == UNION ? usum : sum);
+}
+
+/*-------------------------------------------------------------------*/
+/* promoteAnonStructs - promote anonymous struct/union's fields into */
+/* an enclosing struct/union */
+/*-------------------------------------------------------------------*/
+void
+promoteAnonStructs (int su, structdef * sdef)
+{
+ symbol *field;
+ symbol *subfield;
+ symbol **tofield;
+ symbol *nextfield;
+ symbol *dupfield;
+ int base;
+
+ tofield = &sdef->fields;
+ field = sdef->fields;
+ while (field)
+ {
+ nextfield = field->next;
+ if (!*field->name && IS_STRUCT (field->type))
+ {
+ /* Found an anonymous struct/union. Replace it */
+ /* with the fields it contains and adjust all */
+ /* the offsets */
+
+ base = field->offset;
+ subfield = copySymbolChain (SPEC_STRUCT (field->type)->fields);
+ if (!subfield)
+ continue; /* just in case it's empty */
+
+ *tofield = subfield;
+ for (;;)
+ {
+ /* check for field name conflicts resulting from promotion */
+ dupfield = sdef->fields;
+ while (dupfield && dupfield != subfield)
+ {
+ if (*subfield->name && !strcmp (dupfield->name, subfield->name))
+ {
+ werrorfl (subfield->fileDef, subfield->lineDef,
+ E_DUPLICATE_MEMBER,
+ su==STRUCT ? "struct" : "union",
+ subfield->name);
+ werrorfl (dupfield->fileDef, dupfield->lineDef,
+ E_PREVIOUS_DEF);
+ }
+ dupfield = dupfield->next;
+ }
+
+ subfield->offset += base;
+ if (subfield->next)
+ subfield = subfield->next;
+ else
+ break;
+ }
+ subfield->next = nextfield;
+ tofield = &subfield->next;
+ }
+ else
+ tofield = &field->next;
+ field = nextfield;
+ }