s4:heimdal: import lorikeet-heimdal-200906080040 (commit 904d0124b46eed7a8ad6e5b73e89...
[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$");
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 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
549 static void
550 define_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
785 static void
786 generate_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
802 void
803 generate_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 }