windows-nt/Source/XPSP1/NT/ds/security/asn1/asn1c/genper.c
2020-09-26 16:20:57 +08:00

3562 lines
125 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 GenPERFuncSimpleType(AssignmentList_t ass, PERTypeInfo_t *info, char *valref, TypeFunc_e et, char *encref);
void GenPERStringTableSimpleType(AssignmentList_t ass, PERTypeInfo_t *info);
void GenPEREncSimpleType(AssignmentList_t ass, PERTypeInfo_t *info, char *valref, char *encref);
void GenPEREncGenericUnextended(
AssignmentList_t ass,
PERTypeInfo_t *info,
PERSimpleTypeInfo_t *sinfo,
char *valref,
char *lenref,
char *encref);
void GenPERFuncSequenceSetType(AssignmentList_t ass, char *module, Assignment_t *at, char *valref, char *encref, TypeFunc_e et);
void GenPERFuncChoiceType(AssignmentList_t ass, char *module, Assignment_t *at, char *valref, char *encref, TypeFunc_e et);
void GenPERDecSimpleType(AssignmentList_t ass, PERTypeInfo_t *info, char *valref, char *encref);
void GenPERDecGenericUnextended(
AssignmentList_t ass,
PERTypeInfo_t *info,
PERSimpleTypeInfo_t *sinfo,
char *valref,
char *lenref,
char *encref);
int IsUnconstrainedInteger(PERSimpleTypeInfo_t *sinfo);
extern int g_fDecZeroMemory;
extern int g_nDbgModuleName;
extern unsigned g_cPDUs;
extern int g_fCaseBasedOptimizer;
extern int g_fNoAssert;
/* write header needed for PER encodings */
void
GenPERHeader()
{
// output("#include \"perfnlib.h\"\n");
}
/* set prototypes and function args of PER functions */
void
GetPERPrototype(Arguments_t *args)
{
args->enccast = "ASN1encoding_t, void *";
args->encfunc = "ASN1encoding_t enc, %s *val";
args->Pencfunc = "ASN1encoding_t enc, P%s *val";
args->deccast = "ASN1decoding_t, void *";
args->decfunc = "ASN1decoding_t dec, %s *val";
args->Pdecfunc = "ASN1decoding_t dec, P%s *val";
args->freecast = "void *";
args->freefunc = "%s *val";
args->Pfreefunc = "P%s *val";
args->cmpcast = "void *, void *";
args->cmpfunc = "%s *val1, %s *val2";
args->Pcmpfunc = "P%s *val1, P%s *val2";
}
/* write initialization function needed for PER encodings */
void
GenPERInit(AssignmentList_t ass, char *module)
{
output("%s = ASN1_CreateModule(0x%x, ASN1_PER_RULE_ALIGNED, %s, %d, (const ASN1GenericFun_t *) encfntab, (const ASN1GenericFun_t *) decfntab, freefntab, sizetab, 0x%lx);\n",
module,
ASN1_THIS_VERSION,
g_fNoAssert ? "ASN1FLAGS_NOASSERT" : "ASN1FLAGS_NONE",
g_cPDUs,
g_nDbgModuleName);
}
/* generate function body for a type */
void GenPERFuncType(AssignmentList_t ass, char *module, Assignment_t *at, TypeFunc_e et)
{
Type_t *type;
char *encref;
char *valref;
/* get some informations */
type = at->U.Type.Type;
switch (et) {
case eStringTable:
valref = encref = "";
break;
case eEncode:
encref = "enc";
valref = "val";
break;
case eDecode:
encref = "dec";
valref = "val";
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:
GenPERFuncSimpleType(ass, &type->PERTypeInfo, Dereference(valref), et, encref);
break;
case eType_SequenceOf:
case eType_SetOf:
GenPERFuncSimpleType(ass, &type->PERTypeInfo, Dereference(valref), et, encref);
break;
case eType_Sequence:
case eType_Set:
case eType_InstanceOf:
GenPERFuncSequenceSetType(ass, module, at, valref, encref, et);
break;
case eType_Choice:
GenPERFuncChoiceType(ass, module, at, valref, encref, et);
break;
case eType_Selection:
case eType_Undefined:
MyAbort();
/*NOTREACHED*/
}
}
/* generate function body for components */
void
GenPERFuncComponents(AssignmentList_t ass, char *module, uint32_t optindex, ComponentList_t components, char *valref, char *encref, char *oref, TypeFunc_e et, int inextension, int inchoice)
{
Component_t *com;
NamedType_t *namedType;
char *ide;
char valbuf[256];
char typebuf[256];
int conditional, skip;
/* get a parented encoding_t/decoding_t for sequence/set */
if (inextension && !inchoice) {
switch (et) {
case eStringTable:
break;
case eEncode:
outputvar("ASN1encoding_t ee;\n");
output("if (ASN1_CreateEncoder(%s->module, &ee, NULL, 0, %s) < 0)\n",
encref, encref);
output("return 0;\n");
break;
case eDecode:
outputvar("ASN1decoding_t dd;\n");
break;
}
}
/* 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);
/* skip unnecessary elements */
skip = (namedType->Type->Flags & eTypeFlags_Null) && !inextension;
/* check if optional/default component is present or choice is */
/* selected */
conditional = 0;
switch (et) {
case eStringTable:
break;
case eEncode:
case eDecode:
if (inchoice) {
// lonchanc: we should not skip any case in Decode
// because we cannot tell skipped cases from extension.
// on the other hand, in Encode, we'd better not either.
// when people put in customization in extension,
// we cannot tell as well.
if (skip)
{
output("case %d:\nbreak;\n", optindex);
}
else
{
output("case %d:\n", optindex);
conditional = 1;
}
optindex++;
} else {
if (com->Type == eComponent_Optional ||
com->Type == eComponent_Default ||
inextension) {
if (!skip) {
output("if (%s[%u] & 0x%x) {\n", oref,
optindex / 8, 0x80 >> (optindex & 7));
conditional = 1;
}
optindex++;
}
}
break;
}
/* get a parented encoding_t/decoding_t for choice */
if (inextension && inchoice) {
/* get a parented encoding_t/decoding_t */
switch (et) {
case eStringTable:
break;
case eEncode:
outputvar("ASN1encoding_t ee;\n");
output("if (ASN1_CreateEncoder(%s->module, &ee, NULL, 0, %s) < 0)\n",
encref, encref);
output("return 0;\n");
break;
case eDecode:
outputvar("ASN1decoding_t dd;\n");
break;
}
}
/* dereference pointer if pointer directive used */
if (inchoice) {
if (GetTypeRules(ass, namedType->Type) & eTypeRules_Pointer)
sprintf(valbuf, "*(%s)->u.%s", valref, ide);
else
sprintf(valbuf, "(%s)->u.%s", valref, ide);
} else {
if (GetTypeRules(ass, namedType->Type) & eTypeRules_Pointer)
sprintf(valbuf, "*(%s)->%s", valref, ide);
else
sprintf(valbuf, "(%s)->%s", valref, ide);
}
/* allocate memory if decoding and pointer directive used */
if (et == eDecode &&
(GetTypeRules(ass, namedType->Type) & eTypeRules_Pointer) &&
!(GetType(ass, namedType->Type)->Flags & eTypeFlags_Null)) {
sprintf(typebuf, "%s *",
GetTypeName(ass, namedType->Type));
output("if (!(%s = (%s)ASN1DecAlloc(%s, sizeof(%s))))\n",
Reference(valbuf), typebuf, encref, valbuf);
output("return 0;\n");
}
/* handle subtype value */
if (!skip) {
if (!inextension) {
GenPERFuncSimpleType(ass, &namedType->Type->PERTypeInfo,
valbuf, et, encref);
} else {
switch (et) {
case eStringTable:
GenPERFuncSimpleType(ass, &namedType->Type->PERTypeInfo,
valbuf, et, encref);
break;
case eEncode:
GenPERFuncSimpleType(ass, &namedType->Type->PERTypeInfo,
valbuf, et, "ee");
// lonchanc: added the following API to replace the following
// chunk of code.
output("if (!ASN1PEREncFlushFragmentedToParent(ee))\n");
// output("if (!ASN1PEREncFlush(ee))\n");
// output("return 0;\n");
// output("if (!ASN1PEREncFragmented(%s, ee->len, ee->buf, 8))\n",
// encref);
output("return 0;\n");
break;
case eDecode:
outputvar("ASN1octet_t *db;\n");
outputvar("ASN1uint32_t ds;\n");
output("if (!ASN1PERDecFragmented(%s, &ds, &db, 8))\n",
encref);
output("return 0;\n");
output("if (ASN1_CreateDecoder(%s->module, &dd, db, ds, %s) < 0)\n",
encref, encref);
output("return 0;\n");
GenPERFuncSimpleType(ass, &namedType->Type->PERTypeInfo,
valbuf, et, "dd");
output("ASN1_CloseDecoder(dd);\n");
output("ASN1Free(db);\n");
break;
}
}
}
/* drop the parented encoding_t/decoding_t for choice */
if (inextension && inchoice) {
if (et == eEncode) {
output("ASN1_CloseEncoder2(ee);\n");
}
}
/* end of check for presence of optional/default component */
if (inchoice) {
if (conditional)
output("break;\n");
} else {
if (conditional)
output("}\n");
}
}
/* drop the parented encoding_t/decoding_t for sequence/set */
if (inextension && !inchoice) {
if (et == eEncode) {
output("ASN1_CloseEncoder2(ee);\n");
}
}
}
/* generate function body for sequence/set type */
void GenPERFuncSequenceSetType(AssignmentList_t ass, char *module, Assignment_t *at, char *valref, char *encref, TypeFunc_e et)
{
uint32_t optionals, extensions;
Component_t *components, *com;
PERTypeInfo_t inf;
Type_t *type;
char valbuf[256];
int conditional;
char obuf[256];
type = at->U.Type.Type;
optionals = type->U.SSC.Optionals;
extensions = type->U.SSC.Extensions;
components = type->U.SSC.Components;
inf.Identifier = NULL;
inf.Flags = 0;
inf.Rules = 0;
inf.EnumerationValues = NULL;
inf.NOctets = 0;
inf.Type = eExtension_Unextended;
inf.Root.TableIdentifier = NULL;
inf.Root.Table = NULL;
inf.Root.Data = ePERSTIData_Extension;
inf.Root.SubType = NULL;
inf.Root.SubIdentifier = NULL;
inf.Root.NBits = 0;
inf.Root.Constraint = ePERSTIConstraint_Unconstrained;
intx_setuint32(&inf.Root.LowerVal, 0);
intx_setuint32(&inf.Root.UpperVal, 0);
inf.Root.Alignment = ePERSTIAlignment_BitAligned;
inf.Root.Length = ePERSTILength_NoLength;
inf.Root.LConstraint = ePERSTIConstraint_Unconstrained;
inf.Root.LLowerVal = 0;
inf.Root.LUpperVal = 0;
inf.Root.LNBits = 0;
inf.Root.LAlignment = ePERSTIAlignment_OctetAligned;
/* set/clear missing bits in optional/default bit field */
GenFuncSequenceSetOptionals(ass, valref, components,
optionals, extensions, obuf, et);
/* emit/get extension bit if needed */
if (type->Flags & eTypeFlags_ExtensionMarker) {
switch (et) {
case eStringTable:
break;
case eEncode:
if (type->Flags & eTypeFlags_ExtensionMarker) {
if (!extensions) {
if (g_fCaseBasedOptimizer)
{
output("if (!ASN1PEREncExtensionBitClear(%s))\n", encref);
}
else
{
output("if (!ASN1PEREncBitVal(%s, 1, 0))\n", encref);
}
output("return 0;\n");
} else {
outputvar("ASN1uint32_t y;\n");
output("y = ASN1PEREncCheckExtensions(%d, %s + %d);\n",
extensions, strcmp(obuf, "o") ? obuf : "(val)->o", (optionals + 7) / 8);
output("if (!ASN1PEREncBitVal(%s, 1, y))\n",
encref);
output("return 0;\n");
}
}
break;
case eDecode:
if (type->Flags & eTypeFlags_ExtensionMarker) {
outputvar("ASN1uint32_t y;\n");
if (g_fCaseBasedOptimizer)
{
output("if (!ASN1PERDecExtensionBit(%s, &y))\n", encref);
}
else
{
output("if (!ASN1PERDecBit(%s, &y))\n", encref);
}
output("return 0;\n");
}
break;
}
}
/* emit/get bit field of optionals */
if (optionals) {
inf.Root.NBits = optionals;
inf.Root.Length = ePERSTILength_NoLength;
if (optionals >= 0x10000)
MyAbort();
GenPERFuncSimpleType(ass, &inf, obuf, et, encref);
}
/* emit components of extension root */
GenPERFuncComponents(ass, module, 0, components,
valref, encref, obuf, et, 0, 0);
/* handle extensions */
if (type->Flags & eTypeFlags_ExtensionMarker) {
conditional = 0;
if (!extensions) {
/* skip unknown extension bit field */
if (et == eDecode) {
output("if (y) {\n");
inf.Root.NBits = 1;
inf.Root.Length = ePERSTILength_SmallLength;
inf.Root.LConstraint = ePERSTIConstraint_Semiconstrained;
inf.Root.LLowerVal = 1;
if (g_fCaseBasedOptimizer)
{
output("if (!ASN1PERDecSkipNormallySmallExtensionFragmented(%s))\n",
encref);
output("return 0;\n");
output("}\n");
goto FinalTouch;
}
else
{
GenPERFuncSimpleType(ass, &inf, NULL, et, encref);
conditional = 1;
}
}
} else {
/* check if extension bit is set */
switch (et) {
case eStringTable:
break;
case eEncode:
output("if (y) {\n");
conditional = 1;
break;
case eDecode:
output("if (!y) {\n");
output("ZeroMemory(%s + %d, %d);\n", obuf,
(optionals + 7) / 8, (extensions + 7) / 8);
output("} else {\n");
conditional = 1;
break;
}
/* emit/get bit field of extensions */
inf.Root.NBits = extensions;
inf.Root.Length = ePERSTILength_SmallLength;
inf.Root.LConstraint = ePERSTIConstraint_Semiconstrained;
inf.Root.LLowerVal = 1;
sprintf(valbuf, "%s + %d", obuf, (optionals + 7) / 8);
GenPERFuncSimpleType(ass, &inf, valbuf, et, encref);
/* get start of extensions */
for (com = components; com; com = com->Next) {
if (com->Type == eComponent_ExtensionMarker) {
com = com->Next;
break;
}
}
/* emit components of extension */
GenPERFuncComponents(ass, module, (optionals + 7) & ~7, com,
valref, encref, obuf, et, 1, 0);
}
/* skip unknown extensions */
if (et == eDecode) {
outputvar("ASN1uint32_t i;\n");
outputvar("ASN1uint32_t e;\n");
output("for (i = 0; i < e; i++) {\n");
output("if (!ASN1PERDecSkipFragmented(%s, 8))\n",
encref);
output("return 0;\n");
output("}\n");
}
/* end of extension handling */
if (conditional)
output("}\n");
}
FinalTouch:
/* some user-friendly assignments for non-present optional/default */
/* components */
GenFuncSequenceSetDefaults(ass, valref, components, obuf, et);
}
/* generate function body for choice type */
void GenPERFuncChoiceType(AssignmentList_t ass, char *module, Assignment_t *at, char *valref, char *encref, TypeFunc_e et)
{
Type_t *type;
char valbuf[256];
uint32_t alternatives;
Component_t *components, *com;
int fOptimizeCase = 0;
/* get some informations */
type = at->U.Type.Type;
alternatives = type->U.SSC.Alternatives;
components = type->U.SSC.Components;
/* encode choice selector */
switch (et) {
case eStringTable:
sprintf(valbuf, "(%s)->choice", valref);
break;
case eEncode:
sprintf(valbuf, "(%s)->choice", valref);
if (g_fCaseBasedOptimizer)
{
switch (type->PERTypeInfo.Type)
{
case eExtension_Unconstrained:
break;
case eExtension_Unextended: // no extension mark at all
output("if (!ASN1PEREncSimpleChoice(%s, %s, %u))\n",
encref, valbuf, type->PERTypeInfo.Root.NBits);
output("return 0;\n");
fOptimizeCase = 1;
break;
case eExtension_Extendable: // extension mark exists, but no choice appears after the mark
output("if (!ASN1PEREncSimpleChoiceEx(%s, %s, %u))\n",
encref, valbuf, type->PERTypeInfo.Root.NBits);
output("return 0;\n");
fOptimizeCase = 1;
break;
case eExtension_Extended: // extension mark exists, but some choices appear after the mark
output("if (!ASN1PEREncComplexChoice(%s, %s, %u, %u))\n",
encref, valbuf, type->PERTypeInfo.Root.NBits, intx2uint32(&(type->PERTypeInfo.Additional.LowerVal)));
output("return 0;\n");
fOptimizeCase = 1;
break;
}
}
if (ASN1_CHOICE_BASE)
{
sprintf(valbuf, "(%s)->choice - %d", valref, ASN1_CHOICE_BASE);
}
break;
case eDecode:
sprintf(valbuf, "(%s)->choice", valref);
if (g_fCaseBasedOptimizer)
{
switch (type->PERTypeInfo.Type)
{
case eExtension_Unconstrained:
break;
case eExtension_Unextended: // no extension mark at all
output("if (!ASN1PERDecSimpleChoice(%s, %s, %u))\n",
encref, Reference(valbuf), type->PERTypeInfo.Root.NBits);
output("return 0;\n");
fOptimizeCase = 1;
break;
case eExtension_Extendable: // extension mark exists, but no choice appears after the mark
output("if (!ASN1PERDecSimpleChoiceEx(%s, %s, %u))\n",
encref, Reference(valbuf), type->PERTypeInfo.Root.NBits);
output("return 0;\n");
fOptimizeCase = 1;
break;
case eExtension_Extended: // extension mark exists, but some choices appear after the mark
output("if (!ASN1PERDecComplexChoice(%s, %s, %u, %u))\n",
encref, Reference(valbuf), type->PERTypeInfo.Root.NBits, intx2uint32(&(type->PERTypeInfo.Additional.LowerVal)));
output("return 0;\n");
fOptimizeCase = 1;
break;
}
}
break;
}
if (! fOptimizeCase)
{
if (eDecode == et)
{
output("%s = %d;\n", valbuf, ASN1_CHOICE_INVALID);
}
GenPERFuncSimpleType(ass, &type->PERTypeInfo, valbuf, et, encref);
// lonchanc: in case of decoding, we need to increment choice value
// by the amount of ASN1_CHOICE_BASE
if (et == eDecode && ASN1_CHOICE_BASE)
{
output("(%s)->choice += %d;\n", valref, ASN1_CHOICE_BASE);
}
}
/* finished if choice only contains NULL alternatives or if choice */
/* contains no data to free */
if (type->Flags & eTypeFlags_NullChoice)
return;
/* create switch statement */
switch (et) {
case eStringTable:
break;
case eDecode:
case eEncode:
output("switch ((%s)->choice) {\n", valref);
break;
}
/* generate components of extension root */
GenPERFuncComponents(ass, module, ASN1_CHOICE_BASE, components,
valref, encref, NULL, 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 */
GenPERFuncComponents(ass, module, ASN1_CHOICE_BASE + alternatives, com,
valref, encref, NULL, et, 1, 1);
/* skip unknown extensions */
if (et == eDecode && (type->Flags & eTypeFlags_ExtensionMarker)) {
output("case %d:\n\t/* extension case */\n", ASN1_CHOICE_INVALID + 1);
output("if (!ASN1PERDecSkipFragmented(%s, 8))\n", encref);
output("return 0;\n");
output("break;\n");
}
// debug purpose
switch (et)
{
case eEncode:
output("default:\n\t/* impossible */\n");
output("ASN1EncSetError(%s, ASN1_ERR_CHOICE);\n", encref);
output("return 0;\n");
break;
case eDecode:
output("default:\n\t/* impossible */\n");
output("ASN1DecSetError(%s, ASN1_ERR_CHOICE);\n", encref);
output("return 0;\n");
break;
}
/* end of switch statement */
switch (et) {
case eStringTable:
break;
case eEncode:
case eDecode:
output("}\n");
break;
}
}
/* generate function body for simple type */
void
GenPERFuncSimpleType(AssignmentList_t ass, PERTypeInfo_t *info, char *valref, TypeFunc_e et, char *encref)
{
switch (et) {
case eStringTable:
GenPERStringTableSimpleType(ass, info);
break;
case eEncode:
GenPEREncSimpleType(ass, info, valref, encref);
break;
case eDecode:
GenPERDecSimpleType(ass, info, valref, encref);
break;
}
}
/* generate string table for a simple type */
void
GenPERStringTableSimpleType(AssignmentList_t ass, PERTypeInfo_t *info)
{
ValueConstraint_t *pc;
uint32_t i, n, lo, up;
switch (info->Root.Data) {
case ePERSTIData_String:
case ePERSTIData_TableString:
case ePERSTIData_ZeroString:
case ePERSTIData_ZeroTableString:
if (info->Root.TableIdentifier) {
if (!strcmp(info->Root.TableIdentifier, "ASN1NumericStringTable"))
break;
output("static ASN1stringtableentry_t %sEntries[] = {\n",
info->Root.TableIdentifier);
i = n = 0;
for (pc = info->Root.Table; pc; pc = pc->Next) {
lo = GetValue(ass, pc->Lower.Value)->
U.RestrictedString.Value.value[0];
up = GetValue(ass, pc->Upper.Value)->
U.RestrictedString.Value.value[0];
output("{ %u, %u, %u }, ", lo, up, n);
n += (up - lo) + 1;
i++;
if ((i & 3) == 3 || !pc->Next)
output("\n");
}
output("};\n");
output("\n");
output("static ASN1stringtable_t %s = {\n",
info->Root.TableIdentifier);
output("%d, %sEntries\n", i, info->Root.TableIdentifier);
output("};\n");
output("\n");
}
break;
case ePERSTIData_SetOf:
case ePERSTIData_SequenceOf:
GenPERFuncSimpleType(ass, &info->Root.SubType->PERTypeInfo, "", eStringTable, "");
break;
}
}
/* generate encoding statements for a simple value */
void
GenPEREncSimpleType(AssignmentList_t ass, PERTypeInfo_t *info, char *valref, char *encref)
{
uint32_t i;
char lbbuf[256], ubbuf[256];
char *lenref;
char lenbuf[256], valbuf[256];
char *p;
PERTypeInfo_t inf;
inf = *info;
/* examine type for special handling */
switch (inf.Root.Data) {
case ePERSTIData_BitString:
case ePERSTIData_RZBBitString:
if (inf.Root.cbFixedSizeBitString)
{
sprintf(lenbuf, "%u", inf.Root.LUpperVal);
sprintf(valbuf, "&(%s)", valref);
lenref = lenbuf;
valref = valbuf;
break;
}
// lonchanc: intentionally fall through
case ePERSTIData_OctetString:
if (g_fCaseBasedOptimizer)
{
if (inf.Root.Data == ePERSTIData_OctetString && inf.Type == eExtension_Unextended)
{
switch (inf.Root.Length)
{
case ePERSTILength_NoLength:
if (inf.Root.LConstraint == ePERSTIConstraint_Constrained &&
inf.Root.LLowerVal == inf.Root.LUpperVal &&
inf.Root.LUpperVal < 64 * 1024)
{
// fixed size constraint, eg. OCTET STRING (SIZE (8))
if (inf.pPrivateDirectives->fLenPtr)
{
output("if (!ASN1PEREncOctetString_FixedSizeEx(%s, %s, %u))\n",
encref, Reference(valref), inf.Root.LLowerVal);
}
else
{
output("if (!ASN1PEREncOctetString_FixedSize(%s, (ASN1octetstring2_t *) %s, %u))\n",
encref, Reference(valref), inf.Root.LLowerVal);
}
output("return 0;\n");
return;
}
break;
case ePERSTILength_Length:
break;
case ePERSTILength_BitLength:
if (inf.Root.LConstraint == ePERSTIConstraint_Constrained &&
inf.Root.LLowerVal < inf.Root.LUpperVal &&
inf.Root.LUpperVal < 64 * 1024)
{
// variable size constraint, eg. OCTET STRING (SIZE (4..16))
if (inf.pPrivateDirectives->fLenPtr)
{
output("if (!ASN1PEREncOctetString_VarSizeEx(%s, %s, %u, %u, %u))\n",
encref, Reference(valref), inf.Root.LLowerVal, inf.Root.LUpperVal, inf.Root.LNBits);
}
else
{
output("if (!ASN1PEREncOctetString_VarSize(%s, (ASN1octetstring2_t *) %s, %u, %u, %u))\n",
encref, Reference(valref), inf.Root.LLowerVal, inf.Root.LUpperVal, inf.Root.LNBits);
}
output("return 0;\n");
return;
}
break;
case ePERSTILength_SmallLength:
break;
case ePERSTILength_InfiniteLength: // no size constraint, eg OCTET STRING
/* encode octet string in fragmented format */
output("if (!ASN1PEREncOctetString_NoSize(%s, %s))\n",
encref, Reference(valref));
output("return 0;\n");
return;
} // switch
} // if
}
/* length and value of bit string, octet string and string */
sprintf(lenbuf, "(%s).length", valref);
sprintf(valbuf, "(%s).value", valref);
lenref = lenbuf;
valref = valbuf;
break;
case ePERSTIData_UTF8String:
/* length and value of bit string, octet string and string */
sprintf(lenbuf, "(%s).length", valref);
sprintf(valbuf, "(%s).value", valref);
lenref = lenbuf;
valref = valbuf;
break;
case ePERSTIData_String:
case ePERSTIData_TableString:
/* length and value of bit string, octet string and string */
sprintf(lenbuf, "(%s).length", valref);
sprintf(valbuf, "(%s).value", valref);
lenref = lenbuf;
valref = valbuf;
break;
case ePERSTIData_SequenceOf:
case ePERSTIData_SetOf:
if (inf.Rules & eTypeRules_PointerArrayMask)
{
/* length and value of sequence of/set of value with */
/* length-pointer representation */
if (inf.Rules & eTypeRules_PointerToElement)
{
sprintf(lenbuf, "(%s)->count", valref);
sprintf(valbuf, "(%s)->%s", valref, GetPrivateValueName(inf.pPrivateDirectives, "value"));
}
else
{
sprintf(lenbuf, "(%s)->count", Reference(valref));
sprintf(valbuf, "(%s)->%s", Reference(valref), GetPrivateValueName(inf.pPrivateDirectives, "value"));
}
lenref = lenbuf;
valref = valbuf;
}
else
if (inf.Rules & eTypeRules_LinkedListMask)
{
/* use a loop for sequence of/set of value with */
/* list representation */
if (g_fCaseBasedOptimizer)
{
if (PerOptCase_IsTargetSeqOf(&inf))
{
// generate the iterator
char szElmFn[128];
char szElmFnDecl[256];
sprintf(szElmFn, "ASN1Enc_%s_ElmFn", inf.Identifier);
sprintf(szElmFnDecl, "int ASN1CALL %s(ASN1encoding_t %s, P%s val)",
szElmFn, encref, inf.Identifier);
setoutfile(g_finc);
output("extern %s;\n", szElmFnDecl);
setoutfile(g_fout);
if ((inf.Root.LLowerVal == 0 && inf.Root.LUpperVal == 0) ||
(inf.Root.LUpperVal >= 64 * 1024)
)
{
output("return ASN1PEREncSeqOf_NoSize(%s, (ASN1iterator_t **) %s, (ASN1iterator_encfn) %s);\n",
encref, Reference(valref), szElmFn);
}
else
{
if (inf.Root.LLowerVal == inf.Root.LUpperVal)
MyAbort();
output("return ASN1PEREncSeqOf_VarSize(%s, (ASN1iterator_t **) %s, (ASN1iterator_encfn) %s, %u, %u, %u);\n",
encref, Reference(valref), szElmFn,
inf.Root.LLowerVal, inf.Root.LUpperVal, inf.Root.LNBits);
}
output("}\n\n"); // end of iterator body
// generate the element function
output("static %s\n", szElmFnDecl);
output("{\n");
sprintf(valbuf, "val->%s", GetPrivateValueName(inf.pPrivateDirectives, "value"));
GenPERFuncSimpleType(ass, &inf.Root.SubType->PERTypeInfo, valbuf,
eEncode, encref);
// end of element body
return;
}
}
outputvar("ASN1uint32_t t;\n");
outputvar("P%s f;\n", inf.Identifier);
output("for (t = 0, f = %s; f; f = f->next)\n", valref);
output("t++;\n");
lenref = "t";
} else {
MyAbort();
}
break;
case ePERSTIData_ZeroString:
case ePERSTIData_ZeroTableString:
/* length of a zero-terminated string value */
outputvar("ASN1uint32_t t;\n");
output("t = lstrlenA(%s);\n", valref);
lenref = "t";
break;
case ePERSTIData_Boolean:
/* value of a boolean value */
if (g_fCaseBasedOptimizer)
{
if (PerOptCase_IsBoolean(&inf.Root))
{
lenref = NULL;
break;
}
}
sprintf(valbuf, "(%s) ? 1 : 0", valref);
valref = valbuf;
lenref = NULL;
inf.Root.Data = ePERSTIData_Unsigned;
break;
default:
/* other values have no additional length */
lenref = NULL;
break;
}
/* map enumeration values */
if (inf.EnumerationValues) {
outputvar("ASN1uint32_t u;\n");
output("switch (%s) {\n", valref);
for (i = 0; inf.EnumerationValues[i]; i++) {
output("case %u:\n", intx2uint32(inf.EnumerationValues[i]));
output("u = %u;\n", i);
output("break;\n");
}
output("}\n");
valref = "u";
inf.NOctets = 4;
}
/* check for extended values */
if (inf.Type == eExtension_Extended) {
switch (inf.Root.Data) {
case ePERSTIData_Integer:
case ePERSTIData_Unsigned:
switch (inf.Root.Constraint) {
case ePERSTIConstraint_Unconstrained:
inf.Type = eExtension_Extendable;
break;
case ePERSTIConstraint_Semiconstrained:
if (inf.NOctets == 0) {
sprintf(lbbuf, "%s_lb", inf.Identifier);
outputvarintx(lbbuf, &inf.Root.LowerVal);
output("if (ASN1intx_cmp(%s, &%s) >= 0) {\n",
Reference(valref), lbbuf);
} else if (inf.Root.Data == ePERSTIData_Integer) {
output("if (%s >= %d) {\n",
valref, intx2int32(&inf.Root.LowerVal));
} else {
if (intx2uint32(&inf.Root.LowerVal) > 0) {
output("if (%s >= %u) {\n",
valref, intx2uint32(&inf.Root.LowerVal));
} else {
inf.Type = eExtension_Extendable;
}
}
break;
case ePERSTIConstraint_Upperconstrained:
if (inf.NOctets == 0) {
sprintf(ubbuf, "%s_ub", inf.Identifier);
outputvarintx(ubbuf, &inf.Root.UpperVal);
output("if (ASN1intx_cmp(%s, &%s) <= 0) {\n",
Reference(valref), ubbuf);
} else if (inf.Root.Data == ePERSTIData_Integer) {
output("if (%s <= %d) {\n",
valref, intx2int32(&inf.Root.UpperVal));
} else {
output("if (%s <= %u) {\n",
valref, intx2uint32(&inf.Root.UpperVal));
}
break;
case ePERSTIConstraint_Constrained:
if (inf.NOctets == 0) {
sprintf(lbbuf, "%s_lb", inf.Identifier);
sprintf(ubbuf, "%s_ub", inf.Identifier);
outputvarintx(lbbuf, &inf.Root.LowerVal);
outputvarintx(ubbuf, &inf.Root.UpperVal);
output("if (ASN1intx_cmp(%s, &%s) >= 0 && ASN1intx_cmp(%s, &%s) <= 0) {\n",
Reference(valref), lbbuf, Reference(valref), ubbuf);
} else if (inf.Root.Data == ePERSTIData_Integer) {
output("if (%s >= %d && %s <= %d) {\n",
valref, intx2int32(&inf.Root.LowerVal),
valref, intx2int32(&inf.Root.UpperVal));
} else {
if (intx2uint32(&inf.Root.LowerVal) > 0) {
output("if (%s >= %u && %s <= %u) {\n",
valref, intx2uint32(&inf.Root.LowerVal),
valref, intx2uint32(&inf.Root.UpperVal));
} else {
output("if (%s <= %u) {\n",
valref, intx2uint32(&inf.Root.UpperVal));
}
}
break;
}
break;
case ePERSTIData_SequenceOf:
case ePERSTIData_SetOf:
case ePERSTIData_OctetString:
case ePERSTIData_UTF8String:
case ePERSTIData_BitString:
case ePERSTIData_RZBBitString:
case ePERSTIData_Extension:
switch (inf.Root.LConstraint) {
case ePERSTIConstraint_Semiconstrained:
if (inf.Root.LLowerVal != 0) {
output("if (%s >= %u) {\n",
lenref, inf.Root.LLowerVal);
} else {
inf.Type = eExtension_Extendable;
}
break;
case ePERSTIConstraint_Constrained:
if (inf.Root.LLowerVal != 0) {
output("if (%s >= %u && %s <= %u) {\n",
lenref, inf.Root.LLowerVal, lenref, inf.Root.LUpperVal);
} else {
output("if (%s <= %u) {\n",
lenref, inf.Root.LUpperVal);
}
break;
}
break;
case ePERSTIData_String:
case ePERSTIData_TableString:
case ePERSTIData_ZeroString:
case ePERSTIData_ZeroTableString:
inf.Type = eExtension_Extendable;
switch (inf.Root.LConstraint) {
case ePERSTIConstraint_Semiconstrained:
if (inf.Root.LLowerVal != 0) {
output("if (%s >= %u",
lenref, inf.Root.LLowerVal);
inf.Type = eExtension_Extended;
}
break;
case ePERSTIConstraint_Constrained:
output("if (%s >= %u && %s <= %u",
lenref, inf.Root.LLowerVal, lenref, inf.Root.LUpperVal);
inf.Type = eExtension_Extended;
break;
}
if (inf.Root.TableIdentifier) {
if (inf.Type == eExtension_Extended)
output(" && ");
else
output("if (");
if (inf.NOctets == 1) {
p = "Char";
} else if (inf.NOctets == 2) {
p = "Char16";
} else if (inf.NOctets == 4) {
p = "Char32";
} else
MyAbort();
output("ASN1PEREncCheckTable%sString(%s, %s, %s)",
p, lenref, valref, Reference(inf.Root.TableIdentifier));
inf.Type = eExtension_Extended;
}
if (inf.Type == eExtension_Extended)
output(") {\n");
break;
}
}
/* encode unset extension bit */
if (inf.Type > eExtension_Unextended) {
if (g_fCaseBasedOptimizer)
{
output("if (!ASN1PEREncExtensionBitClear(%s))\n", encref);
}
else
{
output("if (!ASN1PEREncBitVal(%s, 1, 0))\n", encref);
}
output("return 0;\n");
}
/* encode unextended value (of extension root) */
GenPEREncGenericUnextended(ass, &inf, &inf.Root, valref, lenref, encref);
/* type is extended? */
if (inf.Type == eExtension_Extended) {
output("} else {\n");
/* encode set extension bit */
if (g_fCaseBasedOptimizer)
{
output("if (!ASN1PEREncExtensionBitSet(%s))\n", encref);
}
else
{
output("if (!ASN1PEREncBitVal(%s, 1, 1))\n", encref);
}
output("return 0;\n");
/* encode extended value (of extension addition) */
GenPEREncGenericUnextended(ass, &inf, &inf.Additional, valref, lenref, encref);
output("}\n");
}
}
/* generate encoding statements for a simple value (after some special */
/* handling has been done, esp. the evaluation of the extension) */
void GenPEREncGenericUnextended(AssignmentList_t ass, PERTypeInfo_t *info, PERSimpleTypeInfo_t *sinfo, char *valref, char *lenref, char *encref)
{
char valbuf[256];
char *lvref, lvbuf[256];
char lbbuf[256];
char *p;
/* check for empty field */
if (sinfo->NBits == 0)
return;
/* initial calculations for value encoding: */
/* substract lower bound of constraint/semiconstraint value */
/* for Integer and NormallySmall */
switch (sinfo->Constraint) {
case ePERSTIConstraint_Semiconstrained:
case ePERSTIConstraint_Constrained:
switch (sinfo->Data) {
case ePERSTIData_Integer:
case ePERSTIData_Unsigned:
case ePERSTIData_NormallySmall:
if (!info->NOctets) {
/* calculate value-lowerbound for intx_t values */
if (intx_cmp(&sinfo->LowerVal, &intx_0) != 0) {
sprintf(lbbuf, "%s_lb", info->Identifier);
outputvar("ASN1intx_t newval;\n");
outputvarintx(lbbuf, &sinfo->LowerVal);
output("ASN1intx_sub(&newval, %s, &%s);\n",
Reference(valref), lbbuf);
valref = "newval";
}
} else if (sinfo->Data == ePERSTIData_Integer) {
/* calculate value-lowerbound for intx_t values */
if (intx_cmp(&sinfo->LowerVal, &intx_0)) {
char szLowB[24];
sprintf(&szLowB[0], "%d", intx2int32(&sinfo->LowerVal));
if (szLowB[0] == '-')
sprintf(valbuf, "%s + %s", valref, &szLowB[1]); // minus minus become plus
else
sprintf(valbuf, "%s - %s", valref, &szLowB[0]);
valref = valbuf;
}
} else {
/* calculate value-lowerbound for integer values */
if (intx_cmp(&sinfo->LowerVal, &intx_0)) {
sprintf(valbuf, "%s - %u", valref, intx2uint32(&sinfo->LowerVal));
valref = valbuf;
}
}
/* semiconstraint/constraint values will be encoded as unsigned */
if (sinfo->Data == ePERSTIData_Integer)
sinfo->Data = ePERSTIData_Unsigned;
break;
}
break;
}
/* general rules */
if (sinfo->LAlignment == ePERSTIAlignment_OctetAligned &&
sinfo->Length == ePERSTILength_BitLength &&
!(sinfo->LNBits & 7))
sinfo->Alignment = ePERSTIAlignment_BitAligned;
/* octet alignment will be given by length */
if (sinfo->Length == ePERSTILength_InfiniteLength &&
(sinfo->Data == ePERSTIData_Integer && info->NOctets == 0 ||
sinfo->Data == ePERSTIData_Unsigned && info->NOctets == 0 ||
sinfo->Data == ePERSTIData_BitString ||
sinfo->Data == ePERSTIData_RZBBitString ||
sinfo->Data == ePERSTIData_Extension ||
sinfo->Data == ePERSTIData_OctetString ||
sinfo->Data == ePERSTIData_UTF8String ||
sinfo->Data == ePERSTIData_SequenceOf ||
sinfo->Data == ePERSTIData_SetOf ||
sinfo->Data == ePERSTIData_String ||
sinfo->Data == ePERSTIData_TableString ||
sinfo->Data == ePERSTIData_ZeroString ||
sinfo->Data == ePERSTIData_ZeroTableString) ||
sinfo->Data == ePERSTIData_ObjectIdentifier ||
sinfo->Data == ePERSTIData_Real ||
sinfo->Data == ePERSTIData_GeneralizedTime ||
sinfo->Data == ePERSTIData_UTCTime ||
sinfo->Data == ePERSTIData_External ||
sinfo->Data == ePERSTIData_EmbeddedPdv ||
sinfo->Data == ePERSTIData_MultibyteString ||
sinfo->Data == ePERSTIData_UnrestrictedString ||
sinfo->Data == ePERSTIData_Open)
sinfo->LAlignment = sinfo->Alignment = ePERSTIAlignment_BitAligned;
/* alignment will be done by encoding fn */
if (sinfo->Length == ePERSTILength_NoLength ||
sinfo->Length == ePERSTILength_SmallLength)
sinfo->LAlignment = ePERSTIAlignment_BitAligned;
/* no alignment of no/small length */
/* special initial calculations */
switch (sinfo->Data) {
case ePERSTIData_RZBBitString:
/* remove trailing zero-bits */
outputvar("ASN1uint32_t r;\n");
output("r = %s;\n", lenref);
output("ASN1PEREncRemoveZeroBits(&r, %s, %u);\n",
valref, sinfo->LLowerVal);
if (sinfo->LLowerVal) {
outputvar("ASN1uint32_t s;\n");
output("s = r < %u ? %u : r;\n", sinfo->LLowerVal, sinfo->LLowerVal);
lenref = "s";
} else {
lenref = "r";
}
break;
}
if (g_fCaseBasedOptimizer)
{
// lonchanc: special handling for macro operations
if (PerOptCase_IsSignedInteger(sinfo))
{
output("if (!ASN1PEREncInteger(%s, %s))\n", encref, valref);
output("return 0;\n");
return;
}
if (PerOptCase_IsUnsignedInteger(sinfo))
{
output("if (!ASN1PEREncUnsignedInteger(%s, %s))\n", encref, valref);
output("return 0;\n");
return;
}
if (PerOptCase_IsUnsignedShort(sinfo))
{
output("if (!ASN1PEREncUnsignedShort(%s, %s))\n", encref, valref);
output("return 0;\n");
return;
}
if (PerOptCase_IsBoolean(sinfo))
{
output("if (!ASN1PEREncBoolean(%s, %s))\n", encref, valref);
output("return 0;\n");
return;
}
}
/* initial calculations for length: */
/* get length of integer numbers if length req. */
switch (sinfo->Length) {
case ePERSTILength_BitLength:
case ePERSTILength_InfiniteLength:
switch (sinfo->Constraint) {
case ePERSTIConstraint_Unconstrained:
case ePERSTIConstraint_Upperconstrained:
switch (sinfo->Data) {
case ePERSTIData_Integer:
case ePERSTIData_Unsigned:
if (info->NOctets != 0) {
outputvar("ASN1uint32_t l;\n");
if (sinfo->Data == ePERSTIData_Integer)
output("l = ASN1int32_octets(%s);\n", valref);
else
output("l = ASN1uint32_octets(%s);\n", valref);
lenref = "l";
} else {
if (sinfo->Length != ePERSTILength_InfiniteLength) {
outputvar("ASN1uint32_t l;\n");
output("l = ASN1intx_octets(%s);\n",
Reference(valref));
lenref = "l";
}
}
break;
}
break;
case ePERSTIConstraint_Semiconstrained:
case ePERSTIConstraint_Constrained:
switch (sinfo->Data) {
case ePERSTIData_Integer:
case ePERSTIData_Unsigned:
if (info->NOctets != 0) {
outputvar("ASN1uint32_t l;\n");
output("l = ASN1uint32_uoctets(%s);\n", valref);
lenref = "l";
} else {
if (sinfo->Length != ePERSTILength_InfiniteLength) {
outputvar("ASN1uint32_t l;\n");
output("l = ASN1intx_uoctets(%s);\n",
Reference(valref));
lenref = "l";
}
}
break;
}
break;
}
break;
}
/* initial settings for length enconding: */
/* substract lower bound of length from length */
if (sinfo->LLowerVal != 0 && lenref) {
sprintf(lvbuf, "%s - %u", lenref, sinfo->LLowerVal);
lvref = lvbuf;
} else {
lvref = lenref;
}
/* length encoding */
if (sinfo->LAlignment == ePERSTIAlignment_OctetAligned) {
output("ASN1PEREncAlignment(%s);\n", encref);
}
switch (sinfo->Length) {
case ePERSTILength_NoLength:
/* not length used */
break;
case ePERSTILength_BitLength:
/* length will be encoded in a bit field */
output("if (!ASN1PEREncBitVal(%s, %u, %s))\n",
encref, sinfo->LNBits, lvref);
output("return 0;\n");
break;
case ePERSTILength_InfiniteLength:
/* infinite length case: encode length only for integer values, */
/* other length encodings will be the encoding function */
switch (sinfo->Data) {
case ePERSTIData_Integer:
case ePERSTIData_Unsigned:
if (info->NOctets != 0) {
output("if (!ASN1PEREncBitVal(%s, 8, %s))\n",
encref, lvref);
output("return 0;\n");
}
break;
}
break;
}
/* special initial calculations */
switch (sinfo->Data) {
case ePERSTIData_RZBBitString:
/* real length of the bit string */
lenref = "r";
break;
}
/* value encoding */
switch (sinfo->Length) {
case ePERSTILength_NoLength:
/* encode alignment of the value */
if (sinfo->Alignment == ePERSTIAlignment_OctetAligned) {
output("ASN1PEREncAlignment(%s);\n", encref);
}
switch (sinfo->Data) {
case ePERSTIData_Integer:
case ePERSTIData_Unsigned:
/* encode the value as bit field */
if (info->NOctets != 0) {
output("if (!ASN1PEREncBitVal(%s, %u, %s))\n",
encref, sinfo->NBits, valref);
output("return 0;\n");
} else {
output("if (!ASN1PEREncBitIntx(%s, %u, %s))\n",
encref, sinfo->NBits, Reference(valref));
output("return 0;\n");
}
break;
case ePERSTIData_NormallySmall:
/* encode the value as normally small number */
output("if (!ASN1PEREncNormallySmall(%s, %s))\n",
encref, valref);
output("return 0;\n");
break;
case ePERSTIData_BitString:
case ePERSTIData_RZBBitString:
/* encode bit string in a bit field */
output("if (!ASN1PEREncBits(%s, %s, %s))\n",
encref, lenref, valref);
output("return 0;\n");
break;
case ePERSTIData_OctetString:
/* encode octet string in a bit field */
output("if (!ASN1PEREncBits(%s, %s * 8, %s))\n",
encref, lenref, valref);
output("return 0;\n");
break;
case ePERSTIData_UTF8String:
/* encode octet string in a bit field */
output("if (!ASN1PEREncUTF8String(%s, %s, %s))\n",
encref, lenref, valref);
output("return 0;\n");
break;
case ePERSTIData_Extension:
/* encode extension bits in a bit field */
output("if (!ASN1PEREncBits(%s, %u, %s))\n",
encref, sinfo->NBits, valref);
output("return 0;\n");
break;
case ePERSTIData_SetOf:
/* same as BitLength encoding */
goto SetOfEncoding;
case ePERSTIData_SequenceOf:
/* same as BitLength encoding */
goto SequenceOfEncoding;
case ePERSTIData_String:
case ePERSTIData_ZeroString:
/* same as BitLength encoding */
goto StringEncoding;
case ePERSTIData_TableString:
case ePERSTIData_ZeroTableString:
/* same as BitLength encoding */
goto TableStringEncoding;
case ePERSTIData_Reference:
/* call encoding function of referenced type */
output("if (!ASN1Enc_%s(%s, %s))\n",
Identifier2C(sinfo->SubIdentifier),
encref, Reference(valref));
output("return 0;\n");
break;
case ePERSTIData_Real:
/* encode real value */
if (info->NOctets)
output("if (!ASN1PEREncDouble(%s, %s))\n",
encref, valref);
else
output("if (!ASN1PEREncReal(%s, %s))\n",
encref, Reference(valref));
output("return 0;\n");
break;
case ePERSTIData_GeneralizedTime:
/* encode generalized time value */
output("if (!ASN1PEREncGeneralizedTime(%s, %s, %d))\n",
encref, Reference(valref), sinfo->NBits);
output("return 0;\n");
break;
case ePERSTIData_UTCTime:
/* encode utc time value */
output("if (!ASN1PEREncUTCTime(%s, %s, %d))\n",
encref, Reference(valref), sinfo->NBits);
output("return 0;\n");
break;
}
break;
case ePERSTILength_BitLength:
/* encode alignment of the value */
if (sinfo->Alignment == ePERSTIAlignment_OctetAligned) {
output("ASN1PEREncAlignment(%s);\n", encref);
}
switch (sinfo->Data) {
case ePERSTIData_Integer:
case ePERSTIData_Unsigned:
/* encode the value as bit field */
if (info->NOctets != 0) {
output("if (!ASN1PEREncBitVal(%s, %s * 8, %s))\n",
encref, lenref, valref);
output("return 0;\n");
} else {
output("if (!ASN1PEREncBitIntx(%s, %s * 8, %s))\n",
encref, lenref, Reference(valref));
output("return 0;\n");
}
break;
case ePERSTIData_BitString:
case ePERSTIData_RZBBitString:
/* encode the value as bit field */
output("if (!ASN1PEREncBits(%s, %s, %s))\n",
encref, lenref, valref);
output("return 0;\n");
break;
case ePERSTIData_OctetString:
/* encode the value as bit field */
output("if (!ASN1PEREncBits(%s, %s * 8, %s))\n",
encref, lenref, valref);
output("return 0;\n");
break;
case ePERSTIData_UTF8String:
/* encode the value as bit field */
output("if (!ASN1PEREncUTF8String(%s, %s, %s))\n",
encref, lenref, valref);
output("return 0;\n");
break;
case ePERSTIData_SetOf:
SetOfEncoding:
/* skip null set of */
if (sinfo->SubType->Flags & eTypeFlags_Null)
break;
/* canonical PER? */
if (g_eSubEncodingRule == eSubEncoding_Canonical) {
/* encode the elements one by one and sort them */
outputvar("ASN1uint32_t i;\n");
outputvar("ASN1encoding_t e, *p;\n");
if (info->Rules &
(eTypeRules_SinglyLinkedList | eTypeRules_DoublyLinkedList))
MyAbort(); /*XXX*/
output("if (%s) {\n", lenref);
output("e = p = (ASN1encoding_t)malloc(%s * sizeof(ASN1encoding_t));\n",
lenref);
output("ZeroMemory(b, %s * sizeof(ASN1encoding_t));\n", lenref);
output("for (i = 0; i < %s; i++, p++) {\n", lenref);
sprintf(valbuf, "(%s)[i]", valref);
GenPERFuncSimpleType(ass, &sinfo->SubType->PERTypeInfo, valbuf, eEncode, encref);
output("}\n");
output("qsort(e, %s, sizeof(ASN1encoding_t), ASN1PEREncCmpEncodings);\n",
lenref);
output("}\n");
/* then dump them */
output("for (p = e, i = 0; i < %s; i++, p++) {\n", lenref);
output("if (!ASN1PEREncBits(%s, (p->pos - p->buf) * 8 + p->bit, p->buf))\n",
encref);
output("return 0;\n");
output("}\n");
break;
}
/* again in non-canonical PER: */
/*FALLTHROUGH*/
case ePERSTIData_SequenceOf:
SequenceOfEncoding:
/* skip null sequence of */
if (sinfo->SubType->Flags & eTypeFlags_Null)
break;
if (info->Rules & eTypeRules_PointerArrayMask)
{
/* loop over all elements */
outputvar("ASN1uint32_t i;\n");
output("for (i = 0; i < %s; i++) {\n", lenref);
sprintf(valbuf, "(%s)[i]", valref);
}
else
if (info->Rules & eTypeRules_LinkedListMask)
{
/* iterate over all elements */
outputvar("P%s f;\n", info->Identifier);
output("for (f = %s; f; f = f->next) {\n", valref);
sprintf(valbuf, "f->%s", GetPrivateValueName(info->pPrivateDirectives, "value"));
}
/* encode the element */
GenPERFuncSimpleType(ass, &sinfo->SubType->PERTypeInfo, valbuf,
eEncode, encref);
/* loop end */
output("}\n");
break;
case ePERSTIData_String:
case ePERSTIData_ZeroString:
StringEncoding:
/* encode string value */
if (info->NOctets == 1) {
p = "Char";
} else if (info->NOctets == 2) {
p = "Char16";
} else if (info->NOctets == 4) {
p = "Char32";
} else
MyAbort();
output("if (!ASN1PEREnc%sString(%s, %s, %s, %u))\n",
p, encref, lenref, valref, sinfo->NBits);
output("return 0;\n");
break;
case ePERSTIData_TableString:
case ePERSTIData_ZeroTableString:
TableStringEncoding:
/* encode table string value */
if (info->NOctets == 1) {
p = "Char";
} else if (info->NOctets == 2) {
p = "Char16";
} else if (info->NOctets == 4) {
p = "Char32";
} else
MyAbort();
output("if (!ASN1PEREncTable%sString(%s, %s, %s, %u, %s))\n",
p, encref, lenref, valref, sinfo->NBits, Reference(sinfo->TableIdentifier));
output("return 0;\n");
break;
}
break;
case ePERSTILength_InfiniteLength:
/* infinite length case */
switch (sinfo->Data) {
case ePERSTIData_Integer:
case ePERSTIData_Unsigned:
/* encode an integer in fragmented format */
if (info->NOctets != 0) {
output("if (!ASN1PEREncBitVal(%s, %s * 8, %s))\n",
encref, lenref, valref);
output("return 0;\n");
} else {
if (sinfo->Data == ePERSTIData_Integer) {
output("if (!ASN1PEREncFragmentedIntx(%s, %s))\n",
encref, Reference(valref));
output("return 0;\n");
} else {
output("if (!ASN1PEREncFragmentedUIntx(%s, %s))\n",
encref, Reference(valref));
output("return 0;\n");
}
}
break;
case ePERSTIData_BitString:
case ePERSTIData_RZBBitString:
/* encode bit string in fragmented format */
output("if (!ASN1PEREncFragmented(%s, %s, %s, 1))\n",
encref, lenref, valref);
output("return 0;\n");
break;
case ePERSTIData_OctetString:
/* encode octet string in fragmented format */
output("if (!ASN1PEREncFragmented(%s, %s, %s, 8))\n",
encref, lenref, valref);
output("return 0;\n");
break;
case ePERSTIData_UTF8String:
/* encode octet string in fragmented format */
output("if (!ASN1PEREncUTF8String(%s, %s, %s))\n",
encref, lenref, valref);
output("return 0;\n");
break;
case ePERSTIData_Extension:
/* encode extension bits in fragmented format */
output("if (!ASN1PEREncFragmented(%s, %u, %s, 1))\n",
encref, sinfo->NBits, valref);
output("return 0;\n");
break;
case ePERSTIData_SetOf:
/* skip null set of */
if (sinfo->SubType->Flags & eTypeFlags_Null)
break;
/* canonical PER? */
if (g_eSubEncodingRule == eSubEncoding_Canonical) {
/* encode the elements one by one and sort them */
outputvar("ASN1uint32_t i;\n");
outputvar("ASN1uint32_t j, n = 0x4000;\n");
outputvar("ASN1encoding_t e, *p;\n");
if (info->Rules &
(eTypeRules_SinglyLinkedList | eTypeRules_DoublyLinkedList))
MyAbort(); /*XXX*/
output("if (%s) {\n", lenref);
output("e = p = (ASN1encoding_t)malloc(%s * sizeof(ASN1encoding_t));\n",
lenref);
output("ZeroMemory(b, %s * sizeof(ASN1encoding_t));\n", lenref);
output("for (i = 0; i < %s; i++, p++) {\n", lenref);
sprintf(valbuf, "(%s)[i]", valref);
GenPERFuncSimpleType(ass, &sinfo->SubType->PERTypeInfo, valbuf, eEncode, encref);
output("}\n");
output("qsort(e, %s, sizeof(ASN1encoding_t), ASN1PEREncCmpEncodings);\n",
lenref);
output("}\n");
/* then dump them */
output("for (p = e, i = 0; i < %s; i += n) {\n", lenref);
output("if (!ASN1PEREncFragmentedLength(&n, %s, %s - i))\n",
encref, lenref);
output("return 0;\n");
output("for (j = 0; j < n; p++, j++) {\n");
output("if (!ASN1PEREncBits(%s, (p->pos - p->buf) * 8 + p->bit, p->buf))\n",
encref);
output("return 0;\n");
output("}\n");
output("}\n");
output("}\n");
output("if (n >= 0x4000) {\n");
output("if (!ASN1PEREncFragmentedLength(&n, %s, 0))\n",
encref);
output("return 0;\n");
output("}\n");
break;
}
/* again in non-canonical PER: */
/*FALLTHROUGH*/
case ePERSTIData_SequenceOf:
/* skip null sequence of */
if (sinfo->SubType->Flags & eTypeFlags_Null)
break;
outputvar("ASN1uint32_t i;\n");
outputvar("ASN1uint32_t j, n = 0x4000;\n");
if (info->Rules &
(eTypeRules_SinglyLinkedList | eTypeRules_DoublyLinkedList)) {
/* additional iterator needed */
outputvar("P%s f;\n", info->Identifier);
output("f = %s;\n", valref);
}
/* encode all elements */
output("for (i = 0; i < %s;) {\n", lenref);
/* encode fragmented length */
output("if (!ASN1PEREncFragmentedLength(&n, %s, %s - i))\n",
encref, lenref);
output("return 0;\n");
/* encode elements of the fragment */
output("for (j = 0; j < n; i++, j++) {\n");
if (info->Rules & eTypeRules_PointerArrayMask)
{
sprintf(valbuf, "(%s)[i]", valref);
}
else if (info->Rules & eTypeRules_LinkedListMask)
{
sprintf(valbuf, "f->%s", GetPrivateValueName(info->pPrivateDirectives, "value"));
}
else
{
MyAbort();
}
GenPERFuncSimpleType(ass, &sinfo->SubType->PERTypeInfo, valbuf,
eEncode, encref);
/* advance the iterator */
if (info->Rules & eTypeRules_LinkedListMask)
{
output("f = f->next;\n");
}
/* end of inner loop */
output("}\n");
/* end of outer loop */
output("}\n");
/* add an zero-sized fragment if needed */
output("if (n >= 0x4000) {\n");
output("if (!ASN1PEREncFragmentedLength(&n, %s, 0))\n",
encref);
output("return 0;\n");
output("}\n");
break;
case ePERSTIData_ObjectIdentifier:
if (info->pPrivateDirectives->fOidArray || g_fOidArray)
{
/* encode object identifier value */
output("if (!ASN1PEREncObjectIdentifier2(%s, %s))\n",
encref, Reference(valref));
}
else
{
/* encode object identifier value */
output("if (!ASN1PEREncObjectIdentifier(%s, %s))\n",
encref, Reference(valref));
}
output("return 0;\n");
break;
case ePERSTIData_External:
/* encode external value */
output("if (!ASN1PEREncExternal(%s, %s))\n",
encref, Reference(valref));
output("return 0;\n");
break;
case ePERSTIData_EmbeddedPdv:
/* encode embedded pdv value */
if (sinfo->Identification) {
output("if (!ASN1PEREncEmbeddedPdvOpt(%s, %s))\n",
encref, Reference(valref));
} else {
output("if (!ASN1PEREncEmbeddedPdv(%s, %s))\n",
encref, Reference(valref));
}
output("return 0;\n");
break;
case ePERSTIData_MultibyteString:
/* encode multibyte string value */
output("if (!ASN1PEREncMultibyteString(%s, %s))\n",
encref, valref);
output("return 0;\n");
break;
case ePERSTIData_UnrestrictedString:
/* encode character string value */
if (sinfo->Identification) {
output("if (!ASN1PEREncCharacterStringOpt(%s, %s))\n",
encref, Reference(valref));
} else {
output("if (!ASN1PEREncCharacterString(%s, %s))\n",
encref, Reference(valref));
}
output("return 0;\n");
break;
case ePERSTIData_String:
case ePERSTIData_ZeroString:
/* encode string value */
if (info->NOctets == 1) {
p = "Char";
} else if (info->NOctets == 2) {
p = "Char16";
} else if (info->NOctets == 4) {
p = "Char32";
} else
MyAbort();
output("if (!ASN1PEREncFragmented%sString(%s, %s, %s, %u))\n",
p, encref, lenref, valref, sinfo->NBits);
output("return 0;\n");
break;
case ePERSTIData_TableString:
case ePERSTIData_ZeroTableString:
/* encode table string value */
if (info->NOctets == 1) {
p = "Char";
} else if (info->NOctets == 2) {
p = "Char16";
} else if (info->NOctets == 4) {
p = "Char32";
} else
MyAbort();
output("if (!ASN1PEREncFragmentedTable%sString(%s, %s, %s, %u, %s))\n",
p, encref, lenref, valref, sinfo->NBits, Reference(sinfo->TableIdentifier));
output("return 0;\n");
break;
case ePERSTIData_Open:
/* encode open type value */
output("if (!ASN1PEREncOpenType(%s, %s))\n",
encref, Reference(valref));
output("return 0;\n");
break;
}
break;
case ePERSTILength_SmallLength:
/* small length */
switch (sinfo->Data) {
case ePERSTIData_Extension:
/* encode extension bits with normally small length */
output("if (!ASN1PEREncNormallySmallBits(%s, %u, %s))\n",
encref, sinfo->NBits, valref);
output("return 0;\n");
break;
}
}
switch (sinfo->Data) {
case ePERSTIData_RZBBitString:
/* encode additional zero bits for remove zero bits bit string */
/* of short length */
if (sinfo->LLowerVal) {
output("if (%s < %u) {\n", lenref, sinfo->LLowerVal);
output("if (!ASN1PEREncZero(%s, %u - %s))\n",
encref, sinfo->LLowerVal, lenref);
output("return 0;\n");
output("}\n");
}
}
/* free calculated intx_t value */
switch (sinfo->Constraint) {
case ePERSTIConstraint_Semiconstrained:
case ePERSTIConstraint_Constrained:
switch (sinfo->Data) {
case ePERSTIData_Integer:
case ePERSTIData_Unsigned:
case ePERSTIData_NormallySmall:
if (!info->NOctets) {
if (intx_cmp(&sinfo->LowerVal, &intx_0) != 0) {
output("ASN1intx_free(&newval);\n");
}
}
break;
}
break;
}
}
/* generate decoding statements for a simple value */
void
GenPERDecSimpleType(AssignmentList_t ass, PERTypeInfo_t *info, char *valref, char *encref)
{
uint32_t i;
char *oldvalref;
char valbuf[256], lenbuf[256];
char *lenref;
PERTypeInfo_t inf;
inf = *info;
/* examine type for special handling */
switch (inf.Root.Data) {
case ePERSTIData_BitString:
case ePERSTIData_RZBBitString:
if (inf.Root.cbFixedSizeBitString)
{
sprintf(lenbuf, "%u", inf.Root.LUpperVal);
sprintf(valbuf, "%s", valref);
lenref = lenbuf;
valref = valbuf;
break;
}
// lonchanc: intentionally fall through
case ePERSTIData_OctetString:
if (g_fCaseBasedOptimizer)
{
if (inf.Root.Data == ePERSTIData_OctetString && inf.Type == eExtension_Unextended)
{
switch (inf.Root.Length)
{
case ePERSTILength_NoLength:
if (inf.Root.LConstraint == ePERSTIConstraint_Constrained &&
inf.Root.LLowerVal == inf.Root.LUpperVal &&
inf.Root.LUpperVal < 64 * 1024)
{
// fixed size constraint, eg. OCTET STRING (SIZE (8))
if (inf.pPrivateDirectives->fLenPtr)
{
output("if (!ASN1PERDecOctetString_FixedSizeEx(%s, %s, %u))\n",
encref, Reference(valref), inf.Root.LLowerVal);
}
else
{
output("if (!ASN1PERDecOctetString_FixedSize(%s, (ASN1octetstring2_t *) %s, %u))\n",
encref, Reference(valref), inf.Root.LLowerVal);
}
output("return 0;\n");
return;
}
break;
case ePERSTILength_Length:
break;
case ePERSTILength_BitLength:
if (inf.Root.LConstraint == ePERSTIConstraint_Constrained &&
inf.Root.LLowerVal < inf.Root.LUpperVal &&
inf.Root.LUpperVal < 64 * 1024)
{
// variable size constraint, eg. OCTET STRING (SIZE (4..16))
if (inf.pPrivateDirectives->fLenPtr)
{
output("if (!ASN1PERDecOctetString_VarSizeEx(%s, %s, %u, %u, %u))\n",
encref, Reference(valref), inf.Root.LLowerVal, inf.Root.LUpperVal, inf.Root.LNBits);
}
else
{
output("if (!ASN1PERDecOctetString_VarSize(%s, (ASN1octetstring2_t *) %s, %u, %u, %u))\n",
encref, Reference(valref), inf.Root.LLowerVal, inf.Root.LUpperVal, inf.Root.LNBits);
}
output("return 0;\n");
return;
}
break;
case ePERSTILength_SmallLength:
break;
case ePERSTILength_InfiniteLength: // no size constraint
/* get octet string as fragmented */
if (valref)
{
output("if (!ASN1PERDecOctetString_NoSize(%s, %s))\n",
encref, Reference(valref));
output("return 0;\n");
return;
}
break;
} // switch
} // if
}
/* length and value of bit string/octet string/string value */
sprintf(lenbuf, "(%s).length", valref);
sprintf(valbuf, "(%s).value", valref);
lenref = lenbuf;
valref = valbuf;
break;
case ePERSTIData_UTF8String:
/* length and value of bit string/octet string/string value */
sprintf(lenbuf, "(%s).length", valref);
sprintf(valbuf, "(%s).value", valref);
lenref = lenbuf;
valref = valbuf;
break;
case ePERSTIData_String:
case ePERSTIData_TableString:
/* length and value of bit string/octet string/string value */
sprintf(lenbuf, "(%s).length", valref);
sprintf(valbuf, "(%s).value", valref);
lenref = lenbuf;
valref = valbuf;
break;
case ePERSTIData_SequenceOf:
case ePERSTIData_SetOf:
if (inf.Rules & eTypeRules_PointerArrayMask)
{
/* length and value of sequence of/set of value with */
/* length-pointer representation */
if (inf.Rules & eTypeRules_PointerToElement)
{
sprintf(lenbuf, "(%s)->count", valref);
sprintf(valbuf, "(%s)->%s", valref, GetPrivateValueName(inf.pPrivateDirectives, "value"));
}
else
{
sprintf(lenbuf, "(%s)->count", Reference(valref));
sprintf(valbuf, "(%s)->%s", Reference(valref), GetPrivateValueName(inf.pPrivateDirectives, "value"));
}
lenref = lenbuf;
valref = valbuf;
}
else
if (inf.Rules & eTypeRules_LinkedListMask)
{
if (g_fCaseBasedOptimizer)
{
if (PerOptCase_IsTargetSeqOf(&inf))
{
// generate the iterator
char szElmFn[128];
char szElmFnDecl[256];
sprintf(szElmFn, "ASN1Dec_%s_ElmFn", inf.Identifier);
sprintf(szElmFnDecl, "int ASN1CALL %s(ASN1decoding_t %s, P%s val)",
szElmFn, encref, inf.Identifier);
setoutfile(g_finc);
output("extern %s;\n", szElmFnDecl);
setoutfile(g_fout);
if ((inf.Root.LLowerVal == 0 && inf.Root.LUpperVal == 0) ||
(inf.Root.LUpperVal >= 64 * 1024)
)
{
output("return ASN1PERDecSeqOf_NoSize(%s, (ASN1iterator_t **) %s, (ASN1iterator_decfn) %s, sizeof(*%s));\n",
encref, Reference(valref), szElmFn, valref);
}
else
{
if (inf.Root.LLowerVal == inf.Root.LUpperVal)
MyAbort();
output("return ASN1PERDecSeqOf_VarSize(%s, (ASN1iterator_t **) %s, (ASN1iterator_decfn) %s, sizeof(*%s), %u, %u, %u);\n",
encref, Reference(valref), szElmFn, valref,
inf.Root.LLowerVal, inf.Root.LUpperVal, inf.Root.LNBits);
}
output("}\n\n"); // end of iterator body
// generate the element function
output("static %s\n", szElmFnDecl);
output("{\n");
sprintf(valbuf, "val->%s", GetPrivateValueName(inf.pPrivateDirectives, "value"));
GenPERFuncSimpleType(ass, &inf.Root.SubType->PERTypeInfo, valbuf,
eDecode, encref);
// end of element body
return;
}
}
/* use a loop for sequence of/set of value with */
/* list representation */
outputvar("P%s *f;\n", inf.Identifier);
lenref = NULL;
} else {
MyAbort();
}
break;
case ePERSTIData_Extension:
/* length of extension */
if (inf.Root.Length == ePERSTILength_SmallLength)
lenref = "e";
else
lenref = NULL;
break;
case ePERSTIData_Boolean:
if (g_fCaseBasedOptimizer)
{
if (PerOptCase_IsBoolean(&inf.Root))
{
lenref = NULL;
break;
}
}
/* boolean value */
inf.Root.Data = ePERSTIData_Unsigned;
lenref = NULL;
break;
default:
/* other values have no additional length */
lenref = NULL;
break;
}
/* check for extended values */
if (inf.Type > eExtension_Unextended) {
outputvar("ASN1uint32_t x;\n");
if (g_fCaseBasedOptimizer)
{
output("if (!ASN1PERDecExtensionBit(%s, &x))\n", encref);
}
else
{
output("if (!ASN1PERDecBit(%s, &x))\n", encref);
}
output("return 0;\n");
output("if (!x) {\n");
}
/* additional variable for enumeraton value mapping */
oldvalref = valref;
if (inf.EnumerationValues && valref) {
outputvar("ASN1uint32_t u;\n");
valref = "u";
inf.NOctets = 4;
}
/* decode unextended value (of extension root) */
GenPERDecGenericUnextended(ass, &inf, &inf.Root, valref, lenref, encref);
/* map enumeration values if type is extendable */
if (inf.EnumerationValues && oldvalref &&
inf.Type == eExtension_Extendable) {
output("switch (u) {\n");
for (i = 0; inf.EnumerationValues[i]; i++) {
output("case %u:\n", i);
output("%s = %u;\n", oldvalref, intx2uint32(inf.EnumerationValues[i]));
output("break;\n");
}
output("}\n");
}
/* type is extendable? */
if (inf.Type > eExtension_Unextended) {
output("} else {\n");
if (inf.Type == eExtension_Extendable)
valref = lenref = NULL;
/* decode extended value (of extension addition) */
GenPERDecGenericUnextended(ass, &inf, &inf.Additional, valref, lenref, encref);
output("}\n");
}
/* map enumeration values if type is unextended/extended */
if (inf.EnumerationValues && oldvalref &&
inf.Type != eExtension_Extendable) {
output("switch (u) {\n");
for (i = 0; inf.EnumerationValues[i]; i++) {
output("case %u:\n", i);
output("%s = %u;\n", oldvalref, intx2uint32(inf.EnumerationValues[i]));
output("break;\n");
}
output("}\n");
}
}
/* generate decoding statements for a simple value (after some special */
/* handling has been done, esp. the evaluation of the extension) */
void GenPERDecGenericUnextended(
AssignmentList_t ass,
PERTypeInfo_t *info,
PERSimpleTypeInfo_t *sinfo,
char *valref,
char *lenref,
char *encref)
{
char valbuf[256];
char lenbuf[256];
char lbbuf[256];
char *p;
char *oldvalref;
intx_t ix;
/* check for empty field */
if (sinfo->NBits == 0) {
switch (sinfo->Data) {
case ePERSTIData_Null:
return;
case ePERSTIData_Integer:
case ePERSTIData_Unsigned:
if (valref && (sinfo->Constraint == ePERSTIConstraint_Semiconstrained || sinfo->Constraint == ePERSTIConstraint_Constrained)) {
if (info->NOctets == 0) {
sprintf(lbbuf, "%s_lb", info->Identifier);
outputvarintx(lbbuf, &sinfo->LowerVal);
output("ASN1intx_dup(%s, %s);\n", Reference(valref), lbbuf);
} else if (sinfo->Data == ePERSTIData_Integer) {
output("%s = %d;\n", valref, intx2int32(&sinfo->LowerVal));
} else {
output("%s = %u;\n", valref, intx2uint32(&sinfo->LowerVal));
}
}
return;
case ePERSTIData_BitString:
case ePERSTIData_RZBBitString:
case ePERSTIData_OctetString:
case ePERSTIData_UTF8String:
case ePERSTIData_SequenceOf:
case ePERSTIData_SetOf:
case ePERSTIData_String:
case ePERSTIData_TableString:
case ePERSTIData_ZeroString:
case ePERSTIData_ZeroTableString:
if (lenref)
output("%s = 0;\n", lenref);
return;
case ePERSTIData_Extension:
if (sinfo->Length == ePERSTILength_SmallLength)
break;
return;
default:
MyAbort();
}
}
/* check for decoding of non-negative-binary-integer */
switch (sinfo->Constraint) {
case ePERSTIConstraint_Semiconstrained:
case ePERSTIConstraint_Constrained:
if (sinfo->Data == ePERSTIData_Integer)
sinfo->Data = ePERSTIData_Unsigned;
break;
}
/* use newval for dec of semiconstraint/constraint intx_t with lb != 0 */
switch (sinfo->Constraint) {
case ePERSTIConstraint_Semiconstrained:
case ePERSTIConstraint_Constrained:
switch (sinfo->Data) {
case ePERSTIData_Integer:
case ePERSTIData_Unsigned:
case ePERSTIData_NormallySmall:
if (valref) {
if (intx_cmp(&sinfo->LowerVal, &intx_0) != 0) {
if (info->NOctets == 0) {
outputvar("ASN1intx_t newval;\n");
oldvalref = valref;
valref = "newval";
}
}
}
break;
}
break;
}
/* general rules */
if (sinfo->LAlignment == ePERSTIAlignment_OctetAligned && sinfo->Length == ePERSTILength_BitLength &&
!(sinfo->LNBits & 7))
sinfo->Alignment = ePERSTIAlignment_BitAligned;
/* octet alignment will be given my length */
if (sinfo->Length == ePERSTILength_InfiniteLength &&
(sinfo->Data == ePERSTIData_Integer && info->NOctets == 0 ||
sinfo->Data == ePERSTIData_Unsigned && info->NOctets == 0 ||
sinfo->Data == ePERSTIData_BitString ||
sinfo->Data == ePERSTIData_RZBBitString ||
sinfo->Data == ePERSTIData_Extension ||
sinfo->Data == ePERSTIData_OctetString ||
sinfo->Data == ePERSTIData_UTF8String ||
sinfo->Data == ePERSTIData_SequenceOf ||
sinfo->Data == ePERSTIData_SetOf ||
sinfo->Data == ePERSTIData_String ||
sinfo->Data == ePERSTIData_TableString ||
sinfo->Data == ePERSTIData_ZeroString ||
sinfo->Data == ePERSTIData_ZeroTableString) ||
sinfo->Data == ePERSTIData_ObjectIdentifier ||
sinfo->Data == ePERSTIData_Real ||
sinfo->Data == ePERSTIData_GeneralizedTime ||
sinfo->Data == ePERSTIData_UTCTime ||
sinfo->Data == ePERSTIData_External ||
sinfo->Data == ePERSTIData_EmbeddedPdv ||
sinfo->Data == ePERSTIData_MultibyteString ||
sinfo->Data == ePERSTIData_UnrestrictedString ||
sinfo->Data == ePERSTIData_Open)
sinfo->LAlignment = sinfo->Alignment = ePERSTIAlignment_BitAligned;
/* alignment will be done by encoding fn */
if (sinfo->Length == ePERSTILength_NoLength ||
sinfo->Length == ePERSTILength_SmallLength)
sinfo->LAlignment = ePERSTIAlignment_BitAligned;
/* no alignment of no length */
if (g_fCaseBasedOptimizer)
{
// lonchanc: special handling for macro operations
if (PerOptCase_IsSignedInteger(sinfo))
{
output("if (!ASN1PERDecInteger(%s, %s))\n", encref, Reference(valref));
output("return 0;\n");
goto FinalTouch;
}
if (PerOptCase_IsUnsignedInteger(sinfo))
{
output("if (!ASN1PERDecUnsignedInteger(%s, %s))\n", encref, Reference(valref));
output("return 0;\n");
goto FinalTouch;
}
if (PerOptCase_IsUnsignedShort(sinfo))
{
output("if (!ASN1PERDecUnsignedShort(%s, %s))\n", encref, Reference(valref));
output("return 0;\n");
goto FinalTouch;
}
if (PerOptCase_IsBoolean(sinfo))
{
output("if (!ASN1PERDecBoolean(%s, %s))\n", encref, Reference(valref));
output("return 0;\n");
return;
}
}
/* initial settings for length enconding: */
/* add lower bound of length to length */
if (!lenref) {
if (sinfo->Length == ePERSTILength_NoLength &&
sinfo->Data != ePERSTIData_Extension) {
sprintf(lenbuf, "%u", sinfo->LLowerVal);
lenref = lenbuf;
} else if (sinfo->Data != ePERSTIData_ObjectIdentifier &&
sinfo->Data != ePERSTIData_External &&
sinfo->Data != ePERSTIData_EmbeddedPdv &&
sinfo->Data != ePERSTIData_MultibyteString &&
sinfo->Data != ePERSTIData_UnrestrictedString &&
sinfo->Data != ePERSTIData_Extension &&
(sinfo->Length != ePERSTILength_InfiniteLength ||
(sinfo->Data != ePERSTIData_SetOf &&
sinfo->Data != ePERSTIData_SequenceOf) ||
!IsStructuredType(GetType(ass, sinfo->SubType))) &&
((sinfo->Data != ePERSTIData_SetOf &&
sinfo->Data != ePERSTIData_SequenceOf) || valref) &&
(sinfo->Length != ePERSTILength_InfiniteLength ||
info->NOctets != 0 ||
(sinfo->Data != ePERSTIData_Integer &&
sinfo->Data != ePERSTIData_Unsigned)) &&
((sinfo->Data != ePERSTIData_ZeroString &&
sinfo->Data != ePERSTIData_ZeroTableString) ||
sinfo->Length != ePERSTILength_InfiniteLength) &&
(sinfo->Data != ePERSTIData_BitString &&
sinfo->Data != ePERSTIData_UTF8String &&
sinfo->Data != ePERSTIData_OctetString)) {
outputvar("ASN1uint32_t l;\n");
lenref = "l";
}
} else if (sinfo->Length == ePERSTILength_NoLength) {
if ((sinfo->Data == ePERSTIData_BitString ||
sinfo->Data == ePERSTIData_RZBBitString) &&
sinfo->cbFixedSizeBitString)
{
// lonchanc: doing nothing here because lenref is a constant number
}
else
{
output("%s = %u;\n", lenref, sinfo->LLowerVal);
}
}
/* length encoding */
if (sinfo->LAlignment == ePERSTIAlignment_OctetAligned) {
output("ASN1PERDecAlignment(%s);\n", encref);
}
switch (sinfo->Length) {
case ePERSTILength_NoLength:
break;
case ePERSTILength_BitLength:
/* get length */
output("if (!ASN1PERDecU32Val(%s, %u, %s))\n",
encref, sinfo->LNBits, Reference(lenref));
output("return 0;\n");
/* add lower bound of length */
if (sinfo->LLowerVal)
output("%s += %u;\n", lenref, sinfo->LLowerVal);
/*
if (sinfo->LConstraint == ePERSTIConstraint_Constrained) {
output("if (%s > %u)\n", lenref, sinfo->LUpperVal);
output("return ASN1DecError(%s, ASN1_ERR_CORRUPT);\n", encref);
}
*/
break;
case ePERSTILength_InfiniteLength:
/* infinite length case */
switch (sinfo->Data) {
case ePERSTIData_Integer:
case ePERSTIData_Unsigned:
/* get length of integer value */
if (info->NOctets != 0) {
output("if (!ASN1PERDecFragmentedLength(%s, %s))\n",
encref, Reference(lenref));
output("return 0;\n");
if (sinfo->LLowerVal)
output("%s += %u;\n", lenref, sinfo->LLowerVal);
/*
if (sinfo->LConstraint == ePERSTIConstraint_Constrained) {
output("if (%s > %u)\n", lenref, sinfo->LUpperVal);
output("return ASN1DecError(%s, ASN1_ERR_CORRUPT);\n",
encref);
}
*/
}
break;
}
break;
}
/* value decoding */
switch (sinfo->Length) {
case ePERSTILength_NoLength:
/* decode alignment of the value */
if (sinfo->Alignment == ePERSTIAlignment_OctetAligned) {
output("ASN1PERDecAlignment(%s);\n", encref);
}
switch (sinfo->Data) {
case ePERSTIData_Integer:
/* decode the value as bit field */
if (valref) {
if (!info->NOctets) {
output("if (!ASN1PERDecSXVal(%s, %u, %s))\n",
info->NOctets * 8, encref, sinfo->NBits, Reference(valref));
output("return 0;\n");
} else {
output("if (!ASN1PERDecS%dVal(%s, %u, %s))\n",
info->NOctets * 8, encref, sinfo->NBits, Reference(valref));
output("return 0;\n");
}
} else {
output("if (!ASN1PERDecSkipBits(%s, %u))\n",
encref, sinfo->NBits);
output("return 0;\n");
}
break;
case ePERSTIData_Unsigned:
/* decode the value as bit field */
if (valref) {
if (!info->NOctets) {
output("if (!ASN1PERDecUXVal(%s, %u, %s))\n",
info->NOctets * 8, encref, sinfo->NBits, Reference(valref));
output("return 0;\n");
} else {
output("if (!ASN1PERDecU%dVal(%s, %u, %s))\n",
info->NOctets * 8, encref, sinfo->NBits, Reference(valref));
output("return 0;\n");
}
} else {
output("if (!ASN1PERDecSkipBits(%s, %u))\n",
encref, sinfo->NBits);
output("return 0;\n");
}
break;
case ePERSTIData_NormallySmall:
/* decode the value as normally small number */
if (valref) {
if (!info->NOctets) {
MyAbort();
} else {
output("if (!ASN1PERDecN%dVal(%s, %s))\n",
info->NOctets * 8, encref, Reference(valref));
output("return 0;\n");
}
} else {
output("if (!ASN1PERDecSkipNormallySmall(%s))\n",
encref);
output("return 0;\n");
}
break;
case ePERSTIData_BitString:
case ePERSTIData_RZBBitString:
/* decode bit string in a bit field */
if (valref) {
if (sinfo->cbFixedSizeBitString)
{
output("if (!ASN1PERDecExtension(%s, %s, %s))\n",
encref, lenref, Reference(valref));
}
else
{
output("if (!ASN1PERDecBits(%s, %s, %s))\n",
encref, lenref, Reference(valref));
}
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipBits(%s, %s))\n",
encref, lenref);
output("return 0;\n");
}
break;
case ePERSTIData_OctetString:
/* decode octet string in a bit field */
if (valref) {
if (sinfo->LConstraint == ePERSTIConstraint_Constrained &&
(! info->pPrivateDirectives->fLenPtr))
{
output("if (!ASN1PERDecExtension(%s, %s * 8, %s))\n",
encref, lenref, valref);
}
else
{
output("if (!ASN1PERDecBits(%s, %s * 8, %s))\n",
encref, lenref, Reference(valref));
}
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipBits(%s, %s * 8))\n",
encref, lenref);
output("return 0;\n");
}
break;
case ePERSTIData_UTF8String:
/* decode octet string in a bit field */
if (valref) {
output("if (!ASN1PERDecUTF8String(%s, %s, %s))\n",
encref, lenref, Reference(valref));
output("return 0;\n");
} else {
MyAbort();
}
break;
case ePERSTIData_Extension:
/* decode extension bits in a bit field */
if (valref) {
output("if (!ASN1PERDecExtension(%s, %u, %s))\n",
encref, sinfo->NBits, valref);
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipBits(%s, %u))\n",
encref, sinfo->NBits);
output("return 0;\n");
}
break;
case ePERSTIData_SetOf:
/* same as BitLength encoding */
goto SetOfEncoding;
case ePERSTIData_SequenceOf:
/* same as BitLength encoding */
goto SequenceOfEncoding;
case ePERSTIData_String:
/* same as BitLength encoding */
goto StringEncoding;
case ePERSTIData_ZeroString:
/* same as BitLength encoding */
goto ZeroStringEncoding;
case ePERSTIData_TableString:
/* same as BitLength encoding */
goto TableStringEncoding;
case ePERSTIData_ZeroTableString:
/* same as BitLength encoding */
goto ZeroTableStringEncoding;
case ePERSTIData_Reference:
/* call encoding function of referenced type */
if (valref) {
output("if (!ASN1Dec_%s(%s, %s))\n",
Identifier2C(sinfo->SubIdentifier),
encref, Reference(valref));
output("return 0;\n");
} else {
output("if (!ASN1Dec_%s(%s, NULL))\n",
Identifier2C(sinfo->SubIdentifier),
encref);
output("return 0;\n");
}
break;
case ePERSTIData_Real:
/* decode real value */
if (valref) {
if (info->NOctets)
output("if (!ASN1PERDecDouble(%s, %s))\n",
encref, Reference(valref));
else
output("if (!ASN1PERDecReal(%s, %s))\n",
encref, Reference(valref));
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipFragmented(%s, 8))\n",
encref);
output("return 0;\n");
}
break;
case ePERSTIData_GeneralizedTime:
/* decode generalized time value */
if (valref) {
output("if (!ASN1PERDecGeneralizedTime(%s, %s, %d))\n",
encref, Reference(valref), sinfo->NBits);
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipFragmented(%s, %d))\n",
encref, sinfo->NBits);
output("return 0;\n");
}
break;
case ePERSTIData_UTCTime:
/* decode utc time value */
if (valref) {
output("if (!ASN1PERDecUTCTime(%s, %s, %d))\n",
encref, Reference(valref), sinfo->NBits);
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipFragmented(%s, %d))\n",
encref, sinfo->NBits);
output("return 0;\n");
}
break;
}
break;
case ePERSTILength_BitLength:
/* decode alignment of the value */
if (sinfo->Alignment == ePERSTIAlignment_OctetAligned) {
output("ASN1PERDecAlignment(%s);\n", encref);
}
switch (sinfo->Data) {
case ePERSTIData_Integer:
case ePERSTIData_Unsigned:
/* decode the value as bit field */
if (valref) {
if (info->NOctets == 0 && sinfo->Data == ePERSTIData_Integer) {
output("if (!ASN1PERDecSXVal(%s, %s * 8, %s))\n",
encref, lenref, Reference(valref));
output("return 0;\n");
} else if (info->NOctets == 0 && sinfo->Data == ePERSTIData_Unsigned) {
output("if (!ASN1PERDecUXVal(%s, %s * 8, %s))\n",
encref, lenref, Reference(valref));
output("return 0;\n");
} else if (sinfo->Data == ePERSTIData_Integer) {
output("if (!ASN1PERDecS%dVal(%s, %s * 8, %s))\n",
info->NOctets * 8, encref, lenref, Reference(valref));
output("return 0;\n");
} else {
output("if (!ASN1PERDecU%dVal(%s, %s * 8, %s))\n",
info->NOctets * 8, encref, lenref, Reference(valref));
output("return 0;\n");
}
} else {
output("if (!ASN1PERDecSkipBits(%s, %s * 8))\n",
encref, lenref);
output("return 0;\n");
}
break;
case ePERSTIData_BitString:
case ePERSTIData_RZBBitString:
/* decode the value as bit field */
if (valref) {
output("if (!ASN1PERDecBits(%s, %s, %s))\n",
encref, lenref, Reference(valref));
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipBits(%s, %s))\n",
encref, lenref);
output("return 0;\n");
}
break;
case ePERSTIData_OctetString:
/* decode the value as bit field */
if (valref) {
if (sinfo->LConstraint == ePERSTIConstraint_Constrained &&
(! info->pPrivateDirectives->fLenPtr))
{
output("if (!ASN1PERDecExtension(%s, %s * 8, %s))\n",
encref, lenref, valref);
}
else
{
output("if (!ASN1PERDecBits(%s, %s * 8, %s))\n",
encref, lenref, Reference(valref));
}
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipBits(%s, %s * 8))\n",
encref, lenref);
output("return 0;\n");
}
break;
case ePERSTIData_UTF8String:
/* decode the value as bit field */
if (valref) {
output("if (!ASN1PERDecUTF8String(%s, %s, %s))\n",
encref, lenref, Reference(valref));
output("return 0;\n");
} else {
MyAbort();
}
break;
case ePERSTIData_SetOf:
SetOfEncoding:
/*FALLTHROUGH*/
case ePERSTIData_SequenceOf:
SequenceOfEncoding:
/* skip null sequence of/set of */
if (sinfo->SubType->Flags & eTypeFlags_Null)
break;
outputvar("ASN1uint32_t i;\n");
if (!valref || (info->Rules & eTypeRules_PointerArrayMask))
{
// lonchanc: no need to allocate memory for eTypeRules_FixedArray
/* allocate memory for elements */
if (valref && (info->Rules & eTypeRules_LengthPointer))
{
output("if (!%s) {\n", lenref);
output("%s = NULL;\n", valref);
output("} else {\n");
output("if (!(%s = (%s *)ASN1DecAlloc(%s, %s * sizeof(%s))))\n",
valref, sinfo->SubIdentifier, encref,
lenref, Dereference(valref));
output("return 0;\n");
}
/* decode elements */
output("for (i = 0; i < %s; i++) {\n", lenref);
if (valref) {
sprintf(valbuf, "(%s)[i]", valref);
GenPERFuncSimpleType(ass, &sinfo->SubType->PERTypeInfo, valbuf, eDecode, encref);
} else {
GenPERFuncSimpleType(ass, &sinfo->SubType->PERTypeInfo, NULL, eDecode, encref);
}
/* loop end */
output("}\n");
if (valref && (info->Rules & eTypeRules_LengthPointer))
output("}\n"); // closing bracket for else
}
else if (info->Rules & eTypeRules_SinglyLinkedList)
{
char szPrivateValueName[64];
sprintf(&szPrivateValueName[0], "(*f)->%s", GetPrivateValueName(info->pPrivateDirectives, "value"));
/* allocate and decode elements */
outputvar("P%s *f;\n", info->Identifier);
output("f = %s;\n", Reference(valref));
output("for (i = 0; i < %s; i++) {\n", lenref);
output("if (!(*f = (P%s)ASN1DecAlloc(%s, sizeof(**f))))\n",
info->Identifier, encref);
output("return 0;\n");
GenPERFuncSimpleType(ass, &sinfo->SubType->PERTypeInfo, &szPrivateValueName[0],
eDecode, encref);
output("f = &(*f)->next;\n");
output("}\n");
output("*f = NULL;\n");
}
else
if (info->Rules & eTypeRules_DoublyLinkedList)
{
char szPrivateValueName[64];
sprintf(&szPrivateValueName[0], "(*f)->%s", GetPrivateValueName(info->pPrivateDirectives, "value"));
/* allocate and decode elements */
outputvar("P%s *f;\n", info->Identifier);
outputvar("%s b;\n", info->Identifier);
output("f = %s;\n", Reference(valref));
output("b = NULL;\n");
output("for (i = 0; i < %s; i++) {\n", lenref);
output("if (!(*f = (P%s)ASN1DecAlloc(%s, sizeof(**f))))\n",
info->Identifier, encref);
output("return 0;\n");
GenPERFuncSimpleType(ass, &sinfo->SubType->PERTypeInfo, &szPrivateValueName[0],
eDecode, encref);
output("f->prev = b;\n");
output("b = *f;\n");
output("f = &b->next;\n");
output("}\n");
output("*f = NULL;\n");
}
break;
case ePERSTIData_String:
StringEncoding:
/* decode string value */
if (info->NOctets == 1) {
p = "Char";
} else if (info->NOctets == 2) {
p = "Char16";
} else if (info->NOctets == 4) {
p = "Char32";
} else
MyAbort();
if (valref) {
#ifdef ENABLE_CHAR_STR_SIZE
if (info->NOctets == 1 &&
info->Root.LConstraint == ePERSTIConstraint_Constrained)
{
output("if (!ASN1PERDec%sStringNoAlloc(%s, %s, %s, %u))\n",
p, encref, lenref, valref, sinfo->NBits);
}
else
{
output("if (!ASN1PERDec%sString(%s, %s, %s, %u))\n",
p, encref, lenref, Reference(valref), sinfo->NBits);
}
#else
output("if (!ASN1PERDec%sString(%s, %s, %s, %u))\n",
p, encref, lenref, Reference(valref), sinfo->NBits);
#endif
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipBits(%s, %s * %u))\n",
encref, lenref, sinfo->NBits);
output("return 0;\n");
}
break;
case ePERSTIData_ZeroString:
ZeroStringEncoding:
/* decode zero-terminated string value */
if (info->NOctets == 1) {
p = "Char";
} else if (info->NOctets == 2) {
p = "Char16";
} else if (info->NOctets == 4) {
p = "Char32";
} else
MyAbort();
if (valref) {
#ifdef ENABLE_CHAR_STR_SIZE
if (info->NOctets == 1 &&
info->Root.LConstraint == ePERSTIConstraint_Constrained)
{
output("if (!ASN1PERDecZero%sStringNoAlloc(%s, %s, %s, %u))\n",
p, encref, lenref, valref, sinfo->NBits);
}
else
{
output("if (!ASN1PERDecZero%sString(%s, %s, %s, %u))\n",
p, encref, lenref, Reference(valref), sinfo->NBits);
}
#else
output("if (!ASN1PERDecZero%sString(%s, %s, %s, %u))\n",
p, encref, lenref, Reference(valref), sinfo->NBits);
#endif
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipBits(%s, %s * %u))\n",
encref, lenref, sinfo->NBits);
output("return 0;\n");
}
break;
case ePERSTIData_TableString:
TableStringEncoding:
/* decode table string value */
if (info->NOctets == 1) {
p = "Char";
} else if (info->NOctets == 2) {
p = "Char16";
} else if (info->NOctets == 4) {
p = "Char32";
} else
MyAbort();
if (valref) {
#ifdef ENABLE_CHAR_STR_SIZE
if (info->NOctets == 1 &&
info->Root.LConstraint == ePERSTIConstraint_Constrained)
{
output("if (!ASN1PERDecTable%sStringNoAlloc(%s, %s, %s, %u, %s))\n",
p, encref, lenref, valref, sinfo->NBits, Reference(sinfo->TableIdentifier));
}
else
{
output("if (!ASN1PERDecTable%sString(%s, %s, %s, %u, %s))\n",
p, encref, lenref, Reference(valref), sinfo->NBits, Reference(sinfo->TableIdentifier));
}
#else
output("if (!ASN1PERDecTable%sString(%s, %s, %s, %u, %s))\n",
p, encref, lenref, Reference(valref), sinfo->NBits, Reference(sinfo->TableIdentifier));
#endif
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipBits(%s, %s * %u, %s))\n",
encref, lenref, sinfo->NBits, Reference(sinfo->TableIdentifier));
output("return 0;\n");
}
break;
case ePERSTIData_ZeroTableString:
ZeroTableStringEncoding:
/* decode zero-terminated table string value */
if (info->NOctets == 1) {
p = "Char";
} else if (info->NOctets == 2) {
p = "Char16";
} else if (info->NOctets == 4) {
p = "Char32";
} else
MyAbort();
if (valref) {
#ifdef ENABLE_CHAR_STR_SIZE
if (info->NOctets == 1 &&
info->Root.LConstraint == ePERSTIConstraint_Constrained)
{
output("if (!ASN1PERDecZeroTable%sStringNoAlloc(%s, %s, %s, %u, %s))\n",
p, encref, lenref, valref, sinfo->NBits, Reference(sinfo->TableIdentifier));
}
else
{
output("if (!ASN1PERDecZeroTable%sString(%s, %s, %s, %u, %s))\n",
p, encref, lenref, Reference(valref), sinfo->NBits, Reference(sinfo->TableIdentifier));
}
#else
output("if (!ASN1PERDecZeroTable%sString(%s, %s, %s, %u, %s))\n",
p, encref, lenref, Reference(valref), sinfo->NBits, Reference(sinfo->TableIdentifier));
#endif
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipBits(%s, %s * %u, %s))\n",
encref, lenref, sinfo->NBits, Reference(sinfo->TableIdentifier));
output("return 0;\n");
}
break;
}
break;
case ePERSTILength_InfiniteLength:
/* infinite length case */
switch (sinfo->Data) {
case ePERSTIData_Integer:
case ePERSTIData_Unsigned:
/* get integer value as fragmented */
if (valref) {
if (info->NOctets == 0) {
if (sinfo->Data == ePERSTIData_Integer) {
output("if (!ASN1PERDecFragmentedIntx(%s, %s))\n",
encref, Reference(valref));
} else {
output("if (!ASN1PERDecFragmentedUIntx(%s, %s))\n",
encref, Reference(valref));
}
output("return 0;\n");
} else if (sinfo->Data == ePERSTIData_Integer) {
output("if (!ASN1PERDecS%dVal(%s, %s * 8, %s))\n",
info->NOctets * 8, encref, lenref, Reference(valref));
output("return 0;\n");
} else {
output("if (!ASN1PERDecU%dVal(%s, %s * 8, %s))\n",
info->NOctets * 8, encref, lenref, Reference(valref));
output("return 0;\n");
}
} else {
if (info->NOctets != 0) {
output("if (!ASN1PERDecSkipBits(%s, %s * 8))\n",
encref, lenref);
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipFragmented(%s, 8))\n",
encref);
output("return 0;\n");
}
}
break;
case ePERSTIData_Extension:
/* get extension bits as fragmented */
if (valref) {
output("if (!ASN1PERDecFragmentedExtension(%s, %u, %s))\n",
encref, sinfo->NBits, valref);
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipFragmented(%s, 1))\n",
encref);
output("return 0;\n");
}
break;
case ePERSTIData_BitString:
case ePERSTIData_RZBBitString:
/* get bit string as fragmented */
if (valref) {
output("if (!ASN1PERDecFragmented(%s, %s, %s, 1))\n",
encref, Reference(lenref), Reference(valref));
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipFragmented(%s, 1))\n",
encref);
output("return 0;\n");
}
break;
case ePERSTIData_OctetString:
/* get octet string as fragmented */
if (valref) {
output("if (!ASN1PERDecFragmented(%s, %s, %s, 8))\n",
encref, Reference(lenref), Reference(valref));
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipFragmented(%s, 8))\n",
encref);
output("return 0;\n");
}
break;
case ePERSTIData_UTF8String:
/* get octet string as fragmented */
if (valref) {
output("if (!ASN1PERDecUTF8StringEx(%s, %s, %s))\n",
encref, Reference(lenref), Reference(valref));
output("return 0;\n");
} else {
MyAbort();
}
break;
case ePERSTIData_SetOf:
case ePERSTIData_SequenceOf:
/* we need some counters and iterators */
outputvar("ASN1uint32_t i;\n");
outputvar("ASN1uint32_t n;\n");
if (valref)
{
if (info->Rules & eTypeRules_LengthPointer)
{
output("%s = 0;\n", lenref);
output("%s = NULL;\n", valref);
}
else
if (info->Rules & eTypeRules_FixedArray)
{
output("%s = 0;\n", lenref);
}
else
if (info->Rules & eTypeRules_SinglyLinkedList)
{
outputvar("P%s *f;\n", info->Identifier);
output("f = %s;\n", Reference(valref));
}
else
if (info->Rules & eTypeRules_DoublyLinkedList)
{
outputvar("P%s *f;\n", info->Identifier);
outputvar("%s b;\n", info->Identifier);
output("f = %s;\n", Reference(valref));
output("b = NULL;\n");
}
}
/* get all elements of the sequence of/set of */
output("do {\n");
/* get length of a fragment */
output("if (!ASN1PERDecFragmentedLength(%s, &n))\n",
encref);
output("return 0;\n");
if (valref)
{
if (info->Rules & eTypeRules_LengthPointer)
{
// lonchanc: no need to allocate memory for eTypeRules_FixedArray
/* resize memory for the element */
output("if (!(%s = (%s *)ASN1DecRealloc(%s, %s, (%s + n) * sizeof(%s))))\n",
valref, GetTypeName(ass, sinfo->SubType), encref,
valref, lenref, Dereference(valref));
output("return 0;\n");
}
}
/* get the elements of the fragment */
output("for (i = 0; i < n; i++) {\n");
if (valref) {
if (info->Rules & eTypeRules_PointerArrayMask)
{
sprintf(valbuf, "(%s)[%s]", valref, lenref);
}
else
if (info->Rules & eTypeRules_LinkedListMask)
{
output("if (!(*f = (P%s)ASN1DecAlloc(%s, sizeof(**f))))\n",
info->Identifier, encref);
output("return 0;\n");
sprintf(valbuf, "(*f)->%s", GetPrivateValueName(info->pPrivateDirectives, "value"));
}
GenPERFuncSimpleType(ass, &sinfo->SubType->PERTypeInfo, valbuf, eDecode, encref);
if (info->Rules & eTypeRules_SinglyLinkedList)
{
output("f = &(*f)->next;\n");
}
else
if (info->Rules & eTypeRules_DoublyLinkedList)
{
output("(*f)->prev = b;\n");
output("b = *f;\n");
output("f = &b->next;\n");
}
} else {
GenPERFuncSimpleType(ass, &sinfo->SubType->PERTypeInfo, NULL, eDecode, encref);
}
if ((info->Rules & (eTypeRules_LengthPointer | eTypeRules_FixedArray)) && lenref)
output("(%s)++;\n", lenref);
/* end of inner loop */
output("}\n");
/* end of outer loop */
output("} while (n >= 0x4000);\n");
/* terminate list */
if (valref && (info->Rules & (eTypeRules_SinglyLinkedList | eTypeRules_DoublyLinkedList)))
output("*f = NULL;\n");
break;
case ePERSTIData_ObjectIdentifier:
/* decode object identifier value */
if (valref) {
if (info->pPrivateDirectives->fOidArray || g_fOidArray)
{
output("if (!ASN1PERDecObjectIdentifier2(%s, %s))\n",
encref, Reference(valref));
}
else
{
output("if (!ASN1PERDecObjectIdentifier(%s, %s))\n",
encref, Reference(valref));
}
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipFragmented(%s, 8))\n",
encref);
output("return 0;\n");
}
break;
case ePERSTIData_External:
/* decode external value */
output("if (!ASN1PERDecExternal(%s, %s))\n",
encref, Reference(valref));
output("return 0;\n");
break;
case ePERSTIData_EmbeddedPdv:
/* decode embedded pdv value */
if (sinfo->Identification) {
if (!strcmp(sinfo->Identification->Identifier, "fixed")) {
output("if (!ASN1PERDecEmbeddedPdvOpt(%s, %s, NULL, NULL))\n",
encref, Reference(valref));
} else {
output("if (!ASN1PERDecEmbeddedPdvOpt(%s, %s, &%s_identification_syntaxes_abstract, &%s_identification_syntaxes_transfer))\n",
encref, Reference(valref),
info->Identifier, info->Identifier);
}
} else {
output("if (!ASN1PERDecEmbeddedPdv(%s, %s))\n",
encref, Reference(valref));
}
output("return 0;\n");
break;
case ePERSTIData_MultibyteString:
/* decode multibyte string value */
output("if (!ASN1PERDecMultibyteString(%s, %s))\n",
encref, Reference(valref));
output("return 0;\n");
break;
case ePERSTIData_UnrestrictedString:
/* decode character string value */
if (sinfo->Identification) {
if (!strcmp(sinfo->Identification->Identifier, "fixed")) {
output("if (!ASN1PERDecCharacterStringOpt(%s, %s, NULL, NULL))\n",
encref, Reference(valref));
} else {
output("if (!ASN1PERDecCharacterStringOpt(%s, %s, &%s_identification_syntaxes_abstract, &%s_identification_syntaxes_transfer))\n",
encref, Reference(valref),
info->Identifier, info->Identifier);
}
} else {
output("if (!ASN1PERDecCharacterString(%s, %s))\n",
encref, Reference(valref));
}
output("return 0;\n");
break;
case ePERSTIData_String:
/* decode string value as fragmented */
if (info->NOctets == 1) {
p = "Char";
} else if (info->NOctets == 2) {
p = "Char16";
} else if (info->NOctets == 4) {
p = "Char32";
} else
MyAbort();
if (valref) {
output("if (!ASN1PERDecFragmented%sString(%s, %s, %s, %u))\n",
p, encref, Reference(lenref), Reference(valref), sinfo->NBits);
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipFragmented(%s, %u))\n",
encref, sinfo->NBits);
output("return 0;\n");
}
break;
case ePERSTIData_ZeroString:
/* decode zero-terminated string value as fragmented */
if (info->NOctets == 1) {
p = "Char";
} else if (info->NOctets == 2) {
p = "Char16";
} else if (info->NOctets == 4) {
p = "Char32";
} else
MyAbort();
if (valref) {
output("if (!ASN1PERDecFragmentedZero%sString(%s, %s, %u))\n",
p, encref, Reference(valref), sinfo->NBits);
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipFragmented(%s, %u))\n",
encref, sinfo->NBits);
output("return 0;\n");
}
break;
case ePERSTIData_TableString:
/* decode table string value as fragmented */
if (info->NOctets == 1) {
p = "Char";
} else if (info->NOctets == 2) {
p = "Char16";
} else if (info->NOctets == 4) {
p = "Char32";
} else
MyAbort();
if (valref) {
output("if (!ASN1PERDecFragmentedTable%sString(%s, %s, %s, %u, %s))\n",
p, encref, Reference(lenref), Reference(valref), sinfo->NBits,
Reference(sinfo->TableIdentifier));
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipFragmented(%s, %u))\n",
encref, sinfo->NBits);
output("return 0;\n");
}
break;
case ePERSTIData_ZeroTableString:
/* decode zero-terminated table-string as fragmented */
if (info->NOctets == 1) {
p = "Char";
} else if (info->NOctets == 2) {
p = "Char16";
} else if (info->NOctets == 4) {
p = "Char32";
} else
MyAbort();
if (valref) {
output("if (!ASN1PERDecFragmentedZeroTable%sString(%s, %s, %u, %s))\n",
p, encref, Reference(valref), sinfo->NBits, Reference(sinfo->TableIdentifier));
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipFragmented(%s, %u))\n",
encref, sinfo->NBits);
output("return 0;\n");
}
break;
case ePERSTIData_Open:
/* decode open type value */
if (valref) {
output("if (!ASN1PERDecOpenType(%s, %s))\n",
encref, Reference(valref));
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipFragmented(%s, 8))\n",
encref);
output("return 0;\n");
}
break;
}
break;
case ePERSTILength_SmallLength:
switch (sinfo->Data) {
case ePERSTIData_Extension:
/* decode extension bits with normally small length */
if (valref) {
output("if (!ASN1PERDecNormallySmallExtension(%s, %s, %u, %s))\n",
encref, Reference(lenref), sinfo->NBits, valref);
output("return 0;\n");
} else {
output("if (!ASN1PERDecSkipNormallySmallExtension(%s, %s))\n",
encref, Reference(lenref));
output("return 0;\n");
}
break;
}
}
FinalTouch:
/* additional calculations for value decoding: */
/* add lower bound of constraint/semiconstraint value */
switch (sinfo->Constraint) {
case ePERSTIConstraint_Semiconstrained:
case ePERSTIConstraint_Constrained:
switch (sinfo->Data) {
case ePERSTIData_Integer:
case ePERSTIData_Unsigned:
case ePERSTIData_NormallySmall:
if (valref) {
if (intx_cmp(&sinfo->LowerVal, &intx_0) != 0) {
if (info->NOctets != 0) {
if (intx_cmp(&sinfo->LowerVal, &intx_0) > 0) {
output("%s += %u;\n",
valref, intx2uint32(&sinfo->LowerVal));
} else {
intx_neg(&ix, &sinfo->LowerVal);
// LONCHANC: to workaround a compiler bug in vc++.
// output("%s += -%u;\n",
output("%s += 0 - %u;\n",
valref, intx2uint32(&ix));
}
} else {
sprintf(lbbuf, "%s_lb", info->Identifier);
outputvarintx(lbbuf, &sinfo->LowerVal);
output("ASN1intx_add(%s, %s, &%s);\n",
Reference(oldvalref), Reference(valref), lbbuf);
output("ASN1intx_free(%s);\n",
Reference(valref));
}
}
}
break;
}
break;
}
}