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

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;
}
}