Merge lorikeet-heimdal -r 787 into Samba4 tree.
[samba.git] / source4 / heimdal / lib / asn1 / gen.c
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
36 RCSID("$Id: gen.c 22429 2008-01-13 10:25:50Z lha $");
37
38 FILE *headerfile, *codefile, *logfile;
39
40 #define STEM "asn1"
41
42 static const char *orig_filename;
43 static char *header;
44 static const char *headerbase = STEM;
45
46 /*
47  * list of all IMPORTs
48  */
49
50 struct import {
51     const char *module;
52     struct import *next;
53 };
54
55 static struct import *imports = NULL;
56
57 void
58 add_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
69 const char *
70 get_filename (void)
71 {
72     return orig_filename;
73 }
74
75 void
76 init_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     asprintf(&header, "%s.h", headerbase);
87     if (header == NULL)
88         errx(1, "malloc");
89     headerfile = fopen (header, "w");
90     if (headerfile == NULL)
91         err (1, "open %s", header);
92     fprintf (headerfile,
93              "/* Generated from %s */\n"
94              "/* Do not edit */\n\n",
95              filename);
96     fprintf (headerfile, 
97              "#ifndef __%s_h__\n"
98              "#define __%s_h__\n\n", headerbase, headerbase);
99     fprintf (headerfile, 
100              "#include <stddef.h>\n"
101              "#include <time.h>\n\n");
102     fprintf (headerfile,
103              "#ifndef __asn1_common_definitions__\n"
104              "#define __asn1_common_definitions__\n\n");
105     fprintf (headerfile,
106              "typedef struct heim_integer {\n"
107              "  size_t length;\n"
108              "  void *data;\n"
109              "  int negative;\n"
110              "} heim_integer;\n\n");
111     fprintf (headerfile,
112              "typedef struct heim_octet_string {\n"
113              "  size_t length;\n"
114              "  void *data;\n"
115              "} heim_octet_string;\n\n");
116     fprintf (headerfile,
117              "typedef char *heim_general_string;\n\n"
118              );
119     fprintf (headerfile,
120              "typedef char *heim_utf8_string;\n\n"
121              );
122     fprintf (headerfile,
123              "typedef char *heim_printable_string;\n\n"
124              );
125     fprintf (headerfile,
126              "typedef char *heim_ia5_string;\n\n"
127              );
128     fprintf (headerfile,
129              "typedef struct heim_bmp_string {\n"
130              "  size_t length;\n"
131              "  uint16_t *data;\n"
132              "} heim_bmp_string;\n\n");
133     fprintf (headerfile,
134              "typedef struct heim_universal_string {\n"
135              "  size_t length;\n"
136              "  uint32_t *data;\n"
137              "} heim_universal_string;\n\n");
138     fprintf (headerfile,
139              "typedef char *heim_visible_string;\n\n"
140              );
141     fprintf (headerfile,
142              "typedef struct heim_oid {\n"
143              "  size_t length;\n"
144              "  unsigned *components;\n"
145              "} heim_oid;\n\n");
146     fprintf (headerfile,
147              "typedef struct heim_bit_string {\n"
148              "  size_t length;\n"
149              "  void *data;\n"
150              "} heim_bit_string;\n\n");
151     fprintf (headerfile,
152              "typedef struct heim_octet_string heim_any;\n"
153              "typedef struct heim_octet_string heim_any_set;\n\n");
154     fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R)                  \\\n"
155           "  do {                                                         \\\n"
156           "    (BL) = length_##T((S));                                    \\\n"
157           "    (B) = malloc((BL));                                        \\\n"
158           "    if((B) == NULL) {                                          \\\n"
159           "      (R) = ENOMEM;                                            \\\n"
160           "    } else {                                                   \\\n"
161           "      (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n"
162           "                       (S), (L));                              \\\n"
163           "      if((R) != 0) {                                           \\\n"
164           "        free((B));                                             \\\n"
165           "        (B) = NULL;                                            \\\n"
166           "      }                                                        \\\n"
167           "    }                                                          \\\n"
168           "  } while (0)\n\n",
169           headerfile);
170     fprintf (headerfile, "struct units;\n\n");
171     fprintf (headerfile, "#endif\n\n");
172     asprintf(&fn, "%s_files", base);
173     if (fn == NULL)
174         errx(1, "malloc");
175     logfile = fopen(fn, "w");
176     if (logfile == NULL)
177         err (1, "open %s", fn);
178 }
179
180 void
181 close_generate (void)
182 {
183     fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
184
185     fclose (headerfile);
186     fprintf (logfile, "\n");
187     fclose (logfile);
188 }
189
190 void
191 gen_assign_defval(const char *var, struct value *val)
192 {
193     switch(val->type) {
194     case stringvalue:
195         fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue);
196         break;
197     case integervalue:
198         fprintf(codefile, "%s = %d;\n", var, val->u.integervalue);
199         break;
200     case booleanvalue:
201         if(val->u.booleanvalue)
202             fprintf(codefile, "%s = TRUE;\n", var);
203         else
204             fprintf(codefile, "%s = FALSE;\n", var);
205         break;
206     default:
207         abort();
208     }
209 }
210
211 void
212 gen_compare_defval(const char *var, struct value *val)
213 {
214     switch(val->type) {
215     case stringvalue:
216         fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue);
217         break;
218     case integervalue:
219         fprintf(codefile, "if(%s != %d)\n", var, val->u.integervalue);
220         break;
221     case booleanvalue:
222         if(val->u.booleanvalue)
223             fprintf(codefile, "if(!%s)\n", var);
224         else
225             fprintf(codefile, "if(%s)\n", var);
226         break;
227     default:
228         abort();
229     }
230 }
231
232 static void
233 generate_header_of_codefile(const char *name)
234 {
235     char *filename;
236
237     if (codefile != NULL)
238         abort();
239
240     asprintf (&filename, "%s_%s.x", STEM, name);
241     if (filename == NULL)
242         errx(1, "malloc");
243     codefile = fopen (filename, "w");
244     if (codefile == NULL)
245         err (1, "fopen %s", filename);
246     fprintf(logfile, "%s ", filename);
247     free(filename);
248     fprintf (codefile, 
249              "/* Generated from %s */\n"
250              "/* Do not edit */\n\n"
251              "#include <stdio.h>\n"
252              "#include <stdlib.h>\n"
253              "#include <time.h>\n"
254              "#include <string.h>\n"
255              "#include <errno.h>\n"
256              "#include <limits.h>\n"
257              "#include <krb5-types.h>\n",
258              orig_filename);
259
260     fprintf (codefile,
261              "#include <%s.h>\n",
262              headerbase);
263     fprintf (codefile,
264              "#include <asn1_err.h>\n"
265              "#include <der.h>\n"
266              "#include <parse_units.h>\n\n");
267
268 }
269
270 static void
271 close_codefile(void)
272 {
273     if (codefile == NULL)
274         abort();
275
276     fclose(codefile);
277     codefile = NULL;
278 }
279
280
281 void
282 generate_constant (const Symbol *s)
283 {
284     switch(s->value->type) {
285     case booleanvalue:
286         break;
287     case integervalue:
288         fprintf (headerfile, "enum { %s = %d };\n\n",
289                  s->gen_name, s->value->u.integervalue);
290         break;
291     case nullvalue:
292         break;
293     case stringvalue:
294         break;
295     case objectidentifiervalue: {
296         struct objid *o, **list;
297         int i, len;
298
299         generate_header_of_codefile(s->gen_name);
300
301         len = 0;
302         for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
303             len++;
304         list = emalloc(sizeof(*list) * len);
305
306         i = 0;
307         for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
308             list[i++] = o;
309
310         fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name);
311         for (i = len - 1 ; i >= 0; i--) {
312             o = list[i];
313             fprintf(headerfile, "%s(%d) ",
314                     o->label ? o->label : "label-less", o->value);
315         }
316
317         fprintf (headerfile, "} */\n");
318         fprintf (headerfile, "const heim_oid *oid_%s(void);\n\n",
319                  s->gen_name);
320
321         fprintf (codefile, "static unsigned oid_%s_variable_num[%d] =  {",
322                  s->gen_name, len);
323         for (i = len - 1 ; i >= 0; i--) {
324             fprintf(codefile, "%d%s ", list[i]->value, i > 0 ? "," : "");
325         }
326         fprintf(codefile, "};\n");
327
328         fprintf (codefile, "static const heim_oid oid_%s_variable = "
329                  "{ %d, oid_%s_variable_num };\n\n", 
330                  s->gen_name, len, s->gen_name);
331
332         fprintf (codefile, "const heim_oid *oid_%s(void)\n"
333                  "{\n"
334                  "return &oid_%s_variable;\n"
335                  "}\n\n",
336                  s->gen_name, s->gen_name);
337
338         close_codefile();
339
340         break;
341     }
342     default:
343         abort();
344     }
345 }
346
347 static void
348 space(int level)
349 {
350     while(level-- > 0)
351         fprintf(headerfile, "  ");
352 }
353
354 static const char *
355 last_member_p(struct member *m)
356 {
357     struct member *n = ASN1_TAILQ_NEXT(m, members);
358     if (n == NULL)
359         return "";
360     if (n->ellipsis && ASN1_TAILQ_NEXT(n, members) == NULL)
361         return "";
362     return ",";
363 }
364
365 static struct member *
366 have_ellipsis(Type *t)
367 {
368     struct member *m;
369     ASN1_TAILQ_FOREACH(m, t->members, members) {
370         if (m->ellipsis)
371             return m;
372     }
373     return NULL;
374 }
375
376 static void
377 define_asn1 (int level, Type *t)
378 {
379     switch (t->type) {
380     case TType:
381         fprintf (headerfile, "%s", t->symbol->name);
382         break;
383     case TInteger:
384         if(t->members == NULL) {
385             fprintf (headerfile, "INTEGER");
386             if (t->range)
387                 fprintf (headerfile, " (%d..%d)",
388                          t->range->min, t->range->max);
389         } else {
390             Member *m;
391             fprintf (headerfile, "INTEGER {\n");
392             ASN1_TAILQ_FOREACH(m, t->members, members) {
393                 space (level + 1);
394                 fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val, 
395                         last_member_p(m));
396             }
397             space(level);
398             fprintf (headerfile, "}");
399         }
400         break;
401     case TBoolean:
402         fprintf (headerfile, "BOOLEAN");
403         break;
404     case TOctetString:
405         fprintf (headerfile, "OCTET STRING");
406         break;
407     case TEnumerated :
408     case TBitString: {
409         Member *m;
410
411         space(level);
412         if(t->type == TBitString)
413             fprintf (headerfile, "BIT STRING {\n");
414         else
415             fprintf (headerfile, "ENUMERATED {\n");
416         ASN1_TAILQ_FOREACH(m, t->members, members) {
417             space(level + 1);
418             fprintf (headerfile, "%s(%d)%s\n", m->name, m->val, 
419                      last_member_p(m));
420         }
421         space(level);
422         fprintf (headerfile, "}");
423         break;
424     }
425     case TChoice:
426     case TSet:
427     case TSequence: {
428         Member *m;
429         int max_width = 0;
430
431         if(t->type == TChoice)
432             fprintf(headerfile, "CHOICE {\n");
433         else if(t->type == TSet)
434             fprintf(headerfile, "SET {\n");
435         else
436             fprintf(headerfile, "SEQUENCE {\n");
437         ASN1_TAILQ_FOREACH(m, t->members, members) {
438             if(strlen(m->name) > max_width)
439                 max_width = strlen(m->name);
440         }
441         max_width += 3;
442         if(max_width < 16) max_width = 16;
443         ASN1_TAILQ_FOREACH(m, t->members, members) {
444             int width = max_width;
445             space(level + 1);
446             if (m->ellipsis) {
447                 fprintf (headerfile, "...");
448             } else {
449                 width -= fprintf(headerfile, "%s", m->name);
450                 fprintf(headerfile, "%*s", width, "");
451                 define_asn1(level + 1, m->type);
452                 if(m->optional)
453                     fprintf(headerfile, " OPTIONAL");
454             }
455             if(last_member_p(m))
456                 fprintf (headerfile, ",");
457             fprintf (headerfile, "\n");
458         }
459         space(level);
460         fprintf (headerfile, "}");
461         break;
462     }
463     case TSequenceOf:
464         fprintf (headerfile, "SEQUENCE OF ");
465         define_asn1 (0, t->subtype);
466         break;
467     case TSetOf:
468         fprintf (headerfile, "SET OF ");
469         define_asn1 (0, t->subtype);
470         break;
471     case TGeneralizedTime:
472         fprintf (headerfile, "GeneralizedTime");
473         break;
474     case TGeneralString:
475         fprintf (headerfile, "GeneralString");
476         break;
477     case TTag: {
478         const char *classnames[] = { "UNIVERSAL ", "APPLICATION ", 
479                                      "" /* CONTEXT */, "PRIVATE " };
480         if(t->tag.tagclass != ASN1_C_UNIV)
481             fprintf (headerfile, "[%s%d] ", 
482                      classnames[t->tag.tagclass],
483                      t->tag.tagvalue);
484         if(t->tag.tagenv == TE_IMPLICIT)
485             fprintf (headerfile, "IMPLICIT ");
486         define_asn1 (level, t->subtype);
487         break;
488     }
489     case TUTCTime:
490         fprintf (headerfile, "UTCTime");
491         break;
492     case TUTF8String:
493         space(level);
494         fprintf (headerfile, "UTF8String");
495         break;
496     case TPrintableString:
497         space(level);
498         fprintf (headerfile, "PrintableString");
499         break;
500     case TIA5String:
501         space(level);
502         fprintf (headerfile, "IA5String");
503         break;
504     case TBMPString:
505         space(level);
506         fprintf (headerfile, "BMPString");
507         break;
508     case TUniversalString:
509         space(level);
510         fprintf (headerfile, "UniversalString");
511         break;
512     case TVisibleString:
513         space(level);
514         fprintf (headerfile, "VisibleString");
515         break;
516     case TOID :
517         space(level);
518         fprintf(headerfile, "OBJECT IDENTIFIER");
519         break;
520     case TNull:
521         space(level);
522         fprintf (headerfile, "NULL");
523         break;
524     default:
525         abort ();
526     }
527 }
528
529 static void
530 define_type (int level, const char *name, Type *t, int typedefp, int preservep)
531 {
532     switch (t->type) {
533     case TType:
534         space(level);
535         fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name);
536         break;
537     case TInteger:
538         space(level);
539         if(t->members) {
540             Member *m;
541             fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
542             ASN1_TAILQ_FOREACH(m, t->members, members) {
543                 space (level + 1);
544                 fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val, 
545                         last_member_p(m));
546             }
547             fprintf (headerfile, "} %s;\n", name);
548         } else if (t->range == NULL) {
549             fprintf (headerfile, "heim_integer %s;\n", name);
550         } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
551             fprintf (headerfile, "int %s;\n", name);
552         } else if (t->range->min == 0 && t->range->max == UINT_MAX) {
553             fprintf (headerfile, "unsigned int %s;\n", name);
554         } else if (t->range->min == 0 && t->range->max == INT_MAX) {
555             fprintf (headerfile, "unsigned int %s;\n", name);
556         } else
557             errx(1, "%s: unsupported range %d -> %d", 
558                  name, t->range->min, t->range->max);
559         break;
560     case TBoolean:
561         space(level);
562         fprintf (headerfile, "int %s;\n", name);
563         break;
564     case TOctetString:
565         space(level);
566         fprintf (headerfile, "heim_octet_string %s;\n", name);
567         break;
568     case TBitString: {
569         Member *m;
570         Type i;
571         struct range range = { 0, INT_MAX };
572
573         i.type = TInteger;
574         i.range = &range;
575         i.members = NULL;
576         i.constraint = NULL;
577
578         space(level);
579         if(ASN1_TAILQ_EMPTY(t->members)) 
580             fprintf (headerfile, "heim_bit_string %s;\n", name);
581         else {
582             fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
583             ASN1_TAILQ_FOREACH(m, t->members, members) {
584                 char *n;
585                 
586                 asprintf (&n, "%s:1", m->gen_name);
587                 if (n == NULL)
588                     errx(1, "malloc");
589                 define_type (level + 1, n, &i, FALSE, FALSE);
590                 free (n);
591             }
592             space(level);
593             fprintf (headerfile, "} %s;\n\n", name);
594         }
595         break;
596     }
597     case TEnumerated: {
598         Member *m;
599
600         space(level);
601         fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
602         ASN1_TAILQ_FOREACH(m, t->members, members) {
603             space(level + 1);
604             if (m->ellipsis)
605                 fprintf (headerfile, "/* ... */\n");
606             else
607                 fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val,
608                          last_member_p(m));
609         }
610         space(level);
611         fprintf (headerfile, "} %s;\n\n", name);
612         break;
613     }
614     case TSet:
615     case TSequence: {
616         Member *m;
617
618         space(level);
619         fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
620         if (t->type == TSequence && preservep) {
621             space(level + 1);
622             fprintf(headerfile, "heim_octet_string _save;\n");
623         }
624         ASN1_TAILQ_FOREACH(m, t->members, members) {
625             if (m->ellipsis) {
626                 ;
627             } else if (m->optional) {
628                 char *n;
629
630                 asprintf (&n, "*%s", m->gen_name);
631                 if (n == NULL)
632                     errx(1, "malloc");
633                 define_type (level + 1, n, m->type, FALSE, FALSE);
634                 free (n);
635             } else
636                 define_type (level + 1, m->gen_name, m->type, FALSE, FALSE);
637         }
638         space(level);
639         fprintf (headerfile, "} %s;\n", name);
640         break;
641     }
642     case TSetOf:
643     case TSequenceOf: {
644         Type i;
645         struct range range = { 0, INT_MAX };
646
647         i.type = TInteger;
648         i.range = &range;
649         i.members = NULL;
650         i.constraint = NULL;
651
652         space(level);
653         fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
654         define_type (level + 1, "len", &i, FALSE, FALSE);
655         define_type (level + 1, "*val", t->subtype, FALSE, FALSE);
656         space(level);
657         fprintf (headerfile, "} %s;\n", name);
658         break;
659     }
660     case TGeneralizedTime:
661         space(level);
662         fprintf (headerfile, "time_t %s;\n", name);
663         break;
664     case TGeneralString:
665         space(level);
666         fprintf (headerfile, "heim_general_string %s;\n", name);
667         break;
668     case TTag:
669         define_type (level, name, t->subtype, typedefp, preservep);
670         break;
671     case TChoice: {
672         int first = 1;
673         Member *m;
674
675         space(level);
676         fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
677         if (preservep) {
678             space(level + 1);
679             fprintf(headerfile, "heim_octet_string _save;\n");
680         }
681         space(level + 1);
682         fprintf (headerfile, "enum {\n");
683         m = have_ellipsis(t);
684         if (m) {
685             space(level + 2);
686             fprintf (headerfile, "%s = 0,\n", m->label); 
687             first = 0;
688         }
689         ASN1_TAILQ_FOREACH(m, t->members, members) {
690             space(level + 2);
691             if (m->ellipsis)
692                 fprintf (headerfile, "/* ... */\n");
693             else
694                 fprintf (headerfile, "%s%s%s\n", m->label, 
695                          first ? " = 1" : "", 
696                          last_member_p(m));
697             first = 0;
698         }
699         space(level + 1);
700         fprintf (headerfile, "} element;\n");
701         space(level + 1);
702         fprintf (headerfile, "union {\n");
703         ASN1_TAILQ_FOREACH(m, t->members, members) {
704             if (m->ellipsis) {
705                 space(level + 2);
706                 fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");
707             } else if (m->optional) {
708                 char *n;
709
710                 asprintf (&n, "*%s", m->gen_name);
711                 if (n == NULL)
712                     errx(1, "malloc");
713                 define_type (level + 2, n, m->type, FALSE, FALSE);
714                 free (n);
715             } else
716                 define_type (level + 2, m->gen_name, m->type, FALSE, FALSE);
717         }
718         space(level + 1);
719         fprintf (headerfile, "} u;\n");
720         space(level);
721         fprintf (headerfile, "} %s;\n", name);
722         break;
723     }
724     case TUTCTime:
725         space(level);
726         fprintf (headerfile, "time_t %s;\n", name);
727         break;
728     case TUTF8String:
729         space(level);
730         fprintf (headerfile, "heim_utf8_string %s;\n", name);
731         break;
732     case TPrintableString:
733         space(level);
734         fprintf (headerfile, "heim_printable_string %s;\n", name);
735         break;
736     case TIA5String:
737         space(level);
738         fprintf (headerfile, "heim_ia5_string %s;\n", name);
739         break;
740     case TBMPString:
741         space(level);
742         fprintf (headerfile, "heim_bmp_string %s;\n", name);
743         break;
744     case TUniversalString:
745         space(level);
746         fprintf (headerfile, "heim_universal_string %s;\n", name);
747         break;
748     case TVisibleString:
749         space(level);
750         fprintf (headerfile, "heim_visible_string %s;\n", name);
751         break;
752     case TOID :
753         space(level);
754         fprintf (headerfile, "heim_oid %s;\n", name);
755         break;
756     case TNull:
757         space(level);
758         fprintf (headerfile, "int %s;\n", name);
759         break;
760     default:
761         abort ();
762     }
763 }
764
765 static void
766 generate_type_header (const Symbol *s)
767 {
768     int preservep = preserve_type(s->name) ? TRUE : FALSE;
769
770     fprintf (headerfile, "/*\n");
771     fprintf (headerfile, "%s ::= ", s->name);
772     define_asn1 (0, s->type);
773     fprintf (headerfile, "\n*/\n\n");
774
775     fprintf (headerfile, "typedef ");
776     define_type (0, s->gen_name, s->type, TRUE, preservep);
777
778     fprintf (headerfile, "\n");
779 }
780
781
782 void
783 generate_type (const Symbol *s)
784 {
785     generate_header_of_codefile(s->gen_name);
786
787     generate_type_header (s);
788     generate_type_encode (s);
789     generate_type_decode (s);
790     generate_type_free (s);
791     generate_type_length (s);
792     generate_type_copy (s);
793     generate_type_seq (s);
794     generate_glue (s->type, s->gen_name);
795     fprintf(headerfile, "\n\n");
796     close_codefile();
797 }