1 /* $NetBSD: gen.c,v 1.6 2023/06/19 21:41:42 christos 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: gen.c,v 1.6 2023/06/19 21:41:42 christos Exp $");
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.x", headerbase) < 0 || template == NULL)
155 errx(1, "malloc");
156 char *copy = estrdup(filename);
157 char *bn = basename(copy);
158 fprintf (headerfile,
159 "/* Generated from %s */\n"
160 "/* Do not edit */\n\n",
161 bn);
162 fprintf (headerfile,
163 "#ifndef __%s_h__\n"
164 "#define __%s_h__\n\n", headerbase, headerbase);
165 fprintf (headerfile,
166 "#include <stddef.h>\n"
167 "#include <time.h>\n\n");
168 fprintf (headerfile,
169 "#ifndef __asn1_common_definitions__\n"
170 "#define __asn1_common_definitions__\n\n");
171 fprintf (headerfile,
172 "#ifndef __HEIM_BASE_DATA__\n"
173 "#define __HEIM_BASE_DATA__ 1\n"
174 "struct heim_base_data {\n"
175 " size_t length;\n"
176 " void *data;\n"
177 "};\n"
178 "typedef struct heim_base_data heim_octet_string;\n"
179 "#endif\n\n");
180 fprintf (headerfile,
181 "typedef struct heim_integer {\n"
182 " size_t length;\n"
183 " void *data;\n"
184 " int negative;\n"
185 "} heim_integer;\n\n");
186 fprintf (headerfile,
187 "typedef char *heim_general_string;\n\n"
188 );
189 fprintf (headerfile,
190 "typedef char *heim_utf8_string;\n\n"
191 );
192 fprintf (headerfile,
193 "typedef struct heim_base_data heim_printable_string;\n\n"
194 );
195 fprintf (headerfile,
196 "typedef struct heim_base_data heim_ia5_string;\n\n"
197 );
198 fprintf (headerfile,
199 "typedef struct heim_bmp_string {\n"
200 " size_t length;\n"
201 " uint16_t *data;\n"
202 "} heim_bmp_string;\n\n");
203 fprintf (headerfile,
204 "typedef struct heim_universal_string {\n"
205 " size_t length;\n"
206 " uint32_t *data;\n"
207 "} heim_universal_string;\n\n");
208 fprintf (headerfile,
209 "typedef char *heim_visible_string;\n\n"
210 );
211 fprintf (headerfile,
212 "typedef struct heim_oid {\n"
213 " size_t length;\n"
214 " unsigned *components;\n"
215 "} heim_oid;\n\n");
216 fprintf (headerfile,
217 "typedef struct heim_bit_string {\n"
218 " size_t length;\n"
219 " void *data;\n"
220 "} heim_bit_string;\n\n");
221 fprintf (headerfile,
222 "typedef struct heim_base_data heim_any;\n"
223 "typedef struct heim_base_data heim_any_set;\n\n");
224 fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \\\n"
225 " do { \\\n"
226 " (BL) = length_##T((S)); \\\n"
227 " (B) = malloc((BL)); \\\n"
228 " if((B) == NULL) { \\\n"
229 " (R) = ENOMEM; \\\n"
230 " } else { \\\n"
231 " (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n"
232 " (S), (L)); \\\n"
233 " if((R) != 0) { \\\n"
234 " free((B)); \\\n"
235 " (B) = NULL; \\\n"
236 " } \\\n"
237 " } \\\n"
238 " } while (0)\n\n",
239 headerfile);
240 fputs("#ifdef _WIN32\n"
241 "#ifndef ASN1_LIB\n"
242 "#define ASN1EXP __declspec(dllimport)\n"
243 "#else\n"
244 "#define ASN1EXP\n"
245 "#endif\n"
246 "#define ASN1CALL __stdcall\n"
247 "#else\n"
248 "#define ASN1EXP\n"
249 "#define ASN1CALL\n"
250 "#endif\n",
251 headerfile);
252 fprintf (headerfile, "struct units;\n\n");
253 fprintf (headerfile, "#endif\n\n");
254 if (asprintf(&fn, "%s_files", base) < 0 || fn == NULL)
255 errx(1, "malloc");
256 logfile = fopen(fn, "w");
257 if (logfile == NULL)
258 err (1, "open %s", fn);
259
260 /* if one code file, write into the one codefile */
261 if (one_code_file)
262 return;
263
264 templatefile = fopen (template, "w");
265 if (templatefile == NULL)
266 err (1, "open %s", template);
267
268 fprintf (templatefile,
269 "/* Generated from %s */\n"
270 "/* Do not edit */\n\n"
271 "#include <stdio.h>\n"
272 "#include <stdlib.h>\n"
273 "#include <time.h>\n"
274 "#include <string.h>\n"
275 "#include <errno.h>\n"
276 "#include <limits.h>\n"
277 "#include <krb5/%s.h>\n",
278 bn,
279 type_file_string);
280 free(copy);
281
282 fprintf (templatefile,
283 "#include <%s>\n"
284 "#include <%s>\n"
285 "#include <krb5/der.h>\n"
286 "#include <asn1-template.h>\n",
287 header, privheader);
288
289
290 }
291
292 void
close_generate(void)293 close_generate (void)
294 {
295 fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
296
297 if (headerfile)
298 fclose (headerfile);
299 if (privheaderfile)
300 fclose (privheaderfile);
301 if (templatefile)
302 fclose (templatefile);
303 if (logfile) {
304 fprintf (logfile, "\n");
305 fclose (logfile);
306 }
307 }
308
309 void
gen_assign_defval(const char * var,struct value * val)310 gen_assign_defval(const char *var, struct value *val)
311 {
312 switch(val->type) {
313 case stringvalue:
314 fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue);
315 break;
316 case integervalue:
317 fprintf(codefile, "%s = %lld;\n",
318 var, (long long)val->u.integervalue);
319 break;
320 case booleanvalue:
321 if(val->u.booleanvalue)
322 fprintf(codefile, "%s = TRUE;\n", var);
323 else
324 fprintf(codefile, "%s = FALSE;\n", var);
325 break;
326 default:
327 abort();
328 }
329 }
330
331 void
gen_compare_defval(const char * var,struct value * val)332 gen_compare_defval(const char *var, struct value *val)
333 {
334 switch(val->type) {
335 case stringvalue:
336 fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue);
337 break;
338 case integervalue:
339 fprintf(codefile, "if(%s != %lld)\n",
340 var, (long long)val->u.integervalue);
341 break;
342 case booleanvalue:
343 if(val->u.booleanvalue)
344 fprintf(codefile, "if(!%s)\n", var);
345 else
346 fprintf(codefile, "if(%s)\n", var);
347 break;
348 default:
349 abort();
350 }
351 }
352
353 void
generate_header_of_codefile(const char * name)354 generate_header_of_codefile(const char *name)
355 {
356 char *filename = NULL;
357
358 if (codefile != NULL)
359 abort();
360
361 if (asprintf (&filename, "%s_%s.x", STEM, name) < 0 || filename == NULL)
362 errx(1, "malloc");
363 codefile = fopen (filename, "w");
364 if (codefile == NULL)
365 err (1, "fopen %s", filename);
366 if (logfile)
367 fprintf(logfile, "%s ", filename);
368 free(filename);
369 filename = NULL;
370 char *copy = estrdup(orig_filename);
371 char *bn = basename(copy);
372 fprintf (codefile,
373 "/* Generated from %s */\n"
374 "/* Do not edit */\n\n"
375 "#define ASN1_LIB\n\n"
376 "#include <stdio.h>\n"
377 "#include <stdlib.h>\n"
378 "#include <time.h>\n"
379 "#include <string.h>\n"
380 "#include <errno.h>\n"
381 "#include <limits.h>\n"
382 "#include <krb5/%s>\n",
383 bn,
384 type_file_string);
385 free(copy);
386
387 fprintf (codefile,
388 "#include \"%s\"\n"
389 "#include \"%s\"\n",
390 header, privheader);
391 fprintf (codefile,
392 "#include <krb5/asn1_err.h>\n"
393 "#include <krb5/der.h>\n"
394 "#include <asn1-template.h>\n\n");
395
396 if (parse_units_flag)
397 fprintf (codefile,
398 "#include <krb5/parse_units.h>\n\n");
399
400 }
401
402 void
close_codefile(void)403 close_codefile(void)
404 {
405 if (codefile == NULL)
406 abort();
407
408 fclose(codefile);
409 codefile = NULL;
410 }
411
412
413 void
generate_constant(const Symbol * s)414 generate_constant (const Symbol *s)
415 {
416 switch(s->value->type) {
417 case booleanvalue:
418 break;
419 case integervalue:
420 fprintf (headerfile, "enum { %s = %lld };\n\n",
421 s->gen_name,
422 (long long)s->value->u.integervalue);
423 break;
424 case nullvalue:
425 break;
426 case stringvalue:
427 break;
428 case objectidentifiervalue: {
429 struct objid *o, **list;
430 size_t i, len;
431 char *gen_upper;
432
433 if (!one_code_file)
434 generate_header_of_codefile(s->gen_name);
435
436 len = 0;
437 for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
438 len++;
439 if (len == 0) {
440 printf("s->gen_name: %s",s->gen_name);
441 fflush(stdout);
442 break;
443 }
444 list = emalloc(sizeof(*list) * len);
445
446 i = 0;
447 for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
448 list[i++] = o;
449
450 fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name);
451 for (i = len ; i > 0; i--) {
452 o = list[i - 1];
453 fprintf(headerfile, "%s(%d) ",
454 o->label ? o->label : "label-less", o->value);
455 }
456
457 fprintf (codefile, "static unsigned oid_%s_variable_num[%lu] = {",
458 s->gen_name, (unsigned long)len);
459 for (i = len ; i > 0; i--) {
460 fprintf(codefile, "%d%s ", list[i - 1]->value, i > 1 ? "," : "");
461 }
462 fprintf(codefile, "};\n");
463
464 fprintf (codefile, "const heim_oid asn1_oid_%s = "
465 "{ %lu, oid_%s_variable_num };\n\n",
466 s->gen_name, (unsigned long)len, s->gen_name);
467
468 free(list);
469
470 /* header file */
471
472 gen_upper = strdup(s->gen_name);
473 len = strlen(gen_upper);
474 for (i = 0; i < len; i++)
475 gen_upper[i] = toupper((int)s->gen_name[i]);
476
477 fprintf (headerfile, "} */\n");
478 fprintf (headerfile,
479 "extern ASN1EXP const heim_oid asn1_oid_%s;\n"
480 "#define ASN1_OID_%s (&asn1_oid_%s)\n\n",
481 s->gen_name,
482 gen_upper,
483 s->gen_name);
484
485 free(gen_upper);
486
487 if (!one_code_file)
488 close_codefile();
489
490 break;
491 }
492 default:
493 abort();
494 }
495 }
496
497 int
is_primitive_type(int type)498 is_primitive_type(int type)
499 {
500 switch(type) {
501 case TInteger:
502 case TBoolean:
503 case TOctetString:
504 case TBitString:
505 case TEnumerated:
506 case TGeneralizedTime:
507 case TGeneralString:
508 case TTeletexString:
509 case TOID:
510 case TUTCTime:
511 case TUTF8String:
512 case TPrintableString:
513 case TIA5String:
514 case TBMPString:
515 case TUniversalString:
516 case TVisibleString:
517 case TNull:
518 return 1;
519 default:
520 return 0;
521 }
522 }
523
524 static void
space(int level)525 space(int level)
526 {
527 while(level-- > 0)
528 fprintf(headerfile, " ");
529 }
530
531 static const char *
last_member_p(struct member * m)532 last_member_p(struct member *m)
533 {
534 struct member *n = ASN1_TAILQ_NEXT(m, members);
535 if (n == NULL)
536 return "";
537 if (n->ellipsis && ASN1_TAILQ_NEXT(n, members) == NULL)
538 return "";
539 return ",";
540 }
541
542 static struct member *
have_ellipsis(Type * t)543 have_ellipsis(Type *t)
544 {
545 struct member *m;
546 ASN1_TAILQ_FOREACH(m, t->members, members) {
547 if (m->ellipsis)
548 return m;
549 }
550 return NULL;
551 }
552
553 static void
define_asn1(int level,Type * t)554 define_asn1 (int level, Type *t)
555 {
556 switch (t->type) {
557 case TType:
558 fprintf (headerfile, "%s", t->symbol->name);
559 break;
560 case TInteger:
561 if(t->members == NULL) {
562 fprintf (headerfile, "INTEGER");
563 if (t->range)
564 fprintf (headerfile, " (%lld..%lld)",
565 (long long)t->range->min,
566 (long long)t->range->max);
567 } else {
568 Member *m;
569 fprintf (headerfile, "INTEGER {\n");
570 ASN1_TAILQ_FOREACH(m, t->members, members) {
571 space (level + 1);
572 fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val,
573 last_member_p(m));
574 }
575 space(level);
576 fprintf (headerfile, "}");
577 }
578 break;
579 case TBoolean:
580 fprintf (headerfile, "BOOLEAN");
581 break;
582 case TOctetString:
583 fprintf (headerfile, "OCTET STRING");
584 break;
585 case TEnumerated :
586 case TBitString: {
587 Member *m;
588
589 space(level);
590 if(t->type == TBitString)
591 fprintf (headerfile, "BIT STRING {\n");
592 else
593 fprintf (headerfile, "ENUMERATED {\n");
594 ASN1_TAILQ_FOREACH(m, t->members, members) {
595 space(level + 1);
596 fprintf (headerfile, "%s(%d)%s\n", m->name, m->val,
597 last_member_p(m));
598 }
599 space(level);
600 fprintf (headerfile, "}");
601 break;
602 }
603 case TChoice:
604 case TSet:
605 case TSequence: {
606 Member *m;
607 size_t max_width = 0;
608
609 if(t->type == TChoice)
610 fprintf(headerfile, "CHOICE {\n");
611 else if(t->type == TSet)
612 fprintf(headerfile, "SET {\n");
613 else
614 fprintf(headerfile, "SEQUENCE {\n");
615 ASN1_TAILQ_FOREACH(m, t->members, members) {
616 if(strlen(m->name) > max_width)
617 max_width = strlen(m->name);
618 }
619 max_width += 3;
620 if(max_width < 16) max_width = 16;
621 ASN1_TAILQ_FOREACH(m, t->members, members) {
622 size_t width = max_width;
623 space(level + 1);
624 if (m->ellipsis) {
625 fprintf (headerfile, "...");
626 } else {
627 width -= fprintf(headerfile, "%s", m->name);
628 fprintf(headerfile, "%*s", (int)width, "");
629 define_asn1(level + 1, m->type);
630 if(m->optional)
631 fprintf(headerfile, " OPTIONAL");
632 }
633 if(last_member_p(m))
634 fprintf (headerfile, ",");
635 fprintf (headerfile, "\n");
636 }
637 space(level);
638 fprintf (headerfile, "}");
639 break;
640 }
641 case TSequenceOf:
642 fprintf (headerfile, "SEQUENCE OF ");
643 define_asn1 (0, t->subtype);
644 break;
645 case TSetOf:
646 fprintf (headerfile, "SET OF ");
647 define_asn1 (0, t->subtype);
648 break;
649 case TGeneralizedTime:
650 fprintf (headerfile, "GeneralizedTime");
651 break;
652 case TGeneralString:
653 fprintf (headerfile, "GeneralString");
654 break;
655 case TTeletexString:
656 fprintf (headerfile, "TeletexString");
657 break;
658 case TTag: {
659 const char *classnames[] = { "UNIVERSAL ", "APPLICATION ",
660 "" /* CONTEXT */, "PRIVATE " };
661 if(t->tag.tagclass != ASN1_C_UNIV)
662 fprintf (headerfile, "[%s%d] ",
663 classnames[t->tag.tagclass],
664 t->tag.tagvalue);
665 if(t->tag.tagenv == TE_IMPLICIT)
666 fprintf (headerfile, "IMPLICIT ");
667 define_asn1 (level, t->subtype);
668 break;
669 }
670 case TUTCTime:
671 fprintf (headerfile, "UTCTime");
672 break;
673 case TUTF8String:
674 space(level);
675 fprintf (headerfile, "UTF8String");
676 break;
677 case TPrintableString:
678 space(level);
679 fprintf (headerfile, "PrintableString");
680 break;
681 case TIA5String:
682 space(level);
683 fprintf (headerfile, "IA5String");
684 break;
685 case TBMPString:
686 space(level);
687 fprintf (headerfile, "BMPString");
688 break;
689 case TUniversalString:
690 space(level);
691 fprintf (headerfile, "UniversalString");
692 break;
693 case TVisibleString:
694 space(level);
695 fprintf (headerfile, "VisibleString");
696 break;
697 case TOID :
698 space(level);
699 fprintf(headerfile, "OBJECT IDENTIFIER");
700 break;
701 case TNull:
702 space(level);
703 fprintf (headerfile, "NULL");
704 break;
705 default:
706 abort ();
707 }
708 }
709
710 static void
getnewbasename(char ** newbasename,int typedefp,const char * basename,const char * name)711 getnewbasename(char **newbasename, int typedefp, const char *basename, const char *name)
712 {
713 if (typedefp)
714 *newbasename = strdup(name);
715 else {
716 if (name[0] == '*')
717 name++;
718 if (asprintf(newbasename, "%s_%s", basename, name) < 0)
719 errx(1, "malloc");
720 }
721 if (*newbasename == NULL)
722 err(1, "malloc");
723 }
724
725 static void
define_type(int level,const char * name,const char * basename,Type * t,int typedefp,int preservep)726 define_type (int level, const char *name, const char *basename, Type *t, int typedefp, int preservep)
727 {
728 char *newbasename = NULL;
729
730 switch (t->type) {
731 case TType:
732 space(level);
733 fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name);
734 break;
735 case TInteger:
736 space(level);
737 if(t->members) {
738 Member *m;
739 fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
740 ASN1_TAILQ_FOREACH(m, t->members, members) {
741 space (level + 1);
742 fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val,
743 last_member_p(m));
744 }
745 fprintf (headerfile, "} %s;\n", name);
746 } else if (t->range == NULL) {
747 fprintf (headerfile, "heim_integer %s;\n", name);
748 } else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX) {
749 fprintf (headerfile, "int64_t %s;\n", name);
750 } else if (t->range->min >= 0 && t->range->max > UINT_MAX) {
751 fprintf (headerfile, "uint64_t %s;\n", name);
752 } else if (t->range->min >= INT_MIN && t->range->max <= INT_MAX) {
753 fprintf (headerfile, "int %s;\n", name);
754 } else if (t->range->min >= 0 && t->range->max <= UINT_MAX) {
755 fprintf (headerfile, "unsigned int %s;\n", name);
756 } else
757 errx(1, "%s: unsupported range %lld -> %lld",
758 name, (long long)t->range->min, (long long)t->range->max);
759 break;
760 case TBoolean:
761 space(level);
762 fprintf (headerfile, "int %s;\n", name);
763 break;
764 case TOctetString:
765 space(level);
766 fprintf (headerfile, "heim_octet_string %s;\n", name);
767 break;
768 case TBitString: {
769 Member *m;
770 Type i;
771 struct range range = { 0, UINT_MAX };
772
773 i.type = TInteger;
774 i.range = ⦥
775 i.members = NULL;
776 i.constraint = NULL;
777
778 space(level);
779 if(ASN1_TAILQ_EMPTY(t->members))
780 fprintf (headerfile, "heim_bit_string %s;\n", name);
781 else {
782 int pos = 0;
783 getnewbasename(&newbasename, typedefp, basename, name);
784
785 fprintf (headerfile, "struct %s {\n", newbasename);
786 ASN1_TAILQ_FOREACH(m, t->members, members) {
787 char *n = NULL;
788
789 /* pad unused */
790 while (pos < m->val) {
791 if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL)
792 errx(1, "malloc");
793 define_type (level + 1, n, newbasename, &i, FALSE, FALSE);
794 free(n);
795 pos++;
796 }
797
798 n = NULL;
799 if (asprintf (&n, "%s:1", m->gen_name) < 0 || n == NULL)
800 errx(1, "malloc");
801 define_type (level + 1, n, newbasename, &i, FALSE, FALSE);
802 free (n);
803 n = NULL;
804 pos++;
805 }
806 /* pad to 32 elements */
807 while (pos < 32) {
808 char *n = NULL;
809 if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL)
810 errx(1, "malloc");
811 define_type (level + 1, n, newbasename, &i, FALSE, FALSE);
812 free(n);
813 pos++;
814 }
815
816 space(level);
817 fprintf (headerfile, "} %s;\n\n", name);
818 }
819 break;
820 }
821 case TEnumerated: {
822 Member *m;
823
824 space(level);
825 fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
826 ASN1_TAILQ_FOREACH(m, t->members, members) {
827 space(level + 1);
828 if (m->ellipsis)
829 fprintf (headerfile, "/* ... */\n");
830 else
831 fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val,
832 last_member_p(m));
833 }
834 space(level);
835 fprintf (headerfile, "} %s;\n\n", name);
836 break;
837 }
838 case TSet:
839 case TSequence: {
840 Member *m;
841
842 getnewbasename(&newbasename, typedefp, basename, name);
843
844 space(level);
845 fprintf (headerfile, "struct %s {\n", newbasename);
846 if (t->type == TSequence && preservep) {
847 space(level + 1);
848 fprintf(headerfile, "heim_octet_string _save;\n");
849 }
850 ASN1_TAILQ_FOREACH(m, t->members, members) {
851 if (m->ellipsis) {
852 ;
853 } else if (m->optional) {
854 char *n = NULL;
855
856 if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL)
857 errx(1, "malloc");
858 define_type (level + 1, n, newbasename, m->type, FALSE, FALSE);
859 free (n);
860 } else
861 define_type (level + 1, m->gen_name, newbasename, m->type, FALSE, FALSE);
862 }
863 space(level);
864 fprintf (headerfile, "} %s;\n", name);
865 break;
866 }
867 case TSetOf:
868 case TSequenceOf: {
869 Type i;
870 struct range range = { 0, UINT_MAX };
871
872 getnewbasename(&newbasename, typedefp, basename, name);
873
874 i.type = TInteger;
875 i.range = ⦥
876 i.members = NULL;
877 i.constraint = NULL;
878
879 space(level);
880 fprintf (headerfile, "struct %s {\n", newbasename);
881 define_type (level + 1, "len", newbasename, &i, FALSE, FALSE);
882 define_type (level + 1, "*val", newbasename, t->subtype, FALSE, FALSE);
883 space(level);
884 fprintf (headerfile, "} %s;\n", name);
885 break;
886 }
887 case TGeneralizedTime:
888 space(level);
889 fprintf (headerfile, "time_t %s;\n", name);
890 break;
891 case TGeneralString:
892 space(level);
893 fprintf (headerfile, "heim_general_string %s;\n", name);
894 break;
895 case TTeletexString:
896 space(level);
897 fprintf (headerfile, "heim_general_string %s;\n", name);
898 break;
899 case TTag:
900 define_type (level, name, basename, t->subtype, typedefp, preservep);
901 break;
902 case TChoice: {
903 int first = 1;
904 Member *m;
905
906 getnewbasename(&newbasename, typedefp, basename, name);
907
908 space(level);
909 fprintf (headerfile, "struct %s {\n", newbasename);
910 if (preservep) {
911 space(level + 1);
912 fprintf(headerfile, "heim_octet_string _save;\n");
913 }
914 space(level + 1);
915 fprintf (headerfile, "enum %s_enum {\n", newbasename);
916 m = have_ellipsis(t);
917 if (m) {
918 space(level + 2);
919 fprintf (headerfile, "%s = 0,\n", m->label);
920 first = 0;
921 }
922 ASN1_TAILQ_FOREACH(m, t->members, members) {
923 space(level + 2);
924 if (m->ellipsis)
925 fprintf (headerfile, "/* ... */\n");
926 else
927 fprintf (headerfile, "%s%s%s\n", m->label,
928 first ? " = 1" : "",
929 last_member_p(m));
930 first = 0;
931 }
932 space(level + 1);
933 fprintf (headerfile, "} element;\n");
934 space(level + 1);
935 fprintf (headerfile, "union {\n");
936 ASN1_TAILQ_FOREACH(m, t->members, members) {
937 if (m->ellipsis) {
938 space(level + 2);
939 fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");
940 } else if (m->optional) {
941 char *n = NULL;
942
943 if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL)
944 errx(1, "malloc");
945 define_type (level + 2, n, newbasename, m->type, FALSE, FALSE);
946 free (n);
947 } else
948 define_type (level + 2, m->gen_name, newbasename, m->type, FALSE, FALSE);
949 }
950 space(level + 1);
951 fprintf (headerfile, "} u;\n");
952 space(level);
953 fprintf (headerfile, "} %s;\n", name);
954 break;
955 }
956 case TUTCTime:
957 space(level);
958 fprintf (headerfile, "time_t %s;\n", name);
959 break;
960 case TUTF8String:
961 space(level);
962 fprintf (headerfile, "heim_utf8_string %s;\n", name);
963 break;
964 case TPrintableString:
965 space(level);
966 fprintf (headerfile, "heim_printable_string %s;\n", name);
967 break;
968 case TIA5String:
969 space(level);
970 fprintf (headerfile, "heim_ia5_string %s;\n", name);
971 break;
972 case TBMPString:
973 space(level);
974 fprintf (headerfile, "heim_bmp_string %s;\n", name);
975 break;
976 case TUniversalString:
977 space(level);
978 fprintf (headerfile, "heim_universal_string %s;\n", name);
979 break;
980 case TVisibleString:
981 space(level);
982 fprintf (headerfile, "heim_visible_string %s;\n", name);
983 break;
984 case TOID :
985 space(level);
986 fprintf (headerfile, "heim_oid %s;\n", name);
987 break;
988 case TNull:
989 space(level);
990 fprintf (headerfile, "int %s;\n", name);
991 break;
992 default:
993 abort ();
994 }
995 if (newbasename)
996 free(newbasename);
997 }
998
999 static void
generate_type_header(const Symbol * s)1000 generate_type_header (const Symbol *s)
1001 {
1002 int preservep = preserve_type(s->name) ? TRUE : FALSE;
1003
1004 fprintf (headerfile, "/*\n");
1005 fprintf (headerfile, "%s ::= ", s->name);
1006 define_asn1 (0, s->type);
1007 fprintf (headerfile, "\n*/\n\n");
1008
1009 fprintf (headerfile, "typedef ");
1010 define_type (0, s->gen_name, s->gen_name, s->type, TRUE, preservep);
1011
1012 fprintf (headerfile, "\n");
1013 }
1014
1015 void
generate_type(const Symbol * s)1016 generate_type (const Symbol *s)
1017 {
1018 FILE *h;
1019 const char * exp;
1020
1021 if (!one_code_file)
1022 generate_header_of_codefile(s->gen_name);
1023
1024 generate_type_header (s);
1025
1026 if (template_flag)
1027 generate_template(s);
1028
1029 if (template_flag == 0 || is_template_compat(s) == 0) {
1030 generate_type_encode (s);
1031 generate_type_decode (s);
1032 generate_type_free (s);
1033 generate_type_length (s);
1034 generate_type_copy (s);
1035 }
1036 generate_type_seq (s);
1037 generate_glue (s->type, s->gen_name);
1038
1039 /* generate prototypes */
1040
1041 if (is_export(s->name)) {
1042 h = headerfile;
1043 exp = "ASN1EXP ";
1044 } else {
1045 h = privheaderfile;
1046 exp = "";
1047 }
1048
1049 fprintf (h,
1050 "%sint ASN1CALL "
1051 "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
1052 exp,
1053 s->gen_name, s->gen_name);
1054 fprintf (h,
1055 "%sint ASN1CALL "
1056 "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n",
1057 exp,
1058 s->gen_name, s->gen_name);
1059 fprintf (h,
1060 "%ssize_t ASN1CALL length_%s(const %s *);\n",
1061 exp,
1062 s->gen_name, s->gen_name);
1063 fprintf (h,
1064 "%sint ASN1CALL copy_%s (const %s *, %s *);\n",
1065 exp,
1066 s->gen_name, s->gen_name, s->gen_name);
1067 fprintf (h,
1068 "%svoid ASN1CALL free_%s (%s *);\n",
1069 exp,
1070 s->gen_name, s->gen_name);
1071
1072 fprintf(h, "\n\n");
1073
1074 if (!one_code_file) {
1075 fprintf(codefile, "\n\n");
1076 close_codefile();
1077 }
1078 }
1079