xref: /minix/crypto/external/bsd/heimdal/dist/lib/asn1/gen.c (revision 0a6a1f1d)
1 /*	$NetBSD: gen.c,v 1.3 2014/04/24 13:45:34 pettai Exp $	*/
2 
3 /*
4  * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  *
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * 3. Neither the name of the Institute nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 #include "gen_locl.h"
39 #include <libgen.h>
40 
41 __RCSID("NetBSD");
42 
43 FILE *privheaderfile, *headerfile, *codefile, *logfile, *templatefile;
44 
45 #define STEM "asn1"
46 
47 static const char *orig_filename;
48 static char *privheader, *header, *template;
49 static const char *headerbase = STEM;
50 
51 /*
52  * list of all IMPORTs
53  */
54 
55 struct import {
56     const char *module;
57     struct import *next;
58 };
59 
60 static struct import *imports = NULL;
61 
62 void
add_import(const char * module)63 add_import (const char *module)
64 {
65     struct import *tmp = emalloc (sizeof(*tmp));
66 
67     tmp->module = module;
68     tmp->next   = imports;
69     imports     = tmp;
70 
71     fprintf (headerfile, "#include <%s_asn1.h>\n", module);
72 }
73 
74 /*
75  * List of all exported symbols
76  */
77 
78 struct sexport {
79     const char *name;
80     int defined;
81     struct sexport *next;
82 };
83 
84 static struct sexport *exports = NULL;
85 
86 void
add_export(const char * name)87 add_export (const char *name)
88 {
89     struct sexport *tmp = emalloc (sizeof(*tmp));
90 
91     tmp->name   = name;
92     tmp->next   = exports;
93     exports     = tmp;
94 }
95 
96 int
is_export(const char * name)97 is_export(const char *name)
98 {
99     struct sexport *tmp;
100 
101     if (exports == NULL) /* no export list, all exported */
102 	return 1;
103 
104     for (tmp = exports; tmp != NULL; tmp = tmp->next) {
105 	if (strcmp(tmp->name, name) == 0) {
106 	    tmp->defined = 1;
107 	    return 1;
108 	}
109     }
110     return 0;
111 }
112 
113 const char *
get_filename(void)114 get_filename (void)
115 {
116     return orig_filename;
117 }
118 
119 void
init_generate(const char * filename,const char * base)120 init_generate (const char *filename, const char *base)
121 {
122     char *fn = NULL;
123 
124     orig_filename = filename;
125     if (base != NULL) {
126 	headerbase = strdup(base);
127 	if (headerbase == NULL)
128 	    errx(1, "strdup");
129     }
130 
131     /* public header file */
132     if (asprintf(&header, "%s.h", headerbase) < 0 || header == NULL)
133 	errx(1, "malloc");
134     if (asprintf(&fn, "%s.hx", headerbase) < 0 || fn == NULL)
135 	errx(1, "malloc");
136     headerfile = fopen (fn, "w");
137     if (headerfile == NULL)
138 	err (1, "open %s", fn);
139     free(fn);
140     fn = NULL;
141 
142     /* private header file */
143     if (asprintf(&privheader, "%s-priv.h", headerbase) < 0 || privheader == NULL)
144 	errx(1, "malloc");
145     if (asprintf(&fn, "%s-priv.hx", headerbase) < 0 || fn == NULL)
146 	errx(1, "malloc");
147     privheaderfile = fopen (fn, "w");
148     if (privheaderfile == NULL)
149 	err (1, "open %s", fn);
150     free(fn);
151     fn = NULL;
152 
153     /* template file */
154     if (asprintf(&template, "%s-template.c", headerbase) < 0 || template == NULL)
155 	errx(1, "malloc");
156     fprintf (headerfile,
157 	     "/* Generated from %s */\n"
158 	     "/* Do not edit */\n\n",
159 	     basename(filename));
160     fprintf (headerfile,
161 	     "#ifndef __%s_h__\n"
162 	     "#define __%s_h__\n\n", headerbase, headerbase);
163     fprintf (headerfile,
164 	     "#include <stddef.h>\n"
165 	     "#include <time.h>\n\n");
166     fprintf (headerfile,
167 	     "#ifndef __asn1_common_definitions__\n"
168 	     "#define __asn1_common_definitions__\n\n");
169     fprintf (headerfile,
170 	     "typedef struct heim_integer {\n"
171 	     "  size_t length;\n"
172 	     "  void *data;\n"
173 	     "  int negative;\n"
174 	     "} heim_integer;\n\n");
175     fprintf (headerfile,
176 	     "typedef struct heim_octet_string {\n"
177 	     "  size_t length;\n"
178 	     "  void *data;\n"
179 	     "} heim_octet_string;\n\n");
180     fprintf (headerfile,
181 	     "typedef char *heim_general_string;\n\n"
182 	     );
183     fprintf (headerfile,
184 	     "typedef char *heim_utf8_string;\n\n"
185 	     );
186     fprintf (headerfile,
187 	     "typedef struct heim_octet_string heim_printable_string;\n\n"
188 	     );
189     fprintf (headerfile,
190 	     "typedef struct heim_octet_string heim_ia5_string;\n\n"
191 	     );
192     fprintf (headerfile,
193 	     "typedef struct heim_bmp_string {\n"
194 	     "  size_t length;\n"
195 	     "  uint16_t *data;\n"
196 	     "} heim_bmp_string;\n\n");
197     fprintf (headerfile,
198 	     "typedef struct heim_universal_string {\n"
199 	     "  size_t length;\n"
200 	     "  uint32_t *data;\n"
201 	     "} heim_universal_string;\n\n");
202     fprintf (headerfile,
203 	     "typedef char *heim_visible_string;\n\n"
204 	     );
205     fprintf (headerfile,
206 	     "typedef struct heim_oid {\n"
207 	     "  size_t length;\n"
208 	     "  unsigned *components;\n"
209 	     "} heim_oid;\n\n");
210     fprintf (headerfile,
211 	     "typedef struct heim_bit_string {\n"
212 	     "  size_t length;\n"
213 	     "  void *data;\n"
214 	     "} heim_bit_string;\n\n");
215     fprintf (headerfile,
216 	     "typedef struct heim_octet_string heim_any;\n"
217 	     "typedef struct heim_octet_string heim_any_set;\n\n");
218     fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R)                  \\\n"
219 	  "  do {                                                         \\\n"
220 	  "    (BL) = length_##T((S));                                    \\\n"
221 	  "    (B) = malloc((BL));                                        \\\n"
222 	  "    if((B) == NULL) {                                          \\\n"
223 	  "      (R) = ENOMEM;                                            \\\n"
224 	  "    } else {                                                   \\\n"
225 	  "      (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n"
226 	  "                       (S), (L));                              \\\n"
227 	  "      if((R) != 0) {                                           \\\n"
228 	  "        free((B));                                             \\\n"
229 	  "        (B) = NULL;                                            \\\n"
230 	  "      }                                                        \\\n"
231 	  "    }                                                          \\\n"
232 	  "  } while (0)\n\n",
233 	  headerfile);
234     fputs("#ifdef _WIN32\n"
235 	  "#ifndef ASN1_LIB\n"
236 	  "#define ASN1EXP  __declspec(dllimport)\n"
237 	  "#else\n"
238 	  "#define ASN1EXP\n"
239 	  "#endif\n"
240 	  "#define ASN1CALL __stdcall\n"
241 	  "#else\n"
242 	  "#define ASN1EXP\n"
243 	  "#define ASN1CALL\n"
244 	  "#endif\n",
245 	  headerfile);
246     fprintf (headerfile, "struct units;\n\n");
247     fprintf (headerfile, "#endif\n\n");
248     if (asprintf(&fn, "%s_files", base) < 0 || fn == NULL)
249 	errx(1, "malloc");
250     logfile = fopen(fn, "w");
251     if (logfile == NULL)
252 	err (1, "open %s", fn);
253 
254     /* if one code file, write into the one codefile */
255     if (one_code_file)
256 	return;
257 
258     templatefile = fopen (template, "w");
259     if (templatefile == NULL)
260 	err (1, "open %s", template);
261 
262     fprintf (templatefile,
263 	     "/* Generated from %s */\n"
264 	     "/* Do not edit */\n\n"
265 	     "#include <stdio.h>\n"
266 	     "#include <stdlib.h>\n"
267 	     "#include <time.h>\n"
268 	     "#include <string.h>\n"
269 	     "#include <errno.h>\n"
270 	     "#include <limits.h>\n"
271 	     "#include <krb5/krb5-types.h>\n",
272 	     basename(filename));
273 
274     fprintf (templatefile,
275 	     "#include <%s>\n"
276 	     "#include <%s>\n"
277 	     "#include <krb5/der.h>\n"
278 	     "#include <der-private.h>\n"
279 	     "#include <asn1-template.h>\n",
280 	     header, privheader);
281 
282 
283 }
284 
285 void
close_generate(void)286 close_generate (void)
287 {
288     fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
289 
290     if (headerfile)
291         fclose (headerfile);
292     if (privheaderfile)
293         fclose (privheaderfile);
294     if (templatefile)
295         fclose (templatefile);
296     if (logfile)
297         fprintf (logfile, "\n");
298         fclose (logfile);
299 }
300 
301 void
gen_assign_defval(const char * var,struct value * val)302 gen_assign_defval(const char *var, struct value *val)
303 {
304     switch(val->type) {
305     case stringvalue:
306 	fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue);
307 	break;
308     case integervalue:
309 	fprintf(codefile, "%s = %d;\n", var, val->u.integervalue);
310 	break;
311     case booleanvalue:
312 	if(val->u.booleanvalue)
313 	    fprintf(codefile, "%s = TRUE;\n", var);
314 	else
315 	    fprintf(codefile, "%s = FALSE;\n", var);
316 	break;
317     default:
318 	abort();
319     }
320 }
321 
322 void
gen_compare_defval(const char * var,struct value * val)323 gen_compare_defval(const char *var, struct value *val)
324 {
325     switch(val->type) {
326     case stringvalue:
327 	fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue);
328 	break;
329     case integervalue:
330 	fprintf(codefile, "if(%s != %d)\n", var, val->u.integervalue);
331 	break;
332     case booleanvalue:
333 	if(val->u.booleanvalue)
334 	    fprintf(codefile, "if(!%s)\n", var);
335 	else
336 	    fprintf(codefile, "if(%s)\n", var);
337 	break;
338     default:
339 	abort();
340     }
341 }
342 
343 void
generate_header_of_codefile(const char * name)344 generate_header_of_codefile(const char *name)
345 {
346     char *filename = NULL;
347 
348     if (codefile != NULL)
349 	abort();
350 
351     if (asprintf (&filename, "%s_%s.x", STEM, name) < 0 || filename == NULL)
352 	errx(1, "malloc");
353     codefile = fopen (filename, "w");
354     if (codefile == NULL)
355 	err (1, "fopen %s", filename);
356     fprintf(logfile, "%s ", filename);
357     free(filename);
358     filename = NULL;
359     fprintf (codefile,
360 	     "/* Generated from %s */\n"
361 	     "/* Do not edit */\n\n"
362 	     "#define  ASN1_LIB\n\n"
363 	     "#include <stdio.h>\n"
364 	     "#include <stdlib.h>\n"
365 	     "#include <time.h>\n"
366 	     "#include <string.h>\n"
367 	     "#include <errno.h>\n"
368 	     "#include <limits.h>\n"
369 	     "#include <krb5/krb5-types.h>\n",
370 	     basename(orig_filename));
371 
372     fprintf (codefile,
373 	     "#include <%s>\n"
374 	     "#include <%s>\n",
375 	     header, privheader);
376     fprintf (codefile,
377 	     "#include <krb5/asn1_err.h>\n"
378 	     "#include <krb5/der.h>\n"
379 	     "#include <der-private.h>\n"
380 	     "#include <asn1-template.h>\n"
381 	     "#include <krb5/parse_units.h>\n\n");
382 
383 }
384 
385 void
close_codefile(void)386 close_codefile(void)
387 {
388     if (codefile == NULL)
389 	abort();
390 
391     fclose(codefile);
392     codefile = NULL;
393 }
394 
395 
396 void
generate_constant(const Symbol * s)397 generate_constant (const Symbol *s)
398 {
399     switch(s->value->type) {
400     case booleanvalue:
401 	break;
402     case integervalue:
403 	fprintf (headerfile, "enum { %s = %d };\n\n",
404 		 s->gen_name, s->value->u.integervalue);
405 	break;
406     case nullvalue:
407 	break;
408     case stringvalue:
409 	break;
410     case objectidentifiervalue: {
411 	struct objid *o, **list;
412 	unsigned int i, len;
413 	char *gen_upper;
414 
415 	if (!one_code_file)
416 	    generate_header_of_codefile(s->gen_name);
417 
418 	len = 0;
419 	for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
420 	    len++;
421 	if (len == 0) {
422 	    printf("s->gen_name: %s",s->gen_name);
423 	    fflush(stdout);
424 	    break;
425 	}
426 	list = emalloc(sizeof(*list) * len);
427 
428 	i = 0;
429 	for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
430 	    list[i++] = o;
431 
432 	fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name);
433 	for (i = len ; i > 0; i--) {
434 	    o = list[i - 1];
435 	    fprintf(headerfile, "%s(%d) ",
436 		    o->label ? o->label : "label-less", o->value);
437 	}
438 
439 	fprintf (codefile, "static unsigned oid_%s_variable_num[%d] =  {",
440 		 s->gen_name, len);
441 	for (i = len ; i > 0; i--) {
442 	    fprintf(codefile, "%d%s ", list[i - 1]->value, i > 1 ? "," : "");
443 	}
444 	fprintf(codefile, "};\n");
445 
446 	fprintf (codefile, "const heim_oid asn1_oid_%s = "
447 		 "{ %d, oid_%s_variable_num };\n\n",
448 		 s->gen_name, len, s->gen_name);
449 
450 	free(list);
451 
452 	/* header file */
453 
454 	gen_upper = strdup(s->gen_name);
455 	len = strlen(gen_upper);
456 	for (i = 0; i < len; i++)
457 	    gen_upper[i] = toupper((int)s->gen_name[i]);
458 
459 	fprintf (headerfile, "} */\n");
460 	fprintf (headerfile,
461 		 "extern ASN1EXP const heim_oid asn1_oid_%s;\n"
462 		 "#define ASN1_OID_%s (&asn1_oid_%s)\n\n",
463 		 s->gen_name,
464 		 gen_upper,
465 		 s->gen_name);
466 
467 	free(gen_upper);
468 
469 	if (!one_code_file)
470 	    close_codefile();
471 
472 	break;
473     }
474     default:
475 	abort();
476     }
477 }
478 
479 int
is_primitive_type(int type)480 is_primitive_type(int type)
481 {
482     switch(type) {
483     case TInteger:
484     case TBoolean:
485     case TOctetString:
486     case TBitString:
487     case TEnumerated:
488     case TGeneralizedTime:
489     case TGeneralString:
490     case TTeletexString:
491     case TOID:
492     case TUTCTime:
493     case TUTF8String:
494     case TPrintableString:
495     case TIA5String:
496     case TBMPString:
497     case TUniversalString:
498     case TVisibleString:
499     case TNull:
500 	return 1;
501     default:
502 	return 0;
503     }
504 }
505 
506 static void
space(int level)507 space(int level)
508 {
509     while(level-- > 0)
510 	fprintf(headerfile, "  ");
511 }
512 
513 static const char *
last_member_p(struct member * m)514 last_member_p(struct member *m)
515 {
516     struct member *n = ASN1_TAILQ_NEXT(m, members);
517     if (n == NULL)
518 	return "";
519     if (n->ellipsis && ASN1_TAILQ_NEXT(n, members) == NULL)
520 	return "";
521     return ",";
522 }
523 
524 static struct member *
have_ellipsis(Type * t)525 have_ellipsis(Type *t)
526 {
527     struct member *m;
528     ASN1_TAILQ_FOREACH(m, t->members, members) {
529 	if (m->ellipsis)
530 	    return m;
531     }
532     return NULL;
533 }
534 
535 static void
define_asn1(int level,Type * t)536 define_asn1 (int level, Type *t)
537 {
538     switch (t->type) {
539     case TType:
540 	fprintf (headerfile, "%s", t->symbol->name);
541 	break;
542     case TInteger:
543 	if(t->members == NULL) {
544             fprintf (headerfile, "INTEGER");
545 	    if (t->range)
546 		fprintf (headerfile, " (%d..%d)",
547 			 t->range->min, t->range->max);
548         } else {
549 	    Member *m;
550             fprintf (headerfile, "INTEGER {\n");
551 	    ASN1_TAILQ_FOREACH(m, t->members, members) {
552                 space (level + 1);
553 		fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val,
554 			last_member_p(m));
555             }
556 	    space(level);
557             fprintf (headerfile, "}");
558         }
559 	break;
560     case TBoolean:
561 	fprintf (headerfile, "BOOLEAN");
562 	break;
563     case TOctetString:
564 	fprintf (headerfile, "OCTET STRING");
565 	break;
566     case TEnumerated :
567     case TBitString: {
568 	Member *m;
569 
570 	space(level);
571 	if(t->type == TBitString)
572 	    fprintf (headerfile, "BIT STRING {\n");
573 	else
574 	    fprintf (headerfile, "ENUMERATED {\n");
575 	ASN1_TAILQ_FOREACH(m, t->members, members) {
576 	    space(level + 1);
577 	    fprintf (headerfile, "%s(%d)%s\n", m->name, m->val,
578 		     last_member_p(m));
579 	}
580 	space(level);
581 	fprintf (headerfile, "}");
582 	break;
583     }
584     case TChoice:
585     case TSet:
586     case TSequence: {
587 	Member *m;
588 	int max_width = 0;
589 
590 	if(t->type == TChoice)
591 	    fprintf(headerfile, "CHOICE {\n");
592 	else if(t->type == TSet)
593 	    fprintf(headerfile, "SET {\n");
594 	else
595 	    fprintf(headerfile, "SEQUENCE {\n");
596 	ASN1_TAILQ_FOREACH(m, t->members, members) {
597 	    if(strlen(m->name) > max_width)
598 		max_width = strlen(m->name);
599 	}
600 	max_width += 3;
601 	if(max_width < 16) max_width = 16;
602 	ASN1_TAILQ_FOREACH(m, t->members, members) {
603 	    int width = max_width;
604 	    space(level + 1);
605 	    if (m->ellipsis) {
606 		fprintf (headerfile, "...");
607 	    } else {
608 		width -= fprintf(headerfile, "%s", m->name);
609 		fprintf(headerfile, "%*s", width, "");
610 		define_asn1(level + 1, m->type);
611 		if(m->optional)
612 		    fprintf(headerfile, " OPTIONAL");
613 	    }
614 	    if(last_member_p(m))
615 		fprintf (headerfile, ",");
616 	    fprintf (headerfile, "\n");
617 	}
618 	space(level);
619 	fprintf (headerfile, "}");
620 	break;
621     }
622     case TSequenceOf:
623 	fprintf (headerfile, "SEQUENCE OF ");
624 	define_asn1 (0, t->subtype);
625 	break;
626     case TSetOf:
627 	fprintf (headerfile, "SET OF ");
628 	define_asn1 (0, t->subtype);
629 	break;
630     case TGeneralizedTime:
631 	fprintf (headerfile, "GeneralizedTime");
632 	break;
633     case TGeneralString:
634 	fprintf (headerfile, "GeneralString");
635 	break;
636     case TTeletexString:
637 	fprintf (headerfile, "TeletexString");
638 	break;
639     case TTag: {
640 	const char *classnames[] = { "UNIVERSAL ", "APPLICATION ",
641 				     "" /* CONTEXT */, "PRIVATE " };
642 	if(t->tag.tagclass != ASN1_C_UNIV)
643 	    fprintf (headerfile, "[%s%d] ",
644 		     classnames[t->tag.tagclass],
645 		     t->tag.tagvalue);
646 	if(t->tag.tagenv == TE_IMPLICIT)
647 	    fprintf (headerfile, "IMPLICIT ");
648 	define_asn1 (level, t->subtype);
649 	break;
650     }
651     case TUTCTime:
652 	fprintf (headerfile, "UTCTime");
653 	break;
654     case TUTF8String:
655 	space(level);
656 	fprintf (headerfile, "UTF8String");
657 	break;
658     case TPrintableString:
659 	space(level);
660 	fprintf (headerfile, "PrintableString");
661 	break;
662     case TIA5String:
663 	space(level);
664 	fprintf (headerfile, "IA5String");
665 	break;
666     case TBMPString:
667 	space(level);
668 	fprintf (headerfile, "BMPString");
669 	break;
670     case TUniversalString:
671 	space(level);
672 	fprintf (headerfile, "UniversalString");
673 	break;
674     case TVisibleString:
675 	space(level);
676 	fprintf (headerfile, "VisibleString");
677 	break;
678     case TOID :
679 	space(level);
680 	fprintf(headerfile, "OBJECT IDENTIFIER");
681 	break;
682     case TNull:
683 	space(level);
684 	fprintf (headerfile, "NULL");
685 	break;
686     default:
687 	abort ();
688     }
689 }
690 
691 static void
getnewbasename(char ** newbasename,int typedefp,const char * basename,const char * name)692 getnewbasename(char **newbasename, int typedefp, const char *basename, const char *name)
693 {
694     if (typedefp)
695 	*newbasename = strdup(name);
696     else {
697 	if (name[0] == '*')
698 	    name++;
699 	if (asprintf(newbasename, "%s_%s", basename, name) < 0)
700 	    errx(1, "malloc");
701     }
702     if (*newbasename == NULL)
703 	err(1, "malloc");
704 }
705 
706 static void
define_type(int level,const char * name,const char * basename,Type * t,int typedefp,int preservep)707 define_type (int level, const char *name, const char *basename, Type *t, int typedefp, int preservep)
708 {
709     char *newbasename = NULL;
710 
711     switch (t->type) {
712     case TType:
713 	space(level);
714 	fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name);
715 	break;
716     case TInteger:
717 	space(level);
718 	if(t->members) {
719             Member *m;
720             fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
721 	    ASN1_TAILQ_FOREACH(m, t->members, members) {
722                 space (level + 1);
723                 fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val,
724                         last_member_p(m));
725             }
726             fprintf (headerfile, "} %s;\n", name);
727 	} else if (t->range == NULL) {
728 	    fprintf (headerfile, "heim_integer %s;\n", name);
729 	} else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
730 	    fprintf (headerfile, "int %s;\n", name);
731 	} else if (t->range->min == 0 && t->range->max == UINT_MAX) {
732 	    fprintf (headerfile, "unsigned int %s;\n", name);
733 	} else if (t->range->min == 0 && t->range->max == INT_MAX) {
734 	    fprintf (headerfile, "unsigned int %s;\n", name);
735 	} else
736 	    errx(1, "%s: unsupported range %d -> %d",
737 		 name, t->range->min, t->range->max);
738 	break;
739     case TBoolean:
740 	space(level);
741 	fprintf (headerfile, "int %s;\n", name);
742 	break;
743     case TOctetString:
744 	space(level);
745 	fprintf (headerfile, "heim_octet_string %s;\n", name);
746 	break;
747     case TBitString: {
748 	Member *m;
749 	Type i;
750 	struct range range = { 0, INT_MAX };
751 
752 	i.type = TInteger;
753 	i.range = &range;
754 	i.members = NULL;
755 	i.constraint = NULL;
756 
757 	space(level);
758 	if(ASN1_TAILQ_EMPTY(t->members))
759 	    fprintf (headerfile, "heim_bit_string %s;\n", name);
760 	else {
761 	    int pos = 0;
762 	    getnewbasename(&newbasename, typedefp, basename, name);
763 
764 	    fprintf (headerfile, "struct %s {\n", newbasename);
765 	    ASN1_TAILQ_FOREACH(m, t->members, members) {
766 		char *n = NULL;
767 
768 		/* pad unused */
769 		while (pos < m->val) {
770 		    if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL)
771 			errx(1, "malloc");
772 		    define_type (level + 1, n, newbasename, &i, FALSE, FALSE);
773 		    free(n);
774 		    pos++;
775 		}
776 
777 		n = NULL;
778 		if (asprintf (&n, "%s:1", m->gen_name) < 0 || n == NULL)
779 		    errx(1, "malloc");
780 		define_type (level + 1, n, newbasename, &i, FALSE, FALSE);
781 		free (n);
782 		n = NULL;
783 		pos++;
784 	    }
785 	    /* pad to 32 elements */
786 	    while (pos < 32) {
787 		char *n = NULL;
788 		if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL)
789 		    errx(1, "malloc");
790 		define_type (level + 1, n, newbasename, &i, FALSE, FALSE);
791 		free(n);
792 		pos++;
793 	    }
794 
795 	    space(level);
796 	    fprintf (headerfile, "} %s;\n\n", name);
797 	}
798 	break;
799     }
800     case TEnumerated: {
801 	Member *m;
802 
803 	space(level);
804 	fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
805 	ASN1_TAILQ_FOREACH(m, t->members, members) {
806 	    space(level + 1);
807 	    if (m->ellipsis)
808 		fprintf (headerfile, "/* ... */\n");
809 	    else
810 		fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val,
811 			 last_member_p(m));
812 	}
813 	space(level);
814 	fprintf (headerfile, "} %s;\n\n", name);
815 	break;
816     }
817     case TSet:
818     case TSequence: {
819 	Member *m;
820 
821 	getnewbasename(&newbasename, typedefp, basename, name);
822 
823 	space(level);
824 	fprintf (headerfile, "struct %s {\n", newbasename);
825 	if (t->type == TSequence && preservep) {
826 	    space(level + 1);
827 	    fprintf(headerfile, "heim_octet_string _save;\n");
828 	}
829 	ASN1_TAILQ_FOREACH(m, t->members, members) {
830 	    if (m->ellipsis) {
831 		;
832 	    } else if (m->optional) {
833 		char *n = NULL;
834 
835 		if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL)
836 		    errx(1, "malloc");
837 		define_type (level + 1, n, newbasename, m->type, FALSE, FALSE);
838 		free (n);
839 	    } else
840 		define_type (level + 1, m->gen_name, newbasename, m->type, FALSE, FALSE);
841 	}
842 	space(level);
843 	fprintf (headerfile, "} %s;\n", name);
844 	break;
845     }
846     case TSetOf:
847     case TSequenceOf: {
848 	Type i;
849 	struct range range = { 0, INT_MAX };
850 
851 	getnewbasename(&newbasename, typedefp, basename, name);
852 
853 	i.type = TInteger;
854 	i.range = &range;
855 	i.members = NULL;
856 	i.constraint = NULL;
857 
858 	space(level);
859 	fprintf (headerfile, "struct %s {\n", newbasename);
860 	define_type (level + 1, "len", newbasename, &i, FALSE, FALSE);
861 	define_type (level + 1, "*val", newbasename, t->subtype, FALSE, FALSE);
862 	space(level);
863 	fprintf (headerfile, "} %s;\n", name);
864 	break;
865     }
866     case TGeneralizedTime:
867 	space(level);
868 	fprintf (headerfile, "time_t %s;\n", name);
869 	break;
870     case TGeneralString:
871 	space(level);
872 	fprintf (headerfile, "heim_general_string %s;\n", name);
873 	break;
874     case TTeletexString:
875 	space(level);
876 	fprintf (headerfile, "heim_general_string %s;\n", name);
877 	break;
878     case TTag:
879 	define_type (level, name, basename, t->subtype, typedefp, preservep);
880 	break;
881     case TChoice: {
882 	int first = 1;
883 	Member *m;
884 
885 	getnewbasename(&newbasename, typedefp, basename, name);
886 
887 	space(level);
888 	fprintf (headerfile, "struct %s {\n", newbasename);
889 	if (preservep) {
890 	    space(level + 1);
891 	    fprintf(headerfile, "heim_octet_string _save;\n");
892 	}
893 	space(level + 1);
894 	fprintf (headerfile, "enum {\n");
895 	m = have_ellipsis(t);
896 	if (m) {
897 	    space(level + 2);
898 	    fprintf (headerfile, "%s = 0,\n", m->label);
899 	    first = 0;
900 	}
901 	ASN1_TAILQ_FOREACH(m, t->members, members) {
902 	    space(level + 2);
903 	    if (m->ellipsis)
904 		fprintf (headerfile, "/* ... */\n");
905 	    else
906 		fprintf (headerfile, "%s%s%s\n", m->label,
907 			 first ? " = 1" : "",
908 			 last_member_p(m));
909 	    first = 0;
910 	}
911 	space(level + 1);
912 	fprintf (headerfile, "} element;\n");
913 	space(level + 1);
914 	fprintf (headerfile, "union {\n");
915 	ASN1_TAILQ_FOREACH(m, t->members, members) {
916 	    if (m->ellipsis) {
917 		space(level + 2);
918 		fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");
919 	    } else if (m->optional) {
920 		char *n = NULL;
921 
922 		if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL)
923 		    errx(1, "malloc");
924 		define_type (level + 2, n, newbasename, m->type, FALSE, FALSE);
925 		free (n);
926 	    } else
927 		define_type (level + 2, m->gen_name, newbasename, m->type, FALSE, FALSE);
928 	}
929 	space(level + 1);
930 	fprintf (headerfile, "} u;\n");
931 	space(level);
932 	fprintf (headerfile, "} %s;\n", name);
933 	break;
934     }
935     case TUTCTime:
936 	space(level);
937 	fprintf (headerfile, "time_t %s;\n", name);
938 	break;
939     case TUTF8String:
940 	space(level);
941 	fprintf (headerfile, "heim_utf8_string %s;\n", name);
942 	break;
943     case TPrintableString:
944 	space(level);
945 	fprintf (headerfile, "heim_printable_string %s;\n", name);
946 	break;
947     case TIA5String:
948 	space(level);
949 	fprintf (headerfile, "heim_ia5_string %s;\n", name);
950 	break;
951     case TBMPString:
952 	space(level);
953 	fprintf (headerfile, "heim_bmp_string %s;\n", name);
954 	break;
955     case TUniversalString:
956 	space(level);
957 	fprintf (headerfile, "heim_universal_string %s;\n", name);
958 	break;
959     case TVisibleString:
960 	space(level);
961 	fprintf (headerfile, "heim_visible_string %s;\n", name);
962 	break;
963     case TOID :
964 	space(level);
965 	fprintf (headerfile, "heim_oid %s;\n", name);
966 	break;
967     case TNull:
968 	space(level);
969 	fprintf (headerfile, "int %s;\n", name);
970 	break;
971     default:
972 	abort ();
973     }
974     if (newbasename)
975 	free(newbasename);
976 }
977 
978 static void
generate_type_header(const Symbol * s)979 generate_type_header (const Symbol *s)
980 {
981     int preservep = preserve_type(s->name) ? TRUE : FALSE;
982 
983     fprintf (headerfile, "/*\n");
984     fprintf (headerfile, "%s ::= ", s->name);
985     define_asn1 (0, s->type);
986     fprintf (headerfile, "\n*/\n\n");
987 
988     fprintf (headerfile, "typedef ");
989     define_type (0, s->gen_name, s->gen_name, s->type, TRUE, preservep);
990 
991     fprintf (headerfile, "\n");
992 }
993 
994 void
generate_type(const Symbol * s)995 generate_type (const Symbol *s)
996 {
997     FILE *h;
998     const char * exp;
999 
1000     if (!one_code_file)
1001 	generate_header_of_codefile(s->gen_name);
1002 
1003     generate_type_header (s);
1004 
1005     if (template_flag)
1006 	generate_template(s);
1007 
1008     if (template_flag == 0 || is_template_compat(s) == 0) {
1009 	generate_type_encode (s);
1010 	generate_type_decode (s);
1011 	generate_type_free (s);
1012 	generate_type_length (s);
1013 	generate_type_copy (s);
1014     }
1015     generate_type_seq (s);
1016     generate_glue (s->type, s->gen_name);
1017 
1018     /* generate prototypes */
1019 
1020     if (is_export(s->name)) {
1021 	h = headerfile;
1022 	exp = "ASN1EXP ";
1023     } else {
1024 	h = privheaderfile;
1025 	exp = "";
1026     }
1027 
1028     fprintf (h,
1029 	     "%sint    ASN1CALL "
1030 	     "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
1031 	     exp,
1032 	     s->gen_name, s->gen_name);
1033     fprintf (h,
1034 	     "%sint    ASN1CALL "
1035 	     "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n",
1036 	     exp,
1037 	     s->gen_name, s->gen_name);
1038     fprintf (h,
1039 	     "%ssize_t ASN1CALL length_%s(const %s *);\n",
1040 	     exp,
1041 	     s->gen_name, s->gen_name);
1042     fprintf (h,
1043 	     "%sint    ASN1CALL copy_%s  (const %s *, %s *);\n",
1044 	     exp,
1045 	     s->gen_name, s->gen_name, s->gen_name);
1046     fprintf (h,
1047 	     "%svoid   ASN1CALL free_%s  (%s *);\n",
1048 	     exp,
1049 	     s->gen_name, s->gen_name);
1050 
1051     fprintf(h, "\n\n");
1052 
1053     if (!one_code_file) {
1054 	fprintf(codefile, "\n\n");
1055 	close_codefile();
1056 	}
1057 }
1058