Merge Samba3 and Samba4 together
[sfrench/samba-autobuild/.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     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         unsigned 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         if (len == 0) {
305             printf("s->gen_name: %s",s->gen_name);
306             fflush(stdout);
307             break;
308         }
309         list = emalloc(sizeof(*list) * len);
310
311         i = 0;
312         for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
313             list[i++] = o;
314
315         fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name);
316         for (i = len ; i > 0; i--) {
317             o = list[i - 1];
318             fprintf(headerfile, "%s(%d) ",
319                     o->label ? o->label : "label-less", o->value);
320         }
321
322         fprintf (headerfile, "} */\n");
323         fprintf (headerfile, "const heim_oid *oid_%s(void);\n\n",
324                  s->gen_name);
325
326         fprintf (codefile, "static unsigned oid_%s_variable_num[%d] =  {",
327                  s->gen_name, len);
328         for (i = len ; i > 0; i--) {
329             fprintf(codefile, "%d%s ", list[i - 1]->value, i > 1 ? "," : "");
330         }
331         fprintf(codefile, "};\n");
332
333         fprintf (codefile, "static const heim_oid oid_%s_variable = "
334                  "{ %d, oid_%s_variable_num };\n\n", 
335                  s->gen_name, len, s->gen_name);
336
337         fprintf (codefile, "const heim_oid *oid_%s(void)\n"
338                  "{\n"
339                  "return &oid_%s_variable;\n"
340                  "}\n\n",
341                  s->gen_name, s->gen_name);
342
343         close_codefile();
344
345         break;
346     }
347     default:
348         abort();
349     }
350 }
351
352 static void
353 space(int level)
354 {
355     while(level-- > 0)
356         fprintf(headerfile, "  ");
357 }
358
359 static const char *
360 last_member_p(struct member *m)
361 {
362     struct member *n = ASN1_TAILQ_NEXT(m, members);
363     if (n == NULL)
364         return "";
365     if (n->ellipsis && ASN1_TAILQ_NEXT(n, members) == NULL)
366         return "";
367     return ",";
368 }
369
370 static struct member *
371 have_ellipsis(Type *t)
372 {
373     struct member *m;
374     ASN1_TAILQ_FOREACH(m, t->members, members) {
375         if (m->ellipsis)
376             return m;
377     }
378     return NULL;
379 }
380
381 static void
382 define_asn1 (int level, Type *t)
383 {
384     switch (t->type) {
385     case TType:
386         fprintf (headerfile, "%s", t->symbol->name);
387         break;
388     case TInteger:
389         if(t->members == NULL) {
390             fprintf (headerfile, "INTEGER");
391             if (t->range)
392                 fprintf (headerfile, " (%d..%d)",
393                          t->range->min, t->range->max);
394         } else {
395             Member *m;
396             fprintf (headerfile, "INTEGER {\n");
397             ASN1_TAILQ_FOREACH(m, t->members, members) {
398                 space (level + 1);
399                 fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val, 
400                         last_member_p(m));
401             }
402             space(level);
403             fprintf (headerfile, "}");
404         }
405         break;
406     case TBoolean:
407         fprintf (headerfile, "BOOLEAN");
408         break;
409     case TOctetString:
410         fprintf (headerfile, "OCTET STRING");
411         break;
412     case TEnumerated :
413     case TBitString: {
414         Member *m;
415
416         space(level);
417         if(t->type == TBitString)
418             fprintf (headerfile, "BIT STRING {\n");
419         else
420             fprintf (headerfile, "ENUMERATED {\n");
421         ASN1_TAILQ_FOREACH(m, t->members, members) {
422             space(level + 1);
423             fprintf (headerfile, "%s(%d)%s\n", m->name, m->val, 
424                      last_member_p(m));
425         }
426         space(level);
427         fprintf (headerfile, "}");
428         break;
429     }
430     case TChoice:
431     case TSet:
432     case TSequence: {
433         Member *m;
434         int max_width = 0;
435
436         if(t->type == TChoice)
437             fprintf(headerfile, "CHOICE {\n");
438         else if(t->type == TSet)
439             fprintf(headerfile, "SET {\n");
440         else
441             fprintf(headerfile, "SEQUENCE {\n");
442         ASN1_TAILQ_FOREACH(m, t->members, members) {
443             if(strlen(m->name) > max_width)
444                 max_width = strlen(m->name);
445         }
446         max_width += 3;
447         if(max_width < 16) max_width = 16;
448         ASN1_TAILQ_FOREACH(m, t->members, members) {
449             int width = max_width;
450             space(level + 1);
451             if (m->ellipsis) {
452                 fprintf (headerfile, "...");
453             } else {
454                 width -= fprintf(headerfile, "%s", m->name);
455                 fprintf(headerfile, "%*s", width, "");
456                 define_asn1(level + 1, m->type);
457                 if(m->optional)
458                     fprintf(headerfile, " OPTIONAL");
459             }
460             if(last_member_p(m))
461                 fprintf (headerfile, ",");
462             fprintf (headerfile, "\n");
463         }
464         space(level);
465         fprintf (headerfile, "}");
466         break;
467     }
468     case TSequenceOf:
469         fprintf (headerfile, "SEQUENCE OF ");
470         define_asn1 (0, t->subtype);
471         break;
472     case TSetOf:
473         fprintf (headerfile, "SET OF ");
474         define_asn1 (0, t->subtype);
475         break;
476     case TGeneralizedTime:
477         fprintf (headerfile, "GeneralizedTime");
478         break;
479     case TGeneralString:
480         fprintf (headerfile, "GeneralString");
481         break;
482     case TTag: {
483         const char *classnames[] = { "UNIVERSAL ", "APPLICATION ", 
484                                      "" /* CONTEXT */, "PRIVATE " };
485         if(t->tag.tagclass != ASN1_C_UNIV)
486             fprintf (headerfile, "[%s%d] ", 
487                      classnames[t->tag.tagclass],
488                      t->tag.tagvalue);
489         if(t->tag.tagenv == TE_IMPLICIT)
490             fprintf (headerfile, "IMPLICIT ");
491         define_asn1 (level, t->subtype);
492         break;
493     }
494     case TUTCTime:
495         fprintf (headerfile, "UTCTime");
496         break;
497     case TUTF8String:
498         space(level);
499         fprintf (headerfile, "UTF8String");
500         break;
501     case TPrintableString:
502         space(level);
503         fprintf (headerfile, "PrintableString");
504         break;
505     case TIA5String:
506         space(level);
507         fprintf (headerfile, "IA5String");
508         break;
509     case TBMPString:
510         space(level);
511         fprintf (headerfile, "BMPString");
512         break;
513     case TUniversalString:
514         space(level);
515         fprintf (headerfile, "UniversalString");
516         break;
517     case TVisibleString:
518         space(level);
519         fprintf (headerfile, "VisibleString");
520         break;
521     case TOID :
522         space(level);
523         fprintf(headerfile, "OBJECT IDENTIFIER");
524         break;
525     case TNull:
526         space(level);
527         fprintf (headerfile, "NULL");
528         break;
529     default:
530         abort ();
531     }
532 }
533
534 static void
535 define_type (int level, const char *name, Type *t, int typedefp, int preservep)
536 {
537     switch (t->type) {
538     case TType:
539         space(level);
540         fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name);
541         break;
542     case TInteger:
543         space(level);
544         if(t->members) {
545             Member *m;
546             fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
547             ASN1_TAILQ_FOREACH(m, t->members, members) {
548                 space (level + 1);
549                 fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val, 
550                         last_member_p(m));
551             }
552             fprintf (headerfile, "} %s;\n", name);
553         } else if (t->range == NULL) {
554             fprintf (headerfile, "heim_integer %s;\n", name);
555         } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
556             fprintf (headerfile, "int %s;\n", name);
557         } else if (t->range->min == 0 && t->range->max == UINT_MAX) {
558             fprintf (headerfile, "unsigned int %s;\n", name);
559         } else if (t->range->min == 0 && t->range->max == INT_MAX) {
560             fprintf (headerfile, "unsigned int %s;\n", name);
561         } else
562             errx(1, "%s: unsupported range %d -> %d", 
563                  name, t->range->min, t->range->max);
564         break;
565     case TBoolean:
566         space(level);
567         fprintf (headerfile, "int %s;\n", name);
568         break;
569     case TOctetString:
570         space(level);
571         fprintf (headerfile, "heim_octet_string %s;\n", name);
572         break;
573     case TBitString: {
574         Member *m;
575         Type i;
576         struct range range = { 0, INT_MAX };
577
578         i.type = TInteger;
579         i.range = &range;
580         i.members = NULL;
581         i.constraint = NULL;
582
583         space(level);
584         if(ASN1_TAILQ_EMPTY(t->members)) 
585             fprintf (headerfile, "heim_bit_string %s;\n", name);
586         else {
587             fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
588             ASN1_TAILQ_FOREACH(m, t->members, members) {
589                 char *n;
590                 
591                 asprintf (&n, "%s:1", m->gen_name);
592                 if (n == NULL)
593                     errx(1, "malloc");
594                 define_type (level + 1, n, &i, FALSE, FALSE);
595                 free (n);
596             }
597             space(level);
598             fprintf (headerfile, "} %s;\n\n", name);
599         }
600         break;
601     }
602     case TEnumerated: {
603         Member *m;
604
605         space(level);
606         fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
607         ASN1_TAILQ_FOREACH(m, t->members, members) {
608             space(level + 1);
609             if (m->ellipsis)
610                 fprintf (headerfile, "/* ... */\n");
611             else
612                 fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val,
613                          last_member_p(m));
614         }
615         space(level);
616         fprintf (headerfile, "} %s;\n\n", name);
617         break;
618     }
619     case TSet:
620     case TSequence: {
621         Member *m;
622
623         space(level);
624         fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
625         if (t->type == TSequence && preservep) {
626             space(level + 1);
627             fprintf(headerfile, "heim_octet_string _save;\n");
628         }
629         ASN1_TAILQ_FOREACH(m, t->members, members) {
630             if (m->ellipsis) {
631                 ;
632             } else if (m->optional) {
633                 char *n;
634
635                 asprintf (&n, "*%s", m->gen_name);
636                 if (n == NULL)
637                     errx(1, "malloc");
638                 define_type (level + 1, n, m->type, FALSE, FALSE);
639                 free (n);
640             } else
641                 define_type (level + 1, m->gen_name, m->type, FALSE, FALSE);
642         }
643         space(level);
644         fprintf (headerfile, "} %s;\n", name);
645         break;
646     }
647     case TSetOf:
648     case TSequenceOf: {
649         Type i;
650         struct range range = { 0, INT_MAX };
651
652         i.type = TInteger;
653         i.range = &range;
654         i.members = NULL;
655         i.constraint = NULL;
656
657         space(level);
658         fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
659         define_type (level + 1, "len", &i, FALSE, FALSE);
660         define_type (level + 1, "*val", t->subtype, FALSE, FALSE);
661         space(level);
662         fprintf (headerfile, "} %s;\n", name);
663         break;
664     }
665     case TGeneralizedTime:
666         space(level);
667         fprintf (headerfile, "time_t %s;\n", name);
668         break;
669     case TGeneralString:
670         space(level);
671         fprintf (headerfile, "heim_general_string %s;\n", name);
672         break;
673     case TTag:
674         define_type (level, name, t->subtype, typedefp, preservep);
675         break;
676     case TChoice: {
677         int first = 1;
678         Member *m;
679
680         space(level);
681         fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
682         if (preservep) {
683             space(level + 1);
684             fprintf(headerfile, "heim_octet_string _save;\n");
685         }
686         space(level + 1);
687         fprintf (headerfile, "enum {\n");
688         m = have_ellipsis(t);
689         if (m) {
690             space(level + 2);
691             fprintf (headerfile, "%s = 0,\n", m->label); 
692             first = 0;
693         }
694         ASN1_TAILQ_FOREACH(m, t->members, members) {
695             space(level + 2);
696             if (m->ellipsis)
697                 fprintf (headerfile, "/* ... */\n");
698             else
699                 fprintf (headerfile, "%s%s%s\n", m->label, 
700                          first ? " = 1" : "", 
701                          last_member_p(m));
702             first = 0;
703         }
704         space(level + 1);
705         fprintf (headerfile, "} element;\n");
706         space(level + 1);
707         fprintf (headerfile, "union {\n");
708         ASN1_TAILQ_FOREACH(m, t->members, members) {
709             if (m->ellipsis) {
710                 space(level + 2);
711                 fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");
712             } else if (m->optional) {
713                 char *n;
714
715                 asprintf (&n, "*%s", m->gen_name);
716                 if (n == NULL)
717                     errx(1, "malloc");
718                 define_type (level + 2, n, m->type, FALSE, FALSE);
719                 free (n);
720             } else
721                 define_type (level + 2, m->gen_name, m->type, FALSE, FALSE);
722         }
723         space(level + 1);
724         fprintf (headerfile, "} u;\n");
725         space(level);
726         fprintf (headerfile, "} %s;\n", name);
727         break;
728     }
729     case TUTCTime:
730         space(level);
731         fprintf (headerfile, "time_t %s;\n", name);
732         break;
733     case TUTF8String:
734         space(level);
735         fprintf (headerfile, "heim_utf8_string %s;\n", name);
736         break;
737     case TPrintableString:
738         space(level);
739         fprintf (headerfile, "heim_printable_string %s;\n", name);
740         break;
741     case TIA5String:
742         space(level);
743         fprintf (headerfile, "heim_ia5_string %s;\n", name);
744         break;
745     case TBMPString:
746         space(level);
747         fprintf (headerfile, "heim_bmp_string %s;\n", name);
748         break;
749     case TUniversalString:
750         space(level);
751         fprintf (headerfile, "heim_universal_string %s;\n", name);
752         break;
753     case TVisibleString:
754         space(level);
755         fprintf (headerfile, "heim_visible_string %s;\n", name);
756         break;
757     case TOID :
758         space(level);
759         fprintf (headerfile, "heim_oid %s;\n", name);
760         break;
761     case TNull:
762         space(level);
763         fprintf (headerfile, "int %s;\n", name);
764         break;
765     default:
766         abort ();
767     }
768 }
769
770 static void
771 generate_type_header (const Symbol *s)
772 {
773     int preservep = preserve_type(s->name) ? TRUE : FALSE;
774
775     fprintf (headerfile, "/*\n");
776     fprintf (headerfile, "%s ::= ", s->name);
777     define_asn1 (0, s->type);
778     fprintf (headerfile, "\n*/\n\n");
779
780     fprintf (headerfile, "typedef ");
781     define_type (0, s->gen_name, s->type, TRUE, preservep);
782
783     fprintf (headerfile, "\n");
784 }
785
786
787 void
788 generate_type (const Symbol *s)
789 {
790     generate_header_of_codefile(s->gen_name);
791
792     generate_type_header (s);
793     generate_type_encode (s);
794     generate_type_decode (s);
795     generate_type_free (s);
796     generate_type_length (s);
797     generate_type_copy (s);
798     generate_type_seq (s);
799     generate_glue (s->type, s->gen_name);
800     fprintf(headerfile, "\n\n");
801     close_codefile();
802 }