s4:heimdal: import lorikeet-heimdal-200911122202 (commit 9291fd2d101f3eecec550178634f...
[abartlet/samba.git/.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$");
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
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
187 void
188 close_generate (void)
189 {
190     fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
191
192     fclose (headerfile);
193     fprintf (logfile, "\n");
194     fclose (logfile);
195 }
196
197 void
198 gen_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
218 void
219 gen_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
239 void
240 generate_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
277 void
278 close_codefile(void)
279 {
280     if (codefile == NULL)
281         abort();
282
283     fclose(codefile);
284     codefile = NULL;
285 }
286
287
288 void
289 generate_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
367 static void
368 space(int level)
369 {
370     while(level-- > 0)
371         fprintf(headerfile, "  ");
372 }
373
374 static const char *
375 last_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
385 static struct member *
386 have_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
396 static void
397 define_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 TTeletexString:
498         fprintf (headerfile, "TeletexString");
499         break;
500     case TTag: {
501         const char *classnames[] = { "UNIVERSAL ", "APPLICATION ",
502                                      "" /* CONTEXT */, "PRIVATE " };
503         if(t->tag.tagclass != ASN1_C_UNIV)
504             fprintf (headerfile, "[%s%d] ",
505                      classnames[t->tag.tagclass],
506                      t->tag.tagvalue);
507         if(t->tag.tagenv == TE_IMPLICIT)
508             fprintf (headerfile, "IMPLICIT ");
509         define_asn1 (level, t->subtype);
510         break;
511     }
512     case TUTCTime:
513         fprintf (headerfile, "UTCTime");
514         break;
515     case TUTF8String:
516         space(level);
517         fprintf (headerfile, "UTF8String");
518         break;
519     case TPrintableString:
520         space(level);
521         fprintf (headerfile, "PrintableString");
522         break;
523     case TIA5String:
524         space(level);
525         fprintf (headerfile, "IA5String");
526         break;
527     case TBMPString:
528         space(level);
529         fprintf (headerfile, "BMPString");
530         break;
531     case TUniversalString:
532         space(level);
533         fprintf (headerfile, "UniversalString");
534         break;
535     case TVisibleString:
536         space(level);
537         fprintf (headerfile, "VisibleString");
538         break;
539     case TOID :
540         space(level);
541         fprintf(headerfile, "OBJECT IDENTIFIER");
542         break;
543     case TNull:
544         space(level);
545         fprintf (headerfile, "NULL");
546         break;
547     default:
548         abort ();
549     }
550 }
551
552 static void
553 define_type (int level, const char *name, Type *t, int typedefp, int preservep)
554 {
555     switch (t->type) {
556     case TType:
557         space(level);
558         fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name);
559         break;
560     case TInteger:
561         space(level);
562         if(t->members) {
563             Member *m;
564             fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
565             ASN1_TAILQ_FOREACH(m, t->members, members) {
566                 space (level + 1);
567                 fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val,
568                         last_member_p(m));
569             }
570             fprintf (headerfile, "} %s;\n", name);
571         } else if (t->range == NULL) {
572             fprintf (headerfile, "heim_integer %s;\n", name);
573         } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
574             fprintf (headerfile, "int %s;\n", name);
575         } else if (t->range->min == 0 && t->range->max == UINT_MAX) {
576             fprintf (headerfile, "unsigned int %s;\n", name);
577         } else if (t->range->min == 0 && t->range->max == INT_MAX) {
578             fprintf (headerfile, "unsigned int %s;\n", name);
579         } else
580             errx(1, "%s: unsupported range %d -> %d",
581                  name, t->range->min, t->range->max);
582         break;
583     case TBoolean:
584         space(level);
585         fprintf (headerfile, "int %s;\n", name);
586         break;
587     case TOctetString:
588         space(level);
589         fprintf (headerfile, "heim_octet_string %s;\n", name);
590         break;
591     case TBitString: {
592         Member *m;
593         Type i;
594         struct range range = { 0, INT_MAX };
595
596         i.type = TInteger;
597         i.range = &range;
598         i.members = NULL;
599         i.constraint = NULL;
600
601         space(level);
602         if(ASN1_TAILQ_EMPTY(t->members))
603             fprintf (headerfile, "heim_bit_string %s;\n", name);
604         else {
605             fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
606             ASN1_TAILQ_FOREACH(m, t->members, members) {
607                 char *n;
608         
609                 asprintf (&n, "%s:1", m->gen_name);
610                 if (n == NULL)
611                     errx(1, "malloc");
612                 define_type (level + 1, n, &i, FALSE, FALSE);
613                 free (n);
614             }
615             space(level);
616             fprintf (headerfile, "} %s;\n\n", name);
617         }
618         break;
619     }
620     case TEnumerated: {
621         Member *m;
622
623         space(level);
624         fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
625         ASN1_TAILQ_FOREACH(m, t->members, members) {
626             space(level + 1);
627             if (m->ellipsis)
628                 fprintf (headerfile, "/* ... */\n");
629             else
630                 fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val,
631                          last_member_p(m));
632         }
633         space(level);
634         fprintf (headerfile, "} %s;\n\n", name);
635         break;
636     }
637     case TSet:
638     case TSequence: {
639         Member *m;
640
641         space(level);
642         fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
643         if (t->type == TSequence && preservep) {
644             space(level + 1);
645             fprintf(headerfile, "heim_octet_string _save;\n");
646         }
647         ASN1_TAILQ_FOREACH(m, t->members, members) {
648             if (m->ellipsis) {
649                 ;
650             } else if (m->optional) {
651                 char *n;
652
653                 asprintf (&n, "*%s", m->gen_name);
654                 if (n == NULL)
655                     errx(1, "malloc");
656                 define_type (level + 1, n, m->type, FALSE, FALSE);
657                 free (n);
658             } else
659                 define_type (level + 1, m->gen_name, m->type, FALSE, FALSE);
660         }
661         space(level);
662         fprintf (headerfile, "} %s;\n", name);
663         break;
664     }
665     case TSetOf:
666     case TSequenceOf: {
667         Type i;
668         struct range range = { 0, INT_MAX };
669
670         i.type = TInteger;
671         i.range = &range;
672         i.members = NULL;
673         i.constraint = NULL;
674
675         space(level);
676         fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
677         define_type (level + 1, "len", &i, FALSE, FALSE);
678         define_type (level + 1, "*val", t->subtype, FALSE, FALSE);
679         space(level);
680         fprintf (headerfile, "} %s;\n", name);
681         break;
682     }
683     case TGeneralizedTime:
684         space(level);
685         fprintf (headerfile, "time_t %s;\n", name);
686         break;
687     case TGeneralString:
688         space(level);
689         fprintf (headerfile, "heim_general_string %s;\n", name);
690         break;
691     case TTeletexString:
692         space(level);
693         fprintf (headerfile, "heim_general_string %s;\n", name);
694         break;
695     case TTag:
696         define_type (level, name, t->subtype, typedefp, preservep);
697         break;
698     case TChoice: {
699         int first = 1;
700         Member *m;
701
702         space(level);
703         fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
704         if (preservep) {
705             space(level + 1);
706             fprintf(headerfile, "heim_octet_string _save;\n");
707         }
708         space(level + 1);
709         fprintf (headerfile, "enum {\n");
710         m = have_ellipsis(t);
711         if (m) {
712             space(level + 2);
713             fprintf (headerfile, "%s = 0,\n", m->label);
714             first = 0;
715         }
716         ASN1_TAILQ_FOREACH(m, t->members, members) {
717             space(level + 2);
718             if (m->ellipsis)
719                 fprintf (headerfile, "/* ... */\n");
720             else
721                 fprintf (headerfile, "%s%s%s\n", m->label,
722                          first ? " = 1" : "",
723                          last_member_p(m));
724             first = 0;
725         }
726         space(level + 1);
727         fprintf (headerfile, "} element;\n");
728         space(level + 1);
729         fprintf (headerfile, "union {\n");
730         ASN1_TAILQ_FOREACH(m, t->members, members) {
731             if (m->ellipsis) {
732                 space(level + 2);
733                 fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");
734             } else if (m->optional) {
735                 char *n;
736
737                 asprintf (&n, "*%s", m->gen_name);
738                 if (n == NULL)
739                     errx(1, "malloc");
740                 define_type (level + 2, n, m->type, FALSE, FALSE);
741                 free (n);
742             } else
743                 define_type (level + 2, m->gen_name, m->type, FALSE, FALSE);
744         }
745         space(level + 1);
746         fprintf (headerfile, "} u;\n");
747         space(level);
748         fprintf (headerfile, "} %s;\n", name);
749         break;
750     }
751     case TUTCTime:
752         space(level);
753         fprintf (headerfile, "time_t %s;\n", name);
754         break;
755     case TUTF8String:
756         space(level);
757         fprintf (headerfile, "heim_utf8_string %s;\n", name);
758         break;
759     case TPrintableString:
760         space(level);
761         fprintf (headerfile, "heim_printable_string %s;\n", name);
762         break;
763     case TIA5String:
764         space(level);
765         fprintf (headerfile, "heim_ia5_string %s;\n", name);
766         break;
767     case TBMPString:
768         space(level);
769         fprintf (headerfile, "heim_bmp_string %s;\n", name);
770         break;
771     case TUniversalString:
772         space(level);
773         fprintf (headerfile, "heim_universal_string %s;\n", name);
774         break;
775     case TVisibleString:
776         space(level);
777         fprintf (headerfile, "heim_visible_string %s;\n", name);
778         break;
779     case TOID :
780         space(level);
781         fprintf (headerfile, "heim_oid %s;\n", name);
782         break;
783     case TNull:
784         space(level);
785         fprintf (headerfile, "int %s;\n", name);
786         break;
787     default:
788         abort ();
789     }
790 }
791
792 static void
793 generate_type_header (const Symbol *s)
794 {
795     int preservep = preserve_type(s->name) ? TRUE : FALSE;
796
797     fprintf (headerfile, "/*\n");
798     fprintf (headerfile, "%s ::= ", s->name);
799     define_asn1 (0, s->type);
800     fprintf (headerfile, "\n*/\n\n");
801
802     fprintf (headerfile, "typedef ");
803     define_type (0, s->gen_name, s->type, TRUE, preservep);
804
805     fprintf (headerfile, "\n");
806 }
807
808
809 void
810 generate_type (const Symbol *s)
811 {
812     if (!one_code_file)
813         generate_header_of_codefile(s->gen_name);
814
815     generate_type_header (s);
816     generate_type_encode (s);
817     generate_type_decode (s);
818     generate_type_free (s);
819     generate_type_length (s);
820     generate_type_copy (s);
821     generate_type_seq (s);
822     generate_glue (s->type, s->gen_name);
823     fprintf(headerfile, "\n\n");
824
825     if (!one_code_file) {
826         fprintf(codefile, "\n\n");
827         close_codefile();
828         }
829 }