/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */ /* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */ #include "precomp.h" const ASN1uint32_t c_BitMaskMap[sizeof(ASN1uint32_t) * 8] = { #ifdef USE_BIG_ENDIAN 0x80000000, 0x40000000, 0x20000000, 0x10000000, 0x08000000, 0x04000000, 0x02000000, 0x01000000, 0x800000, 0x400000, 0x200000, 0x100000, 0x080000, 0x040000, 0x020000, 0x010000, 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, #else // little endian 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100, 0x800000, 0x400000, 0x200000, 0x100000, 0x080000, 0x040000, 0x020000, 0x010000, 0x80000000, 0x40000000, 0x20000000, 0x10000000, 0x08000000, 0x04000000, 0x02000000, 0x01000000, #endif }; void GenComponents(AssignmentList_t ass, ComponentList_t components, char *identifier, char *completeidentifier, int *choiceoffset, int *optionaloffset); void GenType(AssignmentList_t ass, char *identifier, char *completeidentifier, Type_t *type, int withmodule, int pointer, int array, int fTypeDef); void GenEnumeration(AssignmentList_t ass, ComponentList_t components, char *identifier, char *completeidentifier, int *choiceoffset, int *optionaloffset); int NotInFunTbl(Assignment_t *a); unsigned g_cPDUs = 0; unsigned g_cOptionValueSize = 0; extern int g_fAllEndians; /* generate include file */ void GenInc(AssignmentList_t ass, FILE *finc, char *module) { Assignment_t *a; char *identifier; int offset, i; Type_t *type, *subtype; Value_t *value; unsigned npdu; char *pszPrivateValueName; unsigned cOptionValueSizeSave; setoutfile(finc); module = Identifier2C(module); // print verbatim PrintVerbatim(); /* file header */ output("#ifndef _%s_H_\n", module); output("#define _%s_H_\n\n", module); switch (g_eEncodingRule) { case eEncoding_Packed: output("#include \"msper.h\"\n"); break; case eEncoding_Basic: output("#include \"msber.h\"\n"); break; default: ASSERT(0); break; } output("\n"); for (i = 0; i < g_cGhostFiles; i++) { StripModuleName(g_aGhostFiles[i].pszFileName, g_aGhostFiles[i].pszFileName); strcat(g_aGhostFiles[i].pszFileName, ".h"); output("#include \"%s\"\n", g_aGhostFiles[i].pszFileName); } if (g_cGhostFiles) { output("\n"); } // ghost all the data structures from the ghost asn1 files for (a = ass; a; a = a->Next) { if (a->Type != eAssignment_Type) continue; type = a->U.Type.Type; if (type->Flags & eTypeFlags_Null) continue; if (!(type->Flags & eTypeFlags_GenType)) continue; if (a->Module && a->Module->Identifier) { for (i = 0; i < g_cGhostFiles; i++) { if (! strcmp(a->Module->Identifier, g_aGhostFiles[i].pszModuleName)) { a->fGhost = 1; break; } } } } /* language dependent interface */ switch (g_eProgramLanguage) { case eLanguage_C: // output("#include \"cinterf.h\"\n\n"); output("#ifdef __cplusplus\n"); outputni("extern \"C\" {\n"); output("#endif\n\n"); break; case eLanguage_Cpp: // output("#include \"cppinterf.h\"\n\n"); // break; default: ASSERT(0); break; } /* create endian independent macros */ if (g_fAllEndians) { output("#ifdef ASN1_BIG_ENDIAN\n"); output("#define ASN1_LITE_TO_BIGE_16(n16) ((((n16) & 0xFF) << 8) | (((n16) & 0xFF00) >> 8))\n"); output("#define ASN1_LITE_TO_BIGE_32(n32) ((((n32) & 0xFF) << 24) | (((n32) & 0xFF00) << 8)) | (((n32) & 0xFF0000) >> 8) | (((n32) & 0xFF000000) >> 24)\n"); output("#define ASN1_ENDIAN_16(n16) ASN1_LITE_TO_BIGE_16(n16)\n"); output("#define ASN1_ENDIAN_32(n32) ASN1_LITE_TO_BIGE_32(n32)\n"); output("#else\n"); output("#define ASN1_ENDIAN_16(n16) (n16)\n"); output("#define ASN1_ENDIAN_32(n32) (n32)\n"); output("#endif // ASN1_BIG_ENDIAN\n\n"); } /* typedefs for sequence of/set of with list representation */ npdu = 0; for (a = ass; a; a = a->Next) { if (a->Type != eAssignment_Type) continue; type = a->U.Type.Type; if (type->Flags & eTypeFlags_Null) continue; if (!(type->Flags & eTypeFlags_GenType)) continue; if (a->fGhost) continue; identifier = GetName(a); switch (type->Type) { case eType_SequenceOf: case eType_SetOf: if (GetTypeRules(ass, type) & (eTypeRules_LinkedListMask | eTypeRules_PointerToElement)) { if (g_fExtraStructPtrTypeSS) { output("typedef struct %s_s * P%s;\n", identifier, identifier); } else { output("typedef struct %s * P%s;\n", identifier, identifier); } output("\n"); } break; default: break; } } /* other type definitions */ for (a = ass; a; a = a->Next) { if (a->Type != eAssignment_Type) continue; type = a->U.Type.Type; /* skip null type */ if (type->Flags & eTypeFlags_Null) { if (type->Type == eType_Sequence) { identifier = GetName(a); output("typedef struct %s {\n", identifier); output("char placeholder;\n"); output("} %s;\n\n", identifier); } continue; } /* type definition wanted? */ if (!(type->Flags & eTypeFlags_GenType)) continue; if ((! g_fLongNameForImported) && a->fImportedLocalDuplicate) continue; if (a->fGhost) continue; /* assign an id number to the type */ identifier = GetName(a); /* write type definitions */ switch (type->Type) { case eType_Sequence: case eType_Set: case eType_InstanceOf: // save cOptionValueSizeSave = g_cOptionValueSize; // generate scope-free enumeration offset = 0; GenEnumeration(ass, type->U.SSC.Components, identifier, identifier, NULL, &offset); /* use struct for sequence/set/instanceof type */ /* add a bit field for optional components */ output("typedef struct %s {\n", identifier); if (type->U.SSC.Optionals || type->U.SSC.Extensions) { int cOctets = (type->U.SSC.Optionals + 7) / 8 + (type->U.SSC.Extensions + 7) / 8; g_cOptionValueSize = (cOctets <= 2) ? 16 : 32; output("union {\nASN1uint%u_t %s;\nASN1octet_t o[%d];\n};\n", g_cOptionValueSize, g_pszOptionValue, cOctets); } offset = 0; GenComponents(ass, type->U.SSC.Components, identifier, identifier, NULL, &offset); output("} %s;\n", identifier); // restore g_cOptionValueSize = cOptionValueSizeSave; break; case eType_Choice: // generate scope-free enumeration offset = 0; GenEnumeration(ass, type->U.SSC.Components, identifier, identifier, NULL, &offset); /* use a struct of an selector and a union for choice type */ output("typedef struct %s {\n", identifier); // output("%s o;\n", GetChoiceType(type)); output("ASN1choice_t choice;\n"); if (!(type->Flags & eTypeFlags_NullChoice)) output("union {\n"); offset = ASN1_CHOICE_BASE; GenComponents(ass, type->U.Choice.Components, identifier, identifier, &offset, NULL); if (!(type->Flags & eTypeFlags_NullChoice)) output("} u;\n"); output("} %s;\n", identifier); break; case eType_SequenceOf: case eType_SetOf: // // LONCHANC: The following two lines of code do not apply to // SEQUENCE OF and SET OF. // // generate scope-free enumeration // offset = 0; // GenEnumeration(ass, type->U.SSC.Components, identifier, identifier, NULL, &offset); /* use a struct of length+values for sequence of/set of with */ /* length-pointer representation */ /* use a struct of next+value for sequence of/set of with */ /* singly-linked-list representation */ /* use a struct of next+prev+value for sequence of/set of with */ /* doubly-linked-list representation */ subtype = type->U.SS.Type; if (g_fExtraStructPtrTypeSS && (type->Rules & (eTypeRules_LinkedListMask | eTypeRules_PointerToElement))) { output("typedef struct %s_s {\n", identifier); } else { output("typedef struct %s {\n", identifier); } // fix (xyz..MAX) problem. if (type->Rules == eTypeRules_FixedArray && type->PERTypeInfo.Root.LUpperVal == 0) { type->Rules &= ~ eTypeRules_FixedArray; type->Rules |= g_eDefTypeRuleSS_NonSized; type->PERTypeInfo.Rules &= ~ eTypeRules_FixedArray; type->PERTypeInfo.Rules |= g_eDefTypeRuleSS_NonSized; type->BERTypeInfo.Rules &= ~ eTypeRules_FixedArray; type->BERTypeInfo.Rules |= g_eDefTypeRuleSS_NonSized; } pszPrivateValueName = GetPrivateValueName(&type->PrivateDirectives, "value"); if (type->Rules & eTypeRules_FixedArray) { output("ASN1uint32_t count;\n"); GenType(ass, pszPrivateValueName, pszPrivateValueName, subtype, 0, 0, type->PERTypeInfo.Root.LUpperVal, 0); } else if (type->Rules & eTypeRules_LengthPointer) { output("ASN1uint32_t count;\n"); GenType(ass, pszPrivateValueName, pszPrivateValueName, subtype, 0, 1, 0, 0); } else if (type->Rules & eTypeRules_DoublyLinkedList) { output("P%s next;\n", identifier); output("P%s prev;\n", identifier); GenType(ass, pszPrivateValueName, pszPrivateValueName, subtype, 0, 0, 0, 0); } else if (type->Rules & eTypeRules_SinglyLinkedList) { output("P%s next;\n", identifier); GenType(ass, pszPrivateValueName, pszPrivateValueName, subtype, 0, 0, 0, 0); } else { MyAbort(); } if (type->Rules & eTypeRules_LinkedListMask) { if (g_fExtraStructPtrTypeSS) { output("} %s_Element, *%s;\n", identifier, identifier); } else { output("} %s_Element;\n", identifier); } } else { output("} %s;\n", identifier); } break; default: /* use the builtin type for other types */ output("typedef "); GenType(ass, a->Identifier, identifier, type, 1, 0, 0, 1); break; } if (! NotInFunTbl(a)) { output("#define %s_%s %u\n", identifier, g_pszApiPostfix, npdu); switch (type->Type) { case eType_SequenceOf: case eType_SetOf: if (type->Rules & eTypeRules_LinkedListMask) { output("#define SIZE_%s_%s_%u sizeof(%s_Element)\n", module, g_pszApiPostfix, npdu, identifier); break; } // intentionally fall through default: output("#define SIZE_%s_%s_%u sizeof(%s)\n", module, g_pszApiPostfix, npdu, identifier); break; } npdu++; } output("\n"); } /* write extern declarations for values */ for (a = ass; a; a = a->Next) { if (a->Type != eAssignment_Value) continue; /* extern value wanted? */ if (!(a->U.Value.Value->Flags & eValueFlags_GenExternValue)) continue; value = GetValue(ass, a->U.Value.Value); /* skip value of null type */ if (value->Type->Flags & eTypeFlags_Null) continue; /* output an extern declaration */ switch (value->Type->Type) { case eType_ObjectIdentifier: if (value->Type->PrivateDirectives.fOidPacked) { output("extern ASN1encodedOID_t %s;\n", GetName(a)); break; } else if (value->Type->PrivateDirectives.fOidArray || g_fOidArray) { output("extern ASN1objectidentifier2_t %s;\n", GetName(a)); break; } // intentionally fall through default: output("extern %s %s;\n", GetTypeName(ass, value->Type), GetName(a)); break; } } output("\n"); /* write vars, functions and macros for the interface */ output("extern ASN1module_t %s;\n", module); output("extern void ASN1CALL %s_Startup(void);\n", module); output("extern void ASN1CALL %s_Cleanup(void);\n", module); output("\n"); output("/* Prototypes of element functions for SEQUENCE OF and SET OF constructs */\n"); g_cPDUs = npdu; } /* generate a type */ void GenType(AssignmentList_t ass, char *identifier, char *completeidentifier, Type_t *type, int withmodule, int pointer, int array, int fTypeDef) { char *ptr, *pszOldEnumName; NamedNumber_t *namedNumbers; char arr[20]; char modide[256]; /* skip null type */ // if (type->Flags & eTypeFlags_Null) // return; /* get type name */ ptr = pointer ? "*" : ""; if (array) sprintf(arr, "[%u]", array); else arr[0] = '\0'; identifier = Identifier2C(identifier); if (withmodule) sprintf(modide, "%s%s%s", ptr, completeidentifier, arr); else sprintf(modide, "%s%s%s", ptr, identifier, arr); /* output type declaration */ switch (type->Type) { case eType_Reference: /* use struct ..._s syntax for pointer to structured type */ if (pointer && IsStructuredType(GetReferencedType(ass, type))) { output("struct %s %s;\n", GetTypeName(ass, type), modide); } else { char *psz = PGetTypeName(ass, type); char *psz2 = (0 == strcmp(psz, modide)) ? "_dont_care" : ""; output("%s %s%s;\n", psz, modide, psz2); } break; case eType_OctetString: if (g_eEncodingRule == eEncoding_Packed) { if (type->PERTypeInfo.Root.LConstraint == ePERSTIConstraint_Constrained && (! type->PrivateDirectives.fLenPtr)) { if (strcmp(completeidentifier, modide) == 0) { output("struct %s {\nASN1uint32_t length;\nASN1octet_t value[%u];\n} %s;\n", modide, type->PERTypeInfo.Root.LUpperVal, modide); } else { output("struct %s_%s {\nASN1uint32_t length;\nASN1octet_t value[%u];\n} %s;\n", completeidentifier, modide, type->PERTypeInfo.Root.LUpperVal, modide); } } else { char *psz = GetTypeName(ass, type); char *psz2 = (0 == strcmp(psz, modide)) ? "_dont_care" : ""; output("%s %s%s;\n", psz, modide, psz2); } } else { // only support unbounded in BER char *psz = GetTypeName(ass, type); char *psz2 = (0 == strcmp(psz, modide)) ? "_dont_care" : ""; output("%s %s%s;\n", psz, modide, psz2); } break; case eType_UTF8String: { char *psz = GetTypeName(ass, type); char *psz2 = (0 == strcmp(psz, modide)) ? "_dont_care" : ""; output("%s %s%s;\n", psz, modide, psz2); } break; case eType_InstanceOf: case eType_SequenceOf: case eType_SetOf: case eType_Boolean: case eType_Real: case eType_Sequence: case eType_Set: case eType_Choice: case eType_External: case eType_ObjectIdentifier: case eType_ObjectDescriptor: case eType_BMPString: case eType_UniversalString: case eType_GeneralizedTime: case eType_UTCTime: case eType_EmbeddedPdv: case eType_Open: /* use struct ..._s syntax for pointer to structured type */ if (pointer && IsStructuredType(type)) { output("struct %s %s;\n", GetTypeName(ass, type), modide); } else { char *psz = GetTypeName(ass, type); char *psz2 = (0 == strcmp(psz, modide)) ? "_dont_care" : ""; output("%s %s%s;\n", psz, modide, psz2); } break; case eType_NumericString: case eType_PrintableString: case eType_VisibleString: case eType_ISO646String: case eType_GraphicString: case eType_GeneralString: case eType_VideotexString: case eType_IA5String: case eType_T61String: case eType_TeletexString: case eType_CharacterString: #ifdef ENABLE_CHAR_STR_SIZE { char *psz = GetTypeName(ass, type); if (g_eEncodingRule == eEncoding_Packed && type->PERTypeInfo.Root.LConstraint == ePERSTIConstraint_Constrained && strcmp(psz, "ASN1char_t") == 0) { char *psz2 = (0 == strcmp(psz, modide)) ? "_dont_care" : ""; output("%s %s%s[%u];\n", psz, modide, psz2, type->PERTypeInfo.Root.LUpperVal + 1); } else { char *psz2 = (0 == strcmp(psz, modide)) ? "_dont_care" : ""; output("%s %s%s;\n", psz, modide, psz2); } } #else { char *psz = GetTypeName(ass, type); char *psz2 = (0 == strcmp(psz, modide)) ? "_dont_care" : ""; output("%s %s%s;\n", psz, modide, psz2); } #endif break; case eType_Enumerated: /* use name of the type */ if (fTypeDef) { if (type->PrivateDirectives.pszTypeName) { output("enum %s {\n", type->PrivateDirectives.pszTypeName); pszOldEnumName = type->PrivateDirectives.pszTypeName; } else { output("enum %s {\n", modide); pszOldEnumName = ""; } /* dump named numbers */ namedNumbers = type->U.IEB.NamedNumbers; while (namedNumbers) { switch (namedNumbers->Type) { case eNamedNumber_Normal: if (intxisuint32(&GetValue(ass, namedNumbers->U.Normal.Value)->U.Integer.Value)) { char *psz = Identifier2C(namedNumbers->U.Normal.Identifier); if (IsReservedWord(psz) || DoesEnumNameConflict(psz)) { output("%s_%s = %u,\n", *pszOldEnumName ? pszOldEnumName : modide, psz, intx2uint32(&GetValue(ass, namedNumbers->U.Normal.Value)->U.Integer.Value)); } else { output("%s = %u,\n", psz, intx2uint32(&GetValue(ass, namedNumbers->U.Normal.Value)->U.Integer.Value)); } } else if (intxisint32(&GetValue(ass, namedNumbers->U.Normal.Value)->U.Integer.Value)) { char *psz = Identifier2C(namedNumbers->U.Normal.Identifier); if (IsReservedWord(psz) || DoesEnumNameConflict(psz)) { output("%s_%s = %d,\n", *pszOldEnumName ? pszOldEnumName : modide, psz, intx2uint32(&GetValue(ass, namedNumbers->U.Normal.Value)->U.Integer.Value)); } else { output("%s = %d,\n", psz, intx2uint32(&GetValue(ass, namedNumbers->U.Normal.Value)->U.Integer.Value)); } } break; case eNamedNumber_ExtensionMarker: break; } namedNumbers = namedNumbers->Next; } output("} %s;\n", type->PrivateDirectives.pszTypeName ? type->PrivateDirectives.pszTypeName : modide); } else { if (type->PrivateDirectives.pszTypeName) { pszOldEnumName = type->PrivateDirectives.pszTypeName; } else { pszOldEnumName = modide; } output("%s %s;\n", pszOldEnumName, modide); } break; case eType_Integer: /* use name of the type */ { char *psz = GetTypeName(ass, type); char *psz2 = (0 == strcmp(psz, modide)) ? "_dont_care" : ""; output("%s %s%s;\n", psz, modide, psz2); } /* dump named numbers */ namedNumbers = type->U.IEB.NamedNumbers; while (namedNumbers) { switch (namedNumbers->Type) { case eNamedNumber_Normal: if (intxisuint32(&GetValue(ass, namedNumbers->U.Normal.Value)->U.Integer.Value)) { output("#define %s_%s %u\n", completeidentifier, Identifier2C(namedNumbers->U.Normal.Identifier), intx2uint32(&GetValue(ass, namedNumbers->U.Normal.Value)->U.Integer.Value)); } else if (intxisint32(&GetValue(ass, namedNumbers->U.Normal.Value)->U.Integer.Value)) { output("#define %s_%s %d\n", completeidentifier, Identifier2C(namedNumbers->U.Normal.Identifier), intx2uint32(&GetValue(ass, namedNumbers->U.Normal.Value)->U.Integer.Value)); } break; case eNamedNumber_ExtensionMarker: break; } namedNumbers = namedNumbers->Next; } break; case eType_BitString: // lonchanc: split from eType_Integer /* use name of the type */ if (g_eEncodingRule == eEncoding_Packed) { if (type->PERTypeInfo.Root.cbFixedSizeBitString) { output("ASN1uint%u_t %s;\n", type->PERTypeInfo.Root.cbFixedSizeBitString * 8, modide); } else { char *psz = GetTypeName(ass, type); char *psz2 = (0 == strcmp(psz, modide)) ? "_dont_care" : ""; output("%s %s%s;\n", psz, modide, psz2); } } else { // only support unbounded in BER char *psz = GetTypeName(ass, type); char *psz2 = (0 == strcmp(psz, modide)) ? "_dont_care" : ""; output("%s %s%s;\n", psz, modide, psz2); } /* dump named numbers */ namedNumbers = type->U.IEB.NamedNumbers; while (namedNumbers) { switch (namedNumbers->Type) { case eNamedNumber_Normal: if (intxisuint32(&GetValue(ass, namedNumbers->U.Normal.Value)->U.Integer.Value)) { char *psz = Identifier2C(namedNumbers->U.Normal.Identifier); ASN1uint32_t idx = intx2uint32(&GetValue(ass, namedNumbers->U.Normal.Value)->U.Integer.Value); if (IsReservedWord(psz) || DoesEnumNameConflict(psz)) { output("#define %s_%s 0x%lx\n", completeidentifier, psz, c_BitMaskMap[idx]); } else { output("#define %s 0x%lx\n", psz, c_BitMaskMap[idx]); } } else if (intxisint32(&GetValue(ass, namedNumbers->U.Normal.Value)->U.Integer.Value)) { char *psz = Identifier2C(namedNumbers->U.Normal.Identifier); ASN1uint32_t idx = intx2uint32(&GetValue(ass, namedNumbers->U.Normal.Value)->U.Integer.Value); if (IsReservedWord(psz) || DoesEnumNameConflict(psz)) { output("#define %s_%s 0x%lx\n", completeidentifier, psz, c_BitMaskMap[idx]); } else { output("#define %s 0x%lx\n", psz, c_BitMaskMap[idx]); } } break; case eNamedNumber_ExtensionMarker: break; } namedNumbers = namedNumbers->Next; } break; case eType_Null: break; case eType_Undefined: MyAbort(); /*NOTREACHED*/ } } /* write declarations for components */ void GenComponents(AssignmentList_t ass, ComponentList_t components, char *identifier, char *completeidentifier, int *choiceoffset, int *optionaloffset) { NamedType_t *namedType; int extended = 0; char cidebuf[256]; /* add dummy for empty components */ if (components && !components->Next && components->Type == eComponent_ExtensionMarker) { output("char placeholder;\n"); return; } /* write a declaration for every component */ for (; components; components = components->Next) { switch (components->Type) { case eComponent_Normal: case eComponent_Optional: case eComponent_Default: /* write a selector for optional/default components */ namedType = components->U.NOD.NamedType; if ((extended && optionaloffset) || components->Type == eComponent_Optional || components->Type == eComponent_Default) { char *psz; // construct the option value char szOptionValue[64]; if (g_fAllEndians) { sprintf(szOptionValue, "ASN1_ENDIAN_%u(0x%lx)", g_cOptionValueSize, c_BitMaskMap[*optionaloffset]); } else { sprintf(szOptionValue, "0x%lx", c_BitMaskMap[*optionaloffset]); } psz = Identifier2C(namedType->Identifier); if (IsReservedWord(psz) || DoesOptNameConflict(psz)) // lonchanc: do we always put in _preset definition after extended mark??? // yes, we do. take an example of Setup-UUIE in q931asn.asn. // but, the extension mark does not have option-flag definition associated. // || (extended && optionaloffset)) { output("#define %s_%s_%s %s\n", identifier, psz, g_pszOptionPostfix, &szOptionValue[0]); } else { output("#define %s_%s %s\n", psz, g_pszOptionPostfix, &szOptionValue[0]); } (*optionaloffset)++; } /* write a selector for choice alternatives */ if (choiceoffset) { char *psz = Identifier2C(namedType->Identifier); if (IsReservedWord(psz) || DoesChoiceNameConflict(psz)) { output("#define %s_%s_%s %d\n", identifier, psz, g_pszChoicePostfix, *choiceoffset); } else { output("#define %s_%s %d\n", psz, g_pszChoicePostfix, *choiceoffset); } (*choiceoffset)++; } /* write the declaration itself */ sprintf(cidebuf, "%s_%s", completeidentifier, Identifier2C(namedType->Identifier)); GenType(ass, namedType->Identifier, cidebuf, namedType->Type, 0, GetTypeRules(ass, namedType->Type) & eTypeRules_Pointer, 0, 0); break; case eComponent_ExtensionMarker: /* update the offset when an extension marker is met for a */ /* sequence/set type */ extended = 1; // lonchanc: however, the code generated by TELES handles this properly. // moreover, the code requires it to be rounded up. // as a result, we should enable this feature. if (optionaloffset) *optionaloffset = (*optionaloffset + 7) & ~7; break; } } } // The following is added by Microsoft /* write enumerations for components */ void GenEnumeration(AssignmentList_t ass, ComponentList_t components, char *identifier, char *completeidentifier, int *choiceoffset, int *optionaloffset) { NamedType_t *namedType; int extended = 0; char cidebuf[256]; /* write a declaration for every component */ for (; components; components = components->Next) { switch (components->Type) { case eComponent_Normal: case eComponent_Optional: case eComponent_Default: namedType = components->U.NOD.NamedType; if (namedType && namedType->Type && namedType->Type->Type == eType_Enumerated) { output("typedef "); /* write the declaration itself */ sprintf(cidebuf, "%s_%s", completeidentifier, Identifier2C(namedType->Identifier)); GenType(ass, namedType->Identifier, cidebuf, namedType->Type, 0, GetTypeRules(ass, namedType->Type) & eTypeRules_Pointer, 0, 1); } break; } } }