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 5572 : length_tag(unsigned int tag)
55 : {
56 5572 : size_t len = 0;
57 :
58 5572 : if(tag <= 30)
59 5516 : return 1;
60 196 : while(tag) {
61 84 : tag /= 128;
62 84 : len++;
63 : }
64 56 : 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 322 : add_import (const char *module)
80 : {
81 322 : struct import *tmp = emalloc (sizeof(*tmp));
82 :
83 322 : tmp->module = module;
84 322 : tmp->next = imports;
85 322 : imports = tmp;
86 :
87 322 : fprintf (headerfile, "#include <%s_asn1.h>\n", module);
88 322 : fprintf(jsonfile, "{\"imports\":\"%s\"}\n", module);
89 322 : }
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 1232 : add_export (const char *name)
107 : {
108 1232 : struct sexport *tmp = emalloc (sizeof(*tmp));
109 :
110 1232 : tmp->name = name;
111 1232 : tmp->next = exports;
112 1232 : exports = tmp;
113 1232 : }
114 :
115 : int
116 29022 : is_export(const char *name)
117 : {
118 : struct sexport *tmp;
119 :
120 29022 : if (exports == NULL) /* no export list, all exported */
121 22288 : return 1;
122 :
123 370678 : for (tmp = exports; tmp != NULL; tmp = tmp->next) {
124 369068 : if (strcmp(tmp->name, name) == 0) {
125 5124 : tmp->defined = 1;
126 5124 : return 1;
127 : }
128 : }
129 1610 : return 0;
130 : }
131 :
132 : const char *
133 0 : get_filename (void)
134 : {
135 0 : return orig_filename;
136 : }
137 :
138 : void
139 224 : init_generate (const char *filename, const char *base)
140 : {
141 224 : char *fn = NULL;
142 :
143 224 : orig_filename = filename;
144 224 : if (base != NULL) {
145 224 : headerbase = strdup(base);
146 224 : if (headerbase == NULL)
147 0 : errx(1, "strdup");
148 : }
149 :
150 : /* JSON file */
151 224 : if (asprintf(&fn, "%s.json", headerbase) < 0 || fn == NULL)
152 0 : errx(1, "malloc");
153 224 : jsonfile = fopen(fn, "w");
154 224 : if (jsonfile == NULL)
155 0 : err(1, "open %s", fn);
156 224 : free(fn);
157 224 : fn = NULL;
158 :
159 : /* public header file */
160 224 : if (asprintf(&header, "%s.h", headerbase) < 0 || header == NULL)
161 0 : errx(1, "malloc");
162 224 : if (asprintf(&fn, "%s.h", headerbase) < 0 || fn == NULL)
163 0 : errx(1, "malloc");
164 224 : headerfile = fopen (fn, "w");
165 224 : if (headerfile == NULL)
166 0 : err (1, "open %s", fn);
167 224 : free(fn);
168 224 : fn = NULL;
169 :
170 : /* private header file */
171 224 : if (asprintf(&privheader, "%s-priv.h", headerbase) < 0 || privheader == NULL)
172 0 : errx(1, "malloc");
173 224 : if (asprintf(&fn, "%s-priv.h", headerbase) < 0 || fn == NULL)
174 0 : errx(1, "malloc");
175 224 : privheaderfile = fopen (fn, "w");
176 224 : if (privheaderfile == NULL)
177 0 : err (1, "open %s", fn);
178 224 : free(fn);
179 224 : fn = NULL;
180 :
181 : /* template file */
182 224 : if (asprintf(&template, "%s-template.c", headerbase) < 0 || template == NULL)
183 0 : errx(1, "malloc");
184 224 : fprintf (headerfile,
185 : "/* Generated from %s */\n"
186 : "/* Do not edit */\n\n",
187 : filename);
188 224 : fprintf (headerfile,
189 : "#ifndef __%s_h__\n"
190 : "#define __%s_h__\n\n", headerbase, headerbase);
191 224 : fprintf (headerfile,
192 : "#include <stddef.h>\n"
193 : "#include <stdint.h>\n"
194 : "#include <time.h>\n\n");
195 224 : fprintf (headerfile,
196 : "#ifndef __asn1_common_definitions__\n"
197 : "#define __asn1_common_definitions__\n\n");
198 224 : 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 224 : 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 224 : fprintf (headerfile,
214 : "typedef char *heim_general_string;\n\n"
215 : );
216 224 : fprintf (headerfile,
217 : "typedef char *heim_utf8_string;\n\n"
218 : );
219 224 : fprintf (headerfile,
220 : "typedef struct heim_base_data heim_printable_string;\n\n"
221 : );
222 224 : fprintf (headerfile,
223 : "typedef struct heim_base_data heim_ia5_string;\n\n"
224 : );
225 224 : 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 224 : 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 224 : fprintf (headerfile,
236 : "typedef char *heim_visible_string;\n\n"
237 : );
238 224 : fprintf (headerfile,
239 : "typedef struct heim_oid {\n"
240 : " size_t length;\n"
241 : " unsigned *components;\n"
242 : "} heim_oid;\n\n");
243 224 : 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 224 : 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 224 : fprintf (headerfile,
255 : "enum asn1_print_flags {\n"
256 : " ASN1_PRINT_INDENT = 1,\n"
257 : "};\n\n");
258 224 : 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 224 : 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 224 : fputs("#ifndef ENOTSUP\n"
289 : "/* Very old MSVC CRTs lack ENOTSUP */\n"
290 : "#define ENOTSUP EINVAL\n"
291 : "#endif\n",
292 : headerfile);
293 224 : fprintf (headerfile, "struct units;\n\n");
294 224 : fprintf (headerfile, "#endif\n\n");
295 224 : if (asprintf(&fn, "%s_files", base) < 0 || fn == NULL)
296 0 : errx(1, "malloc");
297 224 : logfile = fopen(fn, "w");
298 224 : if (logfile == NULL)
299 0 : err (1, "open %s", fn);
300 224 : free(fn);
301 224 : fn = NULL;
302 :
303 224 : if (asprintf(&fn, "%s_oids.c", base) < 0 || fn == NULL)
304 0 : errx(1, "malloc");
305 224 : oidsfile = fopen(fn, "w");
306 224 : if (oidsfile == NULL)
307 0 : err (1, "open %s", fn);
308 224 : if (asprintf(&fn, "%s_syms.c", base) < 0 || fn == NULL)
309 0 : errx(1, "malloc");
310 224 : symsfile = fopen(fn, "w");
311 224 : if (symsfile == NULL)
312 0 : err (1, "open %s", fn);
313 224 : free(fn);
314 224 : fn = NULL;
315 :
316 : /* if one code file, write into the one codefile */
317 224 : if (one_code_file)
318 224 : 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 224 : close_generate (void)
350 : {
351 224 : fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
352 :
353 224 : if (headerfile && fclose(headerfile) == EOF)
354 0 : err(1, "writes to public header file failed");
355 224 : if (privheaderfile && fclose(privheaderfile) == EOF)
356 0 : err(1, "writes to private header file failed");
357 224 : if (templatefile && fclose(templatefile) == EOF)
358 0 : err(1, "writes to template file failed");
359 224 : if (!jsonfile) abort();
360 224 : if (fclose(jsonfile) == EOF)
361 0 : err(1, "writes to JSON file failed");
362 224 : if (!oidsfile) abort();
363 224 : if (fclose(oidsfile) == EOF)
364 0 : err(1, "writes to OIDs file failed");
365 224 : if (!symsfile) abort();
366 224 : if (fclose(symsfile) == EOF)
367 0 : err(1, "writes to symbols file failed");
368 224 : if (!logfile) abort();
369 224 : fprintf(logfile, "\n");
370 224 : if (fclose(logfile) == EOF)
371 0 : err(1, "writes to log file failed");
372 224 : }
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 224 : generate_header_of_codefile(const char *name)
420 : {
421 224 : char *filename = NULL;
422 :
423 224 : if (codefile != NULL)
424 0 : abort();
425 :
426 224 : if (asprintf (&filename, "%s_%s.c", STEM, name) < 0 || filename == NULL)
427 0 : errx(1, "malloc");
428 224 : codefile = fopen (filename, "w");
429 224 : if (codefile == NULL)
430 0 : err (1, "fopen %s", filename);
431 224 : if (logfile)
432 224 : fprintf(logfile, "%s ", filename);
433 224 : free(filename);
434 224 : filename = NULL;
435 224 : 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 224 : fprintf (codefile,
452 : "#include \"%s\"\n"
453 : "#include \"%s\"\n",
454 : header, privheader);
455 224 : fprintf (codefile,
456 : "#include <asn1_err.h>\n"
457 : "#include <der.h>\n"
458 : "#include <asn1-template.h>\n\n");
459 :
460 224 : if (parse_units_flag)
461 224 : 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 224 : }
468 :
469 : void
470 224 : close_codefile(void)
471 : {
472 224 : if (codefile == NULL)
473 0 : abort();
474 :
475 224 : if (fclose(codefile) == EOF)
476 0 : err(1, "writes to source code file failed");
477 224 : codefile = NULL;
478 224 : }
479 :
480 : /* Object identifiers are parsed backwards; this reverses that */
481 : struct objid **
482 3626 : objid2list(struct objid *o)
483 : {
484 : struct objid *el, **list;
485 : size_t i, len;
486 :
487 27482 : for (el = o, len = 0; el; el = el->next)
488 23856 : len++;
489 3626 : if (len == 0)
490 210 : return NULL;
491 3416 : list = ecalloc(len + 1, sizeof(*list));
492 :
493 27272 : for (i = 0; o; o = o->next)
494 23856 : list[i++] = o;
495 3416 : list[i] = NULL;
496 :
497 : /* Reverse the list */
498 14350 : for (i = 0; i < (len>>1); i++) {
499 10934 : el = list[i];
500 10934 : list[i] = list[len - (i + 1)];
501 10934 : list[len - (i + 1)] = el;
502 : }
503 3416 : return list;
504 : }
505 :
506 : void
507 4074 : generate_constant (const Symbol *s)
508 : {
509 4074 : switch(s->value->type) {
510 0 : case booleanvalue:
511 0 : break;
512 672 : 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 672 : 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 672 : (long long)s->value->u.integervalue);
525 672 : if (is_export(s->name))
526 644 : fprintf(symsfile, "ASN1_SYM_INTVAL(\"%s\", \"%s\", %s, %lld)\n",
527 : s->name, s->gen_name, s->gen_name,
528 644 : (long long)s->value->u.integervalue);
529 672 : fprintf(jsonfile,
530 : "{\"name\":\"%s\",\"gen_name\":\"%s\",\"type\":\"INTEGER\","
531 : "\"constant\":true,\"exported\":%s,\"value\":%lld}\n",
532 672 : s->name, s->gen_name, is_export(s->name) ? "true" : "false",
533 672 : (long long)s->value->u.integervalue);
534 672 : break;
535 0 : case nullvalue:
536 0 : break;
537 0 : case stringvalue:
538 0 : break;
539 3402 : case objectidentifiervalue: {
540 : struct objid *o, **list;
541 : size_t i, len;
542 : char *gen_upper;
543 :
544 3402 : if (!one_code_file)
545 0 : generate_header_of_codefile(s->gen_name);
546 :
547 3402 : list = objid2list(s->value->u.objectidentifiervalue);
548 3402 : for (len = 0; list && list[len]; len++)
549 : ;
550 3402 : if (len == 0) {
551 0 : errx(1, "Empty OBJECT IDENTIFIER named %s\n", s->name);
552 : break;
553 : }
554 :
555 3402 : fprintf(jsonfile,
556 : "{\"name\":\"%s\",\"gen_name\":\"%s\","
557 : "\"type\":\"OBJECT IDENTIFIER\","
558 : "\"constant\":true,\"exported\":%s,\"value\":[\n",
559 3402 : s->name, s->gen_name, is_export(s->name) ? "true" : "false");
560 3402 : fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name);
561 27132 : for (i = 0; i < len; i++) {
562 23730 : o = list[i];
563 47460 : fprintf(headerfile, "%s(%d) ",
564 23730 : o->label ? o->label : "label-less", o->value);
565 23730 : if (o->label == NULL)
566 7280 : fprintf(jsonfile, "%s{\"label\":null,\"value\":%d}",
567 : i ? "," : "", o->value);
568 : else
569 16450 : fprintf(jsonfile, "%s{\"label\":\"%s\",\"value\":%d}",
570 : i ? "," : "", o->label, o->value);
571 : }
572 3402 : fprintf(jsonfile, "]}\n");
573 :
574 3402 : fprintf (codefile, "static unsigned oid_%s_variable_num[%lu] = {",
575 : s->gen_name, (unsigned long)len);
576 27132 : for (i = 0; list[i]; i++) {
577 23730 : fprintf(codefile, "%s %d", i ? "," : "", list[i]->value);
578 : }
579 3402 : fprintf(codefile, "};\n");
580 :
581 3402 : 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);
584 :
585 3402 : fprintf(oidsfile, "DEFINE_OID_WITH_NAME(%s)\n", s->gen_name);
586 3402 : if (is_export(s->name))
587 3402 : fprintf(symsfile, "ASN1_SYM_OID(\"%s\", \"%s\", %s)\n",
588 : s->name, s->gen_name, s->gen_name);
589 :
590 3402 : free(list);
591 :
592 : /* header file */
593 :
594 3402 : gen_upper = strdup(s->gen_name);
595 3402 : len = strlen(gen_upper);
596 71582 : for (i = 0; i < len; i++)
597 68180 : gen_upper[i] = toupper((int)s->gen_name[i]);
598 :
599 3402 : fprintf (headerfile, "} */\n");
600 3402 : 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);
606 :
607 3402 : free(gen_upper);
608 :
609 3402 : if (!one_code_file)
610 0 : close_codefile();
611 :
612 3402 : break;
613 : }
614 0 : default:
615 0 : abort();
616 : }
617 4074 : }
618 :
619 : int
620 42 : 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 84 : 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 42 : if (t->type == TTag && t->tag.tagenv == TE_EXPLICIT)
642 42 : 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 15862 : 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 33362 : while (t->type == TType &&
668 3276 : t->symbol &&
669 1638 : t->symbol->type) {
670 1162 : if (t->symbol->type->type == TType)
671 0 : t = t->symbol->type; /* Alias */
672 2254 : else if (t->symbol->type->type == TTag &&
673 1092 : 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 15862 : if (t->type == TTag && t->tag.tagclass != ASN1_C_UNIV &&
688 0 : t->tag.tagenv == TE_EXPLICIT)
689 0 : return 0;
690 15862 : if (t->symbol && t->symbol->type) {
691 : /* EXPLICIT non-UNIVERSAL tags are constructed */
692 3374 : if (t->symbol->type->type == TTag &&
693 1666 : t->symbol->type->tag.tagclass != ASN1_C_UNIV &&
694 14 : t->symbol->type->tag.tagenv == TE_EXPLICIT)
695 14 : return 0;
696 : /* EXPLICIT UNIVERSAL tags are constructed if they are SEQUENCE/SET */
697 3346 : if (t->symbol->type->type == TTag &&
698 1638 : t->symbol->type->tag.tagclass == ASN1_C_UNIV) {
699 1638 : switch (t->symbol->type->tag.tagvalue) {
700 700 : case UT_Sequence: return 0;
701 112 : case UT_Set: return 0;
702 826 : default: return 1;
703 : }
704 : }
705 : }
706 14210 : switch(t->type) {
707 7308 : 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 7308 : return 1;
725 560 : case TTag:
726 560 : return is_primitive_type(t->subtype);
727 6342 : default:
728 6342 : return 0;
729 : }
730 : }
731 :
732 : static void
733 98294 : space(int level)
734 : {
735 283486 : while(level-- > 0)
736 86898 : fprintf(headerfile, " ");
737 98294 : }
738 :
739 : static const char *
740 70518 : last_member_p(struct member *m)
741 : {
742 70518 : struct member *n = HEIM_TAILQ_NEXT(m, members);
743 70518 : if (n == NULL)
744 11438 : return "";
745 59080 : if (n->ellipsis && HEIM_TAILQ_NEXT(n, members) == NULL)
746 1218 : return "";
747 57862 : return ",";
748 : }
749 :
750 : static struct member *
751 3500 : have_ellipsis(Type *t)
752 : {
753 : struct member *m;
754 15652 : HEIM_TAILQ_FOREACH(m, t->members, members) {
755 12670 : if (m->ellipsis)
756 518 : return m;
757 : }
758 2982 : return NULL;
759 : }
760 :
761 : static void
762 64148 : define_asn1 (int level, Type *t)
763 : {
764 64148 : switch (t->type) {
765 12558 : case TType:
766 12558 : if (!t->symbol && t->typeref.iosclass) {
767 0 : fprintf(headerfile, "%s.&%s",
768 0 : t->typeref.iosclass->symbol->name,
769 0 : t->typeref.field->name);
770 12558 : } else if (t->symbol)
771 12558 : fprintf(headerfile, "%s", t->symbol->name);
772 : else
773 0 : abort();
774 12558 : break;
775 3486 : case TInteger:
776 3486 : if(t->members == NULL) {
777 2184 : fprintf (headerfile, "INTEGER");
778 2184 : if (t->range)
779 1568 : fprintf (headerfile, " (%lld..%lld)",
780 1568 : (long long)t->range->min,
781 1568 : (long long)t->range->max);
782 : } else {
783 : Member *m;
784 1302 : fprintf (headerfile, "INTEGER {\n");
785 23884 : HEIM_TAILQ_FOREACH(m, t->members, members) {
786 22582 : space (level + 1);
787 45164 : fprintf(headerfile, "%s(%lld)%s\n", m->gen_name,
788 22582 : (long long)m->val, last_member_p(m));
789 : }
790 1302 : space(level);
791 1302 : fprintf (headerfile, "}");
792 : }
793 3486 : break;
794 252 : case TBoolean:
795 252 : fprintf (headerfile, "BOOLEAN");
796 252 : break;
797 2702 : case TOctetString:
798 2702 : fprintf (headerfile, "OCTET STRING");
799 2702 : break;
800 924 : case TEnumerated:
801 : case TBitString: {
802 : Member *m;
803 :
804 924 : space(level);
805 924 : if(t->type == TBitString)
806 924 : fprintf (headerfile, "BIT STRING {\n");
807 : else
808 0 : fprintf (headerfile, "ENUMERATED {\n");
809 6342 : HEIM_TAILQ_FOREACH(m, t->members, members) {
810 5418 : space(level + 1);
811 10836 : fprintf(headerfile, "%s(%lld)%s\n", m->name,
812 5418 : (long long)m->val, last_member_p(m));
813 : }
814 924 : space(level);
815 924 : fprintf (headerfile, "}");
816 924 : break;
817 : }
818 5390 : case TChoice:
819 : case TSet:
820 : case TSequence: {
821 : Member *m;
822 5390 : size_t max_width = 0;
823 :
824 5390 : if(t->type == TChoice)
825 588 : fprintf(headerfile, "CHOICE {\n");
826 4802 : else if(t->type == TSet)
827 0 : fprintf(headerfile, "SET {\n");
828 : else
829 4802 : fprintf(headerfile, "SEQUENCE {\n");
830 24584 : HEIM_TAILQ_FOREACH(m, t->members, members) {
831 19194 : if(strlen(m->name) > max_width)
832 10738 : max_width = strlen(m->name);
833 : }
834 5390 : max_width += 3;
835 5390 : if(max_width < 16) max_width = 16;
836 24584 : HEIM_TAILQ_FOREACH(m, t->members, members) {
837 19194 : size_t width = max_width;
838 19194 : space(level + 1);
839 19194 : if (m->ellipsis) {
840 672 : fprintf (headerfile, "...");
841 : } else {
842 18522 : width -= fprintf(headerfile, "%s", m->name);
843 18522 : fprintf(headerfile, "%*s", (int)width, "");
844 18522 : define_asn1(level + 1, m->type);
845 18522 : if(m->optional)
846 5432 : fprintf(headerfile, " OPTIONAL");
847 : }
848 19194 : if(last_member_p(m))
849 19194 : fprintf (headerfile, ",");
850 19194 : fprintf (headerfile, "\n");
851 : }
852 5390 : space(level);
853 5390 : fprintf (headerfile, "}");
854 5390 : break;
855 : }
856 1918 : case TSequenceOf:
857 1918 : fprintf (headerfile, "SEQUENCE OF ");
858 1918 : define_asn1 (0, t->subtype);
859 1918 : break;
860 252 : case TSetOf:
861 252 : fprintf (headerfile, "SET OF ");
862 252 : define_asn1 (0, t->subtype);
863 252 : break;
864 644 : case TGeneralizedTime:
865 644 : fprintf (headerfile, "GeneralizedTime");
866 644 : break;
867 1036 : case TGeneralString:
868 1036 : fprintf (headerfile, "GeneralString");
869 1036 : break;
870 98 : case TTeletexString:
871 98 : fprintf (headerfile, "TeletexString");
872 98 : break;
873 32452 : case TTag: {
874 32452 : const char *classnames[] = { "UNIVERSAL ", "APPLICATION ",
875 : "" /* CONTEXT */, "PRIVATE " };
876 32452 : if(t->tag.tagclass != ASN1_C_UNIV)
877 27916 : fprintf (headerfile, "[%s%d] ",
878 13958 : classnames[t->tag.tagclass],
879 : t->tag.tagvalue);
880 32452 : if(t->tag.tagenv == TE_IMPLICIT)
881 1260 : fprintf (headerfile, "IMPLICIT ");
882 32452 : define_asn1 (level, t->subtype);
883 32452 : break;
884 : }
885 14 : case TUTCTime:
886 14 : fprintf (headerfile, "UTCTime");
887 14 : break;
888 1204 : case TUTF8String:
889 1204 : space(level);
890 1204 : fprintf (headerfile, "UTF8String");
891 1204 : break;
892 112 : case TPrintableString:
893 112 : space(level);
894 112 : fprintf (headerfile, "PrintableString");
895 112 : break;
896 238 : case TIA5String:
897 238 : space(level);
898 238 : fprintf (headerfile, "IA5String");
899 238 : break;
900 126 : case TBMPString:
901 126 : space(level);
902 126 : fprintf (headerfile, "BMPString");
903 126 : break;
904 98 : case TUniversalString:
905 98 : space(level);
906 98 : fprintf (headerfile, "UniversalString");
907 98 : break;
908 28 : case TVisibleString:
909 28 : space(level);
910 28 : fprintf (headerfile, "VisibleString");
911 28 : break;
912 546 : case TOID :
913 546 : space(level);
914 546 : fprintf(headerfile, "OBJECT IDENTIFIER");
915 546 : break;
916 70 : case TNull:
917 70 : space(level);
918 70 : fprintf (headerfile, "NULL");
919 70 : break;
920 0 : default:
921 0 : abort ();
922 : }
923 64148 : }
924 :
925 : static void
926 9044 : getnewbasename(char **newbasename, int typedefp, const char *basename, const char *name)
927 : {
928 9044 : if (typedefp)
929 8358 : *newbasename = strdup(name);
930 : else {
931 686 : if (name[0] == '*')
932 448 : name++;
933 686 : if (asprintf(newbasename, "%s_%s", basename, name) < 0)
934 0 : errx(1, "malloc");
935 : }
936 9044 : if (*newbasename == NULL)
937 0 : err(1, "malloc");
938 9044 : }
939 :
940 : static void define_type(int, const char *, const char *, Type *, Type *, int, int);
941 :
942 : /*
943 : * Get the SET/SEQUENCE member pair and CLASS field pair defining an open type.
944 : *
945 : * There are three cases:
946 : *
947 : * - open types embedded in OCTET STRING, with the open type object class
948 : * relation declared via a constraint
949 : *
950 : * - open types not embedded in OCTET STRING, which are really more like ANY
951 : * DEFINED BY types, so, HEIM_ANY
952 : *
953 : * - open types in a nested structure member where the type ID field is in a
954 : * member of the ancestor structure (this happens in PKIX's `AttributeSet',
955 : * where the open type is essentially a SET OF HEIM_ANY).
956 : *
957 : * In a type like PKIX's SingleAttribute the type ID member would be the one
958 : * named "type" and the open type member would be the one named "value", and
959 : * the corresponding fields of the ATTRIBUTE class would be named "id" and
960 : * "Type".
961 : *
962 : * NOTE: We assume a single open type member pair in any SET/SEQUENCE. In
963 : * principle there could be more pairs and we could iterate them, or
964 : * better yet, we could be given the name of an open type member and then
965 : * just find its related type ID member and fields, then our caller would
966 : * iterate the SET/SEQUENCE type's members looking for open type members
967 : * and would call this function for each one found.
968 : */
969 : void
970 168 : get_open_type_defn_fields(const Type *t,
971 : Member **typeidmember,
972 : Member **opentypemember,
973 : Field **typeidfield,
974 : Field **opentypefield,
975 : int *is_array_of)
976 : {
977 : Member *m;
978 : Field *junk1, *junk2;
979 168 : char *idmembername = NULL;
980 :
981 168 : if (!typeidfield) typeidfield = &junk1;
982 168 : if (!opentypefield) opentypefield = &junk2;
983 :
984 168 : *typeidfield = *opentypefield = NULL;
985 168 : *typeidmember = *opentypemember = NULL;
986 168 : *is_array_of = 0;
987 :
988 : /* Look for the open type member */
989 364 : HEIM_TAILQ_FOREACH(m, t->members, members) {
990 364 : Type *subtype = m->type;
991 364 : Type *sOfType = NULL;
992 :
993 1456 : while (subtype->type == TTag ||
994 728 : subtype->type == TSetOf ||
995 336 : subtype->type == TSequenceOf) {
996 364 : if (subtype->type == TTag && subtype->subtype) {
997 588 : if (subtype->subtype->type == TOctetString ||
998 280 : subtype->subtype->type == TBitString)
999 : break;
1000 280 : subtype = subtype->subtype;
1001 56 : } else if (subtype->type == TSetOf || subtype->type == TSequenceOf) {
1002 56 : sOfType = subtype;
1003 56 : if (sOfType->symbol)
1004 0 : break;
1005 56 : if (subtype->subtype)
1006 56 : subtype = subtype->subtype;
1007 : } else
1008 : break;
1009 : }
1010 : /*
1011 : * If we traversed through a non-inlined SET OF or SEQUENCE OF type,
1012 : * then this cannot be an open type field.
1013 : */
1014 364 : if (sOfType && sOfType->symbol)
1015 0 : continue;
1016 : /*
1017 : * The type of the field we're interested in has to have an information
1018 : * object constraint.
1019 : */
1020 364 : if (!subtype->constraint)
1021 196 : continue;
1022 168 : if (subtype->type != TType && subtype->type != TTag)
1023 0 : continue;
1024 : /*
1025 : * Check if it's an ANY-like member or like an OCTET STRING CONTAINING
1026 : * member. Those are the only two possibilities.
1027 : */
1028 336 : if ((subtype->type == TTag || subtype->type == TType) &&
1029 196 : subtype->subtype &&
1030 56 : subtype->constraint->ctype == CT_CONTENTS &&
1031 56 : subtype->constraint->u.content.type &&
1032 56 : subtype->constraint->u.content.type->type == TType &&
1033 56 : !subtype->constraint->u.content.type->subtype &&
1034 56 : subtype->constraint->u.content.type->constraint &&
1035 28 : subtype->constraint->u.content.type->constraint->ctype == CT_TABLE_CONSTRAINT) {
1036 : /* Type like OCTET STRING or BIT STRING CONTAINING open type */
1037 28 : if (*opentypemember)
1038 0 : errx(1, "Multiple open type members %s and %s for the same "
1039 0 : "field %s?", (*opentypemember)->name, m->name,
1040 0 : (*opentypefield)->name);
1041 28 : *opentypemember = m;
1042 28 : *opentypefield = subtype->constraint->u.content.type->typeref.field;
1043 28 : *is_array_of = sOfType != NULL;
1044 28 : idmembername = subtype->constraint->u.content.type->constraint->u.content.crel.membername;
1045 28 : break;
1046 140 : } else if (subtype->symbol && strcmp(subtype->symbol->name, "HEIM_ANY") == 0) {
1047 : /* Open type, but NOT embedded in OCTET STRING or BIT STRING */
1048 140 : if (*opentypemember)
1049 0 : errx(1, "Multiple open type members %s and %s for the same "
1050 0 : "field %s?", (*opentypemember)->name, m->name,
1051 0 : (*opentypefield)->name);
1052 140 : *opentypemember = m;
1053 140 : *opentypefield = subtype->typeref.field;
1054 140 : *is_array_of = sOfType != NULL;
1055 140 : idmembername = subtype->constraint->u.content.crel.membername;
1056 140 : break;
1057 : }
1058 : }
1059 :
1060 168 : if (!idmembername)
1061 0 : errx(1, "Missing open type id member in %s",
1062 0 : t->symbol ? t->symbol->name : "<unknown type>");
1063 : /* Look for the type ID member identified in the previous loop */
1064 168 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1065 168 : if (!m->type->subtype || strcmp(m->name, idmembername) != 0)
1066 0 : continue;
1067 336 : if (m->type->constraint &&
1068 168 : m->type->constraint->ctype == CT_TABLE_CONSTRAINT)
1069 168 : *typeidfield = m->type->typeref.field;
1070 0 : else if (m->type->subtype->constraint &&
1071 0 : m->type->subtype->constraint->ctype == CT_TABLE_CONSTRAINT)
1072 0 : *typeidfield = m->type->subtype->typeref.field;
1073 : else
1074 0 : continue;
1075 : /* This is the type ID field (because there _is_ a subtype) */
1076 168 : *typeidmember = m;
1077 168 : break;
1078 : }
1079 168 : }
1080 :
1081 : /*
1082 : * Generate CHOICE-like struct fields for open types declared via
1083 : * X.681/682/683 syntax.
1084 : *
1085 : * We could support multiple open type members in a SET/SEQUENCE, but for now
1086 : * we support only one.
1087 : */
1088 : static void
1089 84 : define_open_type(int level, const char *newbasename, const char *name, const char *basename, Type *pt, Type *t)
1090 : {
1091 : Member *opentypemember, *typeidmember;
1092 : Field *opentypefield, *typeidfield;
1093 : ObjectField *of;
1094 84 : IOSObjectSet *os = pt->actual_parameter;
1095 : IOSObject **objects;
1096 : size_t nobjs, i;
1097 : int is_array_of_open_type;
1098 :
1099 84 : get_open_type_defn_fields(pt, &typeidmember, &opentypemember,
1100 : &typeidfield, &opentypefield,
1101 : &is_array_of_open_type);
1102 168 : if (!opentypemember || !typeidmember ||
1103 168 : !opentypefield || !typeidfield)
1104 0 : errx(1, "Open type specification in %s is incomplete", name);
1105 :
1106 84 : sort_object_set(os, typeidfield, &objects, &nobjs);
1107 :
1108 84 : fprintf(headerfile, "struct {\n");
1109 84 : fprintf(jsonfile, "{\"opentype\":true,\"arraytype\":%s,",
1110 84 : is_array_of_open_type ? "true" : "false");
1111 84 : fprintf(jsonfile, "\"classname\":\"%s\",", os->iosclass->symbol->name);
1112 84 : fprintf(jsonfile, "\"objectsetname\":\"%s\",", os->symbol->name);
1113 84 : fprintf(jsonfile, "\"typeidmember\":\"%s\",", typeidmember->name);
1114 84 : fprintf(jsonfile, "\"opentypemember\":\"%s\",", opentypemember->name);
1115 84 : fprintf(jsonfile, "\"typeidfield\":\"%s\",", typeidfield->name);
1116 84 : fprintf(jsonfile, "\"opentypefield\":\"%s\",", opentypefield->name);
1117 :
1118 : /* Iterate objects in the object set, gen enum labels */
1119 84 : fprintf(headerfile, "enum { choice_%s_iosnumunknown = 0,\n",
1120 : newbasename);
1121 1106 : for (i = 0; i < nobjs; i++) {
1122 3346 : HEIM_TAILQ_FOREACH(of, objects[i]->objfields, objfields) {
1123 2324 : if (strcmp(of->name, typeidfield->name) != 0)
1124 1302 : continue;
1125 1022 : if (!of->value || !of->value->s)
1126 0 : errx(1, "Unknown value in value field %s of object %s",
1127 0 : of->name, objects[i]->symbol->name);
1128 1022 : fprintf(headerfile, "choice_%s_iosnum_%s,\n",
1129 1022 : newbasename, of->value->s->gen_name);
1130 : }
1131 : }
1132 84 : fprintf(headerfile, "} element;\n");
1133 :
1134 84 : if (is_array_of_open_type)
1135 28 : fprintf(headerfile, "unsigned int len;\n");
1136 :
1137 : /* Iterate objects in the object set, gen union arms */
1138 84 : fprintf(headerfile, "union {\nvoid *_any;\n");
1139 84 : fprintf(jsonfile, "\"members\":[");
1140 1106 : for (i = 0; i < nobjs; i++) {
1141 3346 : HEIM_TAILQ_FOREACH(of, objects[i]->objfields, objfields) {
1142 2324 : char *n = NULL;
1143 :
1144 : /* XXX Print the type IDs into the jsonfile too pls */
1145 :
1146 2324 : if (strcmp(of->name, opentypefield->name) != 0)
1147 2604 : continue;
1148 2044 : if (!of->type || (!of->type->symbol && of->type->type != TTag) ||
1149 1022 : of->type->tag.tagclass != ASN1_C_UNIV) {
1150 0 : warnx("Ignoring unknown or unset type field %s of object %s",
1151 0 : of->name, objects[i]->symbol->name);
1152 0 : continue;
1153 : }
1154 :
1155 1022 : if (asprintf(&n, "*%s", objects[i]->symbol->gen_name) < 0 || n == NULL)
1156 0 : err(1, "malloc");
1157 1022 : define_type(level + 2, n, newbasename, NULL, of->type, FALSE, FALSE);
1158 1022 : fprintf(jsonfile, "%s", (i + 1) < nobjs ? "," : "");
1159 1022 : free(n);
1160 : }
1161 : }
1162 84 : fprintf(jsonfile, "]}\n");
1163 84 : if (is_array_of_open_type) {
1164 28 : fprintf(headerfile, "} *val;\n} _ioschoice_%s;\n", opentypemember->gen_name);
1165 : } else {
1166 56 : fprintf(headerfile, "} u;\n");
1167 56 : fprintf(headerfile, "} _ioschoice_%s;\n", opentypemember->gen_name);
1168 : }
1169 84 : free(objects);
1170 84 : }
1171 :
1172 : static const char * const tagclassnames[] = {
1173 : "UNIVERSAL", "APPLICATION", "CONTEXT", "PRIVATE"
1174 : };
1175 :
1176 : static void
1177 46438 : define_type(int level, const char *name, const char *basename, Type *pt, Type *t, int typedefp, int preservep)
1178 : {
1179 46438 : const char *label_prefix = NULL;
1180 46438 : const char *label_prefix_sep = NULL;
1181 46438 : char *newbasename = NULL;
1182 :
1183 102480 : fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
1184 : "\"is_type\":true,\"exported\":%s,\"typedef\":%s,",
1185 : basename, name,
1186 57064 : t->symbol && is_export(t->symbol->name) ? "true" : "false",
1187 : typedefp ? "true" : "false");
1188 :
1189 46438 : switch (t->type) {
1190 10038 : case TType:
1191 10038 : space(level);
1192 10038 : if (!t->symbol && t->actual_parameter) {
1193 0 : define_open_type(level, newbasename, name, basename, t, t);
1194 10038 : } else if (!t->symbol && pt->actual_parameter) {
1195 0 : define_open_type(level, newbasename, name, basename, pt, t);
1196 10038 : } else if (t->symbol) {
1197 10038 : fprintf(headerfile, "%s %s;\n", t->symbol->gen_name, name);
1198 10038 : fprintf(jsonfile, "\"ttype\":\"%s\","
1199 10038 : "\"alias\":true\n", t->symbol->gen_name);
1200 : } else
1201 0 : abort();
1202 10038 : break;
1203 8694 : case TInteger:
1204 8694 : if (t->symbol && t->symbol->emitted_definition)
1205 0 : break;
1206 :
1207 8694 : space(level);
1208 8694 : if(t->members) {
1209 : Member *m;
1210 :
1211 364 : label_prefix = prefix_enum ? name : (enum_prefix ? enum_prefix : "");
1212 364 : label_prefix_sep = prefix_enum ? "_" : "";
1213 364 : fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
1214 364 : fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"enum\","
1215 : "\"members\":[\n");
1216 4424 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1217 4060 : space (level + 1);
1218 8120 : fprintf(headerfile, "%s%s%s = %lld%s\n",
1219 : label_prefix, label_prefix_sep,
1220 4060 : m->gen_name, (long long)m->val, last_member_p(m));
1221 8120 : fprintf(jsonfile, "{\"%s%s%s\":%lld}%s\n",
1222 : label_prefix, label_prefix_sep,
1223 4060 : m->gen_name, (long long)m->val, last_member_p(m));
1224 : }
1225 364 : fprintf(headerfile, "} %s;\n", name);
1226 364 : fprintf(jsonfile, "]");
1227 8330 : } else if (t->range == NULL) {
1228 602 : fprintf(headerfile, "heim_integer %s;\n", name);
1229 602 : fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"heim_integer\"");
1230 7840 : } else if (t->range->min < 0 &&
1231 210 : (t->range->min < INT_MIN || t->range->max > INT_MAX)) {
1232 14 : fprintf(headerfile, "int64_t %s;\n", name);
1233 14 : fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"int64_t\"");
1234 7714 : } else if (t->range->min < 0) {
1235 98 : fprintf (headerfile, "int %s;\n", name);
1236 98 : fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"int\"");
1237 7616 : } else if (t->range->max > UINT_MAX) {
1238 0 : fprintf (headerfile, "uint64_t %s;\n", name);
1239 0 : fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"uint64_t\"");
1240 : } else {
1241 7616 : fprintf (headerfile, "unsigned int %s;\n", name);
1242 7616 : fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"unsigned int\"");
1243 : }
1244 8694 : break;
1245 210 : case TBoolean:
1246 210 : space(level);
1247 210 : fprintf (headerfile, "int %s;\n", name);
1248 210 : fprintf(jsonfile, "\"ttype\":\"BOOLEAN\",\"ctype\":\"unsigned int\"");
1249 210 : break;
1250 1680 : case TOctetString:
1251 1680 : space(level);
1252 1680 : fprintf (headerfile, "heim_octet_string %s;\n", name);
1253 1680 : fprintf(jsonfile, "\"ttype\":\"OCTET STRING\",\"ctype\":\"heim_octet_string\"");
1254 1680 : break;
1255 490 : case TBitString: {
1256 : Member *m;
1257 : Type i;
1258 490 : struct range range = { 0, UINT_MAX };
1259 490 : size_t max_memno = 0;
1260 : size_t bitset_size;
1261 :
1262 490 : if (t->symbol && t->symbol->emitted_definition)
1263 0 : break;
1264 490 : memset(&i, 0, sizeof(i));
1265 :
1266 : /*
1267 : * range.max implies the size of the base unsigned integer used for the
1268 : * bitfield members. If it's less than or equal to UINT_MAX, then that
1269 : * will be unsigned int, otherwise it will be uint64_t.
1270 : *
1271 : * We could just use uint64_t, yes, but for now, and in case that any
1272 : * projects were exposing the BIT STRING types' C representations in
1273 : * ABIs prior to this compiler supporting BIT STRING with larger
1274 : * members, we stick to this.
1275 : */
1276 2212 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1277 1722 : if (m->val > max_memno)
1278 1540 : max_memno = m->val;
1279 : }
1280 490 : if (max_memno > 63)
1281 0 : range.max = INT64_MAX;
1282 : else
1283 490 : range.max = 1ULL << max_memno;
1284 :
1285 490 : i.type = TInteger;
1286 490 : i.range = ⦥
1287 490 : i.members = NULL;
1288 490 : i.constraint = NULL;
1289 :
1290 490 : space(level);
1291 490 : fprintf(jsonfile, "\"ttype\":\"BIT STRING\",");
1292 490 : if(HEIM_TAILQ_EMPTY(t->members)) {
1293 308 : fprintf (headerfile, "heim_bit_string %s;\n", name);
1294 308 : fprintf(jsonfile, "\"ctype\":\"heim_bit_string\"");
1295 : } else {
1296 182 : int64_t pos = 0;
1297 182 : getnewbasename(&newbasename, typedefp || level == 0, basename, name);
1298 :
1299 182 : fprintf (headerfile, "struct %s {\n", newbasename);
1300 182 : fprintf(jsonfile, "\"ctype\":\"struct %s\",\"members\":[\n", newbasename);
1301 1904 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1302 1722 : char *n = NULL;
1303 :
1304 : /*
1305 : * pad unused bits beween declared members (hopefully this
1306 : * forces the compiler to give us an obvious layout)
1307 : */
1308 3766 : while (pos < m->val) {
1309 644 : if (asprintf (&n, "_unused%lld:1", (long long)pos) < 0 ||
1310 322 : n == NULL)
1311 0 : err(1, "malloc");
1312 322 : define_type(level + 1, n, newbasename, NULL, &i, FALSE, FALSE);
1313 322 : fprintf(jsonfile, ",");
1314 322 : free(n);
1315 322 : pos++;
1316 : }
1317 :
1318 1722 : n = NULL;
1319 1722 : if (asprintf (&n, "%s:1", m->gen_name) < 0 || n == NULL)
1320 0 : errx(1, "malloc");
1321 1722 : define_type(level + 1, n, newbasename, NULL, &i, FALSE, FALSE);
1322 1722 : fprintf(jsonfile, "%s", last_member_p(m));
1323 1722 : free (n);
1324 1722 : n = NULL;
1325 1722 : pos++;
1326 : }
1327 : /* pad unused tail (ditto) */
1328 182 : bitset_size = max_memno;
1329 182 : if (max_memno > 31)
1330 0 : bitset_size += 64 - (max_memno % 64);
1331 : else
1332 182 : bitset_size = 32;
1333 182 : if (pos < bitset_size)
1334 154 : fprintf(jsonfile, ",");
1335 4144 : while (pos < bitset_size) {
1336 3780 : char *n = NULL;
1337 7560 : if (asprintf (&n, "_unused%lld:1", (long long)pos) < 0 ||
1338 3780 : n == NULL)
1339 0 : errx(1, "malloc");
1340 3780 : define_type(level + 1, n, newbasename, NULL, &i, FALSE, FALSE);
1341 3780 : fprintf(jsonfile, "%s", (pos + 1) < bitset_size ? "," : "");
1342 3780 : free(n);
1343 3780 : pos++;
1344 : }
1345 :
1346 182 : space(level);
1347 182 : fprintf (headerfile, "} %s;\n\n", name);
1348 182 : fprintf(jsonfile, "]");
1349 : }
1350 490 : break;
1351 : }
1352 0 : case TEnumerated: {
1353 : Member *m;
1354 :
1355 0 : if (t->symbol && t->symbol->emitted_definition)
1356 0 : break;
1357 :
1358 0 : label_prefix = prefix_enum ? name : (enum_prefix ? enum_prefix : "");
1359 0 : label_prefix_sep = prefix_enum ? "_" : "";
1360 0 : space(level);
1361 0 : fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
1362 0 : fprintf(jsonfile, "\"ctype\":\"enum %s\",\"extensible\":%s,\"members\":[\n",
1363 0 : typedefp ? name : "", have_ellipsis(t) ? "true" : "false");
1364 0 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1365 0 : space(level + 1);
1366 0 : if (m->ellipsis) {
1367 0 : fprintf (headerfile, "/* ... */\n");
1368 : } else {
1369 0 : fprintf(headerfile, "%s%s%s = %lld%s\n",
1370 : label_prefix, label_prefix_sep,
1371 0 : m->gen_name, (long long)m->val, last_member_p(m));
1372 0 : fprintf(jsonfile, "{\"%s%s%s\":%lld%s}\n",
1373 : label_prefix, label_prefix_sep,
1374 0 : m->gen_name, (long long)m->val, last_member_p(m));
1375 : }
1376 : }
1377 0 : space(level);
1378 0 : fprintf (headerfile, "} %s;\n\n", name);
1379 0 : fprintf(jsonfile, "]");
1380 0 : break;
1381 : }
1382 3066 : case TSet:
1383 : case TSequence: {
1384 : Member *m;
1385 : struct decoration deco;
1386 3066 : ssize_t more_deco = -1;
1387 3066 : int decorated = 0;
1388 :
1389 3066 : getnewbasename(&newbasename, typedefp || level == 0, basename, name);
1390 :
1391 3066 : space(level);
1392 :
1393 3066 : fprintf (headerfile, "struct %s {\n", newbasename);
1394 9198 : fprintf(jsonfile, "\"ttype\":\"%s\",\"extensible\":%s,"
1395 : "\"ctype\":\"struct %s\"",
1396 3066 : t->type == TSet ? "SET" : "SEQUENCE",
1397 3066 : have_ellipsis(t) ? "true" : "false", newbasename);
1398 3066 : if (t->type == TSequence && preservep) {
1399 84 : space(level + 1);
1400 84 : fprintf(headerfile, "heim_octet_string _save;\n");
1401 84 : fprintf(jsonfile, ",\"preserve\":true");
1402 : }
1403 3066 : fprintf(jsonfile, ",\"members\":[\n");
1404 14420 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1405 11354 : if (m->ellipsis) {
1406 : ;
1407 10878 : } else if (m->optional) {
1408 4074 : char *n = NULL;
1409 :
1410 4074 : if (asprintf(&n, "*%s", m->gen_name) < 0 || n == NULL)
1411 0 : errx(1, "malloc");
1412 4074 : fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
1413 : "\"optional\":true,\"type\":", m->name, m->gen_name);
1414 4074 : define_type(level + 1, n, newbasename, t, m->type, FALSE, FALSE);
1415 4074 : fprintf(jsonfile, "}%s", last_member_p(m));
1416 4074 : free (n);
1417 : } else {
1418 6804 : fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
1419 : "\"optional\":false,\"type\":", m->name, m->gen_name);
1420 6804 : define_type(level + 1, m->gen_name, newbasename, t, m->type, FALSE, FALSE);
1421 6804 : fprintf(jsonfile, "}%s", last_member_p(m));
1422 : }
1423 : }
1424 3066 : fprintf(jsonfile, "]");
1425 3066 : if (t->actual_parameter && t->actual_parameter->objects) {
1426 84 : fprintf(jsonfile, ",\"opentype\":");
1427 84 : define_open_type(level, newbasename, name, basename, t, t);
1428 : }
1429 6174 : while (decorate_type(newbasename, &deco, &more_deco)) {
1430 42 : decorated++;
1431 42 : space(level + 1);
1432 84 : fprintf(headerfile, "%s %s%s;\n", deco.field_type,
1433 42 : deco.opt ? "*" : "", deco.field_name);
1434 42 : if (deco.first)
1435 42 : fprintf(jsonfile, ",\"decorate\":[");
1436 462 : fprintf(jsonfile, "%s{"
1437 : "\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s,"
1438 : "\"external\":%s,\"pointer\":%s,\"void_star\":%s,"
1439 : "\"struct_star\":%s,"
1440 : "\"copy_function\":\"%s\","
1441 : "\"free_function\":\"%s\",\"header_name\":%s%s%s"
1442 : "}",
1443 42 : deco.first ? "" : ",",
1444 : deco.field_type, deco.field_name,
1445 84 : deco.opt ? "true" : "false", deco.ext ? "true" : "false",
1446 84 : deco.ptr ? "true" : "false", deco.void_star ? "true" : "false",
1447 42 : deco.struct_star ? "true" : "false",
1448 42 : deco.copy_function_name ? deco.copy_function_name : "",
1449 42 : deco.free_function_name ? deco.free_function_name : "",
1450 42 : deco.header_name && deco.header_name[0] == '"' ? "" : "\"",
1451 42 : deco.header_name ? deco.header_name : "",
1452 42 : deco.header_name && deco.header_name[0] == '"' ? "" : "\""
1453 : );
1454 : }
1455 3066 : if (decorated)
1456 42 : fprintf(jsonfile, "]");
1457 3066 : space(level);
1458 3066 : fprintf (headerfile, "} %s;\n", name);
1459 3066 : free(deco.field_type);
1460 3066 : break;
1461 : }
1462 1274 : case TSetOf:
1463 : case TSequenceOf: {
1464 : Type i;
1465 1274 : struct range range = { 0, UINT_MAX };
1466 :
1467 1274 : getnewbasename(&newbasename, typedefp || level == 0, basename, name);
1468 :
1469 1274 : memset(&i, 0, sizeof(i));
1470 1274 : i.type = TInteger;
1471 1274 : i.range = ⦥
1472 :
1473 1274 : space(level);
1474 1274 : fprintf (headerfile, "struct %s {\n", newbasename);
1475 2548 : fprintf(jsonfile, "\"ttype\":\"%s\",\"ctype\":\"struct %s\",\"members\":[",
1476 1274 : t->type == TSetOf ? "SET OF" : "SEQUENCE OF", newbasename);
1477 1274 : define_type(level + 1, "len", newbasename, t, &i, FALSE, FALSE);
1478 1274 : fprintf(jsonfile, ",");
1479 1274 : define_type(level + 1, "*val", newbasename, t, t->subtype, FALSE, FALSE);
1480 1274 : space(level);
1481 1274 : fprintf (headerfile, "} %s;\n", name);
1482 1274 : fprintf(jsonfile, "]");
1483 1274 : break;
1484 : }
1485 126 : case TGeneralizedTime:
1486 126 : space(level);
1487 126 : fprintf (headerfile, "time_t %s;\n", name);
1488 126 : fprintf(jsonfile, "\"ttype\":\"GeneralizedTime\",\"ctype\":\"time_t\"");
1489 126 : break;
1490 196 : case TGeneralString:
1491 196 : space(level);
1492 196 : fprintf (headerfile, "heim_general_string %s;\n", name);
1493 196 : fprintf(jsonfile, "\"ttype\":\"GeneralString\",\"ctype\":\"heim_general_string\"");
1494 196 : break;
1495 14 : case TTeletexString:
1496 14 : space(level);
1497 14 : fprintf (headerfile, "heim_general_string %s;\n", name);
1498 14 : fprintf(jsonfile, "\"ttype\":\"TeletexString\",\"ctype\":\"heim_general_string\"");
1499 14 : break;
1500 18704 : case TTag:
1501 37408 : fprintf(jsonfile, "\"tagclass\":\"%s\",\"tagvalue\":%d,\"tagenv\":\"%s\",\n",
1502 18704 : tagclassnames[t->tag.tagclass], t->tag.tagvalue,
1503 18704 : t->tag.tagenv == TE_EXPLICIT ? "EXPLICIT" : "IMPLICIT");
1504 18704 : fprintf(jsonfile, "\"ttype\":\n");
1505 18704 : define_type(level, name, basename, t, t->subtype, typedefp, preservep);
1506 18704 : break;
1507 434 : case TChoice: {
1508 : struct decoration deco;
1509 434 : ssize_t more_deco = -1;
1510 434 : int decorated = 0;
1511 434 : int first = 1;
1512 : Member *m;
1513 :
1514 434 : getnewbasename(&newbasename, typedefp || level == 0, basename, name);
1515 :
1516 434 : space(level);
1517 434 : fprintf (headerfile, "struct %s {\n", newbasename);
1518 434 : fprintf(jsonfile, "\"ttype\":\"CHOICE\",\"ctype\":\"struct %s\"",
1519 : newbasename);
1520 434 : if (preservep) {
1521 14 : space(level + 1);
1522 14 : fprintf(headerfile, "heim_octet_string _save;\n");
1523 14 : fprintf(jsonfile, ",\"preserve\":true");
1524 : }
1525 434 : space(level + 1);
1526 434 : fprintf (headerfile, "enum %s_enum {\n", newbasename);
1527 434 : m = have_ellipsis(t);
1528 434 : if (m) {
1529 70 : space(level + 2);
1530 70 : fprintf (headerfile, "%s = 0,\n", m->label);
1531 70 : first = 0;
1532 : }
1533 434 : fprintf(jsonfile, ",\"extensible\":%s", m ? "true" : "false");
1534 1806 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1535 1372 : space(level + 2);
1536 1372 : if (m->ellipsis)
1537 70 : fprintf (headerfile, "/* ... */\n");
1538 : else
1539 1302 : fprintf (headerfile, "%s%s%s\n", m->label,
1540 : first ? " = 1" : "",
1541 : last_member_p(m));
1542 1372 : first = 0;
1543 : }
1544 434 : space(level + 1);
1545 434 : fprintf (headerfile, "} element;\n");
1546 434 : space(level + 1);
1547 434 : fprintf (headerfile, "union {\n");
1548 434 : fprintf(jsonfile, ",\"members\":[\n");
1549 1806 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1550 1372 : if (m->ellipsis) {
1551 70 : space(level + 2);
1552 70 : fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");
1553 1302 : } else if (m->optional) {
1554 0 : char *n = NULL;
1555 :
1556 0 : if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL)
1557 0 : errx(1, "malloc");
1558 0 : fprintf(jsonfile, "{\"optional\":");
1559 0 : define_type(level + 2, n, newbasename, t, m->type, FALSE, FALSE);
1560 0 : fprintf(jsonfile, "}%s", last_member_p(m));
1561 0 : free (n);
1562 : } else {
1563 1302 : define_type(level + 2, m->gen_name, newbasename, t, m->type, FALSE, FALSE);
1564 1302 : fprintf(jsonfile, "%s", last_member_p(m));
1565 : }
1566 : }
1567 434 : space(level + 1);
1568 434 : fprintf (headerfile, "} u;\n");
1569 434 : fprintf(jsonfile, "]");
1570 :
1571 868 : while (decorate_type(newbasename, &deco, &more_deco)) {
1572 0 : decorated++;
1573 0 : space(level + 1);
1574 0 : fprintf(headerfile, "%s %s%s;\n", deco.field_type,
1575 0 : deco.opt ? "*" : "", deco.field_name);
1576 0 : if (deco.first)
1577 0 : fprintf(jsonfile, ",\"decorate\":[");
1578 0 : fprintf(jsonfile, "%s{"
1579 : "\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s,"
1580 : "\"external\":%s,\"pointer\":%s,\"void_star\":%s,"
1581 : "\"struct_star\":%s,"
1582 : "\"copy_function\":\"%s\","
1583 : "\"free_function\":\"%s\",\"header_name\":%s%s%s"
1584 : "}",
1585 0 : deco.first ? "" : ",",
1586 : deco.field_type, deco.field_name,
1587 0 : deco.opt ? "true" : "false", deco.ext ? "true" : "false",
1588 0 : deco.ptr ? "true" : "false", deco.void_star ? "true" : "false",
1589 0 : deco.struct_star ? "true" : "false",
1590 0 : deco.copy_function_name ? deco.copy_function_name : "",
1591 0 : deco.free_function_name ? deco.free_function_name : "",
1592 0 : deco.header_name && deco.header_name[0] == '"' ? "" : "\"",
1593 0 : deco.header_name ? deco.header_name : "",
1594 0 : deco.header_name && deco.header_name[0] == '"' ? "" : "\""
1595 : );
1596 : }
1597 434 : if (decorated)
1598 0 : fprintf(jsonfile, "]");
1599 :
1600 434 : space(level);
1601 434 : fprintf (headerfile, "} %s;\n", name);
1602 434 : break;
1603 : }
1604 14 : case TUTCTime:
1605 14 : space(level);
1606 14 : fprintf (headerfile, "time_t %s;\n", name);
1607 14 : fprintf(jsonfile, "\"ttype\":\"UTCTime\",\"ctype\":\"time_t\"");
1608 14 : break;
1609 644 : case TUTF8String:
1610 644 : space(level);
1611 644 : fprintf (headerfile, "heim_utf8_string %s;\n", name);
1612 644 : fprintf(jsonfile, "\"ttype\":\"UTF8String\",\"ctype\":\"heim_utf8_string\"");
1613 644 : break;
1614 28 : case TPrintableString:
1615 28 : space(level);
1616 28 : fprintf (headerfile, "heim_printable_string %s;\n", name);
1617 28 : fprintf(jsonfile, "\"ttype\":\"PrintableString\",\"ctype\":\"heim_printable_string\"");
1618 28 : break;
1619 154 : case TIA5String:
1620 154 : space(level);
1621 154 : fprintf (headerfile, "heim_ia5_string %s;\n", name);
1622 154 : fprintf(jsonfile, "\"ttype\":\"IA5String\",\"ctype\":\"heim_ia5_string\"");
1623 154 : break;
1624 42 : case TBMPString:
1625 42 : space(level);
1626 42 : fprintf (headerfile, "heim_bmp_string %s;\n", name);
1627 42 : fprintf(jsonfile, "\"ttype\":\"BMPString\",\"ctype\":\"heim_bmp_string\"");
1628 42 : break;
1629 14 : case TUniversalString:
1630 14 : space(level);
1631 14 : fprintf (headerfile, "heim_universal_string %s;\n", name);
1632 14 : fprintf(jsonfile, "\"ttype\":\"UniversalString\",\"ctype\":\"heim_universal_string\"");
1633 14 : break;
1634 28 : case TVisibleString:
1635 28 : space(level);
1636 28 : fprintf (headerfile, "heim_visible_string %s;\n", name);
1637 28 : fprintf(jsonfile, "\"ttype\":\"VisibleString\",\"ctype\":\"heim_visible_string\"");
1638 28 : break;
1639 518 : case TOID :
1640 518 : space(level);
1641 518 : fprintf (headerfile, "heim_oid %s;\n", name);
1642 518 : fprintf(jsonfile, "\"ttype\":\"OBJECT IDENTIFIER\",\"ctype\":\"heim_oid\"");
1643 518 : break;
1644 70 : case TNull:
1645 70 : space(level);
1646 70 : fprintf (headerfile, "int %s;\n", name);
1647 70 : fprintf(jsonfile, "\"ttype\":\"NULL\",\"ctype\":\"int\"");
1648 70 : break;
1649 0 : default:
1650 0 : abort ();
1651 : }
1652 46438 : fprintf(jsonfile, "}\n");
1653 46438 : free(newbasename);
1654 46438 : }
1655 :
1656 : static void
1657 10892 : declare_type(const Symbol *s, Type *t, int typedefp)
1658 : {
1659 10892 : char *newbasename = NULL;
1660 :
1661 10892 : if (typedefp)
1662 5698 : fprintf(headerfile, "typedef ");
1663 :
1664 10892 : switch (t->type) {
1665 462 : case TType:
1666 462 : define_type(0, s->gen_name, s->gen_name, NULL, s->type, TRUE, TRUE);
1667 462 : if (template_flag)
1668 462 : generate_template_type_forward(s->gen_name);
1669 462 : emitted_declaration(s);
1670 462 : return;
1671 1148 : case TInteger:
1672 : case TBoolean:
1673 : case TOctetString:
1674 : case TBitString:
1675 : case TEnumerated:
1676 : case TGeneralizedTime:
1677 : case TGeneralString:
1678 : case TTeletexString:
1679 : case TUTCTime:
1680 : case TUTF8String:
1681 : case TPrintableString:
1682 : case TIA5String:
1683 : case TBMPString:
1684 : case TUniversalString:
1685 : case TVisibleString:
1686 : case TOID :
1687 : case TNull:
1688 1148 : define_type(0, s->gen_name, s->gen_name, NULL, s->type, TRUE, TRUE);
1689 1148 : if (template_flag)
1690 1050 : generate_template_type_forward(s->gen_name);
1691 1148 : emitted_declaration(s);
1692 1148 : emitted_definition(s);
1693 1148 : return;
1694 5194 : case TTag:
1695 5194 : declare_type(s, t->subtype, FALSE);
1696 5194 : emitted_declaration(s);
1697 5194 : return;
1698 4088 : default:
1699 4088 : break;
1700 : }
1701 :
1702 4088 : switch (t->type) {
1703 2898 : case TSet:
1704 : case TSequence: {
1705 : struct decoration deco;
1706 2898 : ssize_t more_deco = -1;
1707 :
1708 2898 : getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
1709 2898 : fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
1710 5838 : while (decorate_type(newbasename, &deco, &more_deco)) {
1711 42 : if (deco.header_name)
1712 0 : fprintf(headerfile, "#include %s\n", deco.header_name);
1713 42 : free(deco.field_type);
1714 : }
1715 2898 : break;
1716 : }
1717 812 : case TSetOf:
1718 : case TSequenceOf:
1719 812 : getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
1720 812 : fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
1721 812 : break;
1722 378 : case TChoice: {
1723 : struct decoration deco;
1724 378 : ssize_t more_deco = -1;
1725 :
1726 378 : getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
1727 378 : fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
1728 756 : while (decorate_type(newbasename, &deco, &more_deco)) {
1729 0 : if (deco.header_name)
1730 0 : fprintf(headerfile, "#include %s\n", deco.header_name);
1731 0 : free(deco.field_type);
1732 : }
1733 378 : break;
1734 : }
1735 0 : default:
1736 0 : abort ();
1737 : }
1738 4088 : free(newbasename);
1739 4088 : emitted_declaration(s);
1740 : }
1741 :
1742 : static void generate_subtypes_header_helper(const Member *m);
1743 : static void generate_type_header(const Symbol *);
1744 :
1745 : static void
1746 18704 : generate_subtypes_header_helper(const Member *m)
1747 : {
1748 : Member *sm;
1749 : Symbol *s;
1750 :
1751 18704 : if (m->ellipsis)
1752 672 : return;
1753 19978 : if (m->type->symbol && (s = getsym(m->type->symbol->name)) &&
1754 1946 : !s->emitted_definition) {
1755 : /* A field of some named type; recurse */
1756 462 : if (!m->optional && !m->defval)
1757 420 : generate_type_header(s);
1758 462 : return;
1759 : }
1760 17570 : if (!m->type->subtype && !m->type->members)
1761 1484 : return;
1762 32158 : if (m->type->type == TTag &&
1763 40558 : m->type->subtype && m->type->subtype->symbol &&
1764 8414 : (s = getsym(m->type->subtype->symbol->name))) {
1765 8414 : if (!m->optional && !m->defval)
1766 5558 : generate_type_header(s);
1767 8414 : return;
1768 : }
1769 7672 : if (m->type->subtype) {
1770 7658 : switch (m->type->subtype->type) {
1771 70 : case TSet:
1772 : case TSequence:
1773 : case TChoice:
1774 70 : break;
1775 7588 : default:
1776 7588 : return;
1777 : }
1778 : /* A field of some anonymous (inlined) structured type */
1779 378 : HEIM_TAILQ_FOREACH(sm, m->type->subtype->members, members) {
1780 308 : generate_subtypes_header_helper(sm);
1781 : }
1782 : }
1783 84 : if (m->type->members) {
1784 42 : HEIM_TAILQ_FOREACH(sm, m->type->members, members) {
1785 28 : generate_subtypes_header_helper(sm);
1786 : }
1787 : }
1788 : }
1789 :
1790 : static void
1791 11004 : generate_subtypes_header(const Symbol *s)
1792 : {
1793 11004 : Type *t = s->type;
1794 : Member *m;
1795 :
1796 : /*
1797 : * Recurse down structured types to make sure top-level types get
1798 : * defined before they are referenced.
1799 : *
1800 : * We'll take care to skip OPTIONAL member fields of constructed types so
1801 : * that we can have circular types like:
1802 : *
1803 : * Foo ::= SEQUENCE {
1804 : * bar Bar OPTIONAL
1805 : * }
1806 : *
1807 : * Bar ::= SEQUENCE {
1808 : * foo Foo OPTIONAL
1809 : * }
1810 : *
1811 : * not unlike XDR, which uses `*' to mean "optional", except in XDR it's
1812 : * called a "pointer". With some care we should be able to eventually
1813 : * support the silly XDR linked list example:
1814 : *
1815 : * ListOfFoo ::= SEQUENCE {
1816 : * someField SomeType,
1817 : * next ListOfFoo OPTIONAL
1818 : * }
1819 : *
1820 : * Not that anyone needs it -- just use a SEQUENCE OF and be done.
1821 : */
1822 :
1823 26838 : while (t->type == TTag && t->subtype) {
1824 10388 : switch (t->subtype->type) {
1825 4830 : case TTag:
1826 : case TSet:
1827 : case TSequence:
1828 : case TChoice:
1829 4830 : t = t->subtype;
1830 4830 : continue;
1831 5558 : default:
1832 5558 : break;
1833 : }
1834 5558 : break;
1835 : }
1836 :
1837 11004 : switch (t->type) {
1838 5558 : default: return;
1839 378 : case TType: {
1840 : Symbol *s2;
1841 378 : if (t->symbol && (s2 = getsym(t->symbol->name)) != s)
1842 378 : generate_type_header(s2);
1843 378 : return;
1844 : }
1845 5068 : case TSet:
1846 : case TSequence:
1847 : case TChoice:
1848 5068 : break;
1849 : }
1850 :
1851 23436 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1852 18368 : generate_subtypes_header_helper(m);
1853 : }
1854 : }
1855 :
1856 : static void
1857 12054 : generate_type_header (const Symbol *s)
1858 : {
1859 12054 : Type *t = s->type;
1860 :
1861 12054 : if (!s->type)
1862 1050 : return;
1863 :
1864 : /*
1865 : * Recurse down the types of member fields of `s' to make sure that
1866 : * referenced types have had their definitions emitted already if the
1867 : * member fields are not OPTIONAL/DEFAULTed.
1868 : */
1869 11004 : generate_subtypes_header(s);
1870 11004 : fprintf(headerfile, "/*\n");
1871 11004 : fprintf(headerfile, "%s ::= ", s->name);
1872 11004 : define_asn1 (0, s->type);
1873 11004 : fprintf(headerfile, "\n*/\n\n");
1874 :
1875 : /*
1876 : * Emit enums for the outermost tag of this type. These are needed for
1877 : * dealing with IMPLICIT tags so we know what to rewrite the tag to when
1878 : * decoding.
1879 : *
1880 : * See gen_encode.c and gen_decode.c for a complete explanation. Short
1881 : * version: we need to change the prototypes of the length/encode/decode
1882 : * functions to take an optional IMPLICIT tag to use instead of the type's
1883 : * outermost tag, but for now we hack it, and to do that we need to know
1884 : * the type's outermost tag outside the context of the bodies of the codec
1885 : * functions we generate for it. Using an enum means no extra space is
1886 : * needed in stripped objects.
1887 : */
1888 11004 : if (!s->emitted_tag_enums) {
1889 11648 : while (t->type == TType && s->type->symbol && s->type->symbol->type) {
1890 252 : if (t->subtype)
1891 0 : t = t->subtype;
1892 : else
1893 252 : t = s->type->symbol->type;
1894 : }
1895 :
1896 5824 : if (t->type == TType && t->symbol &&
1897 126 : strcmp(t->symbol->name, "HEIM_ANY") != 0) {
1898 : /*
1899 : * This type is ultimately an alias of an imported type, so we don't
1900 : * know its outermost tag here.
1901 : */
1902 336 : fprintf(headerfile,
1903 : "enum { asn1_tag_length_%s = asn1_tag_length_%s,\n"
1904 : " asn1_tag_class_%s = asn1_tag_class_%s,\n"
1905 : " asn1_tag_tag_%s = asn1_tag_tag_%s };\n",
1906 112 : s->gen_name, s->type->symbol->gen_name,
1907 112 : s->gen_name, s->type->symbol->gen_name,
1908 112 : s->gen_name, s->type->symbol->gen_name);
1909 112 : emitted_tag_enums(s);
1910 5586 : } else if (t->type != TType) {
1911 : /* This type's outermost tag is known here */
1912 16716 : fprintf(headerfile,
1913 : "enum { asn1_tag_length_%s = %lu,\n"
1914 : " asn1_tag_class_%s = %d,\n"
1915 : " asn1_tag_tag_%s = %d };\n",
1916 5572 : s->gen_name, (unsigned long)length_tag(s->type->tag.tagvalue),
1917 5572 : s->gen_name, s->type->tag.tagclass,
1918 5572 : s->gen_name, s->type->tag.tagvalue);
1919 5572 : emitted_tag_enums(s);
1920 : }
1921 : }
1922 :
1923 11004 : if (s->emitted_definition)
1924 6454 : return;
1925 :
1926 4550 : if (is_export(s->name))
1927 4354 : fprintf(symsfile, "ASN1_SYM_TYPE(\"%s\", \"%s\", %s)\n",
1928 : s->name, s->gen_name, s->gen_name);
1929 :
1930 4550 : fprintf(headerfile, "typedef ");
1931 4550 : define_type(0, s->gen_name, s->gen_name, NULL, s->type, TRUE,
1932 4550 : preserve_type(s->name) ? TRUE : FALSE);
1933 4550 : fprintf(headerfile, "\n");
1934 :
1935 4550 : emitted_definition(s);
1936 : }
1937 :
1938 : void
1939 5698 : generate_type_header_forwards(const Symbol *s)
1940 : {
1941 5698 : declare_type(s, s->type, TRUE);
1942 5698 : fprintf(headerfile, "\n");
1943 5698 : if (template_flag)
1944 5026 : generate_template_type_forward(s->gen_name);
1945 5698 : }
1946 :
1947 : void
1948 5698 : generate_type (const Symbol *s)
1949 : {
1950 : FILE *h;
1951 : const char * exp;
1952 :
1953 5698 : if (!one_code_file)
1954 0 : generate_header_of_codefile(s->gen_name);
1955 :
1956 5698 : generate_type_header(s);
1957 :
1958 5698 : if (template_flag)
1959 5026 : generate_template(s);
1960 :
1961 5698 : if (template_flag == 0 || is_template_compat(s) == 0) {
1962 672 : generate_type_encode (s);
1963 672 : generate_type_decode (s);
1964 672 : generate_type_free (s);
1965 672 : generate_type_length (s);
1966 672 : generate_type_copy (s);
1967 672 : generate_type_print_stub(s);
1968 : }
1969 5698 : generate_type_seq (s);
1970 5698 : generate_glue (s->type, s->gen_name);
1971 :
1972 : /* generate prototypes */
1973 :
1974 5698 : if (is_export(s->name)) {
1975 5362 : h = headerfile;
1976 5362 : exp = "ASN1EXP ";
1977 : } else {
1978 336 : h = privheaderfile;
1979 336 : exp = "";
1980 : }
1981 :
1982 5698 : fprintf (h,
1983 : "%sint ASN1CALL "
1984 : "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
1985 : exp,
1986 : s->gen_name, s->gen_name);
1987 5698 : fprintf (h,
1988 : "%sint ASN1CALL "
1989 : "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n",
1990 : exp,
1991 : s->gen_name, s->gen_name);
1992 5698 : fprintf (h,
1993 : "%ssize_t ASN1CALL length_%s(const %s *);\n",
1994 : exp,
1995 : s->gen_name, s->gen_name);
1996 5698 : fprintf (h,
1997 : "%sint ASN1CALL copy_%s (const %s *, %s *);\n",
1998 : exp,
1999 : s->gen_name, s->gen_name, s->gen_name);
2000 5698 : fprintf (h,
2001 : "%svoid ASN1CALL free_%s (%s *);\n",
2002 : exp,
2003 : s->gen_name, s->gen_name);
2004 :
2005 5698 : fprintf(h,
2006 : "%schar * ASN1CALL print_%s (const %s *, int);\n",
2007 : exp,
2008 : s->gen_name, s->gen_name);
2009 :
2010 5698 : fprintf(h, "\n\n");
2011 :
2012 5698 : if (!one_code_file) {
2013 0 : fprintf(codefile, "\n\n");
2014 0 : close_codefile();
2015 : }
2016 5698 : }
|