1913 lines
68 KiB
C
1913 lines
68 KiB
C
|
/* 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);
|
||
|
}
|
||
|
|
||
|
|