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