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