• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source4/heimdal/lib/asn1/
1/*
2 * Copyright (c) 1997 - 2005 Kungliga Tekniska H��gskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "gen_locl.h"
35
36RCSID("$Id: gen.c,v 1.1.1.1 2011/06/10 09:34:42 andrew Exp $");
37
38FILE *headerfile, *codefile, *logfile;
39
40#define STEM "asn1"
41
42static const char *orig_filename;
43static char *header;
44static const char *headerbase = STEM;
45
46/*
47 * list of all IMPORTs
48 */
49
50struct import {
51    const char *module;
52    struct import *next;
53};
54
55static struct import *imports = NULL;
56
57void
58add_import (const char *module)
59{
60    struct import *tmp = emalloc (sizeof(*tmp));
61
62    tmp->module = module;
63    tmp->next   = imports;
64    imports     = tmp;
65
66    fprintf (headerfile, "#include <%s_asn1.h>\n", module);
67}
68
69const char *
70get_filename (void)
71{
72    return orig_filename;
73}
74
75void
76init_generate (const char *filename, const char *base)
77{
78    char *fn;
79
80    orig_filename = filename;
81    if (base != NULL) {
82	headerbase = strdup(base);
83	if (headerbase == NULL)
84	    errx(1, "strdup");
85    }
86
87    /* public header file */
88    asprintf(&header, "%s.h", headerbase);
89    if (header == NULL)
90	errx(1, "malloc");
91    asprintf(&fn, "%s.hx", headerbase);
92    if (fn == NULL)
93	errx(1, "malloc");
94    headerfile = fopen (fn, "w");
95    if (headerfile == NULL)
96	err (1, "open %s", fn);
97    free(fn);
98
99    fprintf (headerfile,
100	     "/* Generated from %s */\n"
101	     "/* Do not edit */\n\n",
102	     filename);
103    fprintf (headerfile,
104	     "#ifndef __%s_h__\n"
105	     "#define __%s_h__\n\n", headerbase, headerbase);
106    fprintf (headerfile,
107	     "#include <stddef.h>\n"
108	     "#include <time.h>\n\n");
109    fprintf (headerfile,
110	     "#ifndef __asn1_common_definitions__\n"
111	     "#define __asn1_common_definitions__\n\n");
112    fprintf (headerfile,
113	     "typedef struct heim_integer {\n"
114	     "  size_t length;\n"
115	     "  void *data;\n"
116	     "  int negative;\n"
117	     "} heim_integer;\n\n");
118    fprintf (headerfile,
119	     "typedef struct heim_octet_string {\n"
120	     "  size_t length;\n"
121	     "  void *data;\n"
122	     "} heim_octet_string;\n\n");
123    fprintf (headerfile,
124	     "typedef char *heim_general_string;\n\n"
125	     );
126    fprintf (headerfile,
127	     "typedef char *heim_utf8_string;\n\n"
128	     );
129    fprintf (headerfile,
130	     "typedef char *heim_printable_string;\n\n"
131	     );
132    fprintf (headerfile,
133	     "typedef char *heim_ia5_string;\n\n"
134	     );
135    fprintf (headerfile,
136	     "typedef struct heim_bmp_string {\n"
137	     "  size_t length;\n"
138	     "  uint16_t *data;\n"
139	     "} heim_bmp_string;\n\n");
140    fprintf (headerfile,
141	     "typedef struct heim_universal_string {\n"
142	     "  size_t length;\n"
143	     "  uint32_t *data;\n"
144	     "} heim_universal_string;\n\n");
145    fprintf (headerfile,
146	     "typedef char *heim_visible_string;\n\n"
147	     );
148    fprintf (headerfile,
149	     "typedef struct heim_oid {\n"
150	     "  size_t length;\n"
151	     "  unsigned *components;\n"
152	     "} heim_oid;\n\n");
153    fprintf (headerfile,
154	     "typedef struct heim_bit_string {\n"
155	     "  size_t length;\n"
156	     "  void *data;\n"
157	     "} heim_bit_string;\n\n");
158    fprintf (headerfile,
159	     "typedef struct heim_octet_string heim_any;\n"
160	     "typedef struct heim_octet_string heim_any_set;\n\n");
161    fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R)                  \\\n"
162	  "  do {                                                         \\\n"
163	  "    (BL) = length_##T((S));                                    \\\n"
164	  "    (B) = malloc((BL));                                        \\\n"
165	  "    if((B) == NULL) {                                          \\\n"
166	  "      (R) = ENOMEM;                                            \\\n"
167	  "    } else {                                                   \\\n"
168	  "      (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n"
169	  "                       (S), (L));                              \\\n"
170	  "      if((R) != 0) {                                           \\\n"
171	  "        free((B));                                             \\\n"
172	  "        (B) = NULL;                                            \\\n"
173	  "      }                                                        \\\n"
174	  "    }                                                          \\\n"
175	  "  } while (0)\n\n",
176	  headerfile);
177    fprintf (headerfile, "struct units;\n\n");
178    fprintf (headerfile, "#endif\n\n");
179    asprintf(&fn, "%s_files", base);
180    if (fn == NULL)
181	errx(1, "malloc");
182    logfile = fopen(fn, "w");
183    if (logfile == NULL)
184	err (1, "open %s", fn);
185}
186
187void
188close_generate (void)
189{
190    fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
191
192    fclose (headerfile);
193    fprintf (logfile, "\n");
194    fclose (logfile);
195}
196
197void
198gen_assign_defval(const char *var, struct value *val)
199{
200    switch(val->type) {
201    case stringvalue:
202	fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue);
203	break;
204    case integervalue:
205	fprintf(codefile, "%s = %d;\n", var, val->u.integervalue);
206	break;
207    case booleanvalue:
208	if(val->u.booleanvalue)
209	    fprintf(codefile, "%s = TRUE;\n", var);
210	else
211	    fprintf(codefile, "%s = FALSE;\n", var);
212	break;
213    default:
214	abort();
215    }
216}
217
218void
219gen_compare_defval(const char *var, struct value *val)
220{
221    switch(val->type) {
222    case stringvalue:
223	fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue);
224	break;
225    case integervalue:
226	fprintf(codefile, "if(%s != %d)\n", var, val->u.integervalue);
227	break;
228    case booleanvalue:
229	if(val->u.booleanvalue)
230	    fprintf(codefile, "if(!%s)\n", var);
231	else
232	    fprintf(codefile, "if(%s)\n", var);
233	break;
234    default:
235	abort();
236    }
237}
238
239void
240generate_header_of_codefile(const char *name)
241{
242    char *filename;
243
244    if (codefile != NULL)
245	abort();
246
247    asprintf (&filename, "%s_%s.x", STEM, name);
248    if (filename == NULL)
249	errx(1, "malloc");
250    codefile = fopen (filename, "w");
251    if (codefile == NULL)
252	err (1, "fopen %s", filename);
253    fprintf(logfile, "%s ", filename);
254    free(filename);
255    fprintf (codefile,
256	     "/* Generated from %s */\n"
257	     "/* Do not edit */\n\n"
258	     "#include <stdio.h>\n"
259	     "#include <stdlib.h>\n"
260	     "#include <time.h>\n"
261	     "#include <string.h>\n"
262	     "#include <errno.h>\n"
263	     "#include <limits.h>\n"
264	     "#include <krb5-types.h>\n",
265	     orig_filename);
266
267    fprintf (codefile,
268	     "#include <%s.h>\n",
269	     headerbase);
270    fprintf (codefile,
271	     "#include <asn1_err.h>\n"
272	     "#include <der.h>\n"
273	     "#include <parse_units.h>\n\n");
274
275}
276
277void
278close_codefile(void)
279{
280    if (codefile == NULL)
281	abort();
282
283    fclose(codefile);
284    codefile = NULL;
285}
286
287
288void
289generate_constant (const Symbol *s)
290{
291    switch(s->value->type) {
292    case booleanvalue:
293	break;
294    case integervalue:
295	fprintf (headerfile, "enum { %s = %d };\n\n",
296		 s->gen_name, s->value->u.integervalue);
297	break;
298    case nullvalue:
299	break;
300    case stringvalue:
301	break;
302    case objectidentifiervalue: {
303	struct objid *o, **list;
304	unsigned int i, len;
305
306	if (!one_code_file)
307	    generate_header_of_codefile(s->gen_name);
308
309	len = 0;
310	for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
311	    len++;
312	if (len == 0) {
313	    printf("s->gen_name: %s",s->gen_name);
314	    fflush(stdout);
315	    break;
316	}
317	list = emalloc(sizeof(*list) * len);
318
319	i = 0;
320	for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
321	    list[i++] = o;
322
323	fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name);
324	for (i = len ; i > 0; i--) {
325	    o = list[i - 1];
326	    fprintf(headerfile, "%s(%d) ",
327		    o->label ? o->label : "label-less", o->value);
328	}
329
330	fprintf (headerfile, "} */\n");
331	fprintf (headerfile, "const heim_oid *oid_%s(void);\n",
332		 s->gen_name);
333	fprintf (headerfile,
334		 "extern const heim_oid asn1_oid_%s;\n\n",
335		 s->gen_name);
336
337
338	fprintf (codefile, "static unsigned oid_%s_variable_num[%d] =  {",
339		 s->gen_name, len);
340	for (i = len ; i > 0; i--) {
341	    fprintf(codefile, "%d%s ", list[i - 1]->value, i > 1 ? "," : "");
342	}
343	fprintf(codefile, "};\n");
344
345	fprintf (codefile, "const heim_oid asn1_oid_%s = "
346		 "{ %d, oid_%s_variable_num };\n\n",
347		 s->gen_name, len, s->gen_name);
348
349	fprintf (codefile, "const heim_oid *oid_%s(void)\n"
350		 "{\n"
351		 "return &asn1_oid_%s;\n"
352		 "}\n\n",
353		 s->gen_name, s->gen_name);
354
355	free(list);
356
357	if (!one_code_file)
358	    close_codefile();
359
360	break;
361    }
362    default:
363	abort();
364    }
365}
366
367static void
368space(int level)
369{
370    while(level-- > 0)
371	fprintf(headerfile, "  ");
372}
373
374static const char *
375last_member_p(struct member *m)
376{
377    struct member *n = ASN1_TAILQ_NEXT(m, members);
378    if (n == NULL)
379	return "";
380    if (n->ellipsis && ASN1_TAILQ_NEXT(n, members) == NULL)
381	return "";
382    return ",";
383}
384
385static struct member *
386have_ellipsis(Type *t)
387{
388    struct member *m;
389    ASN1_TAILQ_FOREACH(m, t->members, members) {
390	if (m->ellipsis)
391	    return m;
392    }
393    return NULL;
394}
395
396static void
397define_asn1 (int level, Type *t)
398{
399    switch (t->type) {
400    case TType:
401	fprintf (headerfile, "%s", t->symbol->name);
402	break;
403    case TInteger:
404	if(t->members == NULL) {
405            fprintf (headerfile, "INTEGER");
406	    if (t->range)
407		fprintf (headerfile, " (%d..%d)",
408			 t->range->min, t->range->max);
409        } else {
410	    Member *m;
411            fprintf (headerfile, "INTEGER {\n");
412	    ASN1_TAILQ_FOREACH(m, t->members, members) {
413                space (level + 1);
414		fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val,
415			last_member_p(m));
416            }
417	    space(level);
418            fprintf (headerfile, "}");
419        }
420	break;
421    case TBoolean:
422	fprintf (headerfile, "BOOLEAN");
423	break;
424    case TOctetString:
425	fprintf (headerfile, "OCTET STRING");
426	break;
427    case TEnumerated :
428    case TBitString: {
429	Member *m;
430
431	space(level);
432	if(t->type == TBitString)
433	    fprintf (headerfile, "BIT STRING {\n");
434	else
435	    fprintf (headerfile, "ENUMERATED {\n");
436	ASN1_TAILQ_FOREACH(m, t->members, members) {
437	    space(level + 1);
438	    fprintf (headerfile, "%s(%d)%s\n", m->name, m->val,
439		     last_member_p(m));
440	}
441	space(level);
442	fprintf (headerfile, "}");
443	break;
444    }
445    case TChoice:
446    case TSet:
447    case TSequence: {
448	Member *m;
449	int max_width = 0;
450
451	if(t->type == TChoice)
452	    fprintf(headerfile, "CHOICE {\n");
453	else if(t->type == TSet)
454	    fprintf(headerfile, "SET {\n");
455	else
456	    fprintf(headerfile, "SEQUENCE {\n");
457	ASN1_TAILQ_FOREACH(m, t->members, members) {
458	    if(strlen(m->name) > max_width)
459		max_width = strlen(m->name);
460	}
461	max_width += 3;
462	if(max_width < 16) max_width = 16;
463	ASN1_TAILQ_FOREACH(m, t->members, members) {
464	    int width = max_width;
465	    space(level + 1);
466	    if (m->ellipsis) {
467		fprintf (headerfile, "...");
468	    } else {
469		width -= fprintf(headerfile, "%s", m->name);
470		fprintf(headerfile, "%*s", width, "");
471		define_asn1(level + 1, m->type);
472		if(m->optional)
473		    fprintf(headerfile, " OPTIONAL");
474	    }
475	    if(last_member_p(m))
476		fprintf (headerfile, ",");
477	    fprintf (headerfile, "\n");
478	}
479	space(level);
480	fprintf (headerfile, "}");
481	break;
482    }
483    case TSequenceOf:
484	fprintf (headerfile, "SEQUENCE OF ");
485	define_asn1 (0, t->subtype);
486	break;
487    case TSetOf:
488	fprintf (headerfile, "SET OF ");
489	define_asn1 (0, t->subtype);
490	break;
491    case TGeneralizedTime:
492	fprintf (headerfile, "GeneralizedTime");
493	break;
494    case TGeneralString:
495	fprintf (headerfile, "GeneralString");
496	break;
497    case TTag: {
498	const char *classnames[] = { "UNIVERSAL ", "APPLICATION ",
499				     "" /* CONTEXT */, "PRIVATE " };
500	if(t->tag.tagclass != ASN1_C_UNIV)
501	    fprintf (headerfile, "[%s%d] ",
502		     classnames[t->tag.tagclass],
503		     t->tag.tagvalue);
504	if(t->tag.tagenv == TE_IMPLICIT)
505	    fprintf (headerfile, "IMPLICIT ");
506	define_asn1 (level, t->subtype);
507	break;
508    }
509    case TUTCTime:
510	fprintf (headerfile, "UTCTime");
511	break;
512    case TUTF8String:
513	space(level);
514	fprintf (headerfile, "UTF8String");
515	break;
516    case TPrintableString:
517	space(level);
518	fprintf (headerfile, "PrintableString");
519	break;
520    case TIA5String:
521	space(level);
522	fprintf (headerfile, "IA5String");
523	break;
524    case TBMPString:
525	space(level);
526	fprintf (headerfile, "BMPString");
527	break;
528    case TUniversalString:
529	space(level);
530	fprintf (headerfile, "UniversalString");
531	break;
532    case TVisibleString:
533	space(level);
534	fprintf (headerfile, "VisibleString");
535	break;
536    case TOID :
537	space(level);
538	fprintf(headerfile, "OBJECT IDENTIFIER");
539	break;
540    case TNull:
541	space(level);
542	fprintf (headerfile, "NULL");
543	break;
544    default:
545	abort ();
546    }
547}
548
549static void
550define_type (int level, const char *name, Type *t, int typedefp, int preservep)
551{
552    switch (t->type) {
553    case TType:
554	space(level);
555	fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name);
556	break;
557    case TInteger:
558	space(level);
559	if(t->members) {
560            Member *m;
561            fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
562	    ASN1_TAILQ_FOREACH(m, t->members, members) {
563                space (level + 1);
564                fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val,
565                        last_member_p(m));
566            }
567            fprintf (headerfile, "} %s;\n", name);
568	} else if (t->range == NULL) {
569	    fprintf (headerfile, "heim_integer %s;\n", name);
570	} else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
571	    fprintf (headerfile, "int %s;\n", name);
572	} else if (t->range->min == 0 && t->range->max == UINT_MAX) {
573	    fprintf (headerfile, "unsigned int %s;\n", name);
574	} else if (t->range->min == 0 && t->range->max == INT_MAX) {
575	    fprintf (headerfile, "unsigned int %s;\n", name);
576	} else
577	    errx(1, "%s: unsupported range %d -> %d",
578		 name, t->range->min, t->range->max);
579	break;
580    case TBoolean:
581	space(level);
582	fprintf (headerfile, "int %s;\n", name);
583	break;
584    case TOctetString:
585	space(level);
586	fprintf (headerfile, "heim_octet_string %s;\n", name);
587	break;
588    case TBitString: {
589	Member *m;
590	Type i;
591	struct range range = { 0, INT_MAX };
592
593	i.type = TInteger;
594	i.range = &range;
595	i.members = NULL;
596	i.constraint = NULL;
597
598	space(level);
599	if(ASN1_TAILQ_EMPTY(t->members))
600	    fprintf (headerfile, "heim_bit_string %s;\n", name);
601	else {
602	    fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
603	    ASN1_TAILQ_FOREACH(m, t->members, members) {
604		char *n;
605
606		asprintf (&n, "%s:1", m->gen_name);
607		if (n == NULL)
608		    errx(1, "malloc");
609		define_type (level + 1, n, &i, FALSE, FALSE);
610		free (n);
611	    }
612	    space(level);
613	    fprintf (headerfile, "} %s;\n\n", name);
614	}
615	break;
616    }
617    case TEnumerated: {
618	Member *m;
619
620	space(level);
621	fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
622	ASN1_TAILQ_FOREACH(m, t->members, members) {
623	    space(level + 1);
624	    if (m->ellipsis)
625		fprintf (headerfile, "/* ... */\n");
626	    else
627		fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val,
628			 last_member_p(m));
629	}
630	space(level);
631	fprintf (headerfile, "} %s;\n\n", name);
632	break;
633    }
634    case TSet:
635    case TSequence: {
636	Member *m;
637
638	space(level);
639	fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
640	if (t->type == TSequence && preservep) {
641	    space(level + 1);
642	    fprintf(headerfile, "heim_octet_string _save;\n");
643	}
644	ASN1_TAILQ_FOREACH(m, t->members, members) {
645	    if (m->ellipsis) {
646		;
647	    } else if (m->optional) {
648		char *n;
649
650		asprintf (&n, "*%s", m->gen_name);
651		if (n == NULL)
652		    errx(1, "malloc");
653		define_type (level + 1, n, m->type, FALSE, FALSE);
654		free (n);
655	    } else
656		define_type (level + 1, m->gen_name, m->type, FALSE, FALSE);
657	}
658	space(level);
659	fprintf (headerfile, "} %s;\n", name);
660	break;
661    }
662    case TSetOf:
663    case TSequenceOf: {
664	Type i;
665	struct range range = { 0, INT_MAX };
666
667	i.type = TInteger;
668	i.range = &range;
669	i.members = NULL;
670	i.constraint = NULL;
671
672	space(level);
673	fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
674	define_type (level + 1, "len", &i, FALSE, FALSE);
675	define_type (level + 1, "*val", t->subtype, FALSE, FALSE);
676	space(level);
677	fprintf (headerfile, "} %s;\n", name);
678	break;
679    }
680    case TGeneralizedTime:
681	space(level);
682	fprintf (headerfile, "time_t %s;\n", name);
683	break;
684    case TGeneralString:
685	space(level);
686	fprintf (headerfile, "heim_general_string %s;\n", name);
687	break;
688    case TTag:
689	define_type (level, name, t->subtype, typedefp, preservep);
690	break;
691    case TChoice: {
692	int first = 1;
693	Member *m;
694
695	space(level);
696	fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
697	if (preservep) {
698	    space(level + 1);
699	    fprintf(headerfile, "heim_octet_string _save;\n");
700	}
701	space(level + 1);
702	fprintf (headerfile, "enum {\n");
703	m = have_ellipsis(t);
704	if (m) {
705	    space(level + 2);
706	    fprintf (headerfile, "%s = 0,\n", m->label);
707	    first = 0;
708	}
709	ASN1_TAILQ_FOREACH(m, t->members, members) {
710	    space(level + 2);
711	    if (m->ellipsis)
712		fprintf (headerfile, "/* ... */\n");
713	    else
714		fprintf (headerfile, "%s%s%s\n", m->label,
715			 first ? " = 1" : "",
716			 last_member_p(m));
717	    first = 0;
718	}
719	space(level + 1);
720	fprintf (headerfile, "} element;\n");
721	space(level + 1);
722	fprintf (headerfile, "union {\n");
723	ASN1_TAILQ_FOREACH(m, t->members, members) {
724	    if (m->ellipsis) {
725		space(level + 2);
726		fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");
727	    } else if (m->optional) {
728		char *n;
729
730		asprintf (&n, "*%s", m->gen_name);
731		if (n == NULL)
732		    errx(1, "malloc");
733		define_type (level + 2, n, m->type, FALSE, FALSE);
734		free (n);
735	    } else
736		define_type (level + 2, m->gen_name, m->type, FALSE, FALSE);
737	}
738	space(level + 1);
739	fprintf (headerfile, "} u;\n");
740	space(level);
741	fprintf (headerfile, "} %s;\n", name);
742	break;
743    }
744    case TUTCTime:
745	space(level);
746	fprintf (headerfile, "time_t %s;\n", name);
747	break;
748    case TUTF8String:
749	space(level);
750	fprintf (headerfile, "heim_utf8_string %s;\n", name);
751	break;
752    case TPrintableString:
753	space(level);
754	fprintf (headerfile, "heim_printable_string %s;\n", name);
755	break;
756    case TIA5String:
757	space(level);
758	fprintf (headerfile, "heim_ia5_string %s;\n", name);
759	break;
760    case TBMPString:
761	space(level);
762	fprintf (headerfile, "heim_bmp_string %s;\n", name);
763	break;
764    case TUniversalString:
765	space(level);
766	fprintf (headerfile, "heim_universal_string %s;\n", name);
767	break;
768    case TVisibleString:
769	space(level);
770	fprintf (headerfile, "heim_visible_string %s;\n", name);
771	break;
772    case TOID :
773	space(level);
774	fprintf (headerfile, "heim_oid %s;\n", name);
775	break;
776    case TNull:
777	space(level);
778	fprintf (headerfile, "int %s;\n", name);
779	break;
780    default:
781	abort ();
782    }
783}
784
785static void
786generate_type_header (const Symbol *s)
787{
788    int preservep = preserve_type(s->name) ? TRUE : FALSE;
789
790    fprintf (headerfile, "/*\n");
791    fprintf (headerfile, "%s ::= ", s->name);
792    define_asn1 (0, s->type);
793    fprintf (headerfile, "\n*/\n\n");
794
795    fprintf (headerfile, "typedef ");
796    define_type (0, s->gen_name, s->type, TRUE, preservep);
797
798    fprintf (headerfile, "\n");
799}
800
801
802void
803generate_type (const Symbol *s)
804{
805    if (!one_code_file)
806	generate_header_of_codefile(s->gen_name);
807
808    generate_type_header (s);
809    generate_type_encode (s);
810    generate_type_decode (s);
811    generate_type_free (s);
812    generate_type_length (s);
813    generate_type_copy (s);
814    generate_type_seq (s);
815    generate_glue (s->type, s->gen_name);
816    fprintf(headerfile, "\n\n");
817
818    if (!one_code_file) {
819	fprintf(codefile, "\n\n");
820	close_codefile();
821	}
822}
823