windows-nt/Source/XPSP1/NT/ds/security/asn1/asn1c/genprg.c

1913 lines
68 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */
/* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */
#include "precomp.h"
#include "optcase.h"
void GenFuncType(AssignmentList_t ass, char *module, Assignment_t *at, TypeFunc_e et);
void GenFuncComponents(AssignmentList_t ass, char *module, Type_t *type, char *ideref, uint32_t optindex, ComponentList_t components, char *valref1, char *valref2, TypeFunc_e et, int inextension, int inchoice);
void GenFuncSequenceSetType(AssignmentList_t ass, char *module, Assignment_t *at, char *valref1, char *valref2, TypeFunc_e et);
void GenFuncChoiceType(AssignmentList_t ass, char *module, Assignment_t *at, char *valref1, char *valref2, TypeFunc_e et);
void GenFuncSimpleType(AssignmentList_t ass, Type_t *type, char *ideref, char *valref1, char *valref2, TypeFunc_e et);
void GenFreeSimpleType(AssignmentList_t ass, Type_t *type, char *ideref, char *valref);
void GenCompareSimpleType(AssignmentList_t ass, Type_t *type, char *ideref, char *valref1, char *valref2);
void GenCompareExpression(AssignmentList_t ass, Type_t *type, char *ideref, char *valref1, char *valref2);
void GenFuncValue(AssignmentList_t ass, Assignment_t *at, ValueFunc_e cod);
void GenDeclGeneric(AssignmentList_t ass, char *ideref, char *typeref, Value_t *value, Type_t *t);
void GenDefhGeneric(AssignmentList_t ass, char *ideref, char *typeref, Value_t *value, Type_t *t);
void GenDefnGeneric(AssignmentList_t ass, char *ideref, char *typeref, Value_t *value, Type_t *t);
void GenInitGeneric(AssignmentList_t ass, char *ideref, char *typeref, Value_t *value, Type_t *t);
extern unsigned g_cPDUs;
extern char *g_pszOrigModuleNameLowerCase;
extern int g_fLongNameForImported;
extern int g_fNoAssert;
extern int g_fCaseBasedOptimizer;
extern uint32_t Tag2uint32(AssignmentList_t ass, Tag_t *tag);
int NotInFunTbl(Assignment_t *a)
{
if (a->Type != eAssignment_Type)
{
return 1;
}
if (a->U.Type.Type->PrivateDirectives.fPublic)
{
return 0;
}
return ((a->U.Type.Type->Flags & eTypeFlags_Null) ||
!(a->U.Type.Type->Flags & eTypeFlags_GenType) ||
!(a->U.Type.Type->Flags & eTypeFlags_GenPdu) ||
(a->U.Type.Type->Flags & eTypeFlags_MiddlePDU));
}
/* generate c file */
void
GenPrg(AssignmentList_t ass, FILE *fout, char *module, char *incfilename)
{
Assignment_t *a;
TypeFunc_e et;
ValueFunc_e ev;
Arguments_t args;
unsigned i;
char *pszFunParam;
char *identifier;
char funcbuf[256];
setoutfile(fout);
// print verbatim
PrintVerbatim();
/* file header */
output("#include <windows.h>\n");
output("#include \"%s\"\n", incfilename);
switch (g_eEncodingRule) {
case eEncoding_Packed:
GenPERHeader();
GetPERPrototype(&args);
pszFunParam = "x,y";
break;
case eEncoding_Basic:
GenBERHeader();
GetBERPrototype(&args);
pszFunParam = "x,y,z";
break;
default:
MyAbort();
}
output("\n");
output("ASN1module_t %s = NULL;\n", module);
output("\n");
/* write function prototypes */
for (et = eStringTable; et <= eCopy; et++)
{
for (a = ass; a; a = a->Next)
{
if (a->Type != eAssignment_Type)
continue;
if ((! g_fLongNameForImported) && a->fImportedLocalDuplicate)
continue;
if (a->U.Type.Type->PrivateDirectives.fPublic)
{
a->U.Type.Type->Flags |= eTypeFlags_GenEncode;
a->U.Type.Type->Flags |= eTypeFlags_GenDecode;
a->U.Type.Type->Flags |= eTypeFlags_GenFree;
a->U.Type.Type->Flags |= eTypeFlags_GenCompare;
}
else
{
if ((GetType(ass, a->U.Type.Type)->Flags & eTypeFlags_Null) ||
!(a->U.Type.Type->Flags & eTypeFlags_GenType) ||
!(a->U.Type.Type->Flags & eTypeFlags_GenPdu))
continue;
}
switch (et)
{
case eStringTable:
continue;
case eEncode:
if (!(a->U.Type.Type->Flags & eTypeFlags_GenEncode))
continue;
identifier = GetName(a);
sprintf(funcbuf, IsPSetOfType(ass, a) ? args.Pencfunc : args.encfunc, identifier);
if (a->U.Type.Type->PrivateDirectives.fNoCode)
{
output("#define ASN1Enc_%s(%s) 0\n", identifier, pszFunParam);
}
else
{
output("static int ASN1CALL ASN1Enc_%s(%s);\n", identifier, funcbuf);
}
break;
case eDecode:
if (!(a->U.Type.Type->Flags & eTypeFlags_GenDecode))
continue;
identifier = GetName(a);
sprintf(funcbuf, IsPSetOfType(ass, a) ? args.Pdecfunc : args.decfunc, identifier);
if (a->U.Type.Type->PrivateDirectives.fNoCode)
{
output("#define ASN1Dec_%s(%s) 0\n", identifier, pszFunParam);
}
else
{
output("static int ASN1CALL ASN1Dec_%s(%s);\n", identifier, funcbuf);
}
break;
case eCheck:
continue;
case ePrint:
continue;
case eFree:
if (!(a->U.Type.Type->Flags & eTypeFlags_GenFree) ||
(a->U.Type.Type->Flags & eTypeFlags_Simple))
continue;
identifier = GetName(a);
sprintf(funcbuf, IsPSetOfType(ass, a) ? args.Pfreefunc : args.freefunc, identifier);
if (a->U.Type.Type->PrivateDirectives.fNoCode)
{
output("#define ASN1Free_%s(x) \n", identifier);
}
else
{
output("static void ASN1CALL ASN1Free_%s(%s);\n", identifier, funcbuf);
}
break;
#ifdef ENABLE_COMPARE
case eCompare:
if (!(a->U.Type.Type->Flags & eTypeFlags_GenCompare))
continue;
identifier = GetName(a);
sprintf(funcbuf, IsPSetOfType(ass, a) ? args.Pcmpfun : args.cmpfunc, identifier, identifier);
if (a->U.Type.Type->PrivateDirectives.fNoCode)
{
output("#define ASN1Compare_%s(x,y) 0\n", identifier);
}
else
{
output("static int ASN1CALL ASN1Compare_%s(%s);\n", identifier, funcbuf);
}
break;
#endif // ENABLE_COMPARE
case eCopy:
continue;
}
}
}
output("\n");
/* write a table containing the encode function addresses */
switch (g_eEncodingRule)
{
case eEncoding_Packed:
output("typedef ASN1PerEncFun_t ASN1EncFun_t;\n");
break;
case eEncoding_Basic:
output("typedef ASN1BerEncFun_t ASN1EncFun_t;\n");
break;
default:
output("typedef int (ASN1CALL *ASN1EncFun_t)(%s);\n", args.enccast);
break;
}
output("static const ASN1EncFun_t encfntab[%u] = {\n", g_cPDUs);
for (a = ass; a; a = a->Next) {
if ((! g_fLongNameForImported) && a->fImportedLocalDuplicate)
continue;
if (NotInFunTbl(a))
continue;
if (!(a->U.Type.Type->Flags & eTypeFlags_GenEncode)) {
ASSERT(0);
output("(ASN1EncFun_t) NULL,\n");
continue;
}
output("(ASN1EncFun_t) ASN1Enc_%s,\n", GetName(a));
}
output("};\n");
/* write a table containing the decode function addresses */
switch (g_eEncodingRule)
{
case eEncoding_Packed:
output("typedef ASN1PerDecFun_t ASN1DecFun_t;\n");
break;
case eEncoding_Basic:
output("typedef ASN1BerDecFun_t ASN1DecFun_t;\n");
break;
default:
output("typedef int (ASN1CALL *ASN1DecFun_t)(%s);\n", args.deccast);
break;
}
output("static const ASN1DecFun_t decfntab[%u] = {\n", g_cPDUs);
for (a = ass; a; a = a->Next)
{
if ((! g_fLongNameForImported) && a->fImportedLocalDuplicate)
continue;
if (NotInFunTbl(a))
continue;
if (!(a->U.Type.Type->Flags & eTypeFlags_GenDecode))
{
ASSERT(0);
output("(ASN1DecFun_t) NULL,\n");
continue;
}
output("(ASN1DecFun_t) ASN1Dec_%s,\n", GetName(a));
}
output("};\n");
/* write a table containing the free function addresses */
output("static const ASN1FreeFun_t freefntab[%u] = {\n", g_cPDUs);
for (a = ass; a; a = a->Next)
{
if ((! g_fLongNameForImported) && a->fImportedLocalDuplicate)
continue;
if (NotInFunTbl(a))
continue;
if (!(a->U.Type.Type->Flags & eTypeFlags_GenFree) ||
(a->U.Type.Type->Flags & eTypeFlags_Simple))
{
output("(ASN1FreeFun_t) NULL,\n");
continue;
}
output("(ASN1FreeFun_t) ASN1Free_%s,\n", GetName(a));
}
output("};\n");
#ifdef ENABLE_COMPARE
/* write a table containing the compare function addresses */
output("typedef int (ASN1CALL *ASN1CmpFun_t)(%s);\n", args.cmpcast);
output("static const ASN1CmpFun_t cmpfntab[%u] = {\n", g_cPDUs);
for (a = ass; a; a = a->Next)
{
if ((! g_fLongNameForImported) && a->fImportedLocalDuplicate)
continue;
if (NotInFunTbl(a))
continue;
if (!(a->U.Type.Type->Flags & eTypeFlags_GenCompare))
{
ASSERT(0);
output("(ASN1CmpFun_t) NULL,\n");
continue;
}
output("(ASN1CmpFun_t) ASN1Compare_%s,\n", GetName(a));
}
output("};\n");
output("\n");
#endif // ENABLE_COMPARE
/* write a table containing the sizeof pdu structures */
output("static const ULONG sizetab[%u] = {\n", g_cPDUs);
for (i = 0; i < g_cPDUs; i++)
{
output("SIZE_%s_%s_%u,\n", module, g_pszApiPostfix, i);
}
output("};\n");
output("\n");
/* handle values in 4 steps: */
/* 1. write forward declarations, */
/* 2. write definitions of value components, */
/* 3. write definitions of values, */
/* 4. write assignments into the initialization function */
for (ev = eDecl; ev <= eFinit; ev++)
{
switch (ev)
{
case eDecl:
output("/* forward declarations of values: */\n");
break;
case eDefh:
output("/* definitions of value components: */\n");
break;
case eDefn:
output("/* definitions of values: */\n");
break;
case eInit:
output("\nvoid ASN1CALL %s_Startup(void)\n", module);
output("{\n");
switch (g_eEncodingRule)
{
case eEncoding_Packed:
GenPERInit(ass, module);
break;
case eEncoding_Basic:
GenBERInit(ass, module);
break;
}
break;
case eFinit:
output("\nvoid ASN1CALL %s_Cleanup(void)\n", module);
output("{\n");
output("ASN1_CloseModule(%s);\n", module);
output("%s = NULL;\n", module);
break;
}
for (a = ass; a; a = a->Next)
{
if (a->Type != eAssignment_Value)
continue;
if (GetValue(ass, a->U.Value.Value)->Type->Flags & eTypeFlags_Null)
continue;
switch (ev)
{
case eDecl:
case eDefh:
case eDefn:
case eInit:
case eFinit:
if (!(a->U.Value.Value->Flags & eValueFlags_GenValue))
continue;
break;
}
GenFuncValue(ass, a, ev);
}
if (ev == eInit || ev == eFinit) {
output("}\n");
}
}
output("\n");
/* generate the type functions for all assignments as wanted */
for (a = ass; a; a = a->Next)
{
if (a->Type != eAssignment_Type)
continue;
/* skip null types */
if (a->U.Type.Type->Flags & eTypeFlags_Null)
continue;
if ((! g_fLongNameForImported) && a->fImportedLocalDuplicate)
continue;
if (a->U.Type.Type->PrivateDirectives.fNoCode)
continue;
/* generate the functions */
identifier = GetName(a);
for (et = eStringTable; et <= eCopy; et++)
{
switch (et)
{
case eStringTable:
if (!(a->U.Type.Type->Flags &
(eTypeFlags_GenEncode | eTypeFlags_GenDecode)))
continue;
switch (g_eEncodingRule)
{
case eEncoding_Packed:
GenPERFuncType(ass, module, a, et);
break;
case eEncoding_Basic:
GenBERFuncType(ass, module, a, et);
break;
}
break;
case eEncode:
if (!(a->U.Type.Type->Flags & eTypeFlags_GenEncode))
continue;
sprintf(funcbuf, IsPSetOfType(ass, a) ? args.Pencfunc : args.encfunc, identifier);
output("static int ASN1CALL ASN1Enc_%s(%s)\n",
identifier, funcbuf);
output("{\n");
switch (g_eEncodingRule)
{
case eEncoding_Packed:
GenPERFuncType(ass, module, a, et);
break;
case eEncoding_Basic:
GenBERFuncType(ass, module, a, et);
break;
}
output("return 1;\n");
output("}\n\n");
break;
case eDecode:
if (!(a->U.Type.Type->Flags & eTypeFlags_GenDecode))
continue;
sprintf(funcbuf, IsPSetOfType(ass, a) ? args.Pdecfunc : args.decfunc, identifier);
output("static int ASN1CALL ASN1Dec_%s(%s)\n",
identifier, funcbuf);
output("{\n");
switch (g_eEncodingRule)
{
case eEncoding_Packed:
GenPERFuncType(ass, module, a, et);
break;
case eEncoding_Basic:
GenBERFuncType(ass, module, a, et);
break;
}
output("return 1;\n");
output("}\n\n");
break;
case eCheck:
if (!(a->U.Type.Type->Flags & eTypeFlags_GenCheck))
continue;
GenFuncType(ass, module, a, et);
break;
case ePrint:
if (!(a->U.Type.Type->Flags & eTypeFlags_GenPrint))
continue;
GenFuncType(ass, module, a, et);
break;
case eFree:
if (!(a->U.Type.Type->Flags & eTypeFlags_GenFree) ||
(a->U.Type.Type->Flags & eTypeFlags_Simple))
continue;
sprintf(funcbuf, IsPSetOfType(ass, a) ? args.Pfreefunc : args.freefunc, identifier);
output("static void ASN1CALL ASN1Free_%s(%s)\n",
identifier, funcbuf);
output("{\n");
output("if (val) {\n"); // opening the null pointer check
GenFuncType(ass, module, a, et);
output("}\n"); // closing the null pointer check
output("}\n\n");
break;
#ifdef ENABLE_COMPARE
case eCompare:
if (!(a->U.Type.Type->Flags & eTypeFlags_GenCompare))
continue;
sprintf(funcbuf, IsPSetOfType(ass, a) ? args.Pcmpfunc : args.cmpfunc, identifier);
output("static int ASN1CALL ASN1Compare_%s(%s)\n",
identifier, funcbuf);
output("{\n");
outputvar("int ret;\n");
GenFuncType(ass, module, a, et);
output("return 0;\n");
output("}\n\n");
break;
#endif // ENABLE_COMPARE
case eCopy:
if (!(a->U.Type.Type->Flags & eTypeFlags_GenCopy))
continue;
GenFuncType(ass, module, a, et);
break;
}
}
}
}
/* generate function encoding-independent type-specific functions */
void
GenFuncType(AssignmentList_t ass, char *module, Assignment_t *at, TypeFunc_e et)
{
Type_t *type;
char *ideref;
char *valref1, *valref2;
/* get some informations */
type = at->U.Type.Type;
ideref = GetName(at);
switch (et) {
case eCompare:
valref1 = "val1";
valref2 = "val2";
break;
default:
valref1 = "val";
valref2 = "";
break;
}
/* function body */
switch (type->Type) {
case eType_Boolean:
case eType_Integer:
case eType_Enumerated:
case eType_Real:
case eType_BitString:
case eType_OctetString:
case eType_UTF8String:
case eType_Null:
case eType_EmbeddedPdv:
case eType_External:
case eType_ObjectIdentifier:
case eType_BMPString:
case eType_GeneralString:
case eType_GraphicString:
case eType_IA5String:
case eType_ISO646String:
case eType_NumericString:
case eType_PrintableString:
case eType_TeletexString:
case eType_T61String:
case eType_UniversalString:
case eType_VideotexString:
case eType_VisibleString:
case eType_CharacterString:
case eType_GeneralizedTime:
case eType_UTCTime:
case eType_ObjectDescriptor:
case eType_RestrictedString:
case eType_Open:
case eType_Reference:
/* generate function for a simple type */
GenFuncSimpleType(ass, type, ideref, Dereference(valref1), Dereference(valref2), et);
break;
case eType_SequenceOf:
case eType_SetOf:
/* generate function for seq-of and set-of */
GenFuncSimpleType(ass, type, ideref, Dereference(valref1), Dereference(valref2), et);
break;
case eType_Sequence:
case eType_Set:
case eType_InstanceOf:
/* generate function for a sequence/set/instanceof type */
GenFuncSequenceSetType(ass, module, at, valref1, valref2, et);
break;
case eType_Choice:
/* generate function for a choice type */
GenFuncChoiceType(ass, module, at, valref1, valref2, et);
break;
case eType_Selection:
MyAbort();
/*NOTREACHED*/
case eType_Undefined:
MyAbort();
/*NOTREACHED*/
}
}
/* generate encoding-independent statements for components of a */
/* sequence/set/choice type */
void
GenFuncComponents(AssignmentList_t ass, char *module, Type_t *type, char *ideref, uint32_t optindex, ComponentList_t components, char *valref1, char *valref2, TypeFunc_e et, int inextension, int inchoice)
{
Component_t *com;
NamedType_t *namedType;
char *ide, idebuf[256];
char valbuf1[256], valbuf2[256], valbuf3[256];
int skip;
/* emit components of extension root */
for (com = components; com; com = com->Next) {
if (com->Type == eComponent_ExtensionMarker)
break;
/* get some information */
namedType = com->U.NOD.NamedType;
ide = Identifier2C(namedType->Identifier);
sprintf(idebuf, "%s_%s", ideref, ide);
/* skip unnecessary elements */
switch (et) {
case eFree:
skip = (namedType->Type->Flags & eTypeFlags_Simple);
break;
default:
skip = 0;
break;
}
/* dereference pointer if pointer directive used */
if (inchoice) {
if (GetTypeRules(ass, namedType->Type) & eTypeRules_Pointer) {
sprintf(valbuf1, "*(%s)->u.%s", valref1, ide);
sprintf(valbuf2, "*(%s)->u.%s", valref2, ide);
} else {
sprintf(valbuf1, "(%s)->u.%s", valref1, ide);
sprintf(valbuf2, "(%s)->u.%s", valref2, ide);
}
} else {
if (GetTypeRules(ass, namedType->Type) & eTypeRules_Pointer) {
sprintf(valbuf1, "*(%s)->%s", valref1, ide);
sprintf(valbuf2, "*(%s)->%s", valref2, ide);
} else {
sprintf(valbuf1, "(%s)->%s", valref1, ide);
sprintf(valbuf2, "(%s)->%s", valref2, ide);
}
}
/* check if optional/default component is present */
if (!skip) {
if (inchoice) {
switch (et) {
case eFree:
output("case %d:\n", optindex);
GenFuncSimpleType(ass, namedType->Type, idebuf,
valbuf1, valbuf2, et);
if ((GetTypeRules(ass, namedType->Type) &
eTypeRules_Pointer) &&
!(GetType(ass, namedType->Type)->Flags &
eTypeFlags_Null))
output("ASN1Free(%s);\n", Reference(valbuf1));
output("break;\n");
break;
default:
output("case %d:\n", optindex);
GenFuncSimpleType(ass, namedType->Type, idebuf,
valbuf1, valbuf2, et);
output("break;\n");
break;
}
} else {
if (com->Type == eComponent_Optional ||
com->Type == eComponent_Default ||
inextension) {
switch (et) {
case eFree:
output("if ((%s)->o[%u] & 0x%x) {\n", valref1,
optindex / 8, 0x80 >> (optindex & 7));
GenFuncSimpleType(ass, namedType->Type, idebuf,
valbuf1, valbuf2, et);
if ((GetTypeRules(ass, namedType->Type) &
eTypeRules_Pointer) &&
!(GetType(ass, namedType->Type)->Flags &
eTypeFlags_Null))
output("ASN1Free(%s);\n", Reference(valbuf1));
output("}\n");
break;
case eCompare:
sprintf(valbuf3, "%s_default", idebuf);
output("if (((%s)->o[%u] & 0x%x)) {\n", valref1,
optindex / 8, 0x80 >> (optindex & 7));
output("if (((%s)->o[%u] & 0x%x)) {\n", valref2,
optindex / 8, 0x80 >> (optindex & 7));
GenFuncSimpleType(ass, namedType->Type, idebuf,
valbuf1, valbuf2, et);
output("} else {\n");
if (com->Type == eComponent_Default) {
GenFuncSimpleType(ass, namedType->Type, idebuf,
valbuf1, valbuf3, et);
} else {
output("return 1;\n");
}
output("}\n");
output("} else {\n");
output("if (((%s)->o[%u] & 0x%x)) {\n", valref2,
optindex / 8, 0x80 >> (optindex & 7));
if (com->Type == eComponent_Default) {
GenFuncSimpleType(ass, namedType->Type, idebuf,
valbuf3, valbuf2, et);
} else {
output("return 1;\n");
}
output("}\n");
output("}\n");
break;
default:
GenFuncSimpleType(ass, namedType->Type, idebuf,
valbuf1, valbuf2, et);
break;
}
} else {
GenFuncSimpleType(ass, namedType->Type, idebuf,
valbuf1, valbuf2, et);
}
}
}
if (inchoice ||
com->Type == eComponent_Optional ||
com->Type == eComponent_Default ||
inextension)
optindex++;
}
}
/* generate encoding-independent statements for sequence/set type */
void
GenFuncSequenceSetType(AssignmentList_t ass, char *module, Assignment_t *at, char *valref1, char *valref2, TypeFunc_e et)
{
uint32_t optionals, extensions;
Component_t *components, *com;
Type_t *type;
char *ideref;
type = at->U.Type.Type;
ideref = GetName(at);
optionals = type->U.SSC.Optionals;
extensions = type->U.SSC.Extensions;
components = type->U.SSC.Components;
/* emit components of extension root */
GenFuncComponents(ass, module, type, ideref, 0,
components, valref1, valref2, et, 0, 0);
/* handle extensions */
if (type->Flags & eTypeFlags_ExtensionMarker) {
if (extensions) {
/* get start of extensions */
for (com = components; com; com = com->Next) {
if (com->Type == eComponent_ExtensionMarker) {
com = com->Next;
break;
}
}
/* emit components of extension */
GenFuncComponents(ass, module, type, ideref, (optionals + 7) & ~7,
com, valref1, valref2, et, 1, 0);
}
}
}
/* generate encoding-independent statements for choice type */
void
GenFuncChoiceType(AssignmentList_t ass, char *module, Assignment_t *at, char *valref1, char *valref2, TypeFunc_e et)
{
Type_t *type;
char *ideref;
char valbuf1[256], valbuf2[256];
uint32_t alternatives;
Component_t *components, *com;
/* get some informations */
type = at->U.Type.Type;
ideref = GetName(at);
alternatives = type->U.SSC.Alternatives;
components = type->U.SSC.Components;
/* encode choice selector */
sprintf(valbuf1, "(%s)->choice", valref1);
sprintf(valbuf2, "(%s)->choice", valref2);
GenFuncSimpleType(ass, type, ideref, valbuf1, valbuf2, et);
/* finished if choice only contains NULL alternatives or if choice */
/* contains no data to free */
if ((type->Flags & eTypeFlags_NullChoice) ||
(et == eFree && (type->Flags & eTypeFlags_Simple)))
return;
/* create switch statement */
output("switch ((%s)->choice) {\n", valref1);
/* generate components of extension root */
GenFuncComponents(ass, module, type, ideref, ASN1_CHOICE_BASE,
type->U.SSC.Components, valref1, valref2, et, 0, 1);
/* get start of extensions */
for (com = components; com; com = com->Next) {
if (com->Type == eComponent_ExtensionMarker) {
com = com->Next;
break;
}
}
/* generate components of extension */
GenFuncComponents(ass, module, type, ideref, ASN1_CHOICE_BASE + alternatives,
com, valref1, valref2, et, 1, 1);
/* end of switch statement */
output("}\n");
}
/* generate encoding-independent statements for a simple type */
void
GenFuncSimpleType(AssignmentList_t ass, Type_t *type, char *ideref, char *valref1, char *valref2, TypeFunc_e et)
{
switch (et) {
case eFree:
GenFreeSimpleType(ass, type, ideref, valref1);
break;
#ifdef ENABLE_COMPARE
case eCompare:
GenCompareSimpleType(ass, type, ideref, valref1, valref2);
break;
#endif // ENABLE_COMPARE
}
}
/* generate free statements for a simple type */
void
GenFreeSimpleType(AssignmentList_t ass, Type_t *type, char *ideref, char *valref)
{
char idebuf[256];
char valbuf[256];
char valbuf2[256];
char *itype;
int32_t noctets;
uint32_t zero;
if (type->Flags & eTypeFlags_Simple)
return;
if (type->Type == eType_Reference && !IsStructuredType(GetType(ass, type)))
type = GetType(ass, type);
switch (type->Type) {
case eType_Boolean:
case eType_Integer:
case eType_Enumerated:
/* check if we have to free an intx_t value */
itype = GetTypeName(ass, type);
if (!strcmp(itype, "ASN1intx_t"))
output("ASN1intx_free(%s);\n", Reference(valref));
break;
case eType_BitString:
/* free bit string value */
if (g_eEncodingRule == eEncoding_Packed)
{
if (type->PERTypeInfo.Root.cbFixedSizeBitString == 0)
{
output("ASN1bitstring_free(%s);\n", Reference(valref));
}
}
else
{
// only support unbounded in BER
if (! type->PrivateDirectives.fNoMemCopy)
{
output("ASN1bitstring_free(%s);\n", Reference(valref));
}
}
break;
case eType_OctetString:
/* free octet string value */
if (g_eEncodingRule == eEncoding_Packed)
{
if (type->PERTypeInfo.Root.LConstraint != ePERSTIConstraint_Constrained ||
type->PrivateDirectives.fLenPtr)
{
output("ASN1octetstring_free(%s);\n", Reference(valref));
}
}
else
{
// only support unbounded in BER
if (! type->PrivateDirectives.fNoMemCopy)
{
output("ASN1octetstring_free(%s);\n", Reference(valref));
}
}
break;
case eType_UTF8String:
/* free octet string value */
output("ASN1utf8string_free(%s);\n", Reference(valref));
break;
case eType_ObjectIdentifier:
/* free object identifier value */
if (type->PrivateDirectives.fOidPacked)
{
output("ASN1BEREoid_free(%s);\n", Reference(valref));
}
else
if (! (type->PrivateDirectives.fOidArray || g_fOidArray))
{
output("ASN1objectidentifier_free(%s);\n", Reference(valref));
}
break;
case eType_External:
/* free external value */
output("ASN1external_free(%s);\n", Reference(valref));
break;
case eType_Real:
/* free real value */
output("ASN1real_free(%s);\n", Reference(valref));
break;
case eType_EmbeddedPdv:
/* free embedded pdv value */
output("ASN1embeddedpdv_free(%s);\n", Reference(valref));
break;
case eType_SetOf:
/* create name of identifier */
sprintf(idebuf, "%s_Set", ideref);
goto FreeSequenceSetOf;
case eType_SequenceOf:
/* create name of identifier */
sprintf(idebuf, "%s_Sequence", ideref);
FreeSequenceSetOf:
if (type->Rules & eTypeRules_FixedArray)
{
char *pszPrivateValueName = GetPrivateValueName(&type->PrivateDirectives, "value");
/* free components of sequence of/set of */
if (! (type->Rules & eTypeRules_PointerToElement))
valref = Reference(valref);
if (!(type->U.SS.Type->Flags & eTypeFlags_Simple)) {
outputvar("ASN1uint32_t i;\n");
output("for (i = 0; i < (%s)->count; i++) {\n", valref);
sprintf(valbuf, "(%s)->%s[i]", valref, pszPrivateValueName);
GenFuncSimpleType(ass, type->U.SS.Type, idebuf, valbuf, "", eFree);
output("}\n");
}
}
else
if (type->Rules & eTypeRules_LengthPointer)
{
char *pszPrivateValueName = GetPrivateValueName(&type->PrivateDirectives, "value");
/* free components of sequence of/set of */
if (! (type->Rules & eTypeRules_PointerToElement))
valref = Reference(valref);
if (!(type->U.SS.Type->Flags & eTypeFlags_Simple)) {
sprintf(valbuf2, "(%s)->%s[0]", valref, pszPrivateValueName);
GenFuncSimpleType(ass, type->U.SS.Type, idebuf, valbuf2, "", eFree);
outputvar("ASN1uint32_t i;\n");
output("for (i = 1; i < (%s)->count; i++) {\n", valref);
sprintf(valbuf2, "(%s)->%s[i]", valref, pszPrivateValueName);
GenFuncSimpleType(ass, type->U.SS.Type, idebuf, valbuf2, "", eFree);
output("}\n");
}
// lonchanc: no need to check length because we zero out decoded buffers.
// output("if ((%s)->count)\n", valref);
output("ASN1Free((%s)->%s);\n", valref, pszPrivateValueName);
}
else
if (type->Rules & eTypeRules_LinkedListMask)
{
char szPrivateValueName[68];
if (g_fCaseBasedOptimizer)
{
if (g_eEncodingRule == eEncoding_Packed &&
PerOptCase_IsTargetSeqOf(&type->PERTypeInfo))
{
// generate the iterator
PERTypeInfo_t *info = &type->PERTypeInfo;
char szElmFn[128];
char szElmFnDecl[256];
sprintf(szElmFn, "ASN1Free_%s_ElmFn", info->Identifier);
sprintf(szElmFnDecl, "void ASN1CALL %s(P%s val)",
szElmFn, info->Identifier);
setoutfile(g_finc);
output("extern %s;\n", szElmFnDecl);
setoutfile(g_fout);
output("ASN1PERFreeSeqOf((ASN1iterator_t **) %s, (ASN1iterator_freefn) %s);\n",
Reference(valref), szElmFn);
output("}\n"); // closing the null pointer check
output("}\n\n"); // end of iterator body
// generate the element function
output("static %s\n", szElmFnDecl);
output("{\n");
output("if (val) {\n"); // opening the null pointer check
sprintf(&szPrivateValueName[0], "val->%s", GetPrivateValueName(info->pPrivateDirectives, "value"));
GenFuncSimpleType(ass, type->U.SS.Type, idebuf,
&szPrivateValueName[0], "", eFree);
// output("}\n"); // closing the null pointer check. lonchanc: closed by caller
// end of element body
return;
}
}
/* free components of sequence of/set of */
outputvar("P%s f, ff;\n", ideref);
output("for (f = %s; f; f = ff) {\n", valref);
sprintf(&szPrivateValueName[0], "f->%s", type->PrivateDirectives.pszValueName ? type->PrivateDirectives.pszValueName : "value");
GenFuncSimpleType(ass, type->U.SS.Type, idebuf,
&szPrivateValueName[0], "", eFree);
output("ff = f->next;\n");
/* free list entry of sequence of/set of */
output("ASN1Free(f);\n");
output("}\n");
}
break;
case eType_ObjectDescriptor:
/* free object descriptor value */
output("ASN1ztcharstring_free(%s);\n", valref);
break;
case eType_NumericString:
case eType_PrintableString:
case eType_TeletexString:
case eType_T61String:
case eType_VideotexString:
case eType_IA5String:
case eType_GraphicString:
case eType_VisibleString:
case eType_ISO646String:
case eType_GeneralString:
case eType_UniversalString:
#ifdef ENABLE_CHAR_STR_SIZE
if (g_eEncodingRule == eEncoding_Packed &&
type->PERTypeInfo.NOctets == 1 &&
type->PERTypeInfo.Root.LConstraint == ePERSTIConstraint_Constrained)
{
// it is an array, no need to free it.
break;
}
#endif
case eType_BMPString:
case eType_RestrictedString:
/* free string value */
GetStringType(ass, type, &noctets, &zero);
if (zero) {
switch (noctets) {
case 1:
output("ASN1ztcharstring_free(%s);\n", valref);
break;
case 2:
output("ASN1ztchar16string_free(%s);\n", valref);
break;
case 4:
output("ASN1ztchar32string_free(%s);\n", valref);
break;
}
} else {
switch (noctets) {
case 1:
output("ASN1charstring_free(%s);\n", Reference(valref));
break;
case 2:
output("ASN1char16string_free(%s);\n", Reference(valref));
break;
case 4:
output("ASN1char32string_free(%s);\n", Reference(valref));
break;
}
}
break;
case eType_CharacterString:
/* free character string value */
output("ASN1characterstring_free(%s);\n", Reference(valref));
break;
case eType_Reference:
/* call free function of referenced type */
output("ASN1Free_%s(%s);\n",
GetTypeName(ass, type), Reference(valref));
break;
case eType_Open:
/* free open type value */
if (g_eEncodingRule == eEncoding_Packed || (! type->PrivateDirectives.fNoMemCopy))
{
output("ASN1open_free(%s);\n", Reference(valref));
}
break;
}
}
/* generate compare statements for a simple type */
/*ARGSUSED*/
#ifdef ENABLE_COMPARE
void
GenCompareSimpleType(AssignmentList_t ass, Type_t *type, char *ideref, char *valref1, char *valref2)
{
/* skip null type */
if (type->Flags & eTypeFlags_Null)
return;
/* compare the values and return difference if different */
output("if ((ret = (");
GenCompareExpression(ass, type, ideref, valref1, valref2);
output(")))\n");
output("return ret;\n");
}
#endif // ENABLE_COMPARE
/* generate compare expression for two values of simple type */
/*ARGSUSED*/
#ifdef ENABLE_COMPARE
void
GenCompareExpression(AssignmentList_t ass, Type_t *type, char *ideref, char *valref1, char *valref2)
{
PERSTIData_e dat;
uint32_t noctets;
char *itype;
char *subide;
char *pszPrivateValueName;
/*XXX switch to PER-independent field */
dat = type->PERTypeInfo.Root.Data;
noctets = type->PERTypeInfo.NOctets;
switch (dat) {
case ePERSTIData_Null:
/* null values equal */
output("0");
break;
case ePERSTIData_Boolean:
/* boolean values have to be converted to 0/1 values before */
/* comparison */
output("!!%s - !!%s", valref1, valref2);
break;
case ePERSTIData_Integer:
case ePERSTIData_Unsigned:
/* substract integer values */
if (noctets) {
if (noctets <= 4)
output("%s - %s", valref1, valref2);
else
output("%s < %s ? -1 : %s > %s ? 1 : 0",
valref1, valref2, valref1, valref2);
} else {
output("ASN1intx_cmp(%s, %s)",
Reference(valref1), Reference(valref2));
}
break;
case ePERSTIData_Real:
/* compare real values */
itype = GetTypeName(ass, type);
if (!strcmp(itype, "ASN1real_t"))
output("ASN1real_cmp(%s, %s)",
Reference(valref1), Reference(valref2));
else
output("ASN1double_cmp(%s, %s)",
valref1, valref2);
break;
case ePERSTIData_BitString:
/* compare bit string values */
output("ASN1bitstring_cmp(%s, %s, 0)",
Reference(valref1), Reference(valref2));
break;
case ePERSTIData_RZBBitString:
/* compare remove-zero-bit bit string values */
output("ASN1bitstring_cmp(%s, %s, 1)",
Reference(valref1), Reference(valref2));
break;
case ePERSTIData_OctetString:
/* compare octet string values */
output("ASN1octetstring_cmp(%s, %s)",
Reference(valref1), Reference(valref2));
break;
case ePERSTIData_UTF8String:
/* compare octet string values */
output("ASN1utf8string_cmp(%s, %s)",
Reference(valref1), Reference(valref2));
break;
case ePERSTIData_ObjectIdentifier:
/* compare object identifier values */
output("ASN1objectidentifier_cmp(%s, %s)",
Reference(valref1), Reference(valref2));
break;
case ePERSTIData_String:
case ePERSTIData_TableString:
/* compare string values */
switch (noctets) {
case 1:
output("ASN1charstring_cmp(%s, %s)",
Reference(valref1), Reference(valref2));
break;
case 2:
output("ASN1char16string_cmp(%s, %s)",
Reference(valref1), Reference(valref2));
break;
case 4:
output("ASN1char32string_cmp(%s, %s)",
Reference(valref1), Reference(valref2));
break;
}
break;
case ePERSTIData_ZeroString:
case ePERSTIData_ZeroTableString:
/* compare zero-terminated string values */
switch (noctets) {
case 1:
output("ASN1ztcharstring_cmp(%s, %s)",
valref1, valref2);
break;
case 2:
output("ASN1ztchar16string_cmp(%s, %s)",
valref1, valref2);
break;
case 4:
output("ASN1ztchar32string_cmp(%s, %s)",
valref1, valref2);
break;
}
break;
case ePERSTIData_SequenceOf:
/* compare sequence of values by use of a comparison function */
/* use element comparison function as argument */
subide = GetTypeName(ass, type->U.SS.Type);
pszPrivateValueName = GetPrivateValueName(&type->PrivateDirectives, "value");
if (type->Rules & eTypeRules_PointerArrayMask)
{
output("ASN1sequenceoflengthpointer_cmp((%s)->count, (%s)->%s, (%s)->count, (%s)->%s, sizeof(%s), (int (*)(void *, void *))ASN1Compare_%s)",
Reference(valref1), Reference(valref1), pszPrivateValueName,
Reference(valref2), Reference(valref2), pszPrivateValueName, subide, subide);
}
else
if (type->Rules & eTypeRules_SinglyLinkedList)
{
output("ASN1sequenceofsinglylinkedlist_cmp(%s, %s, offsetof(%s_Element, %s), (ASN1int32_t (*)(void *, void *))ASN1Compare_%s)",
valref1, valref2, ideref, pszPrivateValueName, subide);
}
else
if (type->Rules & eTypeRules_DoublyLinkedList)
{
output("ASN1sequenceofdoublylinkedlist_cmp(%s, %s, offsetof(%s_Element, %s), (ASN1int32_t (*)(void *, void *))ASN1Compare_%s)",
valref1, valref2, ideref, pszPrivateValueName, subide);
}
else
{
MyAbort();
}
break;
case ePERSTIData_SetOf:
/* compare set of values by use of a comparison function */
/* use element comparison function as argument */
subide = GetTypeName(ass, type->U.SS.Type);
pszPrivateValueName = GetPrivateValueName(&type->PrivateDirectives, "value");
if (type->Rules & eTypeRules_PointerArrayMask)
{
output("ASN1setoflengthpointer_cmp((%s)->count, (%s)->%s, (%s)->count, (%s)->%s, sizeof(%s), (int (*)(void *, void *))ASN1Compare_%s)",
Reference(valref1), Reference(valref1), pszPrivateValueName,
Reference(valref2), Reference(valref2), pszPrivateValueName, subide, subide);
}
else
if (type->Rules & eTypeRules_SinglyLinkedList)
{
output("ASN1setofsinglylinkedlist_cmp(%s, %s, offsetof(%s_Element, %s), (ASN1int32_t (*)(void *, void *))ASN1Compare_%s)",
valref1, valref2, ideref, pszPrivateValueName, subide);
}
else
if (type->Rules & eTypeRules_DoublyLinkedList)
{
output("ASN1setofdoublylinkedlist_cmp(%s, %s, offsetof(%s_Element, %s), (ASN1int32_t (*)(void *, void *))ASN1Compare_%s)",
valref1, valref2, ideref, pszPrivateValueName, subide);
}
else
{
MyAbort();
}
break;
case ePERSTIData_Reference:
/* call compare function of referenced value */
output("ASN1Compare_%s(%s, %s)",
GetTypeName(ass, type), Reference(valref1), Reference(valref2));
break;
case ePERSTIData_External:
/* compare external values */
output("ASN1external_cmp(%s, %s)",
Reference(valref1), Reference(valref2));
break;
case ePERSTIData_EmbeddedPdv:
/* compare embedded pdv values */
output("ASN1embeddedpdv_cmp(%s, %s)",
Reference(valref1), Reference(valref2));
break;
case ePERSTIData_MultibyteString:
/* compare multibyte string values */
output("ASN1ztcharstring_cmp(%s, %s)",
valref1, valref2);
break;
case ePERSTIData_UnrestrictedString:
/* compare character string values */
output("ASN1characterstring_cmp(%s, %s)",
Reference(valref1), Reference(valref2));
break;
case ePERSTIData_GeneralizedTime:
/* compare generalized time values */
output("ASN1generalizedtime_cmp(%s, %s)",
Reference(valref1), Reference(valref2));
break;
case ePERSTIData_UTCTime:
/* compare utc time values */
output("ASN1utctime_cmp(%s, %s)",
Reference(valref1), Reference(valref2));
break;
case ePERSTIData_Open:
/* compare open type values */
output("ASN1open_cmp(%s, %s)",
Reference(valref1), Reference(valref2));
break;
}
}
#endif // ENABLE_COMPARE
/* generate encoding-independent statements for better optional flags of */
/* a sequence/set value */
void
GenFuncSequenceSetOptionals(AssignmentList_t ass, char *valref, ComponentList_t components, uint32_t optionals, uint32_t extensions, char *obuf, TypeFunc_e et)
{
uint32_t optindex, inextension, oflg;
Component_t *com;
char *ide;
char *itype;
int flg;
int32_t sign, noctets;
uint32_t zero;
sprintf(obuf, "(%s)->o", valref);
oflg = 0;
if (et == eEncode) {
optindex = 0;
inextension = 0;
for (com = components; com; com = com->Next) {
switch (com->Type) {
case eComponent_Normal:
/* non-optional fields in an extension will be mandatory, */
/* so we can set the optional flag always. */
if (inextension) {
if (!oflg) {
outputvar("ASN1octet_t o[%u];\n",
(optionals + 7) / 8 + (extensions + 7) / 8);
output("CopyMemory(o, (%s)->o, %u);\n", valref,
(optionals + 7) / 8 + (extensions + 7) / 8);
strcpy(obuf, "o");
oflg = 1;
}
output("%s[%u] |= 0x%x;\n", obuf, optindex / 8,
0x80 >> (optindex & 7));
optindex++;
}
break;
case eComponent_Optional:
/* optional pointers with value null are absent, so we */
/* will clear the optional flag */
ide = Identifier2C(com->U.Optional.NamedType->Identifier);
switch (com->U.Optional.NamedType->Type->Type) {
case eType_Reference:
if (GetTypeRules(ass, com->U.Optional.NamedType->Type) &
eTypeRules_Pointer) {
if (!oflg) {
outputvar("ASN1octet_t o[%u];\n",
(optionals + 7) / 8 + (extensions + 7) / 8);
output("CopyMemory(o, (%s)->o, %u);\n", valref,
(optionals + 7) / 8 + (extensions + 7) / 8);
strcpy(obuf, "o");
oflg = 1;
}
output("if (!(%s)->%s)\n", valref, ide);
output("o[%u] &= ~0x%x;\n", valref, optindex / 8,
0x80 >> (optindex & 7));
}
break;
}
optindex++;
break;
case eComponent_Default:
/* default pointers with value null are absent, so we */
/* will clear the optional flag */
ide = Identifier2C(com->U.Default.NamedType->Identifier);
switch (com->U.Default.NamedType->Type->Type) {
case eType_Reference:
if (GetTypeRules(ass, com->U.Default.NamedType->Type) &
eTypeRules_Pointer) {
if (!oflg) {
outputvar("ASN1octet_t o[%u];\n",
(optionals + 7) / 8 + (extensions + 7) / 8);
output("CopyMemory(o, (%s)->o, %u);\n", valref,
(optionals + 7) / 8 + (extensions + 7) / 8);
strcpy(obuf, "o");
oflg = 1;
}
output("if (!(%s)->%s)\n", valref, ide);
output("o[%u] &= ~0x%x;\n", valref, optindex / 8,
0x80 >> (optindex & 7));
}
break;
}
/* if the given value is the default value, we can (BER) */
/* or have to (CER) clear the corresponding optional flag */
flg = 1;
if (!oflg) {
switch (GetTypeType(ass, com->U.Default.NamedType->Type)) {
case eType_Choice:
if (!(GetType(ass, com->U.Default.NamedType->Type)->
Flags & eTypeFlags_NullChoice)) {
if (g_eSubEncodingRule == eSubEncoding_Canonical)
MyAbort(); /*XXX*/
flg = 0;
}
break;
case eType_Sequence:
case eType_Set:
case eType_InstanceOf:
if (g_eSubEncodingRule == eSubEncoding_Canonical)
MyAbort(); /*XXX*/
flg = 0;
break;
case eType_SequenceOf:
case eType_SetOf:
if (GetValue(ass, com->U.Default.Value)->U.SS.Values) {
if (g_eSubEncodingRule == eSubEncoding_Canonical)
MyAbort();
flg = 0;
}
break;
}
if (flg) {
outputvar("ASN1octet_t o[%u];\n",
(optionals + 7) / 8 + (extensions + 7) / 8);
output("CopyMemory(o, (%s)->o, %u);\n", valref,
(optionals + 7) / 8 + (extensions + 7) / 8);
strcpy(obuf, "o");
oflg = 1;
}
}
switch (GetTypeType(ass, com->U.Default.NamedType->Type)) {
case eType_Boolean:
output("if (%s(%s)->%s)\n",
GetValue(ass,
com->U.Default.Value)->U.Boolean.Value ? "" : "!",
valref, ide);
break;
case eType_Integer:
itype = GetIntegerType(ass,
GetType(ass, com->U.Default.NamedType->Type),
&sign);
if (!strcmp(itype, "ASN1intx_t")) {
output("if (!ASN1intx_cmp(&(%s)->%s, &%s))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
} else if (sign > 0) {
output("if ((%s)->%s == %u)\n", valref, ide,
intx2uint32(&GetValue(ass, com->U.Default.Value)
->U.Integer.Value));
} else {
output("if ((%s)->%s == %d)\n", valref, ide,
intx2int32(&GetValue(ass, com->U.Default.Value)
->U.Integer.Value));
}
break;
case eType_BitString:
if (GetValue(ass, com->U.Default.Value)->
U.BitString.Value.length) {
output("if (!ASN1bitstring_cmp(&%s->%s, &%s, %d))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value),
!!GetType(ass, com->U.Default.NamedType->Type)->
U.BitString.NamedNumbers);
} else {
output("if (!(%s)->%s.length)\n", valref, ide);
}
break;
case eType_OctetString:
if (GetValue(ass, com->U.Default.Value)->U.OctetString.
Value.length) {
output("if (!ASN1octetstring_cmp(&%s->%s, &%s))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
} else {
output("if (!(%s)->%s.length)\n", valref, ide);
}
break;
case eType_UTF8String:
if (GetValue(ass, com->U.Default.Value)->U.UTF8String.
Value.length) {
output("if (!ASN1utf8string_cmp(&%s->%s, &%s))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
} else {
output("if (!(%s)->%s.length)\n", valref, ide);
}
break;
case eType_Null:
break;
case eType_ObjectIdentifier:
if (GetValue(ass, com->U.Default.Value)->U.
ObjectIdentifier.Value.length) {
output("if (!ASN1objectidentifier%s_cmp(&%s->%s, &%s))\n",
com->U.Default.NamedType->Type->PrivateDirectives.fOidArray ? "2" : "",
valref, ide,
GetValueName(ass, com->U.Default.Value));
} else {
output("if (!(%s)->%s.length)\n", valref, ide);
}
break;
case eType_ObjectDescriptor:
output("if (!strcmp((%s)->%s, %s))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
break;
case eType_External:
output("if (!ASN1external_cmp(&(%s)->%s, &%s))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
break;
case eType_Real:
itype = GetTypeName(ass, com->U.Default.NamedType->Type);
if (!strcmp(itype, "ASN1real_t")) {
output("if (!ASN1real_cmp(&(%s)->%s, &%s))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
}
else
{
output("if ((%s)->%s == %g)\n",
valref, ide,
real2double(&GetValue(ass,
com->U.Default.Value)->U.Real.Value));
}
break;
case eType_Enumerated:
output("if ((%s)->%s == %u)\n", valref, ide,
GetValue(ass, com->U.Default.Value)->
U.Enumerated.Value);
break;
case eType_EmbeddedPdv:
output("if (!ASN1embeddedpdv_cmp(&(%s)->%s, &%s))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
break;
case eType_NumericString:
case eType_PrintableString:
case eType_TeletexString:
case eType_T61String:
case eType_VideotexString:
case eType_IA5String:
case eType_GraphicString:
case eType_VisibleString:
case eType_ISO646String:
case eType_GeneralString:
case eType_UniversalString:
case eType_BMPString:
case eType_RestrictedString:
GetStringType(ass, com->U.Default.NamedType->Type,
&noctets, &zero);
if (zero) {
switch (noctets) {
case 1:
output("if (!strcmp((%s)->%s, %s))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
break;
case 2:
output("if (!ASN1str16cmp((%s)->%s, %s))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
break;
case 4:
output("if (!ASN1str32cmp((%s)->%s, %s))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
break;
default:
MyAbort();
}
} else {
switch (noctets) {
case 1:
output("if (!ASN1charstring_cmp(&(%s)->%s, &%s))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
break;
case 2:
output("if (!ASN1char16string_cmp(&(%s)->%s, &%s))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
break;
case 4:
output("if (!ASN1char32string_cmp(&(%s)->%s, &%s))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
break;
default:
MyAbort();
}
}
break;
case eType_CharacterString:
output("if (!ASN1characterstring_cmp(&(%s)->%s, &%s))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
break;
case eType_UTCTime:
output("if (!ASN1utctime_cmp(&(%s)->%s, &%s))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
break;
case eType_GeneralizedTime:
output("if (!ASN1generalizedtime_cmp(&(%s)->%s, &%s))\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
break;
case eType_Choice:
if (GetType(ass, com->U.Default.NamedType->Type)->Flags
& eTypeFlags_NullChoice) {
output("if ((%s)->%s.o == %s.o)\n",
valref, ide,
GetValueName(ass, com->U.Default.Value));
} else {
if (g_eSubEncodingRule == eSubEncoding_Canonical)
MyAbort(); /*XXX*/
flg = 0;
}
break;
case eType_Sequence:
case eType_Set:
case eType_InstanceOf:
if (g_eSubEncodingRule == eSubEncoding_Canonical)
MyAbort(); /*XXX*/
flg = 0;
break;
case eType_SequenceOf:
case eType_SetOf:
if (!GetValue(ass, com->U.Default.Value)->U.SS.Values) {
output("if (!(%s)->%s.count)\n", valref, ide);
} else {
if (g_eSubEncodingRule == eSubEncoding_Canonical)
MyAbort();
flg = 0;
}
break;
default:
MyAbort();
}
if (flg)
output("%s[%u] &= ~0x%x;\n", obuf, optindex / 8,
0x80 >> (optindex & 7));
optindex++;
break;
case eComponent_ExtensionMarker:
/* update the optional index for extensions */
optindex = (optindex + 7) & ~7;
inextension = 1;
break;
}
}
}
}
/* generate encoding-independent statements for better optional values of */
/* a sequence/set value */
void
GenFuncSequenceSetDefaults(AssignmentList_t ass, char *valref, ComponentList_t components, char *obuf, TypeFunc_e et)
{
uint32_t optindex, inextension;
Component_t *com;
char *ide;
char *itype;
int32_t sign;
if (et == eDecode) {
optindex = 0;
inextension = 0;
for (com = components; com; com = com->Next) {
switch (com->Type) {
case eComponent_Normal:
/* all values in an extension are optional */
if (!inextension)
break;
/*FALLTHROUGH*/
case eComponent_Optional:
/* clear the pointer if the component is not present */
ide = Identifier2C(com->U.Optional.NamedType->Identifier);
switch (com->U.Optional.NamedType->Type->Type) {
case eType_Reference:
if (GetTypeRules(ass, com->U.Optional.NamedType->Type) &
eTypeRules_Pointer) {
output("if (!(%s[%u] & 0x%x))\n", obuf,
optindex / 8, 0x80 >> (optindex & 7));
output("(%s)->%s = NULL;\n", valref, ide);
}
break;
}
optindex++;
break;
case eComponent_Default:
/* clear the pointer if the component is not present */
ide = Identifier2C(com->U.Default.NamedType->Identifier);
switch (com->U.Optional.NamedType->Type->Type) {
case eType_Reference:
if (GetTypeRules(ass, com->U.Optional.NamedType->Type) &
eTypeRules_Pointer) {
output("if (!(%s[%u] & 0x%x))\n", obuf,
optindex / 8, 0x80 >> (optindex & 7));
output("(%s)->%s = NULL;\n", valref, ide);
}
break;
}
/* set the element to the default value if it is simple */
/* and not present */
switch (GetTypeType(ass, com->U.Default.NamedType->Type)) {
case eType_Boolean:
output("if (!(%s[%u] & 0x%x))\n", obuf, optindex / 8,
0x80 >> (optindex & 7));
output("(%s)->%s = %u;\n",
valref, ide, GetValue(ass, com->U.Default.Value)->
U.Boolean.Value);
break;
case eType_Integer:
output("if (!(%s[%u] & 0x%x))\n", obuf, optindex / 8,
0x80 >> (optindex & 7));
itype = GetIntegerType(ass,
GetType(ass, com->U.Default.NamedType->Type),
&sign);
if (!strcmp(itype, "ASN1intx_t")) {
/*EMPTY*/
} else if (sign > 0) {
output("(%s)->%s = %u;\n", valref, ide,
intx2uint32(&GetValue(ass, com->U.Default.Value)
->U.Integer.Value));
} else {
output("(%s)->%s = %d;\n", valref, ide,
intx2int32(&GetValue(ass, com->U.Default.Value)
->U.Integer.Value));
}
break;
case eType_Enumerated:
output("if (!(%s[%u] & 0x%x))\n", obuf, optindex / 8,
0x80 >> (optindex & 7));
output("(%s)->%s = %u;\n", valref, ide,
GetValue(ass, com->U.Default.Value)->
U.Enumerated.Value);
break;
}
optindex++;
break;
case eComponent_ExtensionMarker:
/* update the optional index for extensions */
optindex = (optindex + 7) & ~7;
inextension = 1;
break;
}
}
}
}
/* generate values */
void
GenFuncValue(AssignmentList_t ass, Assignment_t *av, ValueFunc_e ev)
{
char *ideref;
char *typeref;
Type_t *t;
ideref = GetName(av);
t = GetValue(ass, av->U.Value.Value)->Type;
typeref = GetTypeName(ass, t);
switch (ev) {
case eDecl:
GenDeclGeneric(ass, ideref, typeref, av->U.Value.Value, t);
break;
case eDefh:
GenDefhGeneric(ass, ideref, typeref, av->U.Value.Value, t);
break;
case eDefn:
GenDefnGeneric(ass, ideref, typeref, av->U.Value.Value, t);
break;
case eInit:
GenInitGeneric(ass, ideref, typeref, av->U.Value.Value, t);
break;
case eFinit:
break;
}
}
/* generate forward declarations */
void
GenDeclGeneric(AssignmentList_t ass, char *ideref, char *typeref, Value_t *value, Type_t *t)
{
value = GetValue(ass, value);
#if 0 // duplicate in the generated header file
switch (t->Type)
{
case eType_ObjectIdentifier:
if (t->PrivateDirectives.fOidArray || g_fOidArray)
{
output("extern ASN1objectidentifier2_t *%s;\n", ideref);
break;
}
// intentionally fall through
default:
output("extern %s %s;\n", typeref, ideref);
break;
}
#endif // 0
outputvalue0(ass, ideref, typeref, value);
}
/* generate definitions of value components */
void
GenDefhGeneric(AssignmentList_t ass, char *ideref, char *typeref, Value_t *value, Type_t *t)
{
value = GetValue(ass, value);
outputvalue1(ass, ideref, typeref, value);
}
/* generate definitions of values */
void
GenDefnGeneric(AssignmentList_t ass, char *ideref, char *typeref, Value_t *value, Type_t *t)
{
value = GetValue(ass, value);
switch (t->Type)
{
case eType_ObjectIdentifier:
if (t->PrivateDirectives.fOidPacked ||
t->PrivateDirectives.fOidArray || g_fOidArray)
{
// lonchanc: intentionally comment out the lines below
// output("ASN1objectidentifier2_t *%s = ", ideref);
// break;
return;
}
// intentionally fall through
default:
output("%s %s = ", typeref, ideref);
break;
}
outputvalue2(ass, ideref, value);
output(";\n");
}
/* generate assignments into the initialization function */
/*ARGSUSED*/
void
GenInitGeneric(AssignmentList_t ass, char *ideref, char *typeref, Value_t *value, Type_t *t)
{
outputvalue3(ass, ideref, ideref, value);
}