Line data Source code
1 : /*
2 : * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
7 : *
8 : * Redistribution and use in source and binary forms, with or without
9 : * modification, are permitted provided that the following conditions
10 : * are met:
11 : *
12 : * 1. Redistributions of source code must retain the above copyright
13 : * notice, this list of conditions and the following disclaimer.
14 : *
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.
18 : *
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.
22 : *
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.
34 : */
35 :
36 : #include "gen_locl.h"
37 :
38 : extern const char *enum_prefix;
39 : extern int prefix_enum;
40 :
41 : RCSID("$Id$");
42 :
43 : FILE *jsonfile, *privheaderfile, *headerfile, *oidsfile, *codefile, *logfile, *templatefile;
44 : FILE *symsfile;
45 :
46 : #define STEM "asn1"
47 :
48 : static const char *orig_filename;
49 : static char *privheader, *header, *template;
50 : static const char *headerbase = STEM;
51 :
52 : /* XXX same as der_length_tag */
53 : static size_t
54 7600 : length_tag(unsigned int tag)
55 : {
56 7600 : size_t len = 0;
57 :
58 7600 : if(tag <= 30)
59 7128 : return 1;
60 190 : while(tag) {
61 114 : tag /= 128;
62 114 : len++;
63 : }
64 76 : return len + 1;
65 : }
66 :
67 : /*
68 : * list of all IMPORTs
69 : */
70 :
71 : struct import {
72 : const char *module;
73 : struct import *next;
74 : };
75 :
76 : static struct import *imports = NULL;
77 :
78 : void
79 437 : add_import (const char *module)
80 : {
81 437 : struct import *tmp = emalloc (sizeof(*tmp));
82 :
83 437 : tmp->module = module;
84 437 : tmp->next = imports;
85 437 : imports = tmp;
86 :
87 437 : fprintf (headerfile, "#include <%s_asn1.h>\n", module);
88 437 : fprintf(jsonfile, "{\"imports\":\"%s\"}\n", module);
89 437 : }
90 :
91 : /*
92 : * List of all exported symbols
93 : *
94 : * XXX A hash table would be nice here.
95 : */
96 :
97 : struct sexport {
98 : const char *name;
99 : int defined;
100 : struct sexport *next;
101 : };
102 :
103 : static struct sexport *exports = NULL;
104 :
105 : void
106 1691 : add_export (const char *name)
107 : {
108 1691 : struct sexport *tmp = emalloc (sizeof(*tmp));
109 :
110 1691 : tmp->name = name;
111 1691 : tmp->next = exports;
112 1691 : exports = tmp;
113 1691 : }
114 :
115 : int
116 38855 : is_export(const char *name)
117 : {
118 2045 : struct sexport *tmp;
119 :
120 38855 : if (exports == NULL) /* no export list, all exported */
121 28242 : return 1;
122 :
123 504146 : for (tmp = exports; tmp != NULL; tmp = tmp->next) {
124 501942 : if (strcmp(tmp->name, name) == 0) {
125 6840 : tmp->defined = 1;
126 6840 : return 1;
127 : }
128 : }
129 2088 : return 0;
130 : }
131 :
132 : const char *
133 0 : get_filename (void)
134 : {
135 0 : return orig_filename;
136 : }
137 :
138 : void
139 304 : init_generate (const char *filename, const char *base)
140 : {
141 304 : char *fn = NULL;
142 :
143 304 : orig_filename = filename;
144 304 : if (base != NULL) {
145 304 : headerbase = strdup(base);
146 304 : if (headerbase == NULL)
147 0 : errx(1, "strdup");
148 : }
149 :
150 : /* JSON file */
151 304 : if (asprintf(&fn, "%s.json", headerbase) < 0 || fn == NULL)
152 0 : errx(1, "malloc");
153 304 : jsonfile = fopen(fn, "w");
154 304 : if (jsonfile == NULL)
155 0 : err(1, "open %s", fn);
156 304 : free(fn);
157 304 : fn = NULL;
158 :
159 : /* public header file */
160 304 : if (asprintf(&header, "%s.h", headerbase) < 0 || header == NULL)
161 0 : errx(1, "malloc");
162 304 : if (asprintf(&fn, "%s.h", headerbase) < 0 || fn == NULL)
163 0 : errx(1, "malloc");
164 304 : headerfile = fopen (fn, "w");
165 304 : if (headerfile == NULL)
166 0 : err (1, "open %s", fn);
167 304 : free(fn);
168 304 : fn = NULL;
169 :
170 : /* private header file */
171 304 : if (asprintf(&privheader, "%s-priv.h", headerbase) < 0 || privheader == NULL)
172 0 : errx(1, "malloc");
173 304 : if (asprintf(&fn, "%s-priv.h", headerbase) < 0 || fn == NULL)
174 0 : errx(1, "malloc");
175 304 : privheaderfile = fopen (fn, "w");
176 304 : if (privheaderfile == NULL)
177 0 : err (1, "open %s", fn);
178 304 : free(fn);
179 304 : fn = NULL;
180 :
181 : /* template file */
182 304 : if (asprintf(&template, "%s-template.c", headerbase) < 0 || template == NULL)
183 0 : errx(1, "malloc");
184 304 : fprintf (headerfile,
185 : "/* Generated from %s */\n"
186 : "/* Do not edit */\n\n",
187 : filename);
188 304 : fprintf (headerfile,
189 : "#ifndef __%s_h__\n"
190 : "#define __%s_h__\n\n", headerbase, headerbase);
191 304 : fprintf (headerfile,
192 : "#include <stddef.h>\n"
193 : "#include <stdint.h>\n"
194 : "#include <time.h>\n\n");
195 304 : fprintf (headerfile,
196 : "#ifndef __asn1_common_definitions__\n"
197 : "#define __asn1_common_definitions__\n\n");
198 304 : 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 304 : 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 304 : fprintf (headerfile,
214 : "typedef char *heim_general_string;\n\n"
215 : );
216 304 : fprintf (headerfile,
217 : "typedef char *heim_utf8_string;\n\n"
218 : );
219 304 : fprintf (headerfile,
220 : "typedef struct heim_base_data heim_printable_string;\n\n"
221 : );
222 304 : fprintf (headerfile,
223 : "typedef struct heim_base_data heim_ia5_string;\n\n"
224 : );
225 304 : 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 304 : 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 304 : fprintf (headerfile,
236 : "typedef char *heim_visible_string;\n\n"
237 : );
238 304 : fprintf (headerfile,
239 : "typedef struct heim_oid {\n"
240 : " size_t length;\n"
241 : " unsigned *components;\n"
242 : "} heim_oid;\n\n");
243 304 : 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 304 : 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");
253 :
254 304 : fprintf (headerfile,
255 : "enum asn1_print_flags {\n"
256 : " ASN1_PRINT_INDENT = 1,\n"
257 : "};\n\n");
258 304 : 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 304 : 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 304 : fputs("#ifndef ENOTSUP\n"
289 : "/* Very old MSVC CRTs lack ENOTSUP */\n"
290 : "#define ENOTSUP EINVAL\n"
291 : "#endif\n",
292 : headerfile);
293 304 : fprintf (headerfile, "struct units;\n\n");
294 304 : fprintf (headerfile, "#endif\n\n");
295 304 : if (asprintf(&fn, "%s_files", base) < 0 || fn == NULL)
296 0 : errx(1, "malloc");
297 304 : logfile = fopen(fn, "w");
298 304 : if (logfile == NULL)
299 0 : err (1, "open %s", fn);
300 304 : free(fn);
301 304 : fn = NULL;
302 :
303 304 : if (asprintf(&fn, "%s_oids.c", base) < 0 || fn == NULL)
304 0 : errx(1, "malloc");
305 304 : oidsfile = fopen(fn, "w");
306 304 : if (oidsfile == NULL)
307 0 : err (1, "open %s", fn);
308 304 : if (asprintf(&fn, "%s_syms.c", base) < 0 || fn == NULL)
309 0 : errx(1, "malloc");
310 304 : symsfile = fopen(fn, "w");
311 304 : if (symsfile == NULL)
312 0 : err (1, "open %s", fn);
313 304 : free(fn);
314 304 : fn = NULL;
315 :
316 : /* if one code file, write into the one codefile */
317 304 : if (one_code_file)
318 304 : return;
319 :
320 0 : templatefile = fopen (template, "w");
321 0 : if (templatefile == NULL)
322 0 : err (1, "open %s", template);
323 :
324 0 : 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);
337 :
338 0 : fprintf (templatefile,
339 : "#include <%s>\n"
340 : "#include <%s>\n"
341 : "#include <der.h>\n"
342 : "#include <asn1-template.h>\n",
343 : header, privheader);
344 :
345 :
346 : }
347 :
348 : void
349 304 : close_generate (void)
350 : {
351 304 : fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
352 :
353 304 : if (headerfile && fclose(headerfile) == EOF)
354 0 : err(1, "writes to public header file failed");
355 304 : if (privheaderfile && fclose(privheaderfile) == EOF)
356 0 : err(1, "writes to private header file failed");
357 304 : if (templatefile && fclose(templatefile) == EOF)
358 0 : err(1, "writes to template file failed");
359 304 : if (!jsonfile) abort();
360 304 : if (fclose(jsonfile) == EOF)
361 0 : err(1, "writes to JSON file failed");
362 304 : if (!oidsfile) abort();
363 304 : if (fclose(oidsfile) == EOF)
364 0 : err(1, "writes to OIDs file failed");
365 304 : if (!symsfile) abort();
366 304 : if (fclose(symsfile) == EOF)
367 0 : err(1, "writes to symbols file failed");
368 304 : if (!logfile) abort();
369 304 : fprintf(logfile, "\n");
370 304 : if (fclose(logfile) == EOF)
371 0 : err(1, "writes to log file failed");
372 304 : }
373 :
374 : void
375 0 : gen_assign_defval(const char *var, struct value *val)
376 : {
377 0 : switch(val->type) {
378 0 : case stringvalue:
379 0 : fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue);
380 0 : break;
381 0 : case integervalue:
382 0 : fprintf(codefile, "%s = %lld;\n",
383 0 : var, (long long)val->u.integervalue);
384 0 : break;
385 0 : case booleanvalue:
386 0 : if(val->u.booleanvalue)
387 0 : fprintf(codefile, "%s = 1;\n", var);
388 : else
389 0 : fprintf(codefile, "%s = 0;\n", var);
390 0 : break;
391 0 : default:
392 0 : abort();
393 : }
394 0 : }
395 :
396 : void
397 0 : gen_compare_defval(const char *var, struct value *val)
398 : {
399 0 : switch(val->type) {
400 0 : case stringvalue:
401 0 : fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue);
402 0 : break;
403 0 : case integervalue:
404 0 : fprintf(codefile, "if(%s != %lld)\n",
405 0 : var, (long long)val->u.integervalue);
406 0 : break;
407 0 : case booleanvalue:
408 0 : if(val->u.booleanvalue)
409 0 : fprintf(codefile, "if(!%s)\n", var);
410 : else
411 0 : fprintf(codefile, "if(%s)\n", var);
412 0 : break;
413 0 : default:
414 0 : abort();
415 : }
416 0 : }
417 :
418 : void
419 304 : generate_header_of_codefile(const char *name)
420 : {
421 304 : char *filename = NULL;
422 :
423 304 : if (codefile != NULL)
424 0 : abort();
425 :
426 304 : if (asprintf (&filename, "%s_%s.c", STEM, name) < 0 || filename == NULL)
427 0 : errx(1, "malloc");
428 304 : codefile = fopen (filename, "w");
429 304 : if (codefile == NULL)
430 0 : err (1, "fopen %s", filename);
431 304 : if (logfile)
432 304 : fprintf(logfile, "%s ", filename);
433 304 : free(filename);
434 304 : filename = NULL;
435 304 : 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);
450 :
451 304 : fprintf (codefile,
452 : "#include \"%s\"\n"
453 : "#include \"%s\"\n",
454 : header, privheader);
455 304 : fprintf (codefile,
456 : "#include <asn1_err.h>\n"
457 : "#include <der.h>\n"
458 : "#include <asn1-template.h>\n\n");
459 :
460 304 : if (parse_units_flag)
461 304 : fprintf (codefile,
462 : "#include <parse_units.h>\n\n");
463 :
464 : #ifdef _WIN32
465 : fprintf(codefile, "#pragma warning(disable: 4101)\n\n");
466 : #endif
467 304 : }
468 :
469 : void
470 304 : close_codefile(void)
471 : {
472 304 : if (codefile == NULL)
473 0 : abort();
474 :
475 304 : if (fclose(codefile) == EOF)
476 0 : err(1, "writes to source code file failed");
477 304 : codefile = NULL;
478 304 : }
479 :
480 : /* Object identifiers are parsed backwards; this reverses that */
481 : struct objid **
482 4921 : objid2list(struct objid *o)
483 : {
484 259 : struct objid *el, **list;
485 259 : size_t i, len;
486 :
487 37297 : for (el = o, len = 0; el; el = el->next)
488 32376 : len++;
489 4921 : if (len == 0)
490 270 : return NULL;
491 4636 : list = ecalloc(len + 1, sizeof(*list));
492 :
493 37256 : for (i = 0; o; o = o->next)
494 32376 : list[i++] = o;
495 4636 : list[i] = NULL;
496 :
497 : /* Reverse the list */
498 19475 : for (i = 0; i < (len>>1); i++) {
499 14839 : el = list[i];
500 14839 : list[i] = list[len - (i + 1)];
501 14839 : list[len - (i + 1)] = el;
502 : }
503 4392 : return list;
504 : }
505 :
506 : void
507 5529 : generate_constant (const Symbol *s)
508 : {
509 5529 : switch(s->value->type) {
510 0 : case booleanvalue:
511 0 : break;
512 912 : case integervalue:
513 : /*
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).
517 : */
518 960 : fprintf(headerfile,
519 : "#ifdef %s\n"
520 : "#undef %s\n"
521 : "#endif\n"
522 : "enum { %s = %lld };\n\n",
523 912 : s->gen_name, s->gen_name, s->gen_name,
524 912 : (long long)s->value->u.integervalue);
525 912 : if (is_export(s->name))
526 922 : fprintf(symsfile, "ASN1_SYM_INTVAL(\"%s\", \"%s\", %s, %lld)\n",
527 874 : s->name, s->gen_name, s->gen_name,
528 874 : (long long)s->value->u.integervalue);
529 912 : fprintf(jsonfile,
530 : "{\"name\":\"%s\",\"gen_name\":\"%s\",\"type\":\"INTEGER\","
531 : "\"constant\":true,\"exported\":%s,\"value\":%lld}\n",
532 912 : s->name, s->gen_name, is_export(s->name) ? "true" : "false",
533 912 : (long long)s->value->u.integervalue);
534 864 : break;
535 0 : case nullvalue:
536 0 : break;
537 0 : case stringvalue:
538 0 : break;
539 4617 : case objectidentifiervalue: {
540 243 : struct objid *o, **list;
541 243 : size_t i, len;
542 243 : char *gen_upper;
543 :
544 4617 : if (!one_code_file)
545 0 : generate_header_of_codefile(s->gen_name);
546 :
547 4617 : list = objid2list(s->value->u.objectidentifiervalue);
548 37065 : for (len = 0; list && list[len]; len++)
549 : ;
550 4617 : if (len == 0) {
551 0 : errx(1, "Empty OBJECT IDENTIFIER named %s\n", s->name);
552 243 : break;
553 : }
554 :
555 4617 : fprintf(jsonfile,
556 : "{\"name\":\"%s\",\"gen_name\":\"%s\","
557 : "\"type\":\"OBJECT IDENTIFIER\","
558 : "\"constant\":true,\"exported\":%s,\"value\":[\n",
559 9234 : s->name, s->gen_name, is_export(s->name) ? "true" : "false");
560 4617 : fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name);
561 37065 : for (i = 0; i < len; i++) {
562 32205 : o = list[i];
563 32205 : fprintf(headerfile, "%s(%d) ",
564 32205 : o->label ? o->label : "label-less", o->value);
565 32205 : if (o->label == NULL)
566 9895 : fprintf(jsonfile, "%s{\"label\":null,\"value\":%d}",
567 : i ? "," : "", o->value);
568 : else
569 23073 : fprintf(jsonfile, "%s{\"label\":\"%s\",\"value\":%d}",
570 : i ? "," : "", o->label, o->value);
571 : }
572 4617 : fprintf(jsonfile, "]}\n");
573 :
574 4617 : fprintf (codefile, "static unsigned oid_%s_variable_num[%lu] = {",
575 4617 : s->gen_name, (unsigned long)len);
576 37065 : for (i = 0; list[i]; i++) {
577 32448 : fprintf(codefile, "%s %d", i ? "," : "", list[i]->value);
578 : }
579 4617 : fprintf(codefile, "};\n");
580 :
581 4860 : fprintf (codefile, "const heim_oid asn1_oid_%s = "
582 : "{ %lu, oid_%s_variable_num };\n\n",
583 4617 : s->gen_name, (unsigned long)len, s->gen_name);
584 :
585 4617 : fprintf(oidsfile, "DEFINE_OID_WITH_NAME(%s)\n", s->gen_name);
586 4617 : if (is_export(s->name))
587 4860 : fprintf(symsfile, "ASN1_SYM_OID(\"%s\", \"%s\", %s)\n",
588 4617 : s->name, s->gen_name, s->gen_name);
589 :
590 4617 : free(list);
591 :
592 : /* header file */
593 :
594 4617 : gen_upper = strdup(s->gen_name);
595 4617 : len = strlen(gen_upper);
596 97147 : for (i = 0; i < len; i++)
597 92530 : gen_upper[i] = toupper((unsigned char)s->gen_name[i]);
598 :
599 4617 : fprintf (headerfile, "} */\n");
600 4860 : fprintf (headerfile,
601 : "extern ASN1EXP const heim_oid asn1_oid_%s;\n"
602 : "#define ASN1_OID_%s (&asn1_oid_%s)\n\n",
603 4374 : s->gen_name,
604 : gen_upper,
605 4617 : s->gen_name);
606 :
607 4617 : free(gen_upper);
608 :
609 4617 : if (!one_code_file)
610 0 : close_codefile();
611 :
612 4374 : break;
613 : }
614 0 : default:
615 0 : abort();
616 : }
617 5529 : }
618 :
619 : int
620 57 : is_tagged_type(const Type *t)
621 : {
622 : /*
623 : * Start by chasing aliasings like this:
624 : *
625 : * Type0 ::= ...
626 : * Type1 ::= Type0
627 : * ..
628 : * TypeN ::= TypeN-1
629 : *
630 : * to <Type0>, then check if <Type0> is tagged.
631 : */
632 60 : while (t->type == TType) {
633 0 : if (t->subtype)
634 0 : t = t->subtype;
635 0 : else if (t->symbol && t->symbol->type)
636 0 : t = t->symbol->type;
637 : else
638 0 : abort();
639 :
640 : }
641 57 : if (t->type == TTag && t->tag.tagenv == TE_EXPLICIT)
642 54 : return 1;
643 0 : if (t->type == TTag) {
644 0 : if (t->subtype)
645 0 : return is_tagged_type(t->subtype);
646 0 : if (t->symbol && t->symbol->type)
647 0 : return is_tagged_type(t->symbol->type);
648 : /* This is the tag */
649 0 : return 1;
650 : }
651 0 : return 0;
652 : }
653 :
654 : int
655 21563 : is_primitive_type(const Type *t)
656 : {
657 : /*
658 : * Start by chasing aliasings like this:
659 : *
660 : * Type0 ::= ...
661 : * Type1 ::= Type0
662 : * ..
663 : * TypeN ::= TypeN-1
664 : *
665 : * to <Type0>, then check if <Type0> is primitive.
666 : */
667 21603 : while (t->type == TType &&
668 21603 : t->symbol &&
669 2223 : t->symbol->type) {
670 1577 : if (t->symbol->type->type == TType)
671 0 : t = t->symbol->type; /* Alias */
672 1577 : else if (t->symbol->type->type == TTag &&
673 1482 : t->symbol->type->tag.tagenv == TE_IMPLICIT)
674 : /*
675 : * IMPLICIT-tagged alias, something like:
676 : *
677 : * Type0 ::= [0] IMPLICIT ...
678 : *
679 : * Just recurse.
680 : */
681 0 : return is_primitive_type(t->symbol->type);
682 : else
683 : break;
684 :
685 : }
686 : /* EXPLICIT non-UNIVERSAL tags are always constructed */
687 21603 : if (t->type == TTag && t->tag.tagclass != ASN1_C_UNIV &&
688 0 : t->tag.tagenv == TE_EXPLICIT)
689 0 : return 0;
690 21603 : if (t->symbol && t->symbol->type) {
691 : /* EXPLICIT non-UNIVERSAL tags are constructed */
692 2356 : if (t->symbol->type->type == TTag &&
693 2261 : t->symbol->type->tag.tagclass != ASN1_C_UNIV &&
694 19 : t->symbol->type->tag.tagenv == TE_EXPLICIT)
695 18 : return 0;
696 : /* EXPLICIT UNIVERSAL tags are constructed if they are SEQUENCE/SET */
697 2337 : if (t->symbol->type->type == TTag &&
698 2242 : t->symbol->type->tag.tagclass == ASN1_C_UNIV) {
699 2242 : switch (t->symbol->type->tag.tagvalue) {
700 900 : case UT_Sequence: return 0;
701 144 : case UT_Set: return 0;
702 1140 : default: return 1;
703 : }
704 : }
705 : }
706 19342 : switch(t->type) {
707 9432 : 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 9432 : return 1;
725 760 : case TTag:
726 760 : return is_primitive_type(t->subtype);
727 8626 : default:
728 8626 : return 0;
729 : }
730 : }
731 :
732 : static void
733 85575 : space(int level)
734 : {
735 156959 : while(level-- > 0)
736 81859 : fprintf(headerfile, " ");
737 83304 : }
738 :
739 : static const char *
740 56183 : last_member_p(struct member *m)
741 : {
742 57095 : struct member *n = HEIM_TAILQ_NEXT(m, members);
743 56183 : if (n == NULL)
744 10764 : return "";
745 45072 : if (n->ellipsis && HEIM_TAILQ_NEXT(n, members) == NULL)
746 1464 : return "";
747 41904 : return ",";
748 : }
749 :
750 : static struct member *
751 4769 : have_ellipsis(Type *t)
752 : {
753 251 : struct member *m;
754 21318 : HEIM_TAILQ_FOREACH(m, t->members, members) {
755 17252 : if (m->ellipsis)
756 666 : return m;
757 : }
758 3852 : return NULL;
759 : }
760 :
761 : static void
762 50062 : define_asn1 (int level, Type *t)
763 : {
764 51490 : switch (t->type) {
765 11628 : case TType:
766 11628 : if (!t->symbol && t->typeref.iosclass) {
767 1282 : fprintf(headerfile, "%s.&%s",
768 0 : t->typeref.iosclass->symbol->name,
769 0 : t->typeref.field->name);
770 11628 : } else if (t->symbol)
771 11628 : fprintf(headerfile, "%s", t->symbol->name);
772 : else
773 0 : abort();
774 11016 : break;
775 2185 : case TInteger:
776 2185 : if(t->members == NULL) {
777 1672 : fprintf (headerfile, "INTEGER");
778 1672 : if (t->range)
779 2137 : fprintf (headerfile, " (%lld..%lld)",
780 855 : (long long)t->range->min,
781 855 : (long long)t->range->max);
782 : } else {
783 27 : Member *m;
784 513 : fprintf (headerfile, "INTEGER {\n");
785 6080 : HEIM_TAILQ_FOREACH(m, t->members, members) {
786 5567 : space (level + 1);
787 5860 : fprintf(headerfile, "%s(%lld)%s\n", m->gen_name,
788 5567 : (long long)m->val, last_member_p(m));
789 : }
790 513 : space(level);
791 513 : fprintf (headerfile, "}");
792 : }
793 2070 : break;
794 285 : case TBoolean:
795 285 : fprintf (headerfile, "BOOLEAN");
796 270 : break;
797 2318 : case TOctetString:
798 2318 : fprintf (headerfile, "OCTET STRING");
799 2196 : break;
800 630 : case TEnumerated:
801 : case TBitString: {
802 : Member *m;
803 :
804 665 : space(level);
805 665 : if(t->type == TBitString)
806 665 : fprintf (headerfile, "BIT STRING {\n");
807 : else
808 0 : fprintf (headerfile, "ENUMERATED {\n");
809 3021 : HEIM_TAILQ_FOREACH(m, t->members, members) {
810 2356 : space(level + 1);
811 2480 : fprintf(headerfile, "%s(%lld)%s\n", m->name,
812 2356 : (long long)m->val, last_member_p(m));
813 : }
814 665 : space(level);
815 665 : fprintf (headerfile, "}");
816 630 : break;
817 : }
818 4769 : case TChoice:
819 : case TSet:
820 : case TSequence: {
821 251 : Member *m;
822 4769 : size_t max_width = 0;
823 :
824 4769 : if(t->type == TChoice)
825 589 : fprintf(headerfile, "CHOICE {\n");
826 4180 : else if(t->type == TSet)
827 0 : fprintf(headerfile, "SET {\n");
828 : else
829 4180 : fprintf(headerfile, "SEQUENCE {\n");
830 22097 : HEIM_TAILQ_FOREACH(m, t->members, members) {
831 17328 : if(strlen(m->name) > max_width)
832 8838 : max_width = strlen(m->name);
833 : }
834 4769 : max_width += 3;
835 4769 : if(max_width < 16) max_width = 16;
836 22097 : HEIM_TAILQ_FOREACH(m, t->members, members) {
837 17328 : size_t width = max_width;
838 17328 : space(level + 1);
839 17328 : if (m->ellipsis) {
840 741 : fprintf (headerfile, "...");
841 : } else {
842 16587 : width -= fprintf(headerfile, "%s", m->name);
843 16587 : fprintf(headerfile, "%*s", (int)width, "");
844 16587 : define_asn1(level + 1, m->type);
845 16587 : if(m->optional)
846 5567 : fprintf(headerfile, " OPTIONAL");
847 : }
848 17328 : if(last_member_p(m))
849 17328 : fprintf (headerfile, ",");
850 17328 : fprintf (headerfile, "\n");
851 : }
852 4769 : space(level);
853 4769 : fprintf (headerfile, "}");
854 4518 : break;
855 : }
856 1406 : case TSequenceOf:
857 1406 : fprintf (headerfile, "SEQUENCE OF ");
858 1406 : define_asn1 (0, t->subtype);
859 1406 : break;
860 323 : case TSetOf:
861 323 : fprintf (headerfile, "SET OF ");
862 323 : define_asn1 (0, t->subtype);
863 323 : break;
864 171 : case TGeneralizedTime:
865 171 : fprintf (headerfile, "GeneralizedTime");
866 162 : break;
867 266 : case TGeneralString:
868 266 : fprintf (headerfile, "GeneralString");
869 252 : break;
870 19 : case TTeletexString:
871 19 : fprintf (headerfile, "TeletexString");
872 18 : break;
873 25403 : case TTag: {
874 25403 : const char *classnames[] = { "UNIVERSAL ", "APPLICATION ",
875 : "" /* CONTEXT */, "PRIVATE " };
876 25403 : if(t->tag.tagclass != ASN1_C_UNIV)
877 11609 : fprintf (headerfile, "[%s%d] ",
878 10998 : classnames[t->tag.tagclass],
879 : t->tag.tagvalue);
880 25403 : if(t->tag.tagenv == TE_IMPLICIT)
881 1596 : fprintf (headerfile, "IMPLICIT ");
882 25403 : define_asn1 (level, t->subtype);
883 24066 : break;
884 : }
885 19 : case TUTCTime:
886 19 : fprintf (headerfile, "UTCTime");
887 18 : break;
888 828 : case TUTF8String:
889 874 : space(level);
890 874 : fprintf (headerfile, "UTF8String");
891 828 : break;
892 36 : case TPrintableString:
893 38 : space(level);
894 38 : fprintf (headerfile, "PrintableString");
895 36 : break;
896 198 : case TIA5String:
897 209 : space(level);
898 209 : fprintf (headerfile, "IA5String");
899 198 : break;
900 54 : case TBMPString:
901 57 : space(level);
902 57 : fprintf (headerfile, "BMPString");
903 54 : break;
904 18 : case TUniversalString:
905 19 : space(level);
906 19 : fprintf (headerfile, "UniversalString");
907 18 : break;
908 36 : case TVisibleString:
909 38 : space(level);
910 38 : fprintf (headerfile, "VisibleString");
911 36 : break;
912 666 : case TOID :
913 703 : space(level);
914 703 : fprintf(headerfile, "OBJECT IDENTIFIER");
915 666 : break;
916 90 : case TNull:
917 95 : space(level);
918 95 : fprintf (headerfile, "NULL");
919 90 : break;
920 0 : default:
921 0 : abort ();
922 : }
923 50062 : }
924 :
925 : static void
926 12312 : getnewbasename(char **newbasename, int typedefp, const char *basename, const char *name)
927 : {
928 12312 : if (typedefp)
929 11381 : *newbasename = strdup(name);
930 : else {
931 931 : if (name[0] == '*')
932 608 : name++;
933 931 : if (asprintf(newbasename, "%s_%s", basename, name) < 0)
934 0 : errx(1, "malloc");
935 : }
936 12312 : if (*newbasename == NULL)
937 0 : err(1, "malloc");
938 12312 : }
939 :
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);
947 :
948 : /*
949 : * Get the SET/SEQUENCE member pair and CLASS field pair defining an open type.
950 : *
951 : * There are three cases:
952 : *
953 : * - open types embedded in OCTET STRING, with the open type object class
954 : * relation declared via a constraint
955 : *
956 : * - open types not embedded in OCTET STRING, which are really more like ANY
957 : * DEFINED BY types, so, HEIM_ANY
958 : *
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).
962 : *
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".
967 : *
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.
974 : */
975 : void
976 228 : 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)
982 : {
983 12 : Member *m;
984 12 : Field *junk1, *junk2;
985 228 : char *idmembername = NULL;
986 :
987 228 : if (!typeidfield) typeidfield = &junk1;
988 228 : if (!opentypefield) opentypefield = &junk2;
989 :
990 228 : *typeidfield = *opentypefield = NULL;
991 228 : *typeidmember = *opentypemember = NULL;
992 228 : *is_array_of = 0;
993 :
994 : /* Look for the open type member */
995 494 : HEIM_TAILQ_FOREACH(m, t->members, members) {
996 494 : Type *subtype = m->type;
997 494 : Type *sOfType = NULL;
998 :
999 494 : while (subtype->type == TTag ||
1000 950 : subtype->type == TSetOf ||
1001 432 : subtype->type == TSequenceOf) {
1002 494 : if (subtype->type == TTag && subtype->subtype) {
1003 418 : if (subtype->subtype->type == TOctetString ||
1004 360 : subtype->subtype->type == TBitString)
1005 : break;
1006 360 : subtype = subtype->subtype;
1007 76 : } else if (subtype->type == TSetOf || subtype->type == TSequenceOf) {
1008 76 : sOfType = subtype;
1009 76 : if (sOfType->symbol)
1010 0 : break;
1011 76 : if (subtype->subtype)
1012 76 : subtype = subtype->subtype;
1013 : } else
1014 : break;
1015 : }
1016 : /*
1017 : * If we traversed through a non-inlined SET OF or SEQUENCE OF type,
1018 : * then this cannot be an open type field.
1019 : */
1020 494 : if (sOfType && sOfType->symbol)
1021 0 : continue;
1022 : /*
1023 : * The type of the field we're interested in has to have an information
1024 : * object constraint.
1025 : */
1026 494 : if (!subtype->constraint)
1027 266 : continue;
1028 228 : if (subtype->type != TType && subtype->type != TTag)
1029 0 : continue;
1030 : /*
1031 : * Check if it's an ANY-like member or like an OCTET STRING CONTAINING
1032 : * member. Those are the only two possibilities.
1033 : */
1034 228 : if ((subtype->type == TTag || subtype->type == TType) &&
1035 228 : subtype->subtype &&
1036 38 : subtype->constraint->ctype == CT_CONTENTS &&
1037 38 : subtype->constraint->u.content.type &&
1038 38 : subtype->constraint->u.content.type->type == TType &&
1039 38 : !subtype->constraint->u.content.type->subtype &&
1040 38 : subtype->constraint->u.content.type->constraint &&
1041 38 : subtype->constraint->u.content.type->constraint->ctype == CT_TABLE_CONSTRAINT) {
1042 : /* Type like OCTET STRING or BIT STRING CONTAINING open type */
1043 38 : if (*opentypemember)
1044 0 : errx(1, "Multiple open type members %s and %s for the same "
1045 0 : "field %s?", (*opentypemember)->name, m->name,
1046 0 : (*opentypefield)->name);
1047 38 : *opentypemember = m;
1048 38 : *opentypefield = subtype->constraint->u.content.type->typeref.field;
1049 38 : *is_array_of = sOfType != NULL;
1050 38 : idmembername = subtype->constraint->u.content.type->constraint->u.content.crel.membername;
1051 38 : break;
1052 190 : } else if (subtype->symbol && strcmp(subtype->symbol->name, "HEIM_ANY") == 0) {
1053 : /* Open type, but NOT embedded in OCTET STRING or BIT STRING */
1054 190 : if (*opentypemember)
1055 0 : errx(1, "Multiple open type members %s and %s for the same "
1056 0 : "field %s?", (*opentypemember)->name, m->name,
1057 0 : (*opentypefield)->name);
1058 190 : *opentypemember = m;
1059 190 : *opentypefield = subtype->typeref.field;
1060 190 : *is_array_of = sOfType != NULL;
1061 190 : idmembername = subtype->constraint->u.content.crel.membername;
1062 190 : break;
1063 : }
1064 : }
1065 :
1066 228 : if (!idmembername)
1067 0 : errx(1, "Missing open type id member in %s",
1068 0 : t->symbol ? t->symbol->name : "<unknown type>");
1069 : /* Look for the type ID member identified in the previous loop */
1070 228 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1071 228 : if (!m->type->subtype || strcmp(m->name, idmembername) != 0)
1072 0 : continue;
1073 228 : if (m->type->constraint &&
1074 228 : m->type->constraint->ctype == CT_TABLE_CONSTRAINT)
1075 228 : *typeidfield = m->type->typeref.field;
1076 0 : else if (m->type->subtype->constraint &&
1077 0 : m->type->subtype->constraint->ctype == CT_TABLE_CONSTRAINT)
1078 0 : *typeidfield = m->type->subtype->typeref.field;
1079 : else
1080 0 : continue;
1081 : /* This is the type ID field (because there _is_ a subtype) */
1082 228 : *typeidmember = m;
1083 228 : break;
1084 : }
1085 228 : }
1086 :
1087 : /*
1088 : * Generate CHOICE-like struct fields for open types declared via
1089 : * X.681/682/683 syntax.
1090 : *
1091 : * We could support multiple open type members in a SET/SEQUENCE, but for now
1092 : * we support only one.
1093 : */
1094 : static void
1095 114 : define_open_type(int level, const char *newbasename, const char *name, const char *basename, Type *pt, Type *t)
1096 : {
1097 6 : Member *opentypemember, *typeidmember;
1098 6 : Field *opentypefield, *typeidfield;
1099 6 : ObjectField *of;
1100 114 : IOSObjectSet *os = pt->actual_parameter;
1101 6 : IOSObject **objects;
1102 6 : size_t nobjs, i;
1103 6 : int is_array_of_open_type;
1104 :
1105 114 : get_open_type_defn_fields(pt, &typeidmember, &opentypemember,
1106 : &typeidfield, &opentypefield,
1107 : &is_array_of_open_type);
1108 114 : if (!opentypemember || !typeidmember ||
1109 114 : !opentypefield || !typeidfield)
1110 0 : errx(1, "Open type specification in %s is incomplete", name);
1111 :
1112 114 : sort_object_set(os, typeidfield, &objects, &nobjs);
1113 :
1114 114 : fprintf(headerfile, "struct {\n");
1115 114 : fprintf(jsonfile, "{\"opentype\":true,\"arraytype\":%s,",
1116 114 : is_array_of_open_type ? "true" : "false");
1117 114 : fprintf(jsonfile, "\"classname\":\"%s\",", os->iosclass->symbol->name);
1118 114 : fprintf(jsonfile, "\"objectsetname\":\"%s\",", os->symbol->name);
1119 114 : fprintf(jsonfile, "\"typeidmember\":\"%s\",", typeidmember->name);
1120 114 : fprintf(jsonfile, "\"opentypemember\":\"%s\",", opentypemember->name);
1121 114 : fprintf(jsonfile, "\"typeidfield\":\"%s\",", typeidfield->name);
1122 114 : fprintf(jsonfile, "\"opentypefield\":\"%s\",", opentypefield->name);
1123 :
1124 : /* Iterate objects in the object set, gen enum labels */
1125 114 : fprintf(headerfile, "enum { choice_%s_iosnumunknown = 0,\n",
1126 : newbasename);
1127 114 : fprintf(jsonfile, "\"opentypeids\":[");
1128 1507 : for (i = 0; i < nobjs; i++) {
1129 4541 : HEIM_TAILQ_FOREACH(of, objects[i]->objfields, objfields) {
1130 3154 : if (strcmp(of->name, typeidfield->name) != 0)
1131 1767 : continue;
1132 1387 : if (!of->value || !of->value->s)
1133 0 : errx(1, "Unknown value in value field %s of object %s",
1134 0 : of->name, objects[i]->symbol->name);
1135 1387 : fprintf(headerfile, "choice_%s_iosnum_%s,\n",
1136 1314 : newbasename, of->value->s->gen_name);
1137 1387 : fprintf(jsonfile, "\"%s\"", of->value->s->gen_name);
1138 1486 : fprintf(jsonfile, "%s", (i + 1) < nobjs ? "," : "");
1139 : }
1140 : }
1141 114 : fprintf(jsonfile, "],\n");
1142 114 : fprintf(headerfile, "} element;\n");
1143 :
1144 114 : if (is_array_of_open_type)
1145 38 : fprintf(headerfile, "unsigned int len;\n");
1146 :
1147 : /* Iterate objects in the object set, gen union arms */
1148 114 : fprintf(headerfile, "union {\nvoid *_any;\n");
1149 114 : fprintf(jsonfile, "\"members\":[");
1150 1507 : for (i = 0; i < nobjs; i++) {
1151 4541 : HEIM_TAILQ_FOREACH(of, objects[i]->objfields, objfields) {
1152 3154 : char *n = NULL;
1153 :
1154 : /* XXX Print the type IDs into the jsonfile too pls */
1155 :
1156 3154 : if (strcmp(of->name, opentypefield->name) != 0)
1157 1767 : continue;
1158 1387 : if (!of->type || (!of->type->symbol && of->type->type != TTag) ||
1159 1387 : of->type->tag.tagclass != ASN1_C_UNIV) {
1160 0 : warnx("Ignoring unknown or unset type field %s of object %s",
1161 0 : of->name, objects[i]->symbol->name);
1162 0 : continue;
1163 : }
1164 :
1165 1387 : if (asprintf(&n, "*%s", objects[i]->symbol->gen_name) < 0 || n == NULL)
1166 0 : err(1, "malloc");
1167 1387 : define_type(level + 2, n, newbasename, NULL, of->type, DEF_TYPE_NONE);
1168 1393 : fprintf(jsonfile, "%s", (i + 1) < nobjs ? "," : "");
1169 1387 : free(n);
1170 : }
1171 : }
1172 114 : fprintf(jsonfile, "]}\n");
1173 114 : if (is_array_of_open_type) {
1174 38 : fprintf(headerfile, "} *val;\n} _ioschoice_%s;\n", opentypemember->gen_name);
1175 : } else {
1176 76 : fprintf(headerfile, "} u;\n");
1177 76 : fprintf(headerfile, "} _ioschoice_%s;\n", opentypemember->gen_name);
1178 : }
1179 114 : free(objects);
1180 114 : }
1181 :
1182 : static const char * const tagclassnames[] = {
1183 : "UNIVERSAL", "APPLICATION", "CONTEXT", "PRIVATE"
1184 : };
1185 :
1186 : static void
1187 62510 : define_type(int level, const char *name, const char *basename,
1188 : Type *pt, Type *t, define_type_options opts)
1189 : {
1190 62510 : const char *label_prefix = NULL;
1191 62510 : const char *label_prefix_sep = NULL;
1192 62510 : char *newbasename = NULL;
1193 :
1194 121730 : fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
1195 : "\"is_type\":true,\"exported\":%s,\"typedef\":%s,",
1196 : basename, name,
1197 62510 : t->symbol && is_export(t->symbol->name) ? "true" : "false",
1198 62510 : (opts & DEF_TYPE_TYPEDEFP) ? "true" : "false");
1199 :
1200 62510 : switch (t->type) {
1201 12330 : case TType:
1202 13015 : space(level);
1203 13015 : if (!t->symbol && t->actual_parameter) {
1204 0 : define_open_type(level, newbasename, name, basename, t, t);
1205 13015 : } else if (!t->symbol && pt->actual_parameter) {
1206 0 : define_open_type(level, newbasename, name, basename, pt, t);
1207 13015 : } else if (t->symbol) {
1208 13015 : fprintf(headerfile, "%s %s;\n", t->symbol->gen_name, name);
1209 16305 : fprintf(jsonfile, "\"ttype\":\"%s\","
1210 13015 : "\"alias\":true\n", t->symbol->gen_name);
1211 : } else
1212 0 : abort();
1213 12330 : break;
1214 11818 : case TInteger:
1215 11818 : if (t->symbol && t->symbol->emitted_definition)
1216 0 : break;
1217 :
1218 11818 : space(level);
1219 11818 : if(t->members) {
1220 27 : Member *m;
1221 :
1222 513 : label_prefix = prefix_enum ? name : (enum_prefix ? enum_prefix : "");
1223 513 : label_prefix_sep = prefix_enum ? "_" : "";
1224 513 : fprintf (headerfile, "enum %s {\n", (opts & DEF_TYPE_TYPEDEFP) ? name : "");
1225 513 : fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"enum\","
1226 : "\"members\":[\n");
1227 6080 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1228 5567 : space (level + 1);
1229 5567 : fprintf(headerfile, "%s%s%s = %lld%s\n",
1230 : label_prefix, label_prefix_sep,
1231 5567 : m->gen_name, (long long)m->val, last_member_p(m));
1232 5860 : fprintf(jsonfile, "{\"%s%s%s\":%lld}%s\n",
1233 : label_prefix, label_prefix_sep,
1234 5567 : m->gen_name, (long long)m->val, last_member_p(m));
1235 : }
1236 513 : fprintf(headerfile, "} %s;\n", name);
1237 513 : fprintf(jsonfile, "]");
1238 11305 : } else if (t->range == NULL) {
1239 817 : fprintf(headerfile, "heim_integer %s;\n", name);
1240 817 : fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"heim_integer\"");
1241 10488 : } else if (t->range->min < 0 &&
1242 189 : (t->range->min < INT_MIN || t->range->max > INT_MAX)) {
1243 19 : fprintf(headerfile, "int64_t %s;\n", name);
1244 19 : fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"int64_t\"");
1245 10469 : } else if (t->range->min < 0) {
1246 171 : fprintf (headerfile, "int %s;\n", name);
1247 171 : fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"int\"");
1248 10298 : } else if (t->range->max > UINT_MAX) {
1249 0 : fprintf (headerfile, "uint64_t %s;\n", name);
1250 0 : fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"uint64_t\"");
1251 : } else {
1252 10298 : fprintf (headerfile, "unsigned int %s;\n", name);
1253 10298 : fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"unsigned int\"");
1254 : }
1255 11196 : break;
1256 270 : case TBoolean:
1257 285 : space(level);
1258 285 : fprintf (headerfile, "int %s;\n", name);
1259 285 : fprintf(jsonfile, "\"ttype\":\"BOOLEAN\",\"ctype\":\"unsigned int\"");
1260 270 : break;
1261 2196 : case TOctetString:
1262 2318 : space(level);
1263 2318 : fprintf (headerfile, "heim_octet_string %s;\n", name);
1264 2318 : fprintf(jsonfile, "\"ttype\":\"OCTET STRING\",\"ctype\":\"heim_octet_string\"");
1265 2196 : break;
1266 665 : case TBitString: {
1267 35 : Member *m;
1268 35 : Type i;
1269 665 : struct range range = { 0, UINT_MAX };
1270 665 : size_t max_memno = 0;
1271 35 : size_t bitset_size;
1272 :
1273 665 : if (t->symbol && t->symbol->emitted_definition)
1274 0 : break;
1275 665 : memset(&i, 0, sizeof(i));
1276 :
1277 : /*
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.
1281 : *
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.
1286 : */
1287 3021 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1288 2356 : if (m->val > max_memno)
1289 1998 : max_memno = m->val;
1290 : }
1291 665 : if (max_memno > 63)
1292 0 : range.max = INT64_MAX;
1293 : else
1294 665 : range.max = 1ULL << max_memno;
1295 :
1296 665 : i.type = TInteger;
1297 665 : i.range = ⦥
1298 665 : i.members = NULL;
1299 665 : i.constraint = NULL;
1300 :
1301 665 : space(level);
1302 665 : fprintf(jsonfile, "\"ttype\":\"BIT STRING\",");
1303 665 : if(HEIM_TAILQ_EMPTY(t->members)) {
1304 418 : fprintf (headerfile, "heim_bit_string %s;\n", name);
1305 418 : fprintf(jsonfile, "\"ctype\":\"heim_bit_string\"");
1306 : } else {
1307 247 : int64_t pos = 0;
1308 247 : getnewbasename(&newbasename, (opts & DEF_TYPE_TYPEDEFP) || level == 0, basename, name);
1309 :
1310 247 : fprintf (headerfile, "struct %s {\n", newbasename);
1311 247 : fprintf(jsonfile, "\"ctype\":\"struct %s\",\"members\":[\n", newbasename);
1312 2603 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1313 2356 : char *n = NULL;
1314 :
1315 : /*
1316 : * pad unused bits beween declared members (hopefully this
1317 : * forces the compiler to give us an obvious layout)
1318 : */
1319 2774 : while (pos < m->val) {
1320 418 : if (asprintf (&n, "_unused%lld:1", (long long)pos) < 0 ||
1321 418 : n == NULL)
1322 0 : err(1, "malloc");
1323 418 : define_type(level + 1, n, newbasename, NULL, &i, DEF_TYPE_EMIT_NAME);
1324 418 : fprintf(jsonfile, ",");
1325 418 : free(n);
1326 418 : pos++;
1327 : }
1328 :
1329 2356 : n = NULL;
1330 2356 : if (asprintf (&n, "%s:1", m->gen_name) < 0 || n == NULL)
1331 0 : errx(1, "malloc");
1332 2356 : define_type(level + 1, n, newbasename, NULL, &i, DEF_TYPE_EMIT_NAME);
1333 2467 : fprintf(jsonfile, "%s", last_member_p(m));
1334 2356 : free (n);
1335 2356 : n = NULL;
1336 2356 : pos++;
1337 : }
1338 : /* pad unused tail (ditto) */
1339 247 : bitset_size = max_memno;
1340 247 : if (max_memno > 31)
1341 0 : bitset_size += 64 - (max_memno % 64);
1342 : else
1343 234 : bitset_size = 32;
1344 247 : if (pos < bitset_size)
1345 209 : fprintf(jsonfile, ",");
1346 5377 : while (pos < bitset_size) {
1347 5130 : char *n = NULL;
1348 5130 : if (asprintf (&n, "_unused%lld:1", (long long)pos) < 0 ||
1349 5130 : n == NULL)
1350 0 : errx(1, "malloc");
1351 5130 : define_type(level + 1, n, newbasename, NULL, &i, DEF_TYPE_EMIT_NAME);
1352 5141 : fprintf(jsonfile, "%s", (pos + 1) < bitset_size ? "," : "");
1353 5130 : free(n);
1354 5130 : pos++;
1355 : }
1356 :
1357 247 : space(level);
1358 481 : fprintf(headerfile, "}%s%s;\n\n",
1359 234 : (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
1360 247 : (opts & DEF_TYPE_EMIT_NAME) ? name : "");
1361 269 : fprintf(jsonfile, "]");
1362 : }
1363 630 : break;
1364 : }
1365 0 : case TEnumerated: {
1366 0 : Member *m;
1367 :
1368 0 : if (t->symbol && t->symbol->emitted_definition)
1369 0 : break;
1370 :
1371 0 : label_prefix = prefix_enum ? name : (enum_prefix ? enum_prefix : "");
1372 0 : label_prefix_sep = prefix_enum ? "_" : "";
1373 0 : space(level);
1374 0 : fprintf (headerfile, "enum %s {\n", (opts & DEF_TYPE_TYPEDEFP) ? name : "");
1375 0 : fprintf(jsonfile, "\"ctype\":\"enum %s\",\"extensible\":%s,\"members\":[\n",
1376 0 : (opts & DEF_TYPE_TYPEDEFP) ? name : "", have_ellipsis(t) ? "true" : "false");
1377 0 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1378 0 : space(level + 1);
1379 0 : if (m->ellipsis) {
1380 0 : fprintf (headerfile, "/* ... */\n");
1381 : } else {
1382 0 : fprintf(headerfile, "%s%s%s = %lld%s\n",
1383 : label_prefix, label_prefix_sep,
1384 0 : m->gen_name, (long long)m->val, last_member_p(m));
1385 0 : fprintf(jsonfile, "{\"%s%s%s\":%lld%s}\n",
1386 : label_prefix, label_prefix_sep,
1387 0 : m->gen_name, (long long)m->val, last_member_p(m));
1388 : }
1389 : }
1390 0 : space(level);
1391 0 : fprintf(headerfile, "}%s%s;\n\n",
1392 0 : (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
1393 0 : (opts & DEF_TYPE_EMIT_NAME) ? name : "");
1394 0 : fprintf(jsonfile, "]");
1395 0 : break;
1396 : }
1397 4180 : case TSet:
1398 : case TSequence: {
1399 220 : Member *m;
1400 220 : struct decoration deco;
1401 4180 : ssize_t more_deco = -1;
1402 4180 : int decorated = 0;
1403 :
1404 4180 : getnewbasename(&newbasename, (opts & DEF_TYPE_TYPEDEFP) || level == 0, basename, name);
1405 :
1406 4180 : space(level);
1407 :
1408 4180 : fprintf (headerfile, "struct %s {\n", newbasename);
1409 8360 : fprintf(jsonfile, "\"ttype\":\"%s\",\"extensible\":%s,"
1410 : "\"ctype\":\"struct %s\"",
1411 4180 : t->type == TSet ? "SET" : "SEQUENCE",
1412 4180 : have_ellipsis(t) ? "true" : "false", newbasename);
1413 4180 : if (t->type == TSequence && (opts & DEF_TYPE_PRESERVE)) {
1414 114 : space(level + 1);
1415 114 : fprintf(headerfile, "heim_octet_string _save;\n");
1416 114 : fprintf(jsonfile, ",\"preserve\":true");
1417 : }
1418 4180 : fprintf(jsonfile, ",\"members\":[\n");
1419 19646 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1420 15466 : if (m->ellipsis) {
1421 : ;
1422 14820 : } else if (m->optional || m->defval) {
1423 5776 : char *n = NULL, *defval = NULL;
1424 304 : const char *namep, *defvalp;
1425 :
1426 5776 : if (m->defval) {
1427 209 : switch (m->defval->type) {
1428 0 : case stringvalue:
1429 0 : if (asprintf(&defval, "\"%s\"", m->defval->u.stringvalue) < 0 || defval == NULL)
1430 0 : errx(1, "malloc");
1431 0 : defvalp = defval;
1432 0 : break;
1433 95 : case integervalue:
1434 95 : if (asprintf(&defval, "%lld", (long long)m->defval->u.integervalue) < 0 || defval == NULL)
1435 0 : errx(1, "malloc");
1436 90 : defvalp = defval;
1437 90 : break;
1438 114 : case booleanvalue:
1439 114 : defvalp = m->defval->u.booleanvalue ? "true" : "false";
1440 108 : break;
1441 0 : default:
1442 0 : abort();
1443 : }
1444 : } else
1445 5274 : defvalp = "null";
1446 :
1447 5776 : if (m->optional) {
1448 5567 : if (asprintf(&n, "*%s", m->gen_name) < 0 || n == NULL)
1449 0 : errx(1, "malloc");
1450 5274 : namep = n;
1451 : } else
1452 209 : namep = m->gen_name;
1453 :
1454 5776 : fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
1455 : "\"optional\":%s,\"defval\":%s,\"type\":",
1456 5776 : m->name, m->gen_name, m->optional ? "true" : "false", defvalp);
1457 5776 : define_type(level + 1, namep, newbasename, t, m->type, DEF_TYPE_EMIT_NAME);
1458 5988 : fprintf(jsonfile, "}%s", last_member_p(m));
1459 5776 : free (n);
1460 5776 : free (defval);
1461 : } else {
1462 9044 : fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
1463 : "\"optional\":false,\"type\":", m->name, m->gen_name);
1464 9044 : define_type(level + 1, m->gen_name, newbasename, t, m->type, DEF_TYPE_EMIT_NAME);
1465 9762 : fprintf(jsonfile, "}%s", last_member_p(m));
1466 : }
1467 : }
1468 4180 : fprintf(jsonfile, "]");
1469 4180 : if (t->actual_parameter && t->actual_parameter->objects) {
1470 114 : fprintf(jsonfile, ",\"opentype\":");
1471 114 : define_open_type(level, newbasename, name, basename, t, t);
1472 : }
1473 4256 : while (decorate_type(newbasename, &deco, &more_deco)) {
1474 76 : decorated++;
1475 76 : space(level + 1);
1476 76 : fprintf(headerfile, "%s %s%s;\n", deco.field_type,
1477 76 : deco.opt ? "*" : "", deco.field_name);
1478 76 : if (deco.first)
1479 57 : fprintf(jsonfile, ",\"decorate\":[");
1480 1020 : 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 76 : deco.first ? "" : ",",
1488 : deco.field_type, deco.field_name,
1489 149 : deco.opt ? "true" : "false", deco.ext ? "true" : "false",
1490 151 : deco.ptr ? "true" : "false", deco.void_star ? "true" : "false",
1491 76 : deco.struct_star ? "true" : "false",
1492 76 : deco.copy_function_name ? deco.copy_function_name : "",
1493 76 : deco.free_function_name ? deco.free_function_name : "",
1494 72 : deco.header_name && deco.header_name[0] == '"' ? "" : "\"",
1495 72 : deco.header_name ? deco.header_name : "",
1496 76 : deco.header_name && deco.header_name[0] == '"' ? "" : "\""
1497 : );
1498 : }
1499 4180 : if (decorated)
1500 292 : fprintf(jsonfile, "]");
1501 4180 : space(level);
1502 8348 : fprintf(headerfile, "}%s%s;\n",
1503 3960 : (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
1504 4180 : (opts & DEF_TYPE_EMIT_NAME) ? name : "");
1505 4180 : free(deco.field_type);
1506 4180 : break;
1507 : }
1508 1729 : case TSetOf:
1509 : case TSequenceOf: {
1510 91 : Type i;
1511 1729 : struct range range = { 0, UINT_MAX };
1512 :
1513 1762 : getnewbasename(&newbasename, (opts & DEF_TYPE_TYPEDEFP) || level == 0, basename, name);
1514 :
1515 1729 : memset(&i, 0, sizeof(i));
1516 1729 : i.type = TInteger;
1517 1729 : i.range = ⦥
1518 :
1519 1729 : space(level);
1520 1729 : fprintf (headerfile, "struct %s {\n", newbasename);
1521 1729 : fprintf(jsonfile, "\"ttype\":\"%s\",\"ctype\":\"struct %s\",\"members\":[",
1522 1729 : t->type == TSetOf ? "SET OF" : "SEQUENCE OF", newbasename);
1523 1729 : define_type(level + 1, "len", newbasename, t, &i, DEF_TYPE_NONE);
1524 1729 : fprintf(jsonfile, ",");
1525 1729 : define_type(level + 1, "*val", newbasename, t, t->subtype, DEF_TYPE_NONE | DEF_TYPE_EMIT_NAME);
1526 1729 : space(level);
1527 3425 : fprintf(headerfile, "}%s%s;\n",
1528 1638 : (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
1529 1729 : (opts & DEF_TYPE_EMIT_NAME) ? name : "");
1530 1729 : fprintf(jsonfile, "]");
1531 1729 : break;
1532 : }
1533 162 : case TGeneralizedTime:
1534 171 : space(level);
1535 171 : fprintf (headerfile, "time_t %s;\n", name);
1536 171 : fprintf(jsonfile, "\"ttype\":\"GeneralizedTime\",\"ctype\":\"time_t\"");
1537 162 : break;
1538 252 : case TGeneralString:
1539 266 : space(level);
1540 266 : fprintf (headerfile, "heim_general_string %s;\n", name);
1541 266 : fprintf(jsonfile, "\"ttype\":\"GeneralString\",\"ctype\":\"heim_general_string\"");
1542 252 : break;
1543 18 : case TTeletexString:
1544 19 : space(level);
1545 19 : fprintf (headerfile, "heim_general_string %s;\n", name);
1546 19 : fprintf(jsonfile, "\"ttype\":\"TeletexString\",\"ctype\":\"heim_general_string\"");
1547 18 : break;
1548 25403 : case TTag:
1549 25403 : if (t->implicit_choice) {
1550 38 : fprintf(jsonfile, "\"desired_tagenv\":\"IMPLICIT\",");
1551 : }
1552 28077 : fprintf(jsonfile, "\"tagclass\":\"%s\",\"tagvalue\":%d,\"tagenv\":\"%s\",\n",
1553 25403 : tagclassnames[t->tag.tagclass], t->tag.tagvalue,
1554 25403 : t->tag.tagenv == TE_EXPLICIT ? "EXPLICIT" : "IMPLICIT");
1555 25403 : fprintf(jsonfile, "\"ttype\":\n");
1556 25403 : define_type(level, name, basename, t, t->subtype, opts);
1557 25403 : break;
1558 589 : case TChoice: {
1559 31 : struct decoration deco;
1560 589 : ssize_t more_deco = -1;
1561 589 : int decorated = 0;
1562 589 : int first = 1;
1563 31 : Member *m;
1564 :
1565 589 : getnewbasename(&newbasename, (opts & DEF_TYPE_TYPEDEFP) || level == 0, basename, name);
1566 :
1567 589 : space(level);
1568 589 : fprintf (headerfile, "struct %s {\n", newbasename);
1569 589 : fprintf(jsonfile, "\"ttype\":\"CHOICE\",\"ctype\":\"struct %s\"",
1570 : newbasename);
1571 589 : if ((opts & DEF_TYPE_PRESERVE)) {
1572 19 : space(level + 1);
1573 19 : fprintf(headerfile, "heim_octet_string _save;\n");
1574 19 : fprintf(jsonfile, ",\"preserve\":true");
1575 : }
1576 589 : space(level + 1);
1577 589 : fprintf (headerfile, "enum %s_enum {\n", newbasename);
1578 589 : m = have_ellipsis(t);
1579 589 : if (m) {
1580 95 : space(level + 2);
1581 95 : fprintf (headerfile, "%s = 0,\n", m->label);
1582 95 : first = 0;
1583 : }
1584 615 : fprintf(jsonfile, ",\"extensible\":%s", m ? "true" : "false");
1585 2451 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1586 1862 : space(level + 2);
1587 1862 : if (m->ellipsis)
1588 95 : fprintf (headerfile, "/* ... */\n");
1589 : else
1590 1901 : fprintf (headerfile, "%s%s%s\n", m->label,
1591 : first ? " = 1" : "",
1592 : last_member_p(m));
1593 1862 : first = 0;
1594 : }
1595 589 : space(level + 1);
1596 589 : fprintf (headerfile, "} element;\n");
1597 589 : space(level + 1);
1598 589 : fprintf (headerfile, "union {\n");
1599 589 : fprintf(jsonfile, ",\"members\":[\n");
1600 2451 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1601 1862 : if (m->ellipsis) {
1602 95 : space(level + 2);
1603 95 : fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");
1604 1767 : } else if (m->optional) {
1605 0 : char *n = NULL;
1606 :
1607 0 : if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL)
1608 0 : errx(1, "malloc");
1609 0 : fprintf(jsonfile, "{\"optional\":");
1610 0 : define_type(level + 2, n, newbasename, t, m->type, DEF_TYPE_EMIT_NAME);
1611 0 : fprintf(jsonfile, "}%s", last_member_p(m));
1612 0 : free (n);
1613 : } else {
1614 1767 : define_type(level + 2, m->gen_name, newbasename, t, m->type, DEF_TYPE_EMIT_NAME);
1615 1839 : fprintf(jsonfile, "%s", last_member_p(m));
1616 : }
1617 : }
1618 589 : space(level + 1);
1619 589 : fprintf (headerfile, "} u;\n");
1620 589 : fprintf(jsonfile, "]");
1621 :
1622 589 : while (decorate_type(newbasename, &deco, &more_deco)) {
1623 0 : decorated++;
1624 0 : space(level + 1);
1625 0 : fprintf(headerfile, "%s %s%s;\n", deco.field_type,
1626 0 : deco.opt ? "*" : "", deco.field_name);
1627 0 : if (deco.first)
1628 0 : fprintf(jsonfile, ",\"decorate\":[");
1629 31 : 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 0 : deco.first ? "" : ",",
1637 : deco.field_type, deco.field_name,
1638 0 : deco.opt ? "true" : "false", deco.ext ? "true" : "false",
1639 0 : deco.ptr ? "true" : "false", deco.void_star ? "true" : "false",
1640 0 : deco.struct_star ? "true" : "false",
1641 0 : deco.copy_function_name ? deco.copy_function_name : "",
1642 0 : deco.free_function_name ? deco.free_function_name : "",
1643 0 : deco.header_name && deco.header_name[0] == '"' ? "" : "\"",
1644 0 : deco.header_name ? deco.header_name : "",
1645 0 : deco.header_name && deco.header_name[0] == '"' ? "" : "\""
1646 : );
1647 : }
1648 589 : if (decorated)
1649 35 : fprintf(jsonfile, "]");
1650 :
1651 589 : space(level);
1652 1174 : fprintf(headerfile, "}%s%s;\n",
1653 558 : (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
1654 589 : (opts & DEF_TYPE_EMIT_NAME) ? name : "");
1655 589 : break;
1656 : }
1657 18 : case TUTCTime:
1658 19 : space(level);
1659 19 : fprintf (headerfile, "time_t %s;\n", name);
1660 19 : fprintf(jsonfile, "\"ttype\":\"UTCTime\",\"ctype\":\"time_t\"");
1661 18 : break;
1662 828 : case TUTF8String:
1663 874 : space(level);
1664 874 : fprintf (headerfile, "heim_utf8_string %s;\n", name);
1665 874 : fprintf(jsonfile, "\"ttype\":\"UTF8String\",\"ctype\":\"heim_utf8_string\"");
1666 828 : break;
1667 36 : case TPrintableString:
1668 38 : space(level);
1669 38 : fprintf (headerfile, "heim_printable_string %s;\n", name);
1670 38 : fprintf(jsonfile, "\"ttype\":\"PrintableString\",\"ctype\":\"heim_printable_string\"");
1671 36 : break;
1672 198 : case TIA5String:
1673 209 : space(level);
1674 209 : fprintf (headerfile, "heim_ia5_string %s;\n", name);
1675 209 : fprintf(jsonfile, "\"ttype\":\"IA5String\",\"ctype\":\"heim_ia5_string\"");
1676 198 : break;
1677 54 : case TBMPString:
1678 57 : space(level);
1679 57 : fprintf (headerfile, "heim_bmp_string %s;\n", name);
1680 57 : fprintf(jsonfile, "\"ttype\":\"BMPString\",\"ctype\":\"heim_bmp_string\"");
1681 54 : break;
1682 18 : case TUniversalString:
1683 19 : space(level);
1684 19 : fprintf (headerfile, "heim_universal_string %s;\n", name);
1685 19 : fprintf(jsonfile, "\"ttype\":\"UniversalString\",\"ctype\":\"heim_universal_string\"");
1686 18 : break;
1687 36 : case TVisibleString:
1688 38 : space(level);
1689 38 : fprintf (headerfile, "heim_visible_string %s;\n", name);
1690 38 : fprintf(jsonfile, "\"ttype\":\"VisibleString\",\"ctype\":\"heim_visible_string\"");
1691 36 : break;
1692 666 : case TOID :
1693 703 : space(level);
1694 703 : fprintf (headerfile, "heim_oid %s;\n", name);
1695 703 : fprintf(jsonfile, "\"ttype\":\"OBJECT IDENTIFIER\",\"ctype\":\"heim_oid\"");
1696 666 : break;
1697 90 : case TNull:
1698 95 : space(level);
1699 95 : fprintf (headerfile, "int %s;\n", name);
1700 95 : fprintf(jsonfile, "\"ttype\":\"NULL\",\"ctype\":\"int\"");
1701 90 : break;
1702 0 : default:
1703 0 : abort ();
1704 : }
1705 62510 : fprintf(jsonfile, "}\n");
1706 62510 : free(newbasename);
1707 62510 : }
1708 :
1709 : static void
1710 14858 : declare_type(const Symbol *s, Type *t, int typedefp)
1711 : {
1712 14858 : char *newbasename = NULL;
1713 :
1714 14858 : if (typedefp)
1715 7771 : fprintf(headerfile, "typedef ");
1716 :
1717 14858 : switch (t->type) {
1718 627 : case TType:
1719 627 : define_type(0, s->gen_name, s->gen_name, NULL, s->type,
1720 : DEF_TYPE_PRESERVE | DEF_TYPE_TYPEDEFP |
1721 627 : (s->emitted_declaration ? 0 : DEF_TYPE_EMIT_NAME));
1722 627 : if (template_flag && !s->emitted_declaration)
1723 627 : generate_template_type_forward(s->gen_name);
1724 627 : emitted_declaration(s);
1725 9324 : return;
1726 1577 : 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 1577 : define_type(0, s->gen_name, s->gen_name, NULL, s->type,
1744 : DEF_TYPE_PRESERVE | DEF_TYPE_TYPEDEFP |
1745 1577 : (s->emitted_declaration ? 0 : DEF_TYPE_EMIT_NAME));
1746 1577 : if (template_flag && !s->emitted_declaration)
1747 1444 : generate_template_type_forward(s->gen_name);
1748 1577 : emitted_declaration(s);
1749 1577 : emitted_definition(s);
1750 1577 : return;
1751 7087 : case TTag:
1752 7087 : if (!s->emitted_declaration)
1753 7087 : declare_type(s, t->subtype, FALSE);
1754 7087 : emitted_declaration(s);
1755 7087 : return;
1756 5274 : default:
1757 5567 : break;
1758 : }
1759 :
1760 5567 : switch (t->type) {
1761 3952 : case TSet:
1762 : case TSequence: {
1763 208 : struct decoration deco;
1764 3952 : ssize_t more_deco = -1;
1765 :
1766 3952 : getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
1767 3952 : fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
1768 4028 : while (decorate_type(newbasename, &deco, &more_deco)) {
1769 76 : if (deco.header_name)
1770 0 : fprintf(headerfile, "#include %s\n", deco.header_name);
1771 76 : free(deco.field_type);
1772 : }
1773 3952 : break;
1774 : }
1775 1102 : case TSetOf:
1776 : case TSequenceOf:
1777 1102 : getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
1778 1102 : fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
1779 1044 : break;
1780 513 : case TChoice: {
1781 27 : struct decoration deco;
1782 513 : ssize_t more_deco = -1;
1783 :
1784 513 : getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
1785 513 : fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
1786 513 : while (decorate_type(newbasename, &deco, &more_deco)) {
1787 0 : if (deco.header_name)
1788 0 : fprintf(headerfile, "#include %s\n", deco.header_name);
1789 0 : free(deco.field_type);
1790 : }
1791 513 : break;
1792 : }
1793 0 : default:
1794 0 : abort ();
1795 : }
1796 5567 : free(newbasename);
1797 5567 : emitted_declaration(s);
1798 : }
1799 :
1800 : static void generate_subtypes_header_helper(const Member *m);
1801 : static void generate_type_header(const Symbol *);
1802 :
1803 : static void
1804 25460 : generate_subtypes_header_helper(const Member *m)
1805 : {
1806 1340 : Member *sm;
1807 1340 : Symbol *s;
1808 :
1809 25460 : if (m->ellipsis)
1810 864 : return;
1811 24548 : if (m->type->symbol && (s = getsym(m->type->symbol->name)) &&
1812 2641 : !s->emitted_definition) {
1813 : /* A field of some named type; recurse */
1814 627 : if (!m->optional && !m->defval)
1815 570 : generate_type_header(s);
1816 627 : return;
1817 : }
1818 23921 : if (!m->type->subtype && !m->type->members)
1819 1908 : return;
1820 21907 : if (m->type->type == TTag &&
1821 32724 : m->type->subtype && m->type->subtype->symbol &&
1822 11438 : (s = getsym(m->type->subtype->symbol->name))) {
1823 11438 : if (!m->optional && !m->defval)
1824 7562 : generate_type_header(s);
1825 11438 : return;
1826 : }
1827 10469 : if (m->type->subtype) {
1828 10450 : switch (m->type->subtype->type) {
1829 90 : case TSet:
1830 : case TSequence:
1831 : case TChoice:
1832 95 : break;
1833 9810 : default:
1834 9810 : return;
1835 : }
1836 : /* A field of some anonymous (inlined) structured type */
1837 513 : HEIM_TAILQ_FOREACH(sm, m->type->subtype->members, members) {
1838 418 : generate_subtypes_header_helper(sm);
1839 : }
1840 : }
1841 114 : if (m->type->members) {
1842 57 : HEIM_TAILQ_FOREACH(sm, m->type->members, members) {
1843 38 : generate_subtypes_header_helper(sm);
1844 : }
1845 : }
1846 : }
1847 :
1848 : static void
1849 14991 : generate_subtypes_header(const Symbol *s)
1850 : {
1851 14991 : Type *t = s->type;
1852 789 : Member *m;
1853 :
1854 : /*
1855 : * Recurse down structured types to make sure top-level types get
1856 : * defined before they are referenced.
1857 : *
1858 : * We'll take care to skip OPTIONAL member fields of constructed types so
1859 : * that we can have circular types like:
1860 : *
1861 : * Foo ::= SEQUENCE {
1862 : * bar Bar OPTIONAL
1863 : * }
1864 : *
1865 : * Bar ::= SEQUENCE {
1866 : * foo Foo OPTIONAL
1867 : * }
1868 : *
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:
1872 : *
1873 : * ListOfFoo ::= SEQUENCE {
1874 : * someField SomeType,
1875 : * next ListOfFoo OPTIONAL
1876 : * }
1877 : *
1878 : * Not that anyone needs it -- just use a SEQUENCE OF and be done.
1879 : */
1880 :
1881 21565 : while (t->type == TTag && t->subtype) {
1882 14155 : switch (t->subtype->type) {
1883 6574 : case TTag:
1884 : case TSet:
1885 : case TSequence:
1886 : case TChoice:
1887 6574 : t = t->subtype;
1888 6574 : continue;
1889 7182 : default:
1890 7182 : break;
1891 : }
1892 7182 : break;
1893 : }
1894 :
1895 14991 : switch (t->type) {
1896 7182 : default: return;
1897 513 : case TType: {
1898 27 : Symbol *s2;
1899 513 : if (t->symbol && (s2 = getsym(t->symbol->name)) != s)
1900 513 : generate_type_header(s2);
1901 486 : return;
1902 : }
1903 6534 : case TSet:
1904 : case TSequence:
1905 : case TChoice:
1906 6897 : break;
1907 : }
1908 :
1909 31901 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1910 25004 : generate_subtypes_header_helper(m);
1911 : }
1912 : }
1913 :
1914 : static void
1915 16416 : generate_type_header (const Symbol *s)
1916 : {
1917 16416 : Type *t = s->type;
1918 :
1919 16416 : if (!s->type)
1920 1350 : return;
1921 :
1922 : /*
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.
1926 : */
1927 14991 : generate_subtypes_header(s);
1928 14991 : if (!s->emitted_asn1) {
1929 7771 : fprintf(headerfile, "/*\n");
1930 7771 : fprintf(headerfile, "%s ::= ", s->name);
1931 7771 : define_asn1 (0, s->type);
1932 7771 : fprintf(headerfile, "\n*/\n\n");
1933 7771 : emitted_asn1(s);
1934 : }
1935 :
1936 : /*
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.
1940 : *
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.
1948 : */
1949 14991 : if (!s->emitted_tag_enums) {
1950 8113 : while (t->type == TType && s->type->symbol && s->type->symbol->type) {
1951 342 : if (t->subtype)
1952 0 : t = t->subtype;
1953 : else
1954 751 : t = s->type->symbol->type;
1955 : }
1956 :
1957 7771 : if (t->type == TType && t->symbol &&
1958 171 : strcmp(t->symbol->name, "HEIM_ANY") != 0) {
1959 : /*
1960 : * This type is ultimately an alias of an imported type, so we don't
1961 : * know its outermost tag here.
1962 : */
1963 160 : 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 144 : s->gen_name, s->type->symbol->gen_name,
1968 144 : s->gen_name, s->type->symbol->gen_name,
1969 152 : s->gen_name, s->type->symbol->gen_name);
1970 152 : emitted_tag_enums(s);
1971 7619 : } else if (t->type != TType) {
1972 : /* This type's outermost tag is known here */
1973 15600 : 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 7600 : s->gen_name, (unsigned long)length_tag(s->type->tag.tagvalue),
1978 7200 : s->gen_name, s->type->tag.tagclass,
1979 7600 : s->gen_name, s->type->tag.tagvalue);
1980 7600 : emitted_tag_enums(s);
1981 : }
1982 : }
1983 :
1984 14991 : if (s->emitted_definition)
1985 8334 : return;
1986 :
1987 6194 : if (is_export(s->name))
1988 6254 : fprintf(symsfile, "ASN1_SYM_TYPE(\"%s\", \"%s\", %s)\n",
1989 5928 : s->name, s->gen_name, s->gen_name);
1990 :
1991 6194 : if (!s->emitted_declaration) {
1992 0 : fprintf(headerfile, "typedef ");
1993 0 : define_type(0, s->gen_name, s->gen_name, NULL, s->type,
1994 : DEF_TYPE_TYPEDEFP | DEF_TYPE_EMIT_NAME |
1995 0 : (preserve_type(s->name) ? DEF_TYPE_PRESERVE : 0));
1996 6194 : } else if (s->type->type == TType) {
1997 : /* This is a type alias and we've already declared it */
1998 5681 : } else if (s->type->type == TTag &&
1999 5168 : s->type->subtype != NULL &&
2000 5168 : s->type->subtype->symbol != NULL) {
2001 : /* This is a type alias and we've already declared it */
2002 : } else {
2003 5853 : define_type(0, s->gen_name, s->gen_name, NULL, s->type,
2004 : DEF_TYPE_TYPEDEFP |
2005 5567 : (preserve_type(s->name) ? DEF_TYPE_PRESERVE : 0));
2006 : }
2007 6194 : fprintf(headerfile, "\n");
2008 :
2009 6194 : emitted_definition(s);
2010 : }
2011 :
2012 : void
2013 7771 : generate_type_header_forwards(const Symbol *s)
2014 : {
2015 7771 : declare_type(s, s->type, TRUE);
2016 7771 : fprintf(headerfile, "\n");
2017 7771 : if (template_flag)
2018 6859 : generate_template_type_forward(s->gen_name);
2019 7771 : }
2020 :
2021 : void
2022 7771 : generate_type (const Symbol *s)
2023 : {
2024 409 : FILE *h;
2025 409 : const char * exp;
2026 :
2027 7771 : if (!one_code_file)
2028 0 : generate_header_of_codefile(s->gen_name);
2029 :
2030 7771 : generate_type_header(s);
2031 :
2032 7771 : if (template_flag)
2033 6859 : generate_template(s);
2034 :
2035 7771 : if (template_flag == 0 || is_template_compat(s) == 0) {
2036 912 : generate_type_encode (s);
2037 912 : generate_type_decode (s);
2038 912 : generate_type_free (s);
2039 912 : generate_type_length (s);
2040 912 : generate_type_copy (s);
2041 912 : generate_type_print_stub(s);
2042 : }
2043 7771 : generate_type_seq (s);
2044 7771 : generate_glue (s->type, s->gen_name);
2045 :
2046 : /* generate prototypes */
2047 :
2048 7771 : if (is_export(s->name)) {
2049 7296 : h = headerfile;
2050 7296 : exp = "ASN1EXP ";
2051 : } else {
2052 475 : h = privheaderfile;
2053 475 : exp = "";
2054 : }
2055 :
2056 8180 : fprintf (h,
2057 : "%sint ASN1CALL "
2058 : "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
2059 : exp,
2060 7771 : s->gen_name, s->gen_name);
2061 8180 : fprintf (h,
2062 : "%sint ASN1CALL "
2063 : "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n",
2064 : exp,
2065 7771 : s->gen_name, s->gen_name);
2066 8180 : fprintf (h,
2067 : "%ssize_t ASN1CALL length_%s(const %s *);\n",
2068 : exp,
2069 7771 : s->gen_name, s->gen_name);
2070 8180 : fprintf (h,
2071 : "%sint ASN1CALL copy_%s (const %s *, %s *);\n",
2072 : exp,
2073 7771 : s->gen_name, s->gen_name, s->gen_name);
2074 8180 : fprintf (h,
2075 : "%svoid ASN1CALL free_%s (%s *);\n",
2076 : exp,
2077 7771 : s->gen_name, s->gen_name);
2078 :
2079 8180 : fprintf(h,
2080 : "%schar * ASN1CALL print_%s (const %s *, int);\n",
2081 : exp,
2082 7771 : s->gen_name, s->gen_name);
2083 :
2084 7771 : fprintf(h, "\n\n");
2085 :
2086 7771 : if (!one_code_file) {
2087 0 : fprintf(codefile, "\n\n");
2088 0 : close_codefile();
2089 : }
2090 7771 : }
|