lib/gssapi/krb5: implement GSS_C_CHANNEL_BOUND_FLAG for gss_init_sec_context()
[heimdal.git] / lib / asn1 / gen.c
blob55ec5f647d752bce18532f373f177e3271656b7c
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 extern const char *enum_prefix;
39 extern int prefix_enum;
41 RCSID("$Id$");
43 FILE *jsonfile, *privheaderfile, *headerfile, *oidsfile, *codefile, *logfile, *templatefile;
44 FILE *symsfile;
46 #define STEM "asn1"
48 static const char *orig_filename;
49 static char *privheader, *header, *template;
50 static const char *headerbase = STEM;
52 /* XXX same as der_length_tag */
53 static size_t
54 length_tag(unsigned int tag)
56 size_t len = 0;
58 if(tag <= 30)
59 return 1;
60 while(tag) {
61 tag /= 128;
62 len++;
64 return len + 1;
68 * list of all IMPORTs
71 struct import {
72 const char *module;
73 struct import *next;
76 static struct import *imports = NULL;
78 void
79 add_import (const char *module)
81 struct import *tmp = emalloc (sizeof(*tmp));
83 tmp->module = module;
84 tmp->next = imports;
85 imports = tmp;
87 fprintf (headerfile, "#include <%s_asn1.h>\n", module);
88 fprintf(jsonfile, "{\"imports\":\"%s\"}\n", module);
92 * List of all exported symbols
94 * XXX A hash table would be nice here.
97 struct sexport {
98 const char *name;
99 int defined;
100 struct sexport *next;
103 static struct sexport *exports = NULL;
105 void
106 add_export (const char *name)
108 struct sexport *tmp = emalloc (sizeof(*tmp));
110 tmp->name = name;
111 tmp->next = exports;
112 exports = tmp;
116 is_export(const char *name)
118 struct sexport *tmp;
120 if (exports == NULL) /* no export list, all exported */
121 return 1;
123 for (tmp = exports; tmp != NULL; tmp = tmp->next) {
124 if (strcmp(tmp->name, name) == 0) {
125 tmp->defined = 1;
126 return 1;
129 return 0;
132 const char *
133 get_filename (void)
135 return orig_filename;
138 void
139 init_generate (const char *filename, const char *base)
141 char *fn = NULL;
143 orig_filename = filename;
144 if (base != NULL) {
145 headerbase = strdup(base);
146 if (headerbase == NULL)
147 errx(1, "strdup");
150 /* JSON file */
151 if (asprintf(&fn, "%s.json", headerbase) < 0 || fn == NULL)
152 errx(1, "malloc");
153 jsonfile = fopen(fn, "w");
154 if (jsonfile == NULL)
155 err(1, "open %s", fn);
156 free(fn);
157 fn = NULL;
159 /* public header file */
160 if (asprintf(&header, "%s.h", headerbase) < 0 || header == NULL)
161 errx(1, "malloc");
162 if (asprintf(&fn, "%s.h", headerbase) < 0 || fn == NULL)
163 errx(1, "malloc");
164 headerfile = fopen (fn, "w");
165 if (headerfile == NULL)
166 err (1, "open %s", fn);
167 free(fn);
168 fn = NULL;
170 /* private header file */
171 if (asprintf(&privheader, "%s-priv.h", headerbase) < 0 || privheader == NULL)
172 errx(1, "malloc");
173 if (asprintf(&fn, "%s-priv.h", headerbase) < 0 || fn == NULL)
174 errx(1, "malloc");
175 privheaderfile = fopen (fn, "w");
176 if (privheaderfile == NULL)
177 err (1, "open %s", fn);
178 free(fn);
179 fn = NULL;
181 /* template file */
182 if (asprintf(&template, "%s-template.c", headerbase) < 0 || template == NULL)
183 errx(1, "malloc");
184 fprintf (headerfile,
185 "/* Generated from %s */\n"
186 "/* Do not edit */\n\n",
187 filename);
188 fprintf (headerfile,
189 "#ifndef __%s_h__\n"
190 "#define __%s_h__\n\n", headerbase, headerbase);
191 fprintf (headerfile,
192 "#include <stddef.h>\n"
193 "#include <stdint.h>\n"
194 "#include <time.h>\n\n");
195 fprintf (headerfile,
196 "#ifndef __asn1_common_definitions__\n"
197 "#define __asn1_common_definitions__\n\n");
198 fprintf (headerfile,
199 "#ifndef __HEIM_BASE_DATA__\n"
200 "#define __HEIM_BASE_DATA__ 1\n"
201 "struct heim_base_data {\n"
202 " size_t length;\n"
203 " void *data;\n"
204 "};\n"
205 "typedef struct heim_base_data heim_octet_string;\n"
206 "#endif\n\n");
207 fprintf (headerfile,
208 "typedef struct heim_integer {\n"
209 " size_t length;\n"
210 " void *data;\n"
211 " int negative;\n"
212 "} heim_integer;\n\n");
213 fprintf (headerfile,
214 "typedef char *heim_general_string;\n\n"
216 fprintf (headerfile,
217 "typedef char *heim_utf8_string;\n\n"
219 fprintf (headerfile,
220 "typedef struct heim_base_data heim_printable_string;\n\n"
222 fprintf (headerfile,
223 "typedef struct heim_base_data heim_ia5_string;\n\n"
225 fprintf (headerfile,
226 "typedef struct heim_bmp_string {\n"
227 " size_t length;\n"
228 " uint16_t *data;\n"
229 "} heim_bmp_string;\n\n");
230 fprintf (headerfile,
231 "typedef struct heim_universal_string {\n"
232 " size_t length;\n"
233 " uint32_t *data;\n"
234 "} heim_universal_string;\n\n");
235 fprintf (headerfile,
236 "typedef char *heim_visible_string;\n\n"
238 fprintf (headerfile,
239 "typedef struct heim_oid {\n"
240 " size_t length;\n"
241 " unsigned *components;\n"
242 "} heim_oid;\n\n");
243 fprintf (headerfile,
244 "typedef struct heim_bit_string {\n"
245 " size_t length;\n"
246 " void *data;\n"
247 "} heim_bit_string;\n\n");
248 fprintf (headerfile,
249 "typedef struct heim_base_data heim_any;\n"
250 "typedef struct heim_base_data heim_any_set;\n"
251 "typedef struct heim_base_data HEIM_ANY;\n"
252 "typedef struct heim_base_data HEIM_ANY_SET;\n\n");
254 fprintf (headerfile,
255 "enum asn1_print_flags {\n"
256 " ASN1_PRINT_INDENT = 1,\n"
257 "};\n\n");
258 fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \\\n"
259 " do { \\\n"
260 " (BL) = length_##T((S)); \\\n"
261 " (B) = calloc(1, (BL)); \\\n"
262 " if((B) == NULL) { \\\n"
263 " *(L) = 0; \\\n"
264 " (R) = ENOMEM; \\\n"
265 " } else { \\\n"
266 " (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n"
267 " (S), (L)); \\\n"
268 " if((R) != 0) { \\\n"
269 " free((B)); \\\n"
270 " (B) = NULL; \\\n"
271 " *(L) = 0; \\\n"
272 " } \\\n"
273 " } \\\n"
274 " } while (0)\n\n",
275 headerfile);
276 fputs("#ifdef _WIN32\n"
277 "#ifndef ASN1_LIB\n"
278 "#define ASN1EXP __declspec(dllimport)\n"
279 "#else\n"
280 "#define ASN1EXP\n"
281 "#endif\n"
282 "#define ASN1CALL __stdcall\n"
283 "#else\n"
284 "#define ASN1EXP\n"
285 "#define ASN1CALL\n"
286 "#endif\n",
287 headerfile);
288 fputs("#ifndef ENOTSUP\n"
289 "/* Very old MSVC CRTs lack ENOTSUP */\n"
290 "#define ENOTSUP EINVAL\n"
291 "#endif\n",
292 headerfile);
293 fprintf (headerfile, "struct units;\n\n");
294 fprintf (headerfile, "#endif\n\n");
295 if (asprintf(&fn, "%s_files", base) < 0 || fn == NULL)
296 errx(1, "malloc");
297 logfile = fopen(fn, "w");
298 if (logfile == NULL)
299 err (1, "open %s", fn);
300 free(fn);
301 fn = NULL;
303 if (asprintf(&fn, "%s_oids.c", base) < 0 || fn == NULL)
304 errx(1, "malloc");
305 oidsfile = fopen(fn, "w");
306 if (oidsfile == NULL)
307 err (1, "open %s", fn);
308 if (asprintf(&fn, "%s_syms.c", base) < 0 || fn == NULL)
309 errx(1, "malloc");
310 symsfile = fopen(fn, "w");
311 if (symsfile == NULL)
312 err (1, "open %s", fn);
313 free(fn);
314 fn = NULL;
316 /* if one code file, write into the one codefile */
317 if (one_code_file)
318 return;
320 templatefile = fopen (template, "w");
321 if (templatefile == NULL)
322 err (1, "open %s", template);
324 fprintf (templatefile,
325 "/* Generated from %s */\n"
326 "/* Do not edit */\n\n"
327 "#include <stdio.h>\n"
328 "#include <stdlib.h>\n"
329 "#include <time.h>\n"
330 "#include <string.h>\n"
331 "#include <errno.h>\n"
332 "#include <limits.h>\n"
333 "#include <asn1_err.h>\n"
334 "#include <%s>\n",
335 filename,
336 type_file_string);
338 fprintf (templatefile,
339 "#include <%s>\n"
340 "#include <%s>\n"
341 "#include <der.h>\n"
342 "#include <asn1-template.h>\n",
343 header, privheader);
348 void
349 close_generate (void)
351 fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
353 if (headerfile && fclose(headerfile) == EOF)
354 err(1, "writes to public header file failed");
355 if (privheaderfile && fclose(privheaderfile) == EOF)
356 err(1, "writes to private header file failed");
357 if (templatefile && fclose(templatefile) == EOF)
358 err(1, "writes to template file failed");
359 if (!jsonfile) abort();
360 if (fclose(jsonfile) == EOF)
361 err(1, "writes to JSON file failed");
362 if (!oidsfile) abort();
363 if (fclose(oidsfile) == EOF)
364 err(1, "writes to OIDs file failed");
365 if (!symsfile) abort();
366 if (fclose(symsfile) == EOF)
367 err(1, "writes to symbols file failed");
368 if (!logfile) abort();
369 fprintf(logfile, "\n");
370 if (fclose(logfile) == EOF)
371 err(1, "writes to log file failed");
374 void
375 gen_assign_defval(const char *var, struct value *val)
377 switch(val->type) {
378 case stringvalue:
379 fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue);
380 break;
381 case integervalue:
382 fprintf(codefile, "%s = %lld;\n",
383 var, (long long)val->u.integervalue);
384 break;
385 case booleanvalue:
386 if(val->u.booleanvalue)
387 fprintf(codefile, "%s = 1;\n", var);
388 else
389 fprintf(codefile, "%s = 0;\n", var);
390 break;
391 default:
392 abort();
396 void
397 gen_compare_defval(const char *var, struct value *val)
399 switch(val->type) {
400 case stringvalue:
401 fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue);
402 break;
403 case integervalue:
404 fprintf(codefile, "if(%s != %lld)\n",
405 var, (long long)val->u.integervalue);
406 break;
407 case booleanvalue:
408 if(val->u.booleanvalue)
409 fprintf(codefile, "if(!%s)\n", var);
410 else
411 fprintf(codefile, "if(%s)\n", var);
412 break;
413 default:
414 abort();
418 void
419 generate_header_of_codefile(const char *name)
421 char *filename = NULL;
423 if (codefile != NULL)
424 abort();
426 if (asprintf (&filename, "%s_%s.c", STEM, name) < 0 || filename == NULL)
427 errx(1, "malloc");
428 codefile = fopen (filename, "w");
429 if (codefile == NULL)
430 err (1, "fopen %s", filename);
431 if (logfile)
432 fprintf(logfile, "%s ", filename);
433 free(filename);
434 filename = NULL;
435 fprintf (codefile,
436 "/* Generated from %s */\n"
437 "/* Do not edit */\n\n"
438 "#if defined(_WIN32) && !defined(ASN1_LIB)\n"
439 "# error \"ASN1_LIB must be defined\"\n"
440 "#endif\n"
441 "#include <stdio.h>\n"
442 "#include <stdlib.h>\n"
443 "#include <time.h>\n"
444 "#include <string.h>\n"
445 "#include <errno.h>\n"
446 "#include <limits.h>\n"
447 "#include <%s>\n",
448 orig_filename,
449 type_file_string);
451 fprintf (codefile,
452 "#include \"%s\"\n"
453 "#include \"%s\"\n",
454 header, privheader);
455 fprintf (codefile,
456 "#include <asn1_err.h>\n"
457 "#include <der.h>\n"
458 "#include <asn1-template.h>\n\n");
460 if (parse_units_flag)
461 fprintf (codefile,
462 "#include <parse_units.h>\n\n");
464 #ifdef _WIN32
465 fprintf(codefile, "#pragma warning(disable: 4101)\n\n");
466 #endif
469 void
470 close_codefile(void)
472 if (codefile == NULL)
473 abort();
475 if (fclose(codefile) == EOF)
476 err(1, "writes to source code file failed");
477 codefile = NULL;
480 /* Object identifiers are parsed backwards; this reverses that */
481 struct objid **
482 objid2list(struct objid *o)
484 struct objid *el, **list;
485 size_t i, len;
487 for (el = o, len = 0; el; el = el->next)
488 len++;
489 if (len == 0)
490 return NULL;
491 list = ecalloc(len + 1, sizeof(*list));
493 for (i = 0; o; o = o->next)
494 list[i++] = o;
495 list[i] = NULL;
497 /* Reverse the list */
498 for (i = 0; i < (len>>1); i++) {
499 el = list[i];
500 list[i] = list[len - (i + 1)];
501 list[len - (i + 1)] = el;
503 return list;
506 void
507 generate_constant (const Symbol *s)
509 switch(s->value->type) {
510 case booleanvalue:
511 break;
512 case integervalue:
514 * Work around the fact that OpenSSL defines macros for PKIX constants
515 * that we want to generate as enums, which causes conflicts for things
516 * like ub-name (ub_name).
518 fprintf(headerfile,
519 "#ifdef %s\n"
520 "#undef %s\n"
521 "#endif\n"
522 "enum { %s = %lld };\n\n",
523 s->gen_name, s->gen_name, s->gen_name,
524 (long long)s->value->u.integervalue);
525 if (is_export(s->name))
526 fprintf(symsfile, "ASN1_SYM_INTVAL(\"%s\", \"%s\", %s, %lld)\n",
527 s->name, s->gen_name, s->gen_name,
528 (long long)s->value->u.integervalue);
529 fprintf(jsonfile,
530 "{\"name\":\"%s\",\"gen_name\":\"%s\",\"type\":\"INTEGER\","
531 "\"constant\":true,\"exported\":%s,\"value\":%lld}\n",
532 s->name, s->gen_name, is_export(s->name) ? "true" : "false",
533 (long long)s->value->u.integervalue);
534 break;
535 case nullvalue:
536 break;
537 case stringvalue:
538 break;
539 case objectidentifiervalue: {
540 struct objid *o, **list;
541 size_t i, len;
542 char *gen_upper;
544 if (!one_code_file)
545 generate_header_of_codefile(s->gen_name);
547 list = objid2list(s->value->u.objectidentifiervalue);
548 for (len = 0; list && list[len]; len++)
550 if (len == 0) {
551 errx(1, "Empty OBJECT IDENTIFIER named %s\n", s->name);
552 break;
555 fprintf(jsonfile,
556 "{\"name\":\"%s\",\"gen_name\":\"%s\","
557 "\"type\":\"OBJECT IDENTIFIER\","
558 "\"constant\":true,\"exported\":%s,\"value\":[\n",
559 s->name, s->gen_name, is_export(s->name) ? "true" : "false");
560 fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name);
561 for (i = 0; i < len; i++) {
562 o = list[i];
563 fprintf(headerfile, "%s(%d) ",
564 o->label ? o->label : "label-less", o->value);
565 if (o->label == NULL)
566 fprintf(jsonfile, "%s{\"label\":null,\"value\":%d}",
567 i ? "," : "", o->value);
568 else
569 fprintf(jsonfile, "%s{\"label\":\"%s\",\"value\":%d}",
570 i ? "," : "", o->label, o->value);
572 fprintf(jsonfile, "]}\n");
574 fprintf (codefile, "static unsigned oid_%s_variable_num[%lu] = {",
575 s->gen_name, (unsigned long)len);
576 for (i = 0; list[i]; i++) {
577 fprintf(codefile, "%s %d", i ? "," : "", list[i]->value);
579 fprintf(codefile, "};\n");
581 fprintf (codefile, "const heim_oid asn1_oid_%s = "
582 "{ %lu, oid_%s_variable_num };\n\n",
583 s->gen_name, (unsigned long)len, s->gen_name);
585 fprintf(oidsfile, "DEFINE_OID_WITH_NAME(%s)\n", s->gen_name);
586 if (is_export(s->name))
587 fprintf(symsfile, "ASN1_SYM_OID(\"%s\", \"%s\", %s)\n",
588 s->name, s->gen_name, s->gen_name);
590 free(list);
592 /* header file */
594 gen_upper = strdup(s->gen_name);
595 len = strlen(gen_upper);
596 for (i = 0; i < len; i++)
597 gen_upper[i] = toupper((unsigned char)s->gen_name[i]);
599 fprintf (headerfile, "} */\n");
600 fprintf (headerfile,
601 "extern ASN1EXP const heim_oid asn1_oid_%s;\n"
602 "#define ASN1_OID_%s (&asn1_oid_%s)\n\n",
603 s->gen_name,
604 gen_upper,
605 s->gen_name);
607 free(gen_upper);
609 if (!one_code_file)
610 close_codefile();
612 break;
614 default:
615 abort();
620 is_tagged_type(const Type *t)
623 * Start by chasing aliasings like this:
625 * Type0 ::= ...
626 * Type1 ::= Type0
627 * ..
628 * TypeN ::= TypeN-1
630 * to <Type0>, then check if <Type0> is tagged.
632 while (t->type == TType) {
633 if (t->subtype)
634 t = t->subtype;
635 else if (t->symbol && t->symbol->type)
636 t = t->symbol->type;
637 else
638 abort();
641 if (t->type == TTag && t->tag.tagenv == TE_EXPLICIT)
642 return 1;
643 if (t->type == TTag) {
644 if (t->subtype)
645 return is_tagged_type(t->subtype);
646 if (t->symbol && t->symbol->type)
647 return is_tagged_type(t->symbol->type);
648 /* This is the tag */
649 return 1;
651 return 0;
655 is_primitive_type(const Type *t)
658 * Start by chasing aliasings like this:
660 * Type0 ::= ...
661 * Type1 ::= Type0
662 * ..
663 * TypeN ::= TypeN-1
665 * to <Type0>, then check if <Type0> is primitive.
667 while (t->type == TType &&
668 t->symbol &&
669 t->symbol->type) {
670 if (t->symbol->type->type == TType)
671 t = t->symbol->type; /* Alias */
672 else if (t->symbol->type->type == TTag &&
673 t->symbol->type->tag.tagenv == TE_IMPLICIT)
675 * IMPLICIT-tagged alias, something like:
677 * Type0 ::= [0] IMPLICIT ...
679 * Just recurse.
681 return is_primitive_type(t->symbol->type);
682 else
683 break;
686 /* EXPLICIT non-UNIVERSAL tags are always constructed */
687 if (t->type == TTag && t->tag.tagclass != ASN1_C_UNIV &&
688 t->tag.tagenv == TE_EXPLICIT)
689 return 0;
690 if (t->symbol && t->symbol->type) {
691 /* EXPLICIT non-UNIVERSAL tags are constructed */
692 if (t->symbol->type->type == TTag &&
693 t->symbol->type->tag.tagclass != ASN1_C_UNIV &&
694 t->symbol->type->tag.tagenv == TE_EXPLICIT)
695 return 0;
696 /* EXPLICIT UNIVERSAL tags are constructed if they are SEQUENCE/SET */
697 if (t->symbol->type->type == TTag &&
698 t->symbol->type->tag.tagclass == ASN1_C_UNIV) {
699 switch (t->symbol->type->tag.tagvalue) {
700 case UT_Sequence: return 0;
701 case UT_Set: return 0;
702 default: return 1;
706 switch(t->type) {
707 case TInteger:
708 case TBoolean:
709 case TOctetString:
710 case TBitString:
711 case TEnumerated:
712 case TGeneralizedTime:
713 case TGeneralString:
714 case TTeletexString:
715 case TOID:
716 case TUTCTime:
717 case TUTF8String:
718 case TPrintableString:
719 case TIA5String:
720 case TBMPString:
721 case TUniversalString:
722 case TVisibleString:
723 case TNull:
724 return 1;
725 case TTag:
726 return is_primitive_type(t->subtype);
727 default:
728 return 0;
732 static void
733 space(int level)
735 while(level-- > 0)
736 fprintf(headerfile, " ");
739 static const char *
740 last_member_p(struct member *m)
742 struct member *n = HEIM_TAILQ_NEXT(m, members);
743 if (n == NULL)
744 return "";
745 if (n->ellipsis && HEIM_TAILQ_NEXT(n, members) == NULL)
746 return "";
747 return ",";
750 static struct member *
751 have_ellipsis(Type *t)
753 struct member *m;
754 HEIM_TAILQ_FOREACH(m, t->members, members) {
755 if (m->ellipsis)
756 return m;
758 return NULL;
761 static void
762 define_asn1 (int level, Type *t)
764 switch (t->type) {
765 case TType:
766 if (!t->symbol && t->typeref.iosclass) {
767 fprintf(headerfile, "%s.&%s",
768 t->typeref.iosclass->symbol->name,
769 t->typeref.field->name);
770 } else if (t->symbol)
771 fprintf(headerfile, "%s", t->symbol->name);
772 else
773 abort();
774 break;
775 case TInteger:
776 if(t->members == NULL) {
777 fprintf (headerfile, "INTEGER");
778 if (t->range)
779 fprintf (headerfile, " (%lld..%lld)",
780 (long long)t->range->min,
781 (long long)t->range->max);
782 } else {
783 Member *m;
784 fprintf (headerfile, "INTEGER {\n");
785 HEIM_TAILQ_FOREACH(m, t->members, members) {
786 space (level + 1);
787 fprintf(headerfile, "%s(%lld)%s\n", m->gen_name,
788 (long long)m->val, last_member_p(m));
790 space(level);
791 fprintf (headerfile, "}");
793 break;
794 case TBoolean:
795 fprintf (headerfile, "BOOLEAN");
796 break;
797 case TOctetString:
798 fprintf (headerfile, "OCTET STRING");
799 break;
800 case TEnumerated:
801 case TBitString: {
802 Member *m;
804 space(level);
805 if(t->type == TBitString)
806 fprintf (headerfile, "BIT STRING {\n");
807 else
808 fprintf (headerfile, "ENUMERATED {\n");
809 HEIM_TAILQ_FOREACH(m, t->members, members) {
810 space(level + 1);
811 fprintf(headerfile, "%s(%lld)%s\n", m->name,
812 (long long)m->val, last_member_p(m));
814 space(level);
815 fprintf (headerfile, "}");
816 break;
818 case TChoice:
819 case TSet:
820 case TSequence: {
821 Member *m;
822 size_t max_width = 0;
824 if(t->type == TChoice)
825 fprintf(headerfile, "CHOICE {\n");
826 else if(t->type == TSet)
827 fprintf(headerfile, "SET {\n");
828 else
829 fprintf(headerfile, "SEQUENCE {\n");
830 HEIM_TAILQ_FOREACH(m, t->members, members) {
831 if(strlen(m->name) > max_width)
832 max_width = strlen(m->name);
834 max_width += 3;
835 if(max_width < 16) max_width = 16;
836 HEIM_TAILQ_FOREACH(m, t->members, members) {
837 size_t width = max_width;
838 space(level + 1);
839 if (m->ellipsis) {
840 fprintf (headerfile, "...");
841 } else {
842 width -= fprintf(headerfile, "%s", m->name);
843 fprintf(headerfile, "%*s", (int)width, "");
844 define_asn1(level + 1, m->type);
845 if(m->optional)
846 fprintf(headerfile, " OPTIONAL");
848 if(last_member_p(m))
849 fprintf (headerfile, ",");
850 fprintf (headerfile, "\n");
852 space(level);
853 fprintf (headerfile, "}");
854 break;
856 case TSequenceOf:
857 fprintf (headerfile, "SEQUENCE OF ");
858 define_asn1 (0, t->subtype);
859 break;
860 case TSetOf:
861 fprintf (headerfile, "SET OF ");
862 define_asn1 (0, t->subtype);
863 break;
864 case TGeneralizedTime:
865 fprintf (headerfile, "GeneralizedTime");
866 break;
867 case TGeneralString:
868 fprintf (headerfile, "GeneralString");
869 break;
870 case TTeletexString:
871 fprintf (headerfile, "TeletexString");
872 break;
873 case TTag: {
874 const char *classnames[] = { "UNIVERSAL ", "APPLICATION ",
875 "" /* CONTEXT */, "PRIVATE " };
876 if(t->tag.tagclass != ASN1_C_UNIV)
877 fprintf (headerfile, "[%s%d] ",
878 classnames[t->tag.tagclass],
879 t->tag.tagvalue);
880 if(t->tag.tagenv == TE_IMPLICIT)
881 fprintf (headerfile, "IMPLICIT ");
882 define_asn1 (level, t->subtype);
883 break;
885 case TUTCTime:
886 fprintf (headerfile, "UTCTime");
887 break;
888 case TUTF8String:
889 space(level);
890 fprintf (headerfile, "UTF8String");
891 break;
892 case TPrintableString:
893 space(level);
894 fprintf (headerfile, "PrintableString");
895 break;
896 case TIA5String:
897 space(level);
898 fprintf (headerfile, "IA5String");
899 break;
900 case TBMPString:
901 space(level);
902 fprintf (headerfile, "BMPString");
903 break;
904 case TUniversalString:
905 space(level);
906 fprintf (headerfile, "UniversalString");
907 break;
908 case TVisibleString:
909 space(level);
910 fprintf (headerfile, "VisibleString");
911 break;
912 case TOID :
913 space(level);
914 fprintf(headerfile, "OBJECT IDENTIFIER");
915 break;
916 case TNull:
917 space(level);
918 fprintf (headerfile, "NULL");
919 break;
920 default:
921 abort ();
925 static void
926 getnewbasename(char **newbasename, int typedefp, const char *basename, const char *name)
928 if (typedefp)
929 *newbasename = strdup(name);
930 else {
931 if (name[0] == '*')
932 name++;
933 if (asprintf(newbasename, "%s_%s", basename, name) < 0)
934 errx(1, "malloc");
936 if (*newbasename == NULL)
937 err(1, "malloc");
940 typedef enum define_type_options {
941 DEF_TYPE_NONE = 0,
942 DEF_TYPE_PRESERVE = 1,
943 DEF_TYPE_TYPEDEFP = 2,
944 DEF_TYPE_EMIT_NAME = 4
945 } define_type_options;
946 static void define_type(int, const char *, const char *, Type *, Type *, define_type_options);
949 * Get the SET/SEQUENCE member pair and CLASS field pair defining an open type.
951 * There are three cases:
953 * - open types embedded in OCTET STRING, with the open type object class
954 * relation declared via a constraint
956 * - open types not embedded in OCTET STRING, which are really more like ANY
957 * DEFINED BY types, so, HEIM_ANY
959 * - open types in a nested structure member where the type ID field is in a
960 * member of the ancestor structure (this happens in PKIX's `AttributeSet',
961 * where the open type is essentially a SET OF HEIM_ANY).
963 * In a type like PKIX's SingleAttribute the type ID member would be the one
964 * named "type" and the open type member would be the one named "value", and
965 * the corresponding fields of the ATTRIBUTE class would be named "id" and
966 * "Type".
968 * NOTE: We assume a single open type member pair in any SET/SEQUENCE. In
969 * principle there could be more pairs and we could iterate them, or
970 * better yet, we could be given the name of an open type member and then
971 * just find its related type ID member and fields, then our caller would
972 * iterate the SET/SEQUENCE type's members looking for open type members
973 * and would call this function for each one found.
975 void
976 get_open_type_defn_fields(const Type *t,
977 Member **typeidmember,
978 Member **opentypemember,
979 Field **typeidfield,
980 Field **opentypefield,
981 int *is_array_of)
983 Member *m;
984 Field *junk1, *junk2;
985 char *idmembername = NULL;
987 if (!typeidfield) typeidfield = &junk1;
988 if (!opentypefield) opentypefield = &junk2;
990 *typeidfield = *opentypefield = NULL;
991 *typeidmember = *opentypemember = NULL;
992 *is_array_of = 0;
994 /* Look for the open type member */
995 HEIM_TAILQ_FOREACH(m, t->members, members) {
996 Type *subtype = m->type;
997 Type *sOfType = NULL;
999 while (subtype->type == TTag ||
1000 subtype->type == TSetOf ||
1001 subtype->type == TSequenceOf) {
1002 if (subtype->type == TTag && subtype->subtype) {
1003 if (subtype->subtype->type == TOctetString ||
1004 subtype->subtype->type == TBitString)
1005 break;
1006 subtype = subtype->subtype;
1007 } else if (subtype->type == TSetOf || subtype->type == TSequenceOf) {
1008 sOfType = subtype;
1009 if (sOfType->symbol)
1010 break;
1011 if (subtype->subtype)
1012 subtype = subtype->subtype;
1013 } else
1014 break;
1017 * If we traversed through a non-inlined SET OF or SEQUENCE OF type,
1018 * then this cannot be an open type field.
1020 if (sOfType && sOfType->symbol)
1021 continue;
1023 * The type of the field we're interested in has to have an information
1024 * object constraint.
1026 if (!subtype->constraint)
1027 continue;
1028 if (subtype->type != TType && subtype->type != TTag)
1029 continue;
1031 * Check if it's an ANY-like member or like an OCTET STRING CONTAINING
1032 * member. Those are the only two possibilities.
1034 if ((subtype->type == TTag || subtype->type == TType) &&
1035 subtype->subtype &&
1036 subtype->constraint->ctype == CT_CONTENTS &&
1037 subtype->constraint->u.content.type &&
1038 subtype->constraint->u.content.type->type == TType &&
1039 !subtype->constraint->u.content.type->subtype &&
1040 subtype->constraint->u.content.type->constraint &&
1041 subtype->constraint->u.content.type->constraint->ctype == CT_TABLE_CONSTRAINT) {
1042 /* Type like OCTET STRING or BIT STRING CONTAINING open type */
1043 if (*opentypemember)
1044 errx(1, "Multiple open type members %s and %s for the same "
1045 "field %s?", (*opentypemember)->name, m->name,
1046 (*opentypefield)->name);
1047 *opentypemember = m;
1048 *opentypefield = subtype->constraint->u.content.type->typeref.field;
1049 *is_array_of = sOfType != NULL;
1050 idmembername = subtype->constraint->u.content.type->constraint->u.content.crel.membername;
1051 break;
1052 } else if (subtype->symbol && strcmp(subtype->symbol->name, "HEIM_ANY") == 0) {
1053 /* Open type, but NOT embedded in OCTET STRING or BIT STRING */
1054 if (*opentypemember)
1055 errx(1, "Multiple open type members %s and %s for the same "
1056 "field %s?", (*opentypemember)->name, m->name,
1057 (*opentypefield)->name);
1058 *opentypemember = m;
1059 *opentypefield = subtype->typeref.field;
1060 *is_array_of = sOfType != NULL;
1061 idmembername = subtype->constraint->u.content.crel.membername;
1062 break;
1066 if (!idmembername)
1067 errx(1, "Missing open type id member in %s",
1068 t->symbol ? t->symbol->name : "<unknown type>");
1069 /* Look for the type ID member identified in the previous loop */
1070 HEIM_TAILQ_FOREACH(m, t->members, members) {
1071 if (!m->type->subtype || strcmp(m->name, idmembername) != 0)
1072 continue;
1073 if (m->type->constraint &&
1074 m->type->constraint->ctype == CT_TABLE_CONSTRAINT)
1075 *typeidfield = m->type->typeref.field;
1076 else if (m->type->subtype->constraint &&
1077 m->type->subtype->constraint->ctype == CT_TABLE_CONSTRAINT)
1078 *typeidfield = m->type->subtype->typeref.field;
1079 else
1080 continue;
1081 /* This is the type ID field (because there _is_ a subtype) */
1082 *typeidmember = m;
1083 break;
1088 * Generate CHOICE-like struct fields for open types declared via
1089 * X.681/682/683 syntax.
1091 * We could support multiple open type members in a SET/SEQUENCE, but for now
1092 * we support only one.
1094 static void
1095 define_open_type(int level, const char *newbasename, const char *name, const char *basename, Type *pt, Type *t)
1097 Member *opentypemember, *typeidmember;
1098 Field *opentypefield, *typeidfield;
1099 ObjectField *of;
1100 IOSObjectSet *os = pt->actual_parameter;
1101 IOSObject **objects;
1102 size_t nobjs, i;
1103 int is_array_of_open_type;
1105 get_open_type_defn_fields(pt, &typeidmember, &opentypemember,
1106 &typeidfield, &opentypefield,
1107 &is_array_of_open_type);
1108 if (!opentypemember || !typeidmember ||
1109 !opentypefield || !typeidfield)
1110 errx(1, "Open type specification in %s is incomplete", name);
1112 sort_object_set(os, typeidfield, &objects, &nobjs);
1114 fprintf(headerfile, "struct {\n");
1115 fprintf(jsonfile, "{\"opentype\":true,\"arraytype\":%s,",
1116 is_array_of_open_type ? "true" : "false");
1117 fprintf(jsonfile, "\"classname\":\"%s\",", os->iosclass->symbol->name);
1118 fprintf(jsonfile, "\"objectsetname\":\"%s\",", os->symbol->name);
1119 fprintf(jsonfile, "\"typeidmember\":\"%s\",", typeidmember->name);
1120 fprintf(jsonfile, "\"opentypemember\":\"%s\",", opentypemember->name);
1121 fprintf(jsonfile, "\"typeidfield\":\"%s\",", typeidfield->name);
1122 fprintf(jsonfile, "\"opentypefield\":\"%s\",", opentypefield->name);
1124 /* Iterate objects in the object set, gen enum labels */
1125 fprintf(headerfile, "enum { choice_%s_iosnumunknown = 0,\n",
1126 newbasename);
1127 fprintf(jsonfile, "\"opentypeids\":[");
1128 for (i = 0; i < nobjs; i++) {
1129 HEIM_TAILQ_FOREACH(of, objects[i]->objfields, objfields) {
1130 if (strcmp(of->name, typeidfield->name) != 0)
1131 continue;
1132 if (!of->value || !of->value->s)
1133 errx(1, "Unknown value in value field %s of object %s",
1134 of->name, objects[i]->symbol->name);
1135 fprintf(headerfile, "choice_%s_iosnum_%s,\n",
1136 newbasename, of->value->s->gen_name);
1137 fprintf(jsonfile, "\"%s\"", of->value->s->gen_name);
1138 fprintf(jsonfile, "%s", (i + 1) < nobjs ? "," : "");
1141 fprintf(jsonfile, "],\n");
1142 fprintf(headerfile, "} element;\n");
1144 if (is_array_of_open_type)
1145 fprintf(headerfile, "unsigned int len;\n");
1147 /* Iterate objects in the object set, gen union arms */
1148 fprintf(headerfile, "union {\nvoid *_any;\n");
1149 fprintf(jsonfile, "\"members\":[");
1150 for (i = 0; i < nobjs; i++) {
1151 HEIM_TAILQ_FOREACH(of, objects[i]->objfields, objfields) {
1152 char *n = NULL;
1154 /* XXX Print the type IDs into the jsonfile too pls */
1156 if (strcmp(of->name, opentypefield->name) != 0)
1157 continue;
1158 if (!of->type || (!of->type->symbol && of->type->type != TTag) ||
1159 of->type->tag.tagclass != ASN1_C_UNIV) {
1160 warnx("Ignoring unknown or unset type field %s of object %s",
1161 of->name, objects[i]->symbol->name);
1162 continue;
1165 if (asprintf(&n, "*%s", objects[i]->symbol->gen_name) < 0 || n == NULL)
1166 err(1, "malloc");
1167 define_type(level + 2, n, newbasename, NULL, of->type, DEF_TYPE_NONE);
1168 fprintf(jsonfile, "%s", (i + 1) < nobjs ? "," : "");
1169 free(n);
1172 fprintf(jsonfile, "]}\n");
1173 if (is_array_of_open_type) {
1174 fprintf(headerfile, "} *val;\n} _ioschoice_%s;\n", opentypemember->gen_name);
1175 } else {
1176 fprintf(headerfile, "} u;\n");
1177 fprintf(headerfile, "} _ioschoice_%s;\n", opentypemember->gen_name);
1179 free(objects);
1182 static const char * const tagclassnames[] = {
1183 "UNIVERSAL", "APPLICATION", "CONTEXT", "PRIVATE"
1186 static void
1187 define_type(int level, const char *name, const char *basename,
1188 Type *pt, Type *t, define_type_options opts)
1190 const char *label_prefix = NULL;
1191 const char *label_prefix_sep = NULL;
1192 char *newbasename = NULL;
1194 fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
1195 "\"is_type\":true,\"exported\":%s,\"typedef\":%s,",
1196 basename, name,
1197 t->symbol && is_export(t->symbol->name) ? "true" : "false",
1198 (opts & DEF_TYPE_TYPEDEFP) ? "true" : "false");
1200 switch (t->type) {
1201 case TType:
1202 space(level);
1203 if (!t->symbol && t->actual_parameter) {
1204 define_open_type(level, newbasename, name, basename, t, t);
1205 } else if (!t->symbol && pt->actual_parameter) {
1206 define_open_type(level, newbasename, name, basename, pt, t);
1207 } else if (t->symbol) {
1208 fprintf(headerfile, "%s %s;\n", t->symbol->gen_name, name);
1209 fprintf(jsonfile, "\"ttype\":\"%s\","
1210 "\"alias\":true\n", t->symbol->gen_name);
1211 } else
1212 abort();
1213 break;
1214 case TInteger:
1215 if (t->symbol && t->symbol->emitted_definition)
1216 break;
1218 space(level);
1219 if(t->members) {
1220 Member *m;
1222 label_prefix = prefix_enum ? name : (enum_prefix ? enum_prefix : "");
1223 label_prefix_sep = prefix_enum ? "_" : "";
1224 fprintf (headerfile, "enum %s {\n", (opts & DEF_TYPE_TYPEDEFP) ? name : "");
1225 fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"enum\","
1226 "\"members\":[\n");
1227 HEIM_TAILQ_FOREACH(m, t->members, members) {
1228 space (level + 1);
1229 fprintf(headerfile, "%s%s%s = %lld%s\n",
1230 label_prefix, label_prefix_sep,
1231 m->gen_name, (long long)m->val, last_member_p(m));
1232 fprintf(jsonfile, "{\"%s%s%s\":%lld}%s\n",
1233 label_prefix, label_prefix_sep,
1234 m->gen_name, (long long)m->val, last_member_p(m));
1236 fprintf(headerfile, "} %s;\n", name);
1237 fprintf(jsonfile, "]");
1238 } else if (t->range == NULL) {
1239 fprintf(headerfile, "heim_integer %s;\n", name);
1240 fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"heim_integer\"");
1241 } else if (t->range->min < 0 &&
1242 (t->range->min < INT_MIN || t->range->max > INT_MAX)) {
1243 fprintf(headerfile, "int64_t %s;\n", name);
1244 fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"int64_t\"");
1245 } else if (t->range->min < 0) {
1246 fprintf (headerfile, "int %s;\n", name);
1247 fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"int\"");
1248 } else if (t->range->max > UINT_MAX) {
1249 fprintf (headerfile, "uint64_t %s;\n", name);
1250 fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"uint64_t\"");
1251 } else {
1252 fprintf (headerfile, "unsigned int %s;\n", name);
1253 fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"unsigned int\"");
1255 break;
1256 case TBoolean:
1257 space(level);
1258 fprintf (headerfile, "int %s;\n", name);
1259 fprintf(jsonfile, "\"ttype\":\"BOOLEAN\",\"ctype\":\"unsigned int\"");
1260 break;
1261 case TOctetString:
1262 space(level);
1263 fprintf (headerfile, "heim_octet_string %s;\n", name);
1264 fprintf(jsonfile, "\"ttype\":\"OCTET STRING\",\"ctype\":\"heim_octet_string\"");
1265 break;
1266 case TBitString: {
1267 Member *m;
1268 Type i;
1269 struct range range = { 0, UINT_MAX };
1270 size_t max_memno = 0;
1271 size_t bitset_size;
1273 if (t->symbol && t->symbol->emitted_definition)
1274 break;
1275 memset(&i, 0, sizeof(i));
1278 * range.max implies the size of the base unsigned integer used for the
1279 * bitfield members. If it's less than or equal to UINT_MAX, then that
1280 * will be unsigned int, otherwise it will be uint64_t.
1282 * We could just use uint64_t, yes, but for now, and in case that any
1283 * projects were exposing the BIT STRING types' C representations in
1284 * ABIs prior to this compiler supporting BIT STRING with larger
1285 * members, we stick to this.
1287 HEIM_TAILQ_FOREACH(m, t->members, members) {
1288 if (m->val > max_memno)
1289 max_memno = m->val;
1291 if (max_memno > 63)
1292 range.max = INT64_MAX;
1293 else
1294 range.max = 1ULL << max_memno;
1296 i.type = TInteger;
1297 i.range = &range;
1298 i.members = NULL;
1299 i.constraint = NULL;
1301 space(level);
1302 fprintf(jsonfile, "\"ttype\":\"BIT STRING\",");
1303 if(HEIM_TAILQ_EMPTY(t->members)) {
1304 fprintf (headerfile, "heim_bit_string %s;\n", name);
1305 fprintf(jsonfile, "\"ctype\":\"heim_bit_string\"");
1306 } else {
1307 int64_t pos = 0;
1308 getnewbasename(&newbasename, (opts & DEF_TYPE_TYPEDEFP) || level == 0, basename, name);
1310 fprintf (headerfile, "struct %s {\n", newbasename);
1311 fprintf(jsonfile, "\"ctype\":\"struct %s\",\"members\":[\n", newbasename);
1312 HEIM_TAILQ_FOREACH(m, t->members, members) {
1313 char *n = NULL;
1316 * pad unused bits beween declared members (hopefully this
1317 * forces the compiler to give us an obvious layout)
1319 while (pos < m->val) {
1320 if (asprintf (&n, "_unused%lld:1", (long long)pos) < 0 ||
1321 n == NULL)
1322 err(1, "malloc");
1323 define_type(level + 1, n, newbasename, NULL, &i, DEF_TYPE_EMIT_NAME);
1324 fprintf(jsonfile, ",");
1325 free(n);
1326 pos++;
1329 n = NULL;
1330 if (asprintf (&n, "%s:1", m->gen_name) < 0 || n == NULL)
1331 errx(1, "malloc");
1332 define_type(level + 1, n, newbasename, NULL, &i, DEF_TYPE_EMIT_NAME);
1333 fprintf(jsonfile, "%s", last_member_p(m));
1334 free (n);
1335 n = NULL;
1336 pos++;
1338 /* pad unused tail (ditto) */
1339 bitset_size = max_memno;
1340 if (max_memno > 31)
1341 bitset_size += 64 - (max_memno % 64);
1342 else
1343 bitset_size = 32;
1344 if (pos < bitset_size)
1345 fprintf(jsonfile, ",");
1346 while (pos < bitset_size) {
1347 char *n = NULL;
1348 if (asprintf (&n, "_unused%lld:1", (long long)pos) < 0 ||
1349 n == NULL)
1350 errx(1, "malloc");
1351 define_type(level + 1, n, newbasename, NULL, &i, DEF_TYPE_EMIT_NAME);
1352 fprintf(jsonfile, "%s", (pos + 1) < bitset_size ? "," : "");
1353 free(n);
1354 pos++;
1357 space(level);
1358 fprintf(headerfile, "}%s%s;\n\n",
1359 (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
1360 (opts & DEF_TYPE_EMIT_NAME) ? name : "");
1361 fprintf(jsonfile, "]");
1363 break;
1365 case TEnumerated: {
1366 Member *m;
1368 if (t->symbol && t->symbol->emitted_definition)
1369 break;
1371 label_prefix = prefix_enum ? name : (enum_prefix ? enum_prefix : "");
1372 label_prefix_sep = prefix_enum ? "_" : "";
1373 space(level);
1374 fprintf (headerfile, "enum %s {\n", (opts & DEF_TYPE_TYPEDEFP) ? name : "");
1375 fprintf(jsonfile, "\"ctype\":\"enum %s\",\"extensible\":%s,\"members\":[\n",
1376 (opts & DEF_TYPE_TYPEDEFP) ? name : "", have_ellipsis(t) ? "true" : "false");
1377 HEIM_TAILQ_FOREACH(m, t->members, members) {
1378 space(level + 1);
1379 if (m->ellipsis) {
1380 fprintf (headerfile, "/* ... */\n");
1381 } else {
1382 fprintf(headerfile, "%s%s%s = %lld%s\n",
1383 label_prefix, label_prefix_sep,
1384 m->gen_name, (long long)m->val, last_member_p(m));
1385 fprintf(jsonfile, "{\"%s%s%s\":%lld%s}\n",
1386 label_prefix, label_prefix_sep,
1387 m->gen_name, (long long)m->val, last_member_p(m));
1390 space(level);
1391 fprintf(headerfile, "}%s%s;\n\n",
1392 (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
1393 (opts & DEF_TYPE_EMIT_NAME) ? name : "");
1394 fprintf(jsonfile, "]");
1395 break;
1397 case TSet:
1398 case TSequence: {
1399 Member *m;
1400 struct decoration deco;
1401 ssize_t more_deco = -1;
1402 int decorated = 0;
1404 getnewbasename(&newbasename, (opts & DEF_TYPE_TYPEDEFP) || level == 0, basename, name);
1406 space(level);
1408 fprintf (headerfile, "struct %s {\n", newbasename);
1409 fprintf(jsonfile, "\"ttype\":\"%s\",\"extensible\":%s,"
1410 "\"ctype\":\"struct %s\"",
1411 t->type == TSet ? "SET" : "SEQUENCE",
1412 have_ellipsis(t) ? "true" : "false", newbasename);
1413 if (t->type == TSequence && (opts & DEF_TYPE_PRESERVE)) {
1414 space(level + 1);
1415 fprintf(headerfile, "heim_octet_string _save;\n");
1416 fprintf(jsonfile, ",\"preserve\":true");
1418 fprintf(jsonfile, ",\"members\":[\n");
1419 HEIM_TAILQ_FOREACH(m, t->members, members) {
1420 if (m->ellipsis) {
1422 } else if (m->optional || m->defval) {
1423 char *n = NULL, *defval = NULL;
1424 const char *namep, *defvalp;
1426 if (m->defval) {
1427 switch (m->defval->type) {
1428 case stringvalue:
1429 if (asprintf(&defval, "\"%s\"", m->defval->u.stringvalue) < 0 || defval == NULL)
1430 errx(1, "malloc");
1431 defvalp = defval;
1432 break;
1433 case integervalue:
1434 if (asprintf(&defval, "%lld", (long long)m->defval->u.integervalue) < 0 || defval == NULL)
1435 errx(1, "malloc");
1436 defvalp = defval;
1437 break;
1438 case booleanvalue:
1439 defvalp = m->defval->u.booleanvalue ? "true" : "false";
1440 break;
1441 default:
1442 abort();
1444 } else
1445 defvalp = "null";
1447 if (m->optional) {
1448 if (asprintf(&n, "*%s", m->gen_name) < 0 || n == NULL)
1449 errx(1, "malloc");
1450 namep = n;
1451 } else
1452 namep = m->gen_name;
1454 fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
1455 "\"optional\":%s,\"defval\":%s,\"type\":",
1456 m->name, m->gen_name, m->optional ? "true" : "false", defvalp);
1457 define_type(level + 1, namep, newbasename, t, m->type, DEF_TYPE_EMIT_NAME);
1458 fprintf(jsonfile, "}%s", last_member_p(m));
1459 free (n);
1460 free (defval);
1461 } else {
1462 fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
1463 "\"optional\":false,\"type\":", m->name, m->gen_name);
1464 define_type(level + 1, m->gen_name, newbasename, t, m->type, DEF_TYPE_EMIT_NAME);
1465 fprintf(jsonfile, "}%s", last_member_p(m));
1468 fprintf(jsonfile, "]");
1469 if (t->actual_parameter && t->actual_parameter->objects) {
1470 fprintf(jsonfile, ",\"opentype\":");
1471 define_open_type(level, newbasename, name, basename, t, t);
1473 while (decorate_type(newbasename, &deco, &more_deco)) {
1474 decorated++;
1475 space(level + 1);
1476 fprintf(headerfile, "%s %s%s;\n", deco.field_type,
1477 deco.opt ? "*" : "", deco.field_name);
1478 if (deco.first)
1479 fprintf(jsonfile, ",\"decorate\":[");
1480 fprintf(jsonfile, "%s{"
1481 "\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s,"
1482 "\"external\":%s,\"pointer\":%s,\"void_star\":%s,"
1483 "\"struct_star\":%s,"
1484 "\"copy_function\":\"%s\","
1485 "\"free_function\":\"%s\",\"header_name\":%s%s%s"
1486 "}",
1487 deco.first ? "" : ",",
1488 deco.field_type, deco.field_name,
1489 deco.opt ? "true" : "false", deco.ext ? "true" : "false",
1490 deco.ptr ? "true" : "false", deco.void_star ? "true" : "false",
1491 deco.struct_star ? "true" : "false",
1492 deco.copy_function_name ? deco.copy_function_name : "",
1493 deco.free_function_name ? deco.free_function_name : "",
1494 deco.header_name && deco.header_name[0] == '"' ? "" : "\"",
1495 deco.header_name ? deco.header_name : "",
1496 deco.header_name && deco.header_name[0] == '"' ? "" : "\""
1499 if (decorated)
1500 fprintf(jsonfile, "]");
1501 space(level);
1502 fprintf(headerfile, "}%s%s;\n",
1503 (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
1504 (opts & DEF_TYPE_EMIT_NAME) ? name : "");
1505 free(deco.field_type);
1506 break;
1508 case TSetOf:
1509 case TSequenceOf: {
1510 Type i;
1511 struct range range = { 0, UINT_MAX };
1513 getnewbasename(&newbasename, (opts & DEF_TYPE_TYPEDEFP) || level == 0, basename, name);
1515 memset(&i, 0, sizeof(i));
1516 i.type = TInteger;
1517 i.range = &range;
1519 space(level);
1520 fprintf (headerfile, "struct %s {\n", newbasename);
1521 fprintf(jsonfile, "\"ttype\":\"%s\",\"ctype\":\"struct %s\",\"members\":[",
1522 t->type == TSetOf ? "SET OF" : "SEQUENCE OF", newbasename);
1523 define_type(level + 1, "len", newbasename, t, &i, DEF_TYPE_NONE);
1524 fprintf(jsonfile, ",");
1525 define_type(level + 1, "*val", newbasename, t, t->subtype, DEF_TYPE_NONE | DEF_TYPE_EMIT_NAME);
1526 space(level);
1527 fprintf(headerfile, "}%s%s;\n",
1528 (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
1529 (opts & DEF_TYPE_EMIT_NAME) ? name : "");
1530 fprintf(jsonfile, "]");
1531 break;
1533 case TGeneralizedTime:
1534 space(level);
1535 fprintf (headerfile, "time_t %s;\n", name);
1536 fprintf(jsonfile, "\"ttype\":\"GeneralizedTime\",\"ctype\":\"time_t\"");
1537 break;
1538 case TGeneralString:
1539 space(level);
1540 fprintf (headerfile, "heim_general_string %s;\n", name);
1541 fprintf(jsonfile, "\"ttype\":\"GeneralString\",\"ctype\":\"heim_general_string\"");
1542 break;
1543 case TTeletexString:
1544 space(level);
1545 fprintf (headerfile, "heim_general_string %s;\n", name);
1546 fprintf(jsonfile, "\"ttype\":\"TeletexString\",\"ctype\":\"heim_general_string\"");
1547 break;
1548 case TTag:
1549 if (t->implicit_choice) {
1550 fprintf(jsonfile, "\"desired_tagenv\":\"IMPLICIT\",");
1552 fprintf(jsonfile, "\"tagclass\":\"%s\",\"tagvalue\":%d,\"tagenv\":\"%s\",\n",
1553 tagclassnames[t->tag.tagclass], t->tag.tagvalue,
1554 t->tag.tagenv == TE_EXPLICIT ? "EXPLICIT" : "IMPLICIT");
1555 fprintf(jsonfile, "\"ttype\":\n");
1556 define_type(level, name, basename, t, t->subtype, opts);
1557 break;
1558 case TChoice: {
1559 struct decoration deco;
1560 ssize_t more_deco = -1;
1561 int decorated = 0;
1562 int first = 1;
1563 Member *m;
1565 getnewbasename(&newbasename, (opts & DEF_TYPE_TYPEDEFP) || level == 0, basename, name);
1567 space(level);
1568 fprintf (headerfile, "struct %s {\n", newbasename);
1569 fprintf(jsonfile, "\"ttype\":\"CHOICE\",\"ctype\":\"struct %s\"",
1570 newbasename);
1571 if ((opts & DEF_TYPE_PRESERVE)) {
1572 space(level + 1);
1573 fprintf(headerfile, "heim_octet_string _save;\n");
1574 fprintf(jsonfile, ",\"preserve\":true");
1576 space(level + 1);
1577 fprintf (headerfile, "enum %s_enum {\n", newbasename);
1578 m = have_ellipsis(t);
1579 if (m) {
1580 space(level + 2);
1581 fprintf (headerfile, "%s = 0,\n", m->label);
1582 first = 0;
1584 fprintf(jsonfile, ",\"extensible\":%s", m ? "true" : "false");
1585 HEIM_TAILQ_FOREACH(m, t->members, members) {
1586 space(level + 2);
1587 if (m->ellipsis)
1588 fprintf (headerfile, "/* ... */\n");
1589 else
1590 fprintf (headerfile, "%s%s%s\n", m->label,
1591 first ? " = 1" : "",
1592 last_member_p(m));
1593 first = 0;
1595 space(level + 1);
1596 fprintf (headerfile, "} element;\n");
1597 space(level + 1);
1598 fprintf (headerfile, "union {\n");
1599 fprintf(jsonfile, ",\"members\":[\n");
1600 HEIM_TAILQ_FOREACH(m, t->members, members) {
1601 if (m->ellipsis) {
1602 space(level + 2);
1603 fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");
1604 } else if (m->optional) {
1605 char *n = NULL;
1607 if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL)
1608 errx(1, "malloc");
1609 fprintf(jsonfile, "{\"optional\":");
1610 define_type(level + 2, n, newbasename, t, m->type, DEF_TYPE_EMIT_NAME);
1611 fprintf(jsonfile, "}%s", last_member_p(m));
1612 free (n);
1613 } else {
1614 define_type(level + 2, m->gen_name, newbasename, t, m->type, DEF_TYPE_EMIT_NAME);
1615 fprintf(jsonfile, "%s", last_member_p(m));
1618 space(level + 1);
1619 fprintf (headerfile, "} u;\n");
1620 fprintf(jsonfile, "]");
1622 while (decorate_type(newbasename, &deco, &more_deco)) {
1623 decorated++;
1624 space(level + 1);
1625 fprintf(headerfile, "%s %s%s;\n", deco.field_type,
1626 deco.opt ? "*" : "", deco.field_name);
1627 if (deco.first)
1628 fprintf(jsonfile, ",\"decorate\":[");
1629 fprintf(jsonfile, "%s{"
1630 "\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s,"
1631 "\"external\":%s,\"pointer\":%s,\"void_star\":%s,"
1632 "\"struct_star\":%s,"
1633 "\"copy_function\":\"%s\","
1634 "\"free_function\":\"%s\",\"header_name\":%s%s%s"
1635 "}",
1636 deco.first ? "" : ",",
1637 deco.field_type, deco.field_name,
1638 deco.opt ? "true" : "false", deco.ext ? "true" : "false",
1639 deco.ptr ? "true" : "false", deco.void_star ? "true" : "false",
1640 deco.struct_star ? "true" : "false",
1641 deco.copy_function_name ? deco.copy_function_name : "",
1642 deco.free_function_name ? deco.free_function_name : "",
1643 deco.header_name && deco.header_name[0] == '"' ? "" : "\"",
1644 deco.header_name ? deco.header_name : "",
1645 deco.header_name && deco.header_name[0] == '"' ? "" : "\""
1648 if (decorated)
1649 fprintf(jsonfile, "]");
1651 space(level);
1652 fprintf(headerfile, "}%s%s;\n",
1653 (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
1654 (opts & DEF_TYPE_EMIT_NAME) ? name : "");
1655 break;
1657 case TUTCTime:
1658 space(level);
1659 fprintf (headerfile, "time_t %s;\n", name);
1660 fprintf(jsonfile, "\"ttype\":\"UTCTime\",\"ctype\":\"time_t\"");
1661 break;
1662 case TUTF8String:
1663 space(level);
1664 fprintf (headerfile, "heim_utf8_string %s;\n", name);
1665 fprintf(jsonfile, "\"ttype\":\"UTF8String\",\"ctype\":\"heim_utf8_string\"");
1666 break;
1667 case TPrintableString:
1668 space(level);
1669 fprintf (headerfile, "heim_printable_string %s;\n", name);
1670 fprintf(jsonfile, "\"ttype\":\"PrintableString\",\"ctype\":\"heim_printable_string\"");
1671 break;
1672 case TIA5String:
1673 space(level);
1674 fprintf (headerfile, "heim_ia5_string %s;\n", name);
1675 fprintf(jsonfile, "\"ttype\":\"IA5String\",\"ctype\":\"heim_ia5_string\"");
1676 break;
1677 case TBMPString:
1678 space(level);
1679 fprintf (headerfile, "heim_bmp_string %s;\n", name);
1680 fprintf(jsonfile, "\"ttype\":\"BMPString\",\"ctype\":\"heim_bmp_string\"");
1681 break;
1682 case TUniversalString:
1683 space(level);
1684 fprintf (headerfile, "heim_universal_string %s;\n", name);
1685 fprintf(jsonfile, "\"ttype\":\"UniversalString\",\"ctype\":\"heim_universal_string\"");
1686 break;
1687 case TVisibleString:
1688 space(level);
1689 fprintf (headerfile, "heim_visible_string %s;\n", name);
1690 fprintf(jsonfile, "\"ttype\":\"VisibleString\",\"ctype\":\"heim_visible_string\"");
1691 break;
1692 case TOID :
1693 space(level);
1694 fprintf (headerfile, "heim_oid %s;\n", name);
1695 fprintf(jsonfile, "\"ttype\":\"OBJECT IDENTIFIER\",\"ctype\":\"heim_oid\"");
1696 break;
1697 case TNull:
1698 space(level);
1699 fprintf (headerfile, "int %s;\n", name);
1700 fprintf(jsonfile, "\"ttype\":\"NULL\",\"ctype\":\"int\"");
1701 break;
1702 default:
1703 abort ();
1705 fprintf(jsonfile, "}\n");
1706 free(newbasename);
1709 static void
1710 declare_type(const Symbol *s, Type *t, int typedefp)
1712 char *newbasename = NULL;
1714 if (typedefp)
1715 fprintf(headerfile, "typedef ");
1717 switch (t->type) {
1718 case TType:
1719 define_type(0, s->gen_name, s->gen_name, NULL, s->type,
1720 DEF_TYPE_PRESERVE | DEF_TYPE_TYPEDEFP |
1721 (s->emitted_declaration ? 0 : DEF_TYPE_EMIT_NAME));
1722 if (template_flag && !s->emitted_declaration)
1723 generate_template_type_forward(s->gen_name);
1724 emitted_declaration(s);
1725 return;
1726 case TInteger:
1727 case TBoolean:
1728 case TOctetString:
1729 case TBitString:
1730 case TEnumerated:
1731 case TGeneralizedTime:
1732 case TGeneralString:
1733 case TTeletexString:
1734 case TUTCTime:
1735 case TUTF8String:
1736 case TPrintableString:
1737 case TIA5String:
1738 case TBMPString:
1739 case TUniversalString:
1740 case TVisibleString:
1741 case TOID :
1742 case TNull:
1743 define_type(0, s->gen_name, s->gen_name, NULL, s->type,
1744 DEF_TYPE_PRESERVE | DEF_TYPE_TYPEDEFP |
1745 (s->emitted_declaration ? 0 : DEF_TYPE_EMIT_NAME));
1746 if (template_flag && !s->emitted_declaration)
1747 generate_template_type_forward(s->gen_name);
1748 emitted_declaration(s);
1749 emitted_definition(s);
1750 return;
1751 case TTag:
1752 if (!s->emitted_declaration)
1753 declare_type(s, t->subtype, FALSE);
1754 emitted_declaration(s);
1755 return;
1756 default:
1757 break;
1760 switch (t->type) {
1761 case TSet:
1762 case TSequence: {
1763 struct decoration deco;
1764 ssize_t more_deco = -1;
1766 getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
1767 fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
1768 while (decorate_type(newbasename, &deco, &more_deco)) {
1769 if (deco.header_name)
1770 fprintf(headerfile, "#include %s\n", deco.header_name);
1771 free(deco.field_type);
1773 break;
1775 case TSetOf:
1776 case TSequenceOf:
1777 getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
1778 fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
1779 break;
1780 case TChoice: {
1781 struct decoration deco;
1782 ssize_t more_deco = -1;
1784 getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
1785 fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
1786 while (decorate_type(newbasename, &deco, &more_deco)) {
1787 if (deco.header_name)
1788 fprintf(headerfile, "#include %s\n", deco.header_name);
1789 free(deco.field_type);
1791 break;
1793 default:
1794 abort ();
1796 free(newbasename);
1797 emitted_declaration(s);
1800 static void generate_subtypes_header_helper(const Member *m);
1801 static void generate_type_header(const Symbol *);
1803 static void
1804 generate_subtypes_header_helper(const Member *m)
1806 Member *sm;
1807 Symbol *s;
1809 if (m->ellipsis)
1810 return;
1811 if (m->type->symbol && (s = getsym(m->type->symbol->name)) &&
1812 !s->emitted_definition) {
1813 /* A field of some named type; recurse */
1814 if (!m->optional && !m->defval)
1815 generate_type_header(s);
1816 return;
1818 if (!m->type->subtype && !m->type->members)
1819 return;
1820 if (m->type->type == TTag &&
1821 m->type->subtype && m->type->subtype->symbol &&
1822 (s = getsym(m->type->subtype->symbol->name))) {
1823 if (!m->optional && !m->defval)
1824 generate_type_header(s);
1825 return;
1827 if (m->type->subtype) {
1828 switch (m->type->subtype->type) {
1829 case TSet:
1830 case TSequence:
1831 case TChoice:
1832 break;
1833 default:
1834 return;
1836 /* A field of some anonymous (inlined) structured type */
1837 HEIM_TAILQ_FOREACH(sm, m->type->subtype->members, members) {
1838 generate_subtypes_header_helper(sm);
1841 if (m->type->members) {
1842 HEIM_TAILQ_FOREACH(sm, m->type->members, members) {
1843 generate_subtypes_header_helper(sm);
1848 static void
1849 generate_subtypes_header(const Symbol *s)
1851 Type *t = s->type;
1852 Member *m;
1855 * Recurse down structured types to make sure top-level types get
1856 * defined before they are referenced.
1858 * We'll take care to skip OPTIONAL member fields of constructed types so
1859 * that we can have circular types like:
1861 * Foo ::= SEQUENCE {
1862 * bar Bar OPTIONAL
1865 * Bar ::= SEQUENCE {
1866 * foo Foo OPTIONAL
1869 * not unlike XDR, which uses `*' to mean "optional", except in XDR it's
1870 * called a "pointer". With some care we should be able to eventually
1871 * support the silly XDR linked list example:
1873 * ListOfFoo ::= SEQUENCE {
1874 * someField SomeType,
1875 * next ListOfFoo OPTIONAL
1878 * Not that anyone needs it -- just use a SEQUENCE OF and be done.
1881 while (t->type == TTag && t->subtype) {
1882 switch (t->subtype->type) {
1883 case TTag:
1884 case TSet:
1885 case TSequence:
1886 case TChoice:
1887 t = t->subtype;
1888 continue;
1889 default:
1890 break;
1892 break;
1895 switch (t->type) {
1896 default: return;
1897 case TType: {
1898 Symbol *s2;
1899 if (t->symbol && (s2 = getsym(t->symbol->name)) != s)
1900 generate_type_header(s2);
1901 return;
1903 case TSet:
1904 case TSequence:
1905 case TChoice:
1906 break;
1909 HEIM_TAILQ_FOREACH(m, t->members, members) {
1910 generate_subtypes_header_helper(m);
1914 static void
1915 generate_type_header (const Symbol *s)
1917 Type *t = s->type;
1919 if (!s->type)
1920 return;
1923 * Recurse down the types of member fields of `s' to make sure that
1924 * referenced types have had their definitions emitted already if the
1925 * member fields are not OPTIONAL/DEFAULTed.
1927 generate_subtypes_header(s);
1928 if (!s->emitted_asn1) {
1929 fprintf(headerfile, "/*\n");
1930 fprintf(headerfile, "%s ::= ", s->name);
1931 define_asn1 (0, s->type);
1932 fprintf(headerfile, "\n*/\n\n");
1933 emitted_asn1(s);
1937 * Emit enums for the outermost tag of this type. These are needed for
1938 * dealing with IMPLICIT tags so we know what to rewrite the tag to when
1939 * decoding.
1941 * See gen_encode.c and gen_decode.c for a complete explanation. Short
1942 * version: we need to change the prototypes of the length/encode/decode
1943 * functions to take an optional IMPLICIT tag to use instead of the type's
1944 * outermost tag, but for now we hack it, and to do that we need to know
1945 * the type's outermost tag outside the context of the bodies of the codec
1946 * functions we generate for it. Using an enum means no extra space is
1947 * needed in stripped objects.
1949 if (!s->emitted_tag_enums) {
1950 while (t->type == TType && s->type->symbol && s->type->symbol->type) {
1951 if (t->subtype)
1952 t = t->subtype;
1953 else
1954 t = s->type->symbol->type;
1957 if (t->type == TType && t->symbol &&
1958 strcmp(t->symbol->name, "HEIM_ANY") != 0) {
1960 * This type is ultimately an alias of an imported type, so we don't
1961 * know its outermost tag here.
1963 fprintf(headerfile,
1964 "enum { asn1_tag_length_%s = asn1_tag_length_%s,\n"
1965 " asn1_tag_class_%s = asn1_tag_class_%s,\n"
1966 " asn1_tag_tag_%s = asn1_tag_tag_%s };\n",
1967 s->gen_name, s->type->symbol->gen_name,
1968 s->gen_name, s->type->symbol->gen_name,
1969 s->gen_name, s->type->symbol->gen_name);
1970 emitted_tag_enums(s);
1971 } else if (t->type != TType) {
1972 /* This type's outermost tag is known here */
1973 fprintf(headerfile,
1974 "enum { asn1_tag_length_%s = %lu,\n"
1975 " asn1_tag_class_%s = %d,\n"
1976 " asn1_tag_tag_%s = %d };\n",
1977 s->gen_name, (unsigned long)length_tag(s->type->tag.tagvalue),
1978 s->gen_name, s->type->tag.tagclass,
1979 s->gen_name, s->type->tag.tagvalue);
1980 emitted_tag_enums(s);
1984 if (s->emitted_definition)
1985 return;
1987 if (is_export(s->name))
1988 fprintf(symsfile, "ASN1_SYM_TYPE(\"%s\", \"%s\", %s)\n",
1989 s->name, s->gen_name, s->gen_name);
1991 if (!s->emitted_declaration) {
1992 fprintf(headerfile, "typedef ");
1993 define_type(0, s->gen_name, s->gen_name, NULL, s->type,
1994 DEF_TYPE_TYPEDEFP | DEF_TYPE_EMIT_NAME |
1995 (preserve_type(s->name) ? DEF_TYPE_PRESERVE : 0));
1996 } else if (s->type->type == TType) {
1997 /* This is a type alias and we've already declared it */
1998 } else if (s->type->type == TTag &&
1999 s->type->subtype != NULL &&
2000 s->type->subtype->symbol != NULL) {
2001 /* This is a type alias and we've already declared it */
2002 } else {
2003 define_type(0, s->gen_name, s->gen_name, NULL, s->type,
2004 DEF_TYPE_TYPEDEFP |
2005 (preserve_type(s->name) ? DEF_TYPE_PRESERVE : 0));
2007 fprintf(headerfile, "\n");
2009 emitted_definition(s);
2012 void
2013 generate_type_header_forwards(const Symbol *s)
2015 declare_type(s, s->type, TRUE);
2016 fprintf(headerfile, "\n");
2017 if (template_flag)
2018 generate_template_type_forward(s->gen_name);
2021 void
2022 generate_type (const Symbol *s)
2024 FILE *h;
2025 const char * exp;
2027 if (!one_code_file)
2028 generate_header_of_codefile(s->gen_name);
2030 generate_type_header(s);
2032 if (template_flag)
2033 generate_template(s);
2035 if (template_flag == 0 || is_template_compat(s) == 0) {
2036 generate_type_encode (s);
2037 generate_type_decode (s);
2038 generate_type_free (s);
2039 generate_type_length (s);
2040 generate_type_copy (s);
2041 generate_type_print_stub(s);
2043 generate_type_seq (s);
2044 generate_glue (s->type, s->gen_name);
2046 /* generate prototypes */
2048 if (is_export(s->name)) {
2049 h = headerfile;
2050 exp = "ASN1EXP ";
2051 } else {
2052 h = privheaderfile;
2053 exp = "";
2056 fprintf (h,
2057 "%sint ASN1CALL "
2058 "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
2059 exp,
2060 s->gen_name, s->gen_name);
2061 fprintf (h,
2062 "%sint ASN1CALL "
2063 "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n",
2064 exp,
2065 s->gen_name, s->gen_name);
2066 fprintf (h,
2067 "%ssize_t ASN1CALL length_%s(const %s *);\n",
2068 exp,
2069 s->gen_name, s->gen_name);
2070 fprintf (h,
2071 "%sint ASN1CALL copy_%s (const %s *, %s *);\n",
2072 exp,
2073 s->gen_name, s->gen_name, s->gen_name);
2074 fprintf (h,
2075 "%svoid ASN1CALL free_%s (%s *);\n",
2076 exp,
2077 s->gen_name, s->gen_name);
2079 fprintf(h,
2080 "%schar * ASN1CALL print_%s (const %s *, int);\n",
2081 exp,
2082 s->gen_name, s->gen_name);
2084 fprintf(h, "\n\n");
2086 if (!one_code_file) {
2087 fprintf(codefile, "\n\n");
2088 close_codefile();