1319 lines
33 KiB
C
1319 lines
33 KiB
C
/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */
|
|
/* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */
|
|
|
|
#include "precomp.h"
|
|
|
|
#define IDCHRSET "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
|
|
|
|
#define INDENT 4
|
|
#define TABSIZE 8
|
|
|
|
static FILE *fout;
|
|
static int xcurrindent = 0;
|
|
static int xindentflag = 0;
|
|
static char *xbuf = 0;
|
|
static int xbufsize = 0;
|
|
static int xbuflen = 0;
|
|
static int ycurrindent = 1;
|
|
static char *ybuf = 0;
|
|
static int ybufsize = 0;
|
|
static int ybuflen = 0;
|
|
|
|
void xputc(char c);
|
|
void xputs(char *s);
|
|
void xflush();
|
|
void yputc(char c);
|
|
void yputs(char *s);
|
|
void yflush();
|
|
|
|
/* set the output file */
|
|
void
|
|
setoutfile(FILE *f)
|
|
{
|
|
xflush();
|
|
fout = f;
|
|
}
|
|
|
|
/* print indentation up to current indentation level */
|
|
static void
|
|
findent()
|
|
{
|
|
int indent;
|
|
|
|
indent = xcurrindent * INDENT;
|
|
while (indent >= TABSIZE) {
|
|
xputc('\t');
|
|
indent -= TABSIZE;
|
|
}
|
|
while (indent-- > 0)
|
|
xputc(' ');
|
|
}
|
|
|
|
/* print indentation up to current indentation level */
|
|
/* but expect one character to be printed already */
|
|
static void
|
|
findent1()
|
|
{
|
|
int indent;
|
|
|
|
indent = xcurrindent * INDENT;
|
|
if (indent > 0 && indent < TABSIZE)
|
|
indent--;
|
|
while (indent >= TABSIZE) {
|
|
xputc('\t');
|
|
indent -= TABSIZE;
|
|
}
|
|
while (indent-- > 0)
|
|
xputc(' ');
|
|
}
|
|
|
|
/* output function doing indentation automatically */
|
|
void
|
|
outputv(const char *format, va_list args)
|
|
{
|
|
static char buf[4098];
|
|
static int pos = 0;
|
|
char *p, *q;
|
|
int l;
|
|
|
|
/* get the string to write */
|
|
vsprintf(buf + pos, format, args);
|
|
|
|
/* print it line by line */
|
|
for (p = buf; *p; p = q) {
|
|
q = strchr(p, '\n');
|
|
if (!q) {
|
|
for (q = buf; *p;)
|
|
*q++ = *p++;
|
|
*q = 0;
|
|
pos = q - buf;
|
|
return;
|
|
}
|
|
*q++ = 0;
|
|
|
|
/* examine the first character for correct indentation */
|
|
if (strchr(IDCHRSET, *p)) {
|
|
l = strspn(p, IDCHRSET);
|
|
} else if (*p == '{' || *p == '}' || *p == '*' || *p == '&' ||
|
|
*p == '(' || *p == ')' || *p == '#') {
|
|
l = 1;
|
|
} else {
|
|
l = 0;
|
|
}
|
|
|
|
if (!l) {
|
|
|
|
/* no indentation at all */
|
|
xputs(p);
|
|
xputc('\n');
|
|
continue;
|
|
}
|
|
|
|
if (p[0] == '#') {
|
|
|
|
/* preprocessor directive: indent after # */
|
|
xputc('#');
|
|
findent1();
|
|
xputs(p + 1);
|
|
xputc('\n');
|
|
continue;
|
|
}
|
|
|
|
/* closing brace? then unindent */
|
|
if (p[0] == '}')
|
|
xcurrindent--;
|
|
|
|
/* print the indentation, but labels will be less indented */
|
|
if (p[strlen(p) - 1] == ':') {
|
|
xcurrindent--;
|
|
findent();
|
|
xcurrindent++;
|
|
} else {
|
|
findent();
|
|
}
|
|
|
|
/* output the line */
|
|
xputs(p);
|
|
xputc('\n');
|
|
|
|
/* back at indentation level 0? then we can flush our buffers */
|
|
/* first the variables then the other lines */
|
|
if (!xcurrindent) {
|
|
yflush();
|
|
xflush();
|
|
}
|
|
|
|
/* undo indentation of non-braced if/else/switch/for/while/do stmt */
|
|
if (xindentflag) {
|
|
xcurrindent--;
|
|
xindentflag = 0;
|
|
}
|
|
|
|
/* indent after opening brace */
|
|
if (p[strlen(p) - 1] == '{') {
|
|
xcurrindent++;
|
|
xindentflag = 0;
|
|
|
|
/* indent one line after if/else/switch/for/while/do stmt */
|
|
} else if (l == 2 && !memcmp(p, "if", l) ||
|
|
l == 4 && !memcmp(p, "else", l) ||
|
|
l == 6 && !memcmp(p, "switch", l) ||
|
|
l == 3 && !memcmp(p, "for", l) ||
|
|
l == 5 && !memcmp(p, "while", l) ||
|
|
l == 2 && !memcmp(p, "do", l)) {
|
|
xcurrindent++;
|
|
xindentflag = 1;
|
|
}
|
|
}
|
|
|
|
/* empty buffer after printing */
|
|
pos = 0;
|
|
}
|
|
|
|
/* output function doing indentation automatically */
|
|
/*PRINTFLIKE1*/
|
|
void
|
|
output(const char *format, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
outputv(format, args);
|
|
va_end(args);
|
|
}
|
|
|
|
/* output function without indentation */
|
|
void
|
|
outputniv(const char *format, va_list args)
|
|
{
|
|
static char buf[512];
|
|
|
|
vsprintf(buf, format, args);
|
|
xputs(buf);
|
|
}
|
|
|
|
/* output function without indentation */
|
|
/*PRINTFLIKE1*/
|
|
void
|
|
outputni(const char *format, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
outputniv(format, args);
|
|
va_end(args);
|
|
}
|
|
|
|
/* output an intx value definition */
|
|
void
|
|
outputintx(const char *name, intx_t *val)
|
|
{
|
|
outputoctets(name, val->length, val->value);
|
|
output("static ASN1intx_t %s = { %d, %s_octets };\n",
|
|
name, val->length, name);
|
|
}
|
|
|
|
/* output an real value definition */
|
|
void
|
|
outputreal(const char *name, real_t *val)
|
|
{
|
|
char buf[256];
|
|
switch (val->type) {
|
|
case eReal_Normal:
|
|
sprintf(buf, "%s_mantissa", name);
|
|
outputoctets(buf, val->mantissa.length, val->mantissa.value);
|
|
sprintf(buf, "%s_exponent", name);
|
|
outputoctets(buf, val->exponent.length, val->exponent.value);
|
|
output("ASN1real_t %s = { eReal_Normal, { %u, %s_mantissa_octets }, %u, { %u, %s_exponent_octets } };\n",
|
|
name, val->mantissa.length, name,
|
|
val->base, val->exponent.length, name);
|
|
break;
|
|
case eReal_PlusInfinity:
|
|
output("ASN1real_t %s = { eReal_PlusInfinity };\n", name);
|
|
break;
|
|
case eReal_MinusInfinity:
|
|
output("ASN1real_t %s = { eReal_MinusInfinity };\n", name);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* output an octet array definition */
|
|
void
|
|
outputoctets(const char *name, uint32_t length, octet_t *val)
|
|
{
|
|
uint32_t i;
|
|
char buf[1024];
|
|
char *p;
|
|
|
|
p = buf;
|
|
for (i = 0; i < length; i++) {
|
|
sprintf(p, "0x%02x", val[i]);
|
|
p += 4;
|
|
if (i < length - 1) {
|
|
sprintf(p, ", ");
|
|
p += 2;
|
|
}
|
|
}
|
|
*p = 0;
|
|
output("static ASN1octet_t %s_octets[%u] = { %s };\n",
|
|
name, length, buf);
|
|
}
|
|
|
|
/* output an uint32 array definition */
|
|
void
|
|
outputuint32s(const char *name, uint32_t length, uint32_t *val)
|
|
{
|
|
uint32_t i;
|
|
char buf[256];
|
|
char *p;
|
|
|
|
p = buf;
|
|
for (i = 0; i < length; i++) {
|
|
sprintf(p, "%u", val[i]);
|
|
p += strlen(p);
|
|
if (i < length - 1) {
|
|
sprintf(p, ", ");
|
|
p += 2;
|
|
}
|
|
}
|
|
*p = 0;
|
|
output("static ASN1uint32_t %s_elems[%u] = { %s };\n",
|
|
name, length, buf);
|
|
}
|
|
|
|
/* output forward declaration for a value */
|
|
void
|
|
outputvalue0(AssignmentList_t ass, char *ideref, char *typeref, Value_t *value)
|
|
{
|
|
Type_t *type;
|
|
char buf[256];
|
|
char *itype;
|
|
int32_t noctets;
|
|
uint32_t zero;
|
|
uint32_t i;
|
|
Value_t *values;
|
|
Component_t *components;
|
|
NamedValue_t *namedvalue;
|
|
int32_t sign;
|
|
char *pszStatic = "extern";
|
|
|
|
value = GetValue(ass, value);
|
|
type = GetType(ass, value->Type);
|
|
value = GetValue(ass, value);
|
|
switch (type->Type) {
|
|
case eType_Integer:
|
|
itype = GetIntegerType(ass, type, &sign);
|
|
if (!strcmp(itype, "ASN1intx_t")) {
|
|
output("%s ASN1octet_t %s_octets[%u];\n", pszStatic,
|
|
ideref, value->U.Integer.Value.length);
|
|
}
|
|
break;
|
|
case eType_Real:
|
|
itype = GetRealType(type);
|
|
if (!strcmp(itype, "ASN1real_t"))
|
|
{
|
|
switch (value->U.Real.Value.type) {
|
|
case eReal_Normal:
|
|
output("%s ASN1octet_t %s_mantissa_octets[%u];\n", pszStatic,
|
|
ideref, value->U.Real.Value.mantissa.length);
|
|
output("%s ASN1octet_t %s_exponent_octets[%u];\n", pszStatic,
|
|
ideref, value->U.Real.Value.exponent.length);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case eType_BitString:
|
|
output("%s ASN1octet_t %s_octets[%u];\n", pszStatic,
|
|
ideref, (value->U.BitString.Value.length + 7) / 8);
|
|
break;
|
|
case eType_OctetString:
|
|
output("%s ASN1octet_t %s_octets[%u];\n", pszStatic,
|
|
ideref, value->U.OctetString.Value.length);
|
|
break;
|
|
case eType_UTF8String:
|
|
output("%s ASN1wchar_t %s_wchars[%u];\n", pszStatic,
|
|
ideref, value->U.UTF8String.Value.length);
|
|
break;
|
|
case eType_ObjectIdentifier:
|
|
if (type->PrivateDirectives.fOidPacked ||
|
|
type->PrivateDirectives.fOidArray || g_fOidArray)
|
|
{
|
|
// doing nothing
|
|
}
|
|
else
|
|
{
|
|
output("%s ASN1uint32_t %s_elems[%u];\n", pszStatic,
|
|
ideref, value->U.ObjectIdentifier.Value.length);
|
|
}
|
|
break;
|
|
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_RestrictedString:
|
|
itype = GetStringType(ass, type, &noctets, &zero);
|
|
switch (noctets) {
|
|
case 1:
|
|
output("%s ASN1char_t %s_chars[%u];\n", pszStatic,
|
|
ideref, value->U.RestrictedString.Value.length + zero);
|
|
break;
|
|
case 2:
|
|
output("%s ASN1char16_t %s_chars[%u];\n", pszStatic,
|
|
ideref, value->U.RestrictedString.Value.length + zero);
|
|
break;
|
|
case 4:
|
|
output("%s ASN1char32_t %s_chars[%u];\n", pszStatic,
|
|
ideref, value->U.RestrictedString.Value.length + zero);
|
|
break;
|
|
}
|
|
break;
|
|
case eType_ObjectDescriptor:
|
|
output("%s ASN1char_t %s_chars[%u];\n", pszStatic,
|
|
ideref, value->U.ObjectDescriptor.Value.length + 1);
|
|
break;
|
|
case eType_SequenceOf:
|
|
case eType_SetOf:
|
|
if (type->Rules & (eTypeRules_LengthPointer | eTypeRules_FixedArray))
|
|
{
|
|
for (i = 0, values = value->U.SS.Values; values;
|
|
i++, values = values->Next) {}
|
|
if (value->U.SS.Values) {
|
|
for (i = 0, values = value->U.SS.Values; values;
|
|
i++, values = values->Next) {
|
|
sprintf(buf, "%s_value%d", ideref, i);
|
|
outputvalue0(ass, buf,
|
|
GetTypeName(ass, type->U.SS.Type), values);
|
|
}
|
|
output("%s %s %s_values[%u];\n", pszStatic,
|
|
GetTypeName(ass, type->U.SS.Type),
|
|
ideref, i);
|
|
}
|
|
}
|
|
else
|
|
if (type->Rules & (eTypeRules_SinglyLinkedList | eTypeRules_DoublyLinkedList))
|
|
{
|
|
for (i = 0, values = value->U.SS.Values; values;
|
|
i++, values = values->Next) {
|
|
sprintf(buf, "%s_element%d", ideref, i);
|
|
outputvalue0(ass, buf, GetTypeName(ass, type->U.SS.Type),
|
|
values);
|
|
output("%s %s_Element %s_value%d;\n", pszStatic,
|
|
typeref, ideref, i);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MyAbort();
|
|
}
|
|
break;
|
|
case eType_Sequence:
|
|
case eType_Set:
|
|
case eType_External:
|
|
case eType_EmbeddedPdv:
|
|
case eType_CharacterString:
|
|
case eType_InstanceOf:
|
|
for (components = type->U.SSC.Components; components;
|
|
components = components->Next) {
|
|
switch (components->Type) {
|
|
case eComponent_Normal:
|
|
case eComponent_Optional:
|
|
case eComponent_Default:
|
|
namedvalue = FindNamedValue(value->U.SSC.NamedValues,
|
|
components->U.NOD.NamedType->Identifier);
|
|
if (!namedvalue)
|
|
break;
|
|
sprintf(buf, "%s_%s", ideref,
|
|
Identifier2C(components->U.NOD.NamedType->Identifier));
|
|
outputvalue0(ass, buf,
|
|
GetTypeName(ass, components->U.NOD.NamedType->Type),
|
|
namedvalue->Value);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* output definitions of value components */
|
|
void
|
|
outputvalue1(AssignmentList_t ass, char *ideref, char *typeref, Value_t *value)
|
|
{
|
|
static uint32_t nOidPackedCount = 0;
|
|
Type_t *type;
|
|
char buf[256];
|
|
char *itype;
|
|
int32_t noctets;
|
|
uint32_t zero;
|
|
uint32_t i;
|
|
Value_t *values;
|
|
Component_t *components;
|
|
NamedValue_t *namedvalue;
|
|
int32_t sign;
|
|
|
|
value = GetValue(ass, value);
|
|
type = GetType(ass, value->Type);
|
|
value = GetValue(ass, value);
|
|
switch (type->Type) {
|
|
case eType_Integer:
|
|
itype = GetIntegerType(ass, type, &sign);
|
|
if (!strcmp(itype, "ASN1intx_t")) {
|
|
outputoctets(ideref, value->U.Integer.Value.length,
|
|
value->U.Integer.Value.value);
|
|
}
|
|
break;
|
|
case eType_Real:
|
|
itype = GetRealType(type);
|
|
if (!strcmp(itype, "ASN1real_t")) {
|
|
switch (value->U.Real.Value.type) {
|
|
case eReal_Normal:
|
|
sprintf(buf, "%s_mantissa", ideref);
|
|
outputoctets(buf, value->U.Real.Value.mantissa.length,
|
|
value->U.Real.Value.mantissa.value);
|
|
sprintf(buf, "%s_exponent", ideref);
|
|
outputoctets(buf, value->U.Real.Value.exponent.length,
|
|
value->U.Real.Value.exponent.value);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case eType_BitString:
|
|
outputoctets(ideref, (value->U.BitString.Value.length + 7) / 8,
|
|
value->U.BitString.Value.value);
|
|
break;
|
|
case eType_OctetString:
|
|
outputoctets(ideref, value->U.OctetString.Value.length,
|
|
value->U.OctetString.Value.value);
|
|
break;
|
|
case eType_UTF8String:
|
|
itype = GetStringType(ass, type, &noctets, &zero);
|
|
output("static ASN1wchar_t %s_wchars[%u] = { ",
|
|
ideref, value->U.UTF8String.Value.length + zero);
|
|
for (i = 0; i < value->U.UTF8String.Value.length; i++) {
|
|
output("0x%x", value->U.UTF8String.Value.value[i]);
|
|
if (i < value->U.UTF8String.Value.length - 1)
|
|
output(", ");
|
|
}
|
|
if (zero) {
|
|
if (value->U.UTF8String.Value.length)
|
|
output(", 0x0");
|
|
else
|
|
output("0x0");
|
|
}
|
|
output(" };\n");
|
|
break;
|
|
case eType_ObjectIdentifier:
|
|
if (type->PrivateDirectives.fOidPacked)
|
|
{
|
|
uint32_t length = value->U.ObjectIdentifier.Value.length;
|
|
uint32_t *val = value->U.ObjectIdentifier.Value.value;
|
|
uint32_t i, j, cb;
|
|
uint32_t count = 0;
|
|
uint32_t node;
|
|
unsigned char aLittleEndian[16];
|
|
char buf[1024];
|
|
char *p = buf;
|
|
sprintf(p, "{");
|
|
p += strlen(p);
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
// get node value
|
|
node = val[i];
|
|
|
|
// special case for the first node
|
|
if (0 == i && length > 1)
|
|
{
|
|
i++;
|
|
node = node * 40 + val[1];
|
|
}
|
|
|
|
// encode this node
|
|
ZeroMemory(aLittleEndian, sizeof(aLittleEndian));
|
|
for (j = 0; node != 0; j++)
|
|
{
|
|
aLittleEndian[j] = (unsigned char) (node & 0x7f);
|
|
if (j != 0)
|
|
{
|
|
aLittleEndian[j] |= (unsigned char) 0x80;
|
|
}
|
|
node >>= 7;
|
|
}
|
|
cb = j ? j : 1; // at least one byte for zero value
|
|
|
|
// print out the values
|
|
for (j = 0; j < cb; j ++)
|
|
{
|
|
count++;
|
|
sprintf(p, " %u,", (unsigned char) aLittleEndian[cb - j - 1]);
|
|
p += strlen(p);
|
|
}
|
|
}
|
|
--p; // remove the last ','
|
|
strcpy(p, " }");
|
|
output("static ASN1octet_t s_oid%u[] = %s;\n", nOidPackedCount, buf);
|
|
output("ASN1encodedOID_t %s = { %u, s_oid%u };\n", ideref, count, nOidPackedCount);
|
|
nOidPackedCount++;
|
|
}
|
|
else
|
|
if (type->PrivateDirectives.fOidArray || g_fOidArray)
|
|
{
|
|
uint32_t length = value->U.ObjectIdentifier.Value.length;
|
|
uint32_t *val = value->U.ObjectIdentifier.Value.value;
|
|
uint32_t i;
|
|
char buf[1024];
|
|
char *p = buf;
|
|
sprintf(p, "{ ");
|
|
p += strlen(p);
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
if (i == length - 1)
|
|
{
|
|
sprintf(p, "%u }", val[i]);
|
|
}
|
|
else
|
|
{
|
|
sprintf(p, "%u, ", val[i]);
|
|
}
|
|
p += strlen(p);
|
|
}
|
|
*p = 0;
|
|
output("ASN1objectidentifier2_t %s = {\n%u, %s\n};\n", ideref, length, buf);
|
|
}
|
|
else
|
|
{
|
|
uint32_t length = value->U.ObjectIdentifier.Value.length;
|
|
uint32_t *val = value->U.ObjectIdentifier.Value.value;
|
|
uint32_t i;
|
|
char buf[1024];
|
|
char *p = buf;
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
if (i == length - 1)
|
|
{
|
|
sprintf(p, "{ NULL, %u }", val[i]);
|
|
}
|
|
else
|
|
{
|
|
sprintf(p, "{ (ASN1objectidentifier_t) &(%s_list[%u]), %u },\n", ideref, i+1, val[i]);
|
|
}
|
|
p += strlen(p);
|
|
}
|
|
*p = 0;
|
|
output("static const struct ASN1objectidentifier_s %s_list[%u] = {\n%s\n};\n",
|
|
ideref, length, buf);
|
|
}
|
|
break;
|
|
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_RestrictedString:
|
|
itype = GetStringType(ass, type, &noctets, &zero);
|
|
switch (noctets) {
|
|
case 1:
|
|
output("static ASN1char_t %s_chars[%u] = { ",
|
|
ideref, value->U.RestrictedString.Value.length + zero);
|
|
break;
|
|
case 2:
|
|
output("static ASN1char16_t %s_chars[%u] = { ",
|
|
ideref, value->U.RestrictedString.Value.length + zero);
|
|
break;
|
|
case 4:
|
|
output("static ASN1char32_t %s_chars[%u] = { ",
|
|
ideref, value->U.RestrictedString.Value.length + zero);
|
|
break;
|
|
}
|
|
for (i = 0; i < value->U.RestrictedString.Value.length; i++) {
|
|
output("0x%x", value->U.RestrictedString.Value.value[i]);
|
|
if (i < value->U.RestrictedString.Value.length - 1)
|
|
output(", ");
|
|
}
|
|
if (zero) {
|
|
if (value->U.RestrictedString.Value.length)
|
|
output(", 0x0");
|
|
else
|
|
output("0x0");
|
|
}
|
|
output(" };\n");
|
|
break;
|
|
case eType_ObjectDescriptor:
|
|
output("static ASN1char_t %s_chars[%u] = { ",
|
|
ideref, value->U.ObjectDescriptor.Value.length + 1);
|
|
for (i = 0; i < value->U.ObjectDescriptor.Value.length; i++) {
|
|
output("0x%x, ", value->U.ObjectDescriptor.Value.value[i]);
|
|
}
|
|
output("0x0 };\n");
|
|
break;
|
|
case eType_SequenceOf:
|
|
case eType_SetOf:
|
|
if (type->Rules &
|
|
(eTypeRules_LengthPointer | eTypeRules_FixedArray)) {
|
|
if (value->U.SS.Values) {
|
|
for (i = 0, values = value->U.SS.Values; values;
|
|
i++, values = values->Next) {
|
|
sprintf(buf, "%s_value%d", ideref, i);
|
|
outputvalue1(ass, buf,
|
|
GetTypeName(ass, type->U.SS.Type),
|
|
values);
|
|
}
|
|
output("static %s %s_values[%u] = { ",
|
|
GetTypeName(ass, type->U.SS.Type),
|
|
ideref, i);
|
|
for (i = 0, values = value->U.SS.Values; values;
|
|
i++, values = values->Next) {
|
|
if (i)
|
|
output(", ");
|
|
sprintf(buf, "%s_value%d", ideref, i);
|
|
outputvalue2(ass, buf, values);
|
|
}
|
|
output(" };\n");
|
|
}
|
|
} else if (type->Rules &
|
|
(eTypeRules_SinglyLinkedList | eTypeRules_DoublyLinkedList)) {
|
|
for (i = 0, values = value->U.SS.Values; values;
|
|
i++, values = values->Next) {
|
|
sprintf(buf, "%s_element%d", ideref, i);
|
|
outputvalue1(ass, buf, GetTypeName(ass, type->U.SS.Type),
|
|
values);
|
|
}
|
|
for (i = 0, values = value->U.SS.Values; values;
|
|
i++, values = values->Next) {
|
|
output("static %s_Element %s_value%d = { ",
|
|
typeref, ideref, i);
|
|
if (values->Next)
|
|
output("&%s_value%d, ", ideref, i + 1);
|
|
else
|
|
output("0, ");
|
|
if (type->Rules & eTypeRules_DoublyLinkedList) {
|
|
if (i)
|
|
output("&%s_value%d, ", ideref, i - 1);
|
|
else
|
|
output("0, ");
|
|
}
|
|
sprintf(buf, "%s_element%d", ideref, i);
|
|
outputvalue2(ass, buf, values);
|
|
output(" };\n");
|
|
}
|
|
} else {
|
|
MyAbort();
|
|
}
|
|
break;
|
|
case eType_Sequence:
|
|
case eType_Set:
|
|
case eType_External:
|
|
case eType_EmbeddedPdv:
|
|
case eType_CharacterString:
|
|
case eType_InstanceOf:
|
|
for (components = type->U.SSC.Components; components;
|
|
components = components->Next) {
|
|
switch (components->Type) {
|
|
case eComponent_Normal:
|
|
case eComponent_Optional:
|
|
case eComponent_Default:
|
|
namedvalue = FindNamedValue(value->U.SSC.NamedValues,
|
|
components->U.NOD.NamedType->Identifier);
|
|
if (!namedvalue)
|
|
break;
|
|
sprintf(buf, "%s_%s", ideref,
|
|
Identifier2C(components->U.NOD.NamedType->Identifier));
|
|
outputvalue1(ass, buf,
|
|
GetTypeName(ass, components->U.NOD.NamedType->Type),
|
|
namedvalue->Value);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case eType_Choice:
|
|
namedvalue = value->U.Choice.NamedValues;
|
|
components = FindComponent(ass, type->U.Choice.Components,
|
|
namedvalue->Identifier);
|
|
sprintf(buf, "%s_%s", ideref,
|
|
Identifier2C(components->U.NOD.NamedType->Identifier));
|
|
outputvalue1(ass, buf, GetTypeName(ass,
|
|
components->U.NOD.NamedType->Type),
|
|
namedvalue->Value);
|
|
output("static %s %s = ",
|
|
GetTypeName(ass, components->U.NOD.NamedType->Type), buf);
|
|
outputvalue2(ass, buf, namedvalue->Value);
|
|
output(";\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* output definition of value */
|
|
void
|
|
outputvalue2(AssignmentList_t ass, char *ideref, Value_t *value)
|
|
{
|
|
Type_t *type;
|
|
char buf[256];
|
|
char *itype;
|
|
int32_t noctets;
|
|
uint32_t zero;
|
|
uint32_t i;
|
|
Value_t *values;
|
|
Component_t *components;
|
|
NamedValue_t *namedvalue;
|
|
char *comma;
|
|
uint32_t ext;
|
|
uint32_t opt;
|
|
int32_t sign;
|
|
|
|
value = GetValue(ass, value);
|
|
type = GetType(ass, value->Type);
|
|
value = GetValue(ass, value);
|
|
switch (type->Type) {
|
|
case eType_Boolean:
|
|
output("%d", value->U.Boolean.Value);
|
|
break;
|
|
case eType_Integer:
|
|
itype = GetIntegerType(ass, type, &sign);
|
|
if (!strcmp(itype, "ASN1intx_t")) {
|
|
output("{ %d, %s_octets }", value->U.Integer.Value.length, ideref);
|
|
} else if (sign > 0) {
|
|
output("%u", intx2uint32(&value->U.Integer.Value));
|
|
} else {
|
|
output("%d", intx2int32(&value->U.Integer.Value));
|
|
}
|
|
break;
|
|
case eType_Enumerated:
|
|
output("%u", value->U.Enumerated.Value);
|
|
break;
|
|
case eType_Real:
|
|
itype = GetRealType(type);
|
|
if (!strcmp(itype, "ASN1real_t")) {
|
|
switch (value->U.Real.Value.type) {
|
|
case eReal_Normal:
|
|
output("{ eReal_Normal, { %u, %s_mantissa_octets }, %u, { %u, %s_exponent_octets } }",
|
|
value->U.Real.Value.mantissa.length, ideref,
|
|
value->U.Real.Value.base,
|
|
value->U.Real.Value.exponent.length, ideref);
|
|
break;
|
|
case eReal_PlusInfinity:
|
|
output("{ eReal_PlusInfinity }");
|
|
break;
|
|
case eReal_MinusInfinity:
|
|
output("{ eReal_MinusInfinity }");
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (value->U.Real.Value.type) {
|
|
case eReal_Normal:
|
|
output("%g", real2double(&value->U.Real.Value));
|
|
break;
|
|
case eReal_PlusInfinity:
|
|
case eReal_MinusInfinity:
|
|
output("0.0");
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case eType_BitString:
|
|
output("{ %u, %s_octets }",
|
|
value->U.BitString.Value.length, ideref);
|
|
break;
|
|
case eType_OctetString:
|
|
output("{ %u, %s_octets }",
|
|
value->U.OctetString.Value.length, ideref);
|
|
break;
|
|
case eType_UTF8String:
|
|
output("{ %u, %s_utf8chars }",
|
|
value->U.UTF8String.Value.length, ideref);
|
|
break;
|
|
case eType_ObjectIdentifier:
|
|
if (type->PrivateDirectives.fOidPacked)
|
|
{
|
|
// doing nothing
|
|
}
|
|
else
|
|
if (type->PrivateDirectives.fOidArray || g_fOidArray)
|
|
{
|
|
output("(ASN1objectidentifier2_t *) &%s_list", ideref);
|
|
}
|
|
else
|
|
{
|
|
output("(ASN1objectidentifier_t) %s_list", ideref);
|
|
}
|
|
break;
|
|
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_RestrictedString:
|
|
itype = GetStringType(ass, type, &noctets, &zero);
|
|
if (zero) {
|
|
output("%s_chars", ideref);
|
|
} else {
|
|
output("{ %u, %s_chars }",
|
|
value->U.RestrictedString.Value.length, ideref);
|
|
}
|
|
break;
|
|
case eType_ObjectDescriptor:
|
|
output("%s_chars", ideref);
|
|
break;
|
|
case eType_GeneralizedTime:
|
|
output("{ %d, %d, %d, %d, %d, %d, %d, %d, %d }",
|
|
value->U.GeneralizedTime.Value.year,
|
|
value->U.GeneralizedTime.Value.month,
|
|
value->U.GeneralizedTime.Value.day,
|
|
value->U.GeneralizedTime.Value.hour,
|
|
value->U.GeneralizedTime.Value.minute,
|
|
value->U.GeneralizedTime.Value.second,
|
|
value->U.GeneralizedTime.Value.millisecond,
|
|
value->U.GeneralizedTime.Value.universal,
|
|
value->U.GeneralizedTime.Value.diff);
|
|
break;
|
|
case eType_UTCTime:
|
|
output("{ %d, %d, %d, %d, %d, %d, %d, %d }",
|
|
value->U.UTCTime.Value.year,
|
|
value->U.UTCTime.Value.month,
|
|
value->U.UTCTime.Value.day,
|
|
value->U.UTCTime.Value.hour,
|
|
value->U.UTCTime.Value.minute,
|
|
value->U.UTCTime.Value.second,
|
|
value->U.UTCTime.Value.universal,
|
|
value->U.UTCTime.Value.diff);
|
|
break;
|
|
case eType_SequenceOf:
|
|
case eType_SetOf:
|
|
if (type->Rules &
|
|
(eTypeRules_LengthPointer | eTypeRules_FixedArray)) {
|
|
if (value->U.SS.Values) {
|
|
for (i = 0, values = value->U.SS.Values; values;
|
|
i++, values = values->Next) {}
|
|
output("{ %d, %s_values }", i, ideref);
|
|
} else {
|
|
output("{ 0, NULL }");
|
|
}
|
|
} else if (type->Rules &
|
|
(eTypeRules_SinglyLinkedList | eTypeRules_DoublyLinkedList)) {
|
|
output("&%s_value0", ideref);
|
|
} else {
|
|
MyAbort();
|
|
}
|
|
break;
|
|
case eType_Sequence:
|
|
case eType_Set:
|
|
case eType_External:
|
|
case eType_EmbeddedPdv:
|
|
case eType_CharacterString:
|
|
case eType_InstanceOf:
|
|
comma = "";
|
|
output("{ ");
|
|
if (type->U.SSC.Optionals || type->U.SSC.Extensions) {
|
|
output("{ ");
|
|
ext = 0;
|
|
opt = 0;
|
|
i = 0;
|
|
comma = "";
|
|
for (components = type->U.SSC.Components; components;
|
|
components = components->Next) {
|
|
switch (components->Type) {
|
|
case eComponent_Normal:
|
|
if (!ext)
|
|
break;
|
|
/*FALLTHROUGH*/
|
|
case eComponent_Optional:
|
|
case eComponent_Default:
|
|
namedvalue = FindNamedValue(value->U.SSC.NamedValues,
|
|
components->U.NOD.NamedType->Identifier);
|
|
if (namedvalue)
|
|
opt |= (0x80 >> i);
|
|
if (++i > 7) {
|
|
output("%s0x%02x", comma, opt);
|
|
opt = 0;
|
|
i = 0;
|
|
comma = ", ";
|
|
}
|
|
break;
|
|
case eComponent_ExtensionMarker:
|
|
if (i) {
|
|
output("%s0x%02x", comma, opt);
|
|
opt = 0;
|
|
i = 0;
|
|
comma = ", ";
|
|
}
|
|
ext = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (i)
|
|
output("%s0x%02x", comma, opt);
|
|
output(" }");
|
|
comma = ", ";
|
|
}
|
|
for (components = type->U.SSC.Components; components;
|
|
components = components->Next) {
|
|
switch (components->Type) {
|
|
case eComponent_Normal:
|
|
case eComponent_Optional:
|
|
case eComponent_Default:
|
|
namedvalue = FindNamedValue(value->U.SSC.NamedValues,
|
|
components->U.NOD.NamedType->Identifier);
|
|
if (!namedvalue) {
|
|
output("%s0", comma);
|
|
} else {
|
|
output("%s", comma);
|
|
sprintf(buf, "%s_%s", ideref,
|
|
Identifier2C(components->U.NOD.NamedType->Identifier));
|
|
outputvalue2(ass, buf, namedvalue->Value);
|
|
}
|
|
comma = ", ";
|
|
break;
|
|
}
|
|
}
|
|
output(" }");
|
|
break;
|
|
case eType_Choice:
|
|
i = ASN1_CHOICE_BASE;
|
|
for (components = type->U.SSC.Components; components;
|
|
components = components->Next) {
|
|
switch (components->Type) {
|
|
case eComponent_Normal:
|
|
if (!strcmp(value->U.SSC.NamedValues->Identifier,
|
|
components->U.NOD.NamedType->Identifier))
|
|
break;
|
|
i++;
|
|
continue;
|
|
case eComponent_ExtensionMarker:
|
|
continue;
|
|
default:
|
|
MyAbort();
|
|
}
|
|
break;
|
|
}
|
|
output("{ %d }", i);
|
|
}
|
|
}
|
|
|
|
/* output assignments needed in initialization function */
|
|
void
|
|
outputvalue3(AssignmentList_t ass, char *ideref, char *valref, Value_t *value)
|
|
{
|
|
Type_t *type;
|
|
NamedValue_t *named;
|
|
Value_t *values;
|
|
int i;
|
|
char idebuf[256];
|
|
char valbuf[256];
|
|
char *itype;
|
|
|
|
value = GetValue(ass, value);
|
|
type = GetType(ass, value->Type);
|
|
switch (type->Type) {
|
|
case eType_SequenceOf:
|
|
case eType_SetOf:
|
|
for (values = value->U.SS.Values, i = 0; values;
|
|
values = values->Next, i++) {
|
|
if (type->Rules &
|
|
(eTypeRules_LengthPointer | eTypeRules_FixedArray)) {
|
|
sprintf(idebuf, "%s.value[%d]", ideref, i);
|
|
} else if (type->Rules &
|
|
(eTypeRules_SinglyLinkedList | eTypeRules_DoublyLinkedList)) {
|
|
sprintf(idebuf, "%s_value%d", ideref, i);
|
|
} else {
|
|
MyAbort();
|
|
}
|
|
sprintf(valbuf, "%s_value%d", valref, i);
|
|
outputvalue3(ass, idebuf, valbuf, values);
|
|
}
|
|
break;
|
|
case eType_Choice:
|
|
output("%s.u.%s = %s_%s;\n",
|
|
ideref, Identifier2C(value->U.SSC.NamedValues->Identifier),
|
|
valref, Identifier2C(value->U.SSC.NamedValues->Identifier));
|
|
/*FALLTHROUGH*/
|
|
case eType_Sequence:
|
|
case eType_Set:
|
|
case eType_External:
|
|
case eType_EmbeddedPdv:
|
|
case eType_CharacterString:
|
|
case eType_InstanceOf:
|
|
for (named = value->U.SSC.NamedValues; named; named = named->Next) {
|
|
sprintf(idebuf, "%s.%s", ideref,
|
|
Identifier2C(named->Identifier));
|
|
sprintf(valbuf, "%s_%s", valref,
|
|
Identifier2C(named->Identifier));
|
|
outputvalue3(ass, idebuf, valbuf, named->Value);
|
|
}
|
|
break;
|
|
case eType_Real:
|
|
itype = GetRealType(type);
|
|
if (strcmp(itype, "ASN1real_t"))
|
|
{
|
|
switch (value->U.Real.Value.type) {
|
|
case eReal_Normal:
|
|
break;
|
|
case eReal_PlusInfinity:
|
|
output("%s = ASN1double_pinf();\n", ideref);
|
|
break;
|
|
case eReal_MinusInfinity:
|
|
output("%s = ASN1double_minf();\n", ideref);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* print indentation up to current indentation level for variables */
|
|
static void
|
|
findentvar()
|
|
{
|
|
int indent;
|
|
|
|
indent = ycurrindent * INDENT;
|
|
while (indent >= TABSIZE) {
|
|
yputc('\t');
|
|
indent -= TABSIZE;
|
|
}
|
|
while (indent--)
|
|
yputc(' ');
|
|
}
|
|
|
|
/* print indentation up to current indentation level for variables */
|
|
void
|
|
outputvarv(const char *format, va_list args)
|
|
{
|
|
static char buf[512];
|
|
static int pos = 0;
|
|
char *p, *q;
|
|
int l;
|
|
|
|
/* get the string to write */
|
|
vsprintf(buf + pos, format, args);
|
|
|
|
/* print it line by line */
|
|
for (p = buf; *p; p = q) {
|
|
q = strchr(p, '\n');
|
|
if (!q) {
|
|
for (q = buf; *p;)
|
|
*q++ = *p++;
|
|
*q = 0;
|
|
pos = q - buf;
|
|
return;
|
|
}
|
|
*q++ = 0;
|
|
|
|
/* output every variable only once */
|
|
if (ycurrindent == 1) {
|
|
l = 0;
|
|
while (l < ybuflen) {
|
|
if (!memcmp(ybuf + l + INDENT / TABSIZE + INDENT % TABSIZE,
|
|
p, strlen(p)))
|
|
break;
|
|
l += (strchr(ybuf + l, '\n') - (ybuf + l)) + 1;
|
|
}
|
|
if (l < ybuflen)
|
|
continue;
|
|
}
|
|
|
|
/* examine the first character for correct indentation */
|
|
if (strchr(IDCHRSET, *p)) {
|
|
l = strspn(p, IDCHRSET);
|
|
} else if (*p == '{' || *p == '}') {
|
|
l = 1;
|
|
} else {
|
|
l = 0;
|
|
}
|
|
|
|
if (!l) {
|
|
|
|
/* no indentation at all */
|
|
yputs(p);
|
|
yputc('\n');
|
|
continue;
|
|
}
|
|
|
|
/* closing brace? then unindent */
|
|
if (p[0] == '}')
|
|
ycurrindent--;
|
|
|
|
/* print indentation */
|
|
findentvar();
|
|
|
|
/* output the line */
|
|
yputs(p);
|
|
yputc('\n');
|
|
|
|
/* indent after opening brace */
|
|
if (p[strlen(p) - 1] == '{') {
|
|
ycurrindent++;
|
|
}
|
|
}
|
|
pos = 0;
|
|
}
|
|
|
|
/* print indentation up to current indentation level for variables */
|
|
/*PRINTFLIKE1*/
|
|
void
|
|
outputvar(const char *format, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
outputvarv(format, args);
|
|
va_end(args);
|
|
}
|
|
|
|
/* output an octet array definition for variables */
|
|
void
|
|
outputvaroctets(const char *name, uint32_t length, octet_t *val)
|
|
{
|
|
uint32_t i;
|
|
char buf[256];
|
|
char *p;
|
|
|
|
p = buf;
|
|
for (i = 0; i < length; i++) {
|
|
sprintf(p, "0x%02x", val[i]);
|
|
p += 4;
|
|
if (i < length - 1) {
|
|
sprintf(p, ", ");
|
|
p += 2;
|
|
}
|
|
}
|
|
outputvar("static ASN1octet_t %s_octets[%u] = { %s };\n",
|
|
name, length, buf);
|
|
}
|
|
|
|
/* output an intx value definition for variables */
|
|
void outputvarintx(const char *name, intx_t *val)
|
|
{
|
|
outputvaroctets(name, val->length, val->value);
|
|
outputvar("static ASN1intx_t %s = { %d, %s_octets };\n",
|
|
name, val->length, name);
|
|
}
|
|
|
|
/* output an real value definition for variables */
|
|
void outputvarreal(const char *name, real_t *val)
|
|
{
|
|
char buf[256];
|
|
switch (val->type) {
|
|
case eReal_Normal:
|
|
sprintf(buf, "%s_mantissa", name);
|
|
outputvaroctets(buf, val->mantissa.length, val->mantissa.value);
|
|
sprintf(buf, "%s_exponent", name);
|
|
outputvaroctets(buf, val->exponent.length, val->exponent.value);
|
|
outputvar("ASN1real_t %s = { eReal_Normal, { %u, %s_mantissa_octets }, %u, { %u, %s_exponent_octets } };\n",
|
|
name, val->mantissa.length, name,
|
|
val->base, val->exponent.length, name);
|
|
break;
|
|
case eReal_PlusInfinity:
|
|
outputvar("ASN1real_t %s = { eReal_PlusInfinity };\n", name);
|
|
break;
|
|
case eReal_MinusInfinity:
|
|
outputvar("ASN1real_t %s = { eReal_MinusInfinity };\n", name);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* output a character of the function body */
|
|
void xputc(char c)
|
|
{
|
|
if (xbuflen + 1 > xbufsize) {
|
|
xbufsize += 1024;
|
|
if (!xbuf)
|
|
xbuf = (char *)malloc(xbufsize);
|
|
else
|
|
xbuf = (char *)realloc(xbuf, xbufsize);
|
|
}
|
|
xbuf[xbuflen++] = c;
|
|
}
|
|
|
|
/* output a string of the function body */
|
|
void xputs(char *s)
|
|
{
|
|
int sl;
|
|
|
|
sl = strlen(s);
|
|
if (xbuflen + sl > xbufsize) {
|
|
while (xbuflen + sl > xbufsize)
|
|
xbufsize += 1024;
|
|
if (!xbuf)
|
|
xbuf = (char *)malloc(xbufsize);
|
|
else
|
|
xbuf = (char *)realloc(xbuf, xbufsize);
|
|
}
|
|
memcpy(xbuf + xbuflen, s, sl);
|
|
xbuflen += sl;
|
|
}
|
|
|
|
/* flush the function body into the output file */
|
|
void xflush()
|
|
{
|
|
if (xbuflen) {
|
|
fwrite(xbuf, xbuflen, 1, fout);
|
|
#if 0
|
|
fflush(fout);
|
|
#endif
|
|
xbuflen = 0;
|
|
}
|
|
}
|
|
|
|
/* output a character of the function variables */
|
|
void yputc(char c)
|
|
{
|
|
if (ybuflen + 1 > ybufsize) {
|
|
ybufsize += 1024;
|
|
if (!ybuf)
|
|
ybuf = (char *)malloc(ybufsize);
|
|
else
|
|
ybuf = (char *)realloc(ybuf, ybufsize);
|
|
}
|
|
ybuf[ybuflen++] = c;
|
|
}
|
|
|
|
/* output a string of the function variables */
|
|
void yputs(char *s)
|
|
{
|
|
int sl;
|
|
|
|
sl = strlen(s);
|
|
if (ybuflen + sl > ybufsize) {
|
|
while (ybuflen + sl > ybufsize)
|
|
ybufsize += 1024;
|
|
if (!ybuf)
|
|
ybuf = (char *)malloc(ybufsize);
|
|
else
|
|
ybuf = (char *)realloc(ybuf, ybufsize);
|
|
}
|
|
memcpy(ybuf + ybuflen, s, sl);
|
|
ybuflen += sl;
|
|
}
|
|
|
|
/* flush the function variables into the output file */
|
|
void yflush()
|
|
{
|
|
if (ybuflen) {
|
|
fwrite(ybuf, ybuflen, 1, fout);
|
|
#if 0
|
|
fflush(fout);
|
|
#endif
|
|
ybuflen = 0;
|
|
}
|
|
}
|