155682Smarkm/*
2178825Sdfr * Copyright (c) 1997 - 2005 Kungliga Tekniska H�gskolan
355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden).
455682Smarkm * All rights reserved.
555682Smarkm *
655682Smarkm * Redistribution and use in source and binary forms, with or without
755682Smarkm * modification, are permitted provided that the following conditions
855682Smarkm * are met:
955682Smarkm *
1055682Smarkm * 1. Redistributions of source code must retain the above copyright
1155682Smarkm *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1455682Smarkm *    notice, this list of conditions and the following disclaimer in the
1555682Smarkm *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors
1855682Smarkm *    may be used to endorse or promote products derived from this software
1955682Smarkm *    without specific prior written permission.
2055682Smarkm *
2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2455682Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3155682Smarkm * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include "gen_locl.h"
3555682Smarkm
36178825SdfrRCSID("$Id: gen.c 22429 2008-01-13 10:25:50Z lha $");
3755682Smarkm
3855682SmarkmFILE *headerfile, *codefile, *logfile;
3955682Smarkm
4055682Smarkm#define STEM "asn1"
4155682Smarkm
4272445Sassarstatic const char *orig_filename;
43120945Snectarstatic char *header;
44178825Sdfrstatic const char *headerbase = STEM;
4555682Smarkm
4690926Snectar/*
4790926Snectar * list of all IMPORTs
4890926Snectar */
4990926Snectar
5090926Snectarstruct import {
5190926Snectar    const char *module;
5290926Snectar    struct import *next;
5390926Snectar};
5490926Snectar
5590926Snectarstatic struct import *imports = NULL;
5690926Snectar
5790926Snectarvoid
5890926Snectaradd_import (const char *module)
5990926Snectar{
6090926Snectar    struct import *tmp = emalloc (sizeof(*tmp));
6190926Snectar
6290926Snectar    tmp->module = module;
6390926Snectar    tmp->next   = imports;
6490926Snectar    imports     = tmp;
65178825Sdfr
66178825Sdfr    fprintf (headerfile, "#include <%s_asn1.h>\n", module);
6790926Snectar}
6890926Snectar
6972445Sassarconst char *
70178825Sdfrget_filename (void)
7172445Sassar{
7272445Sassar    return orig_filename;
7372445Sassar}
7472445Sassar
7555682Smarkmvoid
7672445Sassarinit_generate (const char *filename, const char *base)
7755682Smarkm{
78178825Sdfr    char *fn;
79178825Sdfr
8055682Smarkm    orig_filename = filename;
81178825Sdfr    if (base != NULL) {
82178825Sdfr	headerbase = strdup(base);
83178825Sdfr	if (headerbase == NULL)
84178825Sdfr	    errx(1, "strdup");
85178825Sdfr    }
86120945Snectar    asprintf(&header, "%s.h", headerbase);
87178825Sdfr    if (header == NULL)
88178825Sdfr	errx(1, "malloc");
8955682Smarkm    headerfile = fopen (header, "w");
9055682Smarkm    if (headerfile == NULL)
9155682Smarkm	err (1, "open %s", header);
9255682Smarkm    fprintf (headerfile,
9355682Smarkm	     "/* Generated from %s */\n"
9455682Smarkm	     "/* Do not edit */\n\n",
9555682Smarkm	     filename);
9655682Smarkm    fprintf (headerfile,
9755682Smarkm	     "#ifndef __%s_h__\n"
9855682Smarkm	     "#define __%s_h__\n\n", headerbase, headerbase);
9955682Smarkm    fprintf (headerfile,
10055682Smarkm	     "#include <stddef.h>\n"
10155682Smarkm	     "#include <time.h>\n\n");
10255682Smarkm    fprintf (headerfile,
10355682Smarkm	     "#ifndef __asn1_common_definitions__\n"
10455682Smarkm	     "#define __asn1_common_definitions__\n\n");
10555682Smarkm    fprintf (headerfile,
106178825Sdfr	     "typedef struct heim_integer {\n"
10755682Smarkm	     "  size_t length;\n"
10855682Smarkm	     "  void *data;\n"
109178825Sdfr	     "  int negative;\n"
110178825Sdfr	     "} heim_integer;\n\n");
11155682Smarkm    fprintf (headerfile,
112178825Sdfr	     "typedef struct heim_octet_string {\n"
113178825Sdfr	     "  size_t length;\n"
114178825Sdfr	     "  void *data;\n"
115178825Sdfr	     "} heim_octet_string;\n\n");
116178825Sdfr    fprintf (headerfile,
117178825Sdfr	     "typedef char *heim_general_string;\n\n"
11855682Smarkm	     );
11990926Snectar    fprintf (headerfile,
120178825Sdfr	     "typedef char *heim_utf8_string;\n\n"
121178825Sdfr	     );
122178825Sdfr    fprintf (headerfile,
123178825Sdfr	     "typedef char *heim_printable_string;\n\n"
124178825Sdfr	     );
125178825Sdfr    fprintf (headerfile,
126178825Sdfr	     "typedef char *heim_ia5_string;\n\n"
127178825Sdfr	     );
128178825Sdfr    fprintf (headerfile,
129178825Sdfr	     "typedef struct heim_bmp_string {\n"
13090926Snectar	     "  size_t length;\n"
131178825Sdfr	     "  uint16_t *data;\n"
132178825Sdfr	     "} heim_bmp_string;\n\n");
133178825Sdfr    fprintf (headerfile,
134178825Sdfr	     "typedef struct heim_universal_string {\n"
135178825Sdfr	     "  size_t length;\n"
136178825Sdfr	     "  uint32_t *data;\n"
137178825Sdfr	     "} heim_universal_string;\n\n");
138178825Sdfr    fprintf (headerfile,
139178825Sdfr	     "typedef char *heim_visible_string;\n\n"
140178825Sdfr	     );
141178825Sdfr    fprintf (headerfile,
142178825Sdfr	     "typedef struct heim_oid {\n"
143178825Sdfr	     "  size_t length;\n"
14490926Snectar	     "  unsigned *components;\n"
145178825Sdfr	     "} heim_oid;\n\n");
146178825Sdfr    fprintf (headerfile,
147178825Sdfr	     "typedef struct heim_bit_string {\n"
148178825Sdfr	     "  size_t length;\n"
149178825Sdfr	     "  void *data;\n"
150178825Sdfr	     "} heim_bit_string;\n\n");
151178825Sdfr    fprintf (headerfile,
152178825Sdfr	     "typedef struct heim_octet_string heim_any;\n"
153178825Sdfr	     "typedef struct heim_octet_string heim_any_set;\n\n");
154103423Snectar    fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R)                  \\\n"
155103423Snectar	  "  do {                                                         \\\n"
156103423Snectar	  "    (BL) = length_##T((S));                                    \\\n"
157103423Snectar	  "    (B) = malloc((BL));                                        \\\n"
158103423Snectar	  "    if((B) == NULL) {                                          \\\n"
159103423Snectar	  "      (R) = ENOMEM;                                            \\\n"
160103423Snectar	  "    } else {                                                   \\\n"
161103423Snectar	  "      (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n"
162103423Snectar	  "                       (S), (L));                              \\\n"
163103423Snectar	  "      if((R) != 0) {                                           \\\n"
164103423Snectar	  "        free((B));                                             \\\n"
165103423Snectar	  "        (B) = NULL;                                            \\\n"
166103423Snectar	  "      }                                                        \\\n"
167103423Snectar	  "    }                                                          \\\n"
168103423Snectar	  "  } while (0)\n\n",
169103423Snectar	  headerfile);
170178825Sdfr    fprintf (headerfile, "struct units;\n\n");
17155682Smarkm    fprintf (headerfile, "#endif\n\n");
172178825Sdfr    asprintf(&fn, "%s_files", base);
173178825Sdfr    if (fn == NULL)
174178825Sdfr	errx(1, "malloc");
175178825Sdfr    logfile = fopen(fn, "w");
17655682Smarkm    if (logfile == NULL)
177178825Sdfr	err (1, "open %s", fn);
17855682Smarkm}
17955682Smarkm
18055682Smarkmvoid
18172445Sassarclose_generate (void)
18255682Smarkm{
18355682Smarkm    fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
18455682Smarkm
18555682Smarkm    fclose (headerfile);
18655682Smarkm    fprintf (logfile, "\n");
18755682Smarkm    fclose (logfile);
18855682Smarkm}
18955682Smarkm
19055682Smarkmvoid
191178825Sdfrgen_assign_defval(const char *var, struct value *val)
192178825Sdfr{
193178825Sdfr    switch(val->type) {
194178825Sdfr    case stringvalue:
195178825Sdfr	fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue);
196178825Sdfr	break;
197178825Sdfr    case integervalue:
198178825Sdfr	fprintf(codefile, "%s = %d;\n", var, val->u.integervalue);
199178825Sdfr	break;
200178825Sdfr    case booleanvalue:
201178825Sdfr	if(val->u.booleanvalue)
202178825Sdfr	    fprintf(codefile, "%s = TRUE;\n", var);
203178825Sdfr	else
204178825Sdfr	    fprintf(codefile, "%s = FALSE;\n", var);
205178825Sdfr	break;
206178825Sdfr    default:
207178825Sdfr	abort();
208178825Sdfr    }
209178825Sdfr}
210178825Sdfr
211178825Sdfrvoid
212178825Sdfrgen_compare_defval(const char *var, struct value *val)
213178825Sdfr{
214178825Sdfr    switch(val->type) {
215178825Sdfr    case stringvalue:
216178825Sdfr	fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue);
217178825Sdfr	break;
218178825Sdfr    case integervalue:
219178825Sdfr	fprintf(codefile, "if(%s != %d)\n", var, val->u.integervalue);
220178825Sdfr	break;
221178825Sdfr    case booleanvalue:
222178825Sdfr	if(val->u.booleanvalue)
223178825Sdfr	    fprintf(codefile, "if(!%s)\n", var);
224178825Sdfr	else
225178825Sdfr	    fprintf(codefile, "if(%s)\n", var);
226178825Sdfr	break;
227178825Sdfr    default:
228178825Sdfr	abort();
229178825Sdfr    }
230178825Sdfr}
231178825Sdfr
232178825Sdfrstatic void
233178825Sdfrgenerate_header_of_codefile(const char *name)
234178825Sdfr{
235178825Sdfr    char *filename;
236178825Sdfr
237178825Sdfr    if (codefile != NULL)
238178825Sdfr	abort();
239178825Sdfr
240178825Sdfr    asprintf (&filename, "%s_%s.x", STEM, name);
241178825Sdfr    if (filename == NULL)
242178825Sdfr	errx(1, "malloc");
243178825Sdfr    codefile = fopen (filename, "w");
244178825Sdfr    if (codefile == NULL)
245178825Sdfr	err (1, "fopen %s", filename);
246178825Sdfr    fprintf(logfile, "%s ", filename);
247178825Sdfr    free(filename);
248178825Sdfr    fprintf (codefile,
249178825Sdfr	     "/* Generated from %s */\n"
250178825Sdfr	     "/* Do not edit */\n\n"
251178825Sdfr	     "#include <stdio.h>\n"
252178825Sdfr	     "#include <stdlib.h>\n"
253178825Sdfr	     "#include <time.h>\n"
254178825Sdfr	     "#include <string.h>\n"
255178825Sdfr	     "#include <errno.h>\n"
256178825Sdfr	     "#include <limits.h>\n"
257178825Sdfr	     "#include <krb5-types.h>\n",
258178825Sdfr	     orig_filename);
259178825Sdfr
260178825Sdfr    fprintf (codefile,
261178825Sdfr	     "#include <%s.h>\n",
262178825Sdfr	     headerbase);
263178825Sdfr    fprintf (codefile,
264178825Sdfr	     "#include <asn1_err.h>\n"
265178825Sdfr	     "#include <der.h>\n"
266178825Sdfr	     "#include <parse_units.h>\n\n");
267178825Sdfr
268178825Sdfr}
269178825Sdfr
270178825Sdfrstatic void
271178825Sdfrclose_codefile(void)
272178825Sdfr{
273178825Sdfr    if (codefile == NULL)
274178825Sdfr	abort();
275178825Sdfr
276178825Sdfr    fclose(codefile);
277178825Sdfr    codefile = NULL;
278178825Sdfr}
279178825Sdfr
280178825Sdfr
281178825Sdfrvoid
28255682Smarkmgenerate_constant (const Symbol *s)
28355682Smarkm{
284178825Sdfr    switch(s->value->type) {
285178825Sdfr    case booleanvalue:
286178825Sdfr	break;
287178825Sdfr    case integervalue:
288178825Sdfr	fprintf (headerfile, "enum { %s = %d };\n\n",
289178825Sdfr		 s->gen_name, s->value->u.integervalue);
290178825Sdfr	break;
291178825Sdfr    case nullvalue:
292178825Sdfr	break;
293178825Sdfr    case stringvalue:
294178825Sdfr	break;
295178825Sdfr    case objectidentifiervalue: {
296178825Sdfr	struct objid *o, **list;
297178825Sdfr	int i, len;
298178825Sdfr
299178825Sdfr	generate_header_of_codefile(s->gen_name);
300178825Sdfr
301178825Sdfr	len = 0;
302178825Sdfr	for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
303178825Sdfr	    len++;
304178825Sdfr	list = emalloc(sizeof(*list) * len);
305178825Sdfr
306178825Sdfr	i = 0;
307178825Sdfr	for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
308178825Sdfr	    list[i++] = o;
309178825Sdfr
310178825Sdfr	fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name);
311178825Sdfr	for (i = len - 1 ; i >= 0; i--) {
312178825Sdfr	    o = list[i];
313178825Sdfr	    fprintf(headerfile, "%s(%d) ",
314178825Sdfr		    o->label ? o->label : "label-less", o->value);
315178825Sdfr	}
316178825Sdfr
317178825Sdfr	fprintf (headerfile, "} */\n");
318178825Sdfr	fprintf (headerfile, "const heim_oid *oid_%s(void);\n\n",
319178825Sdfr		 s->gen_name);
320178825Sdfr
321178825Sdfr	fprintf (codefile, "static unsigned oid_%s_variable_num[%d] =  {",
322178825Sdfr		 s->gen_name, len);
323178825Sdfr	for (i = len - 1 ; i >= 0; i--) {
324178825Sdfr	    fprintf(codefile, "%d%s ", list[i]->value, i > 0 ? "," : "");
325178825Sdfr	}
326178825Sdfr	fprintf(codefile, "};\n");
327178825Sdfr
328178825Sdfr	fprintf (codefile, "static const heim_oid oid_%s_variable = "
329178825Sdfr		 "{ %d, oid_%s_variable_num };\n\n",
330178825Sdfr		 s->gen_name, len, s->gen_name);
331178825Sdfr
332178825Sdfr	fprintf (codefile, "const heim_oid *oid_%s(void)\n"
333178825Sdfr		 "{\n"
334178825Sdfr		 "return &oid_%s_variable;\n"
335178825Sdfr		 "}\n\n",
336178825Sdfr		 s->gen_name, s->gen_name);
337178825Sdfr
338178825Sdfr	close_codefile();
339178825Sdfr
340178825Sdfr	break;
341178825Sdfr    }
342178825Sdfr    default:
343178825Sdfr	abort();
344178825Sdfr    }
34555682Smarkm}
34655682Smarkm
34755682Smarkmstatic void
34855682Smarkmspace(int level)
34955682Smarkm{
35055682Smarkm    while(level-- > 0)
35155682Smarkm	fprintf(headerfile, "  ");
35255682Smarkm}
35355682Smarkm
354178825Sdfrstatic const char *
355178825Sdfrlast_member_p(struct member *m)
356178825Sdfr{
357178825Sdfr    struct member *n = ASN1_TAILQ_NEXT(m, members);
358178825Sdfr    if (n == NULL)
359178825Sdfr	return "";
360178825Sdfr    if (n->ellipsis && ASN1_TAILQ_NEXT(n, members) == NULL)
361178825Sdfr	return "";
362178825Sdfr    return ",";
363178825Sdfr}
364178825Sdfr
365178825Sdfrstatic struct member *
366178825Sdfrhave_ellipsis(Type *t)
367178825Sdfr{
368178825Sdfr    struct member *m;
369178825Sdfr    ASN1_TAILQ_FOREACH(m, t->members, members) {
370178825Sdfr	if (m->ellipsis)
371178825Sdfr	    return m;
372178825Sdfr    }
373178825Sdfr    return NULL;
374178825Sdfr}
375178825Sdfr
37655682Smarkmstatic void
37755682Smarkmdefine_asn1 (int level, Type *t)
37855682Smarkm{
37955682Smarkm    switch (t->type) {
38055682Smarkm    case TType:
38155682Smarkm	fprintf (headerfile, "%s", t->symbol->name);
38255682Smarkm	break;
38355682Smarkm    case TInteger:
384178825Sdfr	if(t->members == NULL) {
385178825Sdfr            fprintf (headerfile, "INTEGER");
386178825Sdfr	    if (t->range)
387178825Sdfr		fprintf (headerfile, " (%d..%d)",
388178825Sdfr			 t->range->min, t->range->max);
389178825Sdfr        } else {
390178825Sdfr	    Member *m;
391178825Sdfr            fprintf (headerfile, "INTEGER {\n");
392178825Sdfr	    ASN1_TAILQ_FOREACH(m, t->members, members) {
393178825Sdfr                space (level + 1);
394178825Sdfr		fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val,
395178825Sdfr			last_member_p(m));
396178825Sdfr            }
397178825Sdfr	    space(level);
398178825Sdfr            fprintf (headerfile, "}");
399178825Sdfr        }
40055682Smarkm	break;
401178825Sdfr    case TBoolean:
402178825Sdfr	fprintf (headerfile, "BOOLEAN");
40372445Sassar	break;
40455682Smarkm    case TOctetString:
40555682Smarkm	fprintf (headerfile, "OCTET STRING");
40655682Smarkm	break;
407178825Sdfr    case TEnumerated :
40855682Smarkm    case TBitString: {
40955682Smarkm	Member *m;
41055682Smarkm
41155682Smarkm	space(level);
412178825Sdfr	if(t->type == TBitString)
413178825Sdfr	    fprintf (headerfile, "BIT STRING {\n");
414178825Sdfr	else
415178825Sdfr	    fprintf (headerfile, "ENUMERATED {\n");
416178825Sdfr	ASN1_TAILQ_FOREACH(m, t->members, members) {
41755682Smarkm	    space(level + 1);
41855682Smarkm	    fprintf (headerfile, "%s(%d)%s\n", m->name, m->val,
419178825Sdfr		     last_member_p(m));
42055682Smarkm	}
42155682Smarkm	space(level);
42255682Smarkm	fprintf (headerfile, "}");
42355682Smarkm	break;
42455682Smarkm    }
425178825Sdfr    case TChoice:
426178825Sdfr    case TSet:
42755682Smarkm    case TSequence: {
42855682Smarkm	Member *m;
42955682Smarkm	int max_width = 0;
43055682Smarkm
431178825Sdfr	if(t->type == TChoice)
432178825Sdfr	    fprintf(headerfile, "CHOICE {\n");
433178825Sdfr	else if(t->type == TSet)
434178825Sdfr	    fprintf(headerfile, "SET {\n");
435178825Sdfr	else
436178825Sdfr	    fprintf(headerfile, "SEQUENCE {\n");
437178825Sdfr	ASN1_TAILQ_FOREACH(m, t->members, members) {
438178825Sdfr	    if(strlen(m->name) > max_width)
439178825Sdfr		max_width = strlen(m->name);
44055682Smarkm	}
441178825Sdfr	max_width += 3;
44255682Smarkm	if(max_width < 16) max_width = 16;
443178825Sdfr	ASN1_TAILQ_FOREACH(m, t->members, members) {
444178825Sdfr	    int width = max_width;
44555682Smarkm	    space(level + 1);
446178825Sdfr	    if (m->ellipsis) {
447178825Sdfr		fprintf (headerfile, "...");
448178825Sdfr	    } else {
449178825Sdfr		width -= fprintf(headerfile, "%s", m->name);
450178825Sdfr		fprintf(headerfile, "%*s", width, "");
451178825Sdfr		define_asn1(level + 1, m->type);
452178825Sdfr		if(m->optional)
453178825Sdfr		    fprintf(headerfile, " OPTIONAL");
454178825Sdfr	    }
455178825Sdfr	    if(last_member_p(m))
45655682Smarkm		fprintf (headerfile, ",");
45755682Smarkm	    fprintf (headerfile, "\n");
45855682Smarkm	}
45955682Smarkm	space(level);
46055682Smarkm	fprintf (headerfile, "}");
46155682Smarkm	break;
46255682Smarkm    }
463178825Sdfr    case TSequenceOf:
46455682Smarkm	fprintf (headerfile, "SEQUENCE OF ");
46555682Smarkm	define_asn1 (0, t->subtype);
46655682Smarkm	break;
467178825Sdfr    case TSetOf:
468178825Sdfr	fprintf (headerfile, "SET OF ");
469178825Sdfr	define_asn1 (0, t->subtype);
470178825Sdfr	break;
47155682Smarkm    case TGeneralizedTime:
47255682Smarkm	fprintf (headerfile, "GeneralizedTime");
47355682Smarkm	break;
47455682Smarkm    case TGeneralString:
47555682Smarkm	fprintf (headerfile, "GeneralString");
47655682Smarkm	break;
477178825Sdfr    case TTag: {
478178825Sdfr	const char *classnames[] = { "UNIVERSAL ", "APPLICATION ",
479178825Sdfr				     "" /* CONTEXT */, "PRIVATE " };
480178825Sdfr	if(t->tag.tagclass != ASN1_C_UNIV)
481178825Sdfr	    fprintf (headerfile, "[%s%d] ",
482178825Sdfr		     classnames[t->tag.tagclass],
483178825Sdfr		     t->tag.tagvalue);
484178825Sdfr	if(t->tag.tagenv == TE_IMPLICIT)
485178825Sdfr	    fprintf (headerfile, "IMPLICIT ");
48655682Smarkm	define_asn1 (level, t->subtype);
48755682Smarkm	break;
488178825Sdfr    }
489178825Sdfr    case TUTCTime:
490178825Sdfr	fprintf (headerfile, "UTCTime");
491178825Sdfr	break;
492178825Sdfr    case TUTF8String:
493178825Sdfr	space(level);
494178825Sdfr	fprintf (headerfile, "UTF8String");
495178825Sdfr	break;
496178825Sdfr    case TPrintableString:
497178825Sdfr	space(level);
498178825Sdfr	fprintf (headerfile, "PrintableString");
499178825Sdfr	break;
500178825Sdfr    case TIA5String:
501178825Sdfr	space(level);
502178825Sdfr	fprintf (headerfile, "IA5String");
503178825Sdfr	break;
504178825Sdfr    case TBMPString:
505178825Sdfr	space(level);
506178825Sdfr	fprintf (headerfile, "BMPString");
507178825Sdfr	break;
508178825Sdfr    case TUniversalString:
509178825Sdfr	space(level);
510178825Sdfr	fprintf (headerfile, "UniversalString");
511178825Sdfr	break;
512178825Sdfr    case TVisibleString:
513178825Sdfr	space(level);
514178825Sdfr	fprintf (headerfile, "VisibleString");
515178825Sdfr	break;
516178825Sdfr    case TOID :
517178825Sdfr	space(level);
518178825Sdfr	fprintf(headerfile, "OBJECT IDENTIFIER");
519178825Sdfr	break;
520178825Sdfr    case TNull:
521178825Sdfr	space(level);
522178825Sdfr	fprintf (headerfile, "NULL");
523178825Sdfr	break;
52455682Smarkm    default:
52555682Smarkm	abort ();
52655682Smarkm    }
52755682Smarkm}
52855682Smarkm
52955682Smarkmstatic void
530178825Sdfrdefine_type (int level, const char *name, Type *t, int typedefp, int preservep)
53155682Smarkm{
53255682Smarkm    switch (t->type) {
53355682Smarkm    case TType:
53455682Smarkm	space(level);
53555682Smarkm	fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name);
53655682Smarkm	break;
53755682Smarkm    case TInteger:
53855682Smarkm	space(level);
539178825Sdfr	if(t->members) {
54072445Sassar            Member *m;
54172445Sassar            fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
542178825Sdfr	    ASN1_TAILQ_FOREACH(m, t->members, members) {
54372445Sassar                space (level + 1);
54472445Sassar                fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val,
545178825Sdfr                        last_member_p(m));
54672445Sassar            }
54772445Sassar            fprintf (headerfile, "} %s;\n", name);
548178825Sdfr	} else if (t->range == NULL) {
549178825Sdfr	    fprintf (headerfile, "heim_integer %s;\n", name);
550178825Sdfr	} else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
551178825Sdfr	    fprintf (headerfile, "int %s;\n", name);
552178825Sdfr	} else if (t->range->min == 0 && t->range->max == UINT_MAX) {
553178825Sdfr	    fprintf (headerfile, "unsigned int %s;\n", name);
554178825Sdfr	} else if (t->range->min == 0 && t->range->max == INT_MAX) {
555178825Sdfr	    fprintf (headerfile, "unsigned int %s;\n", name);
556178825Sdfr	} else
557178825Sdfr	    errx(1, "%s: unsupported range %d -> %d",
558178825Sdfr		 name, t->range->min, t->range->max);
55955682Smarkm	break;
560178825Sdfr    case TBoolean:
56155682Smarkm	space(level);
562178825Sdfr	fprintf (headerfile, "int %s;\n", name);
56355682Smarkm	break;
56455682Smarkm    case TOctetString:
56555682Smarkm	space(level);
566178825Sdfr	fprintf (headerfile, "heim_octet_string %s;\n", name);
56755682Smarkm	break;
56855682Smarkm    case TBitString: {
56955682Smarkm	Member *m;
57055682Smarkm	Type i;
571178825Sdfr	struct range range = { 0, INT_MAX };
57255682Smarkm
573178825Sdfr	i.type = TInteger;
574178825Sdfr	i.range = &range;
575178825Sdfr	i.members = NULL;
576178825Sdfr	i.constraint = NULL;
577178825Sdfr
57855682Smarkm	space(level);
579178825Sdfr	if(ASN1_TAILQ_EMPTY(t->members))
580178825Sdfr	    fprintf (headerfile, "heim_bit_string %s;\n", name);
581178825Sdfr	else {
582178825Sdfr	    fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
583178825Sdfr	    ASN1_TAILQ_FOREACH(m, t->members, members) {
584178825Sdfr		char *n;
585178825Sdfr
586178825Sdfr		asprintf (&n, "%s:1", m->gen_name);
587178825Sdfr		if (n == NULL)
588178825Sdfr		    errx(1, "malloc");
589178825Sdfr		define_type (level + 1, n, &i, FALSE, FALSE);
590178825Sdfr		free (n);
591178825Sdfr	    }
592178825Sdfr	    space(level);
593178825Sdfr	    fprintf (headerfile, "} %s;\n\n", name);
59455682Smarkm	}
59555682Smarkm	break;
59655682Smarkm    }
59790926Snectar    case TEnumerated: {
59890926Snectar	Member *m;
59990926Snectar
60090926Snectar	space(level);
60190926Snectar	fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
602178825Sdfr	ASN1_TAILQ_FOREACH(m, t->members, members) {
60390926Snectar	    space(level + 1);
604178825Sdfr	    if (m->ellipsis)
605178825Sdfr		fprintf (headerfile, "/* ... */\n");
606178825Sdfr	    else
607178825Sdfr		fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val,
608178825Sdfr			 last_member_p(m));
60990926Snectar	}
61090926Snectar	space(level);
61190926Snectar	fprintf (headerfile, "} %s;\n\n", name);
61290926Snectar	break;
61390926Snectar    }
614178825Sdfr    case TSet:
61555682Smarkm    case TSequence: {
61655682Smarkm	Member *m;
61755682Smarkm
61855682Smarkm	space(level);
61955682Smarkm	fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
620178825Sdfr	if (t->type == TSequence && preservep) {
621178825Sdfr	    space(level + 1);
622178825Sdfr	    fprintf(headerfile, "heim_octet_string _save;\n");
623178825Sdfr	}
624178825Sdfr	ASN1_TAILQ_FOREACH(m, t->members, members) {
625178825Sdfr	    if (m->ellipsis) {
626178825Sdfr		;
627178825Sdfr	    } else if (m->optional) {
62855682Smarkm		char *n;
62955682Smarkm
63055682Smarkm		asprintf (&n, "*%s", m->gen_name);
631178825Sdfr		if (n == NULL)
632178825Sdfr		    errx(1, "malloc");
633178825Sdfr		define_type (level + 1, n, m->type, FALSE, FALSE);
63455682Smarkm		free (n);
63555682Smarkm	    } else
636178825Sdfr		define_type (level + 1, m->gen_name, m->type, FALSE, FALSE);
63755682Smarkm	}
63855682Smarkm	space(level);
63955682Smarkm	fprintf (headerfile, "} %s;\n", name);
64055682Smarkm	break;
64155682Smarkm    }
642178825Sdfr    case TSetOf:
64355682Smarkm    case TSequenceOf: {
64455682Smarkm	Type i;
645178825Sdfr	struct range range = { 0, INT_MAX };
64655682Smarkm
647178825Sdfr	i.type = TInteger;
648178825Sdfr	i.range = &range;
649178825Sdfr	i.members = NULL;
650178825Sdfr	i.constraint = NULL;
65155682Smarkm
65255682Smarkm	space(level);
65355682Smarkm	fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
654178825Sdfr	define_type (level + 1, "len", &i, FALSE, FALSE);
655178825Sdfr	define_type (level + 1, "*val", t->subtype, FALSE, FALSE);
65655682Smarkm	space(level);
65755682Smarkm	fprintf (headerfile, "} %s;\n", name);
65855682Smarkm	break;
65955682Smarkm    }
66055682Smarkm    case TGeneralizedTime:
66155682Smarkm	space(level);
66255682Smarkm	fprintf (headerfile, "time_t %s;\n", name);
66355682Smarkm	break;
66455682Smarkm    case TGeneralString:
66555682Smarkm	space(level);
666178825Sdfr	fprintf (headerfile, "heim_general_string %s;\n", name);
66755682Smarkm	break;
668178825Sdfr    case TTag:
669178825Sdfr	define_type (level, name, t->subtype, typedefp, preservep);
67055682Smarkm	break;
671178825Sdfr    case TChoice: {
672178825Sdfr	int first = 1;
673178825Sdfr	Member *m;
674178825Sdfr
675178825Sdfr	space(level);
676178825Sdfr	fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
677178825Sdfr	if (preservep) {
678178825Sdfr	    space(level + 1);
679178825Sdfr	    fprintf(headerfile, "heim_octet_string _save;\n");
680178825Sdfr	}
681178825Sdfr	space(level + 1);
682178825Sdfr	fprintf (headerfile, "enum {\n");
683178825Sdfr	m = have_ellipsis(t);
684178825Sdfr	if (m) {
685178825Sdfr	    space(level + 2);
686178825Sdfr	    fprintf (headerfile, "%s = 0,\n", m->label);
687178825Sdfr	    first = 0;
688178825Sdfr	}
689178825Sdfr	ASN1_TAILQ_FOREACH(m, t->members, members) {
690178825Sdfr	    space(level + 2);
691178825Sdfr	    if (m->ellipsis)
692178825Sdfr		fprintf (headerfile, "/* ... */\n");
693178825Sdfr	    else
694178825Sdfr		fprintf (headerfile, "%s%s%s\n", m->label,
695178825Sdfr			 first ? " = 1" : "",
696178825Sdfr			 last_member_p(m));
697178825Sdfr	    first = 0;
698178825Sdfr	}
699178825Sdfr	space(level + 1);
700178825Sdfr	fprintf (headerfile, "} element;\n");
701178825Sdfr	space(level + 1);
702178825Sdfr	fprintf (headerfile, "union {\n");
703178825Sdfr	ASN1_TAILQ_FOREACH(m, t->members, members) {
704178825Sdfr	    if (m->ellipsis) {
705178825Sdfr		space(level + 2);
706178825Sdfr		fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");
707178825Sdfr	    } else if (m->optional) {
708178825Sdfr		char *n;
709178825Sdfr
710178825Sdfr		asprintf (&n, "*%s", m->gen_name);
711178825Sdfr		if (n == NULL)
712178825Sdfr		    errx(1, "malloc");
713178825Sdfr		define_type (level + 2, n, m->type, FALSE, FALSE);
714178825Sdfr		free (n);
715178825Sdfr	    } else
716178825Sdfr		define_type (level + 2, m->gen_name, m->type, FALSE, FALSE);
717178825Sdfr	}
718178825Sdfr	space(level + 1);
719178825Sdfr	fprintf (headerfile, "} u;\n");
720178825Sdfr	space(level);
721178825Sdfr	fprintf (headerfile, "} %s;\n", name);
722178825Sdfr	break;
723178825Sdfr    }
724178825Sdfr    case TUTCTime:
725178825Sdfr	space(level);
726178825Sdfr	fprintf (headerfile, "time_t %s;\n", name);
727178825Sdfr	break;
728178825Sdfr    case TUTF8String:
729178825Sdfr	space(level);
730178825Sdfr	fprintf (headerfile, "heim_utf8_string %s;\n", name);
731178825Sdfr	break;
732178825Sdfr    case TPrintableString:
733178825Sdfr	space(level);
734178825Sdfr	fprintf (headerfile, "heim_printable_string %s;\n", name);
735178825Sdfr	break;
736178825Sdfr    case TIA5String:
737178825Sdfr	space(level);
738178825Sdfr	fprintf (headerfile, "heim_ia5_string %s;\n", name);
739178825Sdfr	break;
740178825Sdfr    case TBMPString:
741178825Sdfr	space(level);
742178825Sdfr	fprintf (headerfile, "heim_bmp_string %s;\n", name);
743178825Sdfr	break;
744178825Sdfr    case TUniversalString:
745178825Sdfr	space(level);
746178825Sdfr	fprintf (headerfile, "heim_universal_string %s;\n", name);
747178825Sdfr	break;
748178825Sdfr    case TVisibleString:
749178825Sdfr	space(level);
750178825Sdfr	fprintf (headerfile, "heim_visible_string %s;\n", name);
751178825Sdfr	break;
752178825Sdfr    case TOID :
753178825Sdfr	space(level);
754178825Sdfr	fprintf (headerfile, "heim_oid %s;\n", name);
755178825Sdfr	break;
756178825Sdfr    case TNull:
757178825Sdfr	space(level);
758178825Sdfr	fprintf (headerfile, "int %s;\n", name);
759178825Sdfr	break;
76055682Smarkm    default:
76155682Smarkm	abort ();
76255682Smarkm    }
76355682Smarkm}
76455682Smarkm
76555682Smarkmstatic void
76655682Smarkmgenerate_type_header (const Symbol *s)
76755682Smarkm{
768178825Sdfr    int preservep = preserve_type(s->name) ? TRUE : FALSE;
769178825Sdfr
77055682Smarkm    fprintf (headerfile, "/*\n");
77155682Smarkm    fprintf (headerfile, "%s ::= ", s->name);
77255682Smarkm    define_asn1 (0, s->type);
77355682Smarkm    fprintf (headerfile, "\n*/\n\n");
77455682Smarkm
77555682Smarkm    fprintf (headerfile, "typedef ");
776178825Sdfr    define_type (0, s->gen_name, s->type, TRUE, preservep);
77755682Smarkm
77855682Smarkm    fprintf (headerfile, "\n");
77955682Smarkm}
78055682Smarkm
78155682Smarkm
78255682Smarkmvoid
78355682Smarkmgenerate_type (const Symbol *s)
78455682Smarkm{
785178825Sdfr    generate_header_of_codefile(s->gen_name);
78655682Smarkm
78755682Smarkm    generate_type_header (s);
78855682Smarkm    generate_type_encode (s);
78955682Smarkm    generate_type_decode (s);
79055682Smarkm    generate_type_free (s);
79155682Smarkm    generate_type_length (s);
79255682Smarkm    generate_type_copy (s);
793178825Sdfr    generate_type_seq (s);
794178825Sdfr    generate_glue (s->type, s->gen_name);
79555682Smarkm    fprintf(headerfile, "\n\n");
796178825Sdfr    close_codefile();
79755682Smarkm}
798