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