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 : RCSID("$Id$");
39 :
40 : FILE *privheaderfile, *headerfile, *codefile, *logfile, *templatefile;
41 :
42 : #define STEM "asn1"
43 :
44 : static const char *orig_filename;
45 : static char *privheader, *header, *template;
46 : static const char *headerbase = STEM;
47 :
48 : /*
49 : * list of all IMPORTs
50 : */
51 :
52 : struct import {
53 : const char *module;
54 : struct import *next;
55 : };
56 :
57 : static struct import *imports = NULL;
58 :
59 : void
60 : add_import (const char *module)
61 17 : {
62 17 : struct import *tmp = emalloc (sizeof(*tmp));
63 :
64 17 : tmp->module = module;
65 17 : tmp->next = imports;
66 17 : imports = tmp;
67 :
68 17 : fprintf (headerfile, "#include <%s_asn1.h>\n", module);
69 17 : }
70 :
71 : /*
72 : * List of all exported symbols
73 : */
74 :
75 : struct sexport {
76 : const char *name;
77 : int defined;
78 : struct sexport *next;
79 : };
80 :
81 : static struct sexport *exports = NULL;
82 :
83 : void
84 : add_export (const char *name)
85 70 : {
86 70 : struct sexport *tmp = emalloc (sizeof(*tmp));
87 :
88 70 : tmp->name = name;
89 70 : tmp->next = exports;
90 70 : exports = tmp;
91 70 : }
92 :
93 : int
94 : is_export(const char *name)
95 293 : {
96 : struct sexport *tmp;
97 :
98 293 : if (exports == NULL) /* no export list, all exported */
99 200 : return 1;
100 :
101 4161 : for (tmp = exports; tmp != NULL; tmp = tmp->next) {
102 4137 : if (strcmp(tmp->name, name) == 0) {
103 69 : tmp->defined = 1;
104 69 : return 1;
105 : }
106 : }
107 24 : return 0;
108 : }
109 :
110 : const char *
111 : get_filename (void)
112 0 : {
113 0 : return orig_filename;
114 : }
115 :
116 : void
117 : init_generate (const char *filename, const char *base)
118 14 : {
119 : char *fn;
120 :
121 14 : orig_filename = filename;
122 14 : if (base != NULL) {
123 14 : headerbase = strdup(base);
124 14 : if (headerbase == NULL)
125 0 : errx(1, "strdup");
126 : }
127 :
128 : /* public header file */
129 14 : asprintf(&header, "%s.h", headerbase);
130 14 : if (header == NULL)
131 0 : errx(1, "malloc");
132 14 : asprintf(&fn, "%s.hx", headerbase);
133 14 : if (fn == NULL)
134 0 : errx(1, "malloc");
135 14 : headerfile = fopen (fn, "w");
136 14 : if (headerfile == NULL)
137 0 : err (1, "open %s", fn);
138 14 : free(fn);
139 :
140 : /* private header file */
141 14 : asprintf(&privheader, "%s-priv.h", headerbase);
142 14 : if (privheader == NULL)
143 0 : errx(1, "malloc");
144 14 : asprintf(&fn, "%s-priv.hx", headerbase);
145 14 : if (fn == NULL)
146 0 : errx(1, "malloc");
147 14 : privheaderfile = fopen (fn, "w");
148 14 : if (privheaderfile == NULL)
149 0 : err (1, "open %s", fn);
150 14 : free(fn);
151 :
152 : /* template file */
153 14 : asprintf(&template, "%s-template.c", headerbase);
154 14 : if (template == NULL)
155 0 : errx(1, "malloc");
156 :
157 14 : fprintf (headerfile,
158 : "/* Generated from %s */\n"
159 : "/* Do not edit */\n\n",
160 : filename);
161 14 : fprintf (headerfile,
162 : "#ifndef __%s_h__\n"
163 : "#define __%s_h__\n\n", headerbase, headerbase);
164 14 : fprintf (headerfile,
165 : "#include <stddef.h>\n"
166 : "#include <time.h>\n\n");
167 14 : fprintf (headerfile,
168 : "#ifndef __asn1_common_definitions__\n"
169 : "#define __asn1_common_definitions__\n\n");
170 14 : fprintf (headerfile,
171 : "typedef struct heim_integer {\n"
172 : " size_t length;\n"
173 : " void *data;\n"
174 : " int negative;\n"
175 : "} heim_integer;\n\n");
176 14 : fprintf (headerfile,
177 : "typedef struct heim_octet_string {\n"
178 : " size_t length;\n"
179 : " void *data;\n"
180 : "} heim_octet_string;\n\n");
181 14 : fprintf (headerfile,
182 : "typedef char *heim_general_string;\n\n"
183 : );
184 14 : fprintf (headerfile,
185 : "typedef char *heim_utf8_string;\n\n"
186 : );
187 14 : fprintf (headerfile,
188 : "typedef char *heim_printable_string;\n\n"
189 : );
190 14 : fprintf (headerfile,
191 : "typedef char *heim_ia5_string;\n\n"
192 : );
193 14 : fprintf (headerfile,
194 : "typedef struct heim_bmp_string {\n"
195 : " size_t length;\n"
196 : " uint16_t *data;\n"
197 : "} heim_bmp_string;\n\n");
198 14 : fprintf (headerfile,
199 : "typedef struct heim_universal_string {\n"
200 : " size_t length;\n"
201 : " uint32_t *data;\n"
202 : "} heim_universal_string;\n\n");
203 14 : fprintf (headerfile,
204 : "typedef char *heim_visible_string;\n\n"
205 : );
206 14 : fprintf (headerfile,
207 : "typedef struct heim_oid {\n"
208 : " size_t length;\n"
209 : " unsigned *components;\n"
210 : "} heim_oid;\n\n");
211 14 : fprintf (headerfile,
212 : "typedef struct heim_bit_string {\n"
213 : " size_t length;\n"
214 : " void *data;\n"
215 : "} heim_bit_string;\n\n");
216 14 : fprintf (headerfile,
217 : "typedef struct heim_octet_string heim_any;\n"
218 : "typedef struct heim_octet_string heim_any_set;\n\n");
219 14 : fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \\\n"
220 : " do { \\\n"
221 : " (BL) = length_##T((S)); \\\n"
222 : " (B) = malloc((BL)); \\\n"
223 : " if((B) == NULL) { \\\n"
224 : " (R) = ENOMEM; \\\n"
225 : " } else { \\\n"
226 : " (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n"
227 : " (S), (L)); \\\n"
228 : " if((R) != 0) { \\\n"
229 : " free((B)); \\\n"
230 : " (B) = NULL; \\\n"
231 : " } \\\n"
232 : " } \\\n"
233 : " } while (0)\n\n",
234 : headerfile);
235 14 : fprintf (headerfile, "struct units;\n\n");
236 14 : fprintf (headerfile, "#endif\n\n");
237 14 : asprintf(&fn, "%s_files", base);
238 14 : if (fn == NULL)
239 0 : errx(1, "malloc");
240 14 : logfile = fopen(fn, "w");
241 14 : if (logfile == NULL)
242 0 : err (1, "open %s", fn);
243 :
244 : /* if one code file, write into the one codefile */
245 14 : if (one_code_file)
246 14 : return;
247 :
248 0 : templatefile = fopen (template, "w");
249 0 : if (templatefile == NULL)
250 0 : err (1, "open %s", template);
251 :
252 0 : fprintf (templatefile,
253 : "/* Generated from %s */\n"
254 : "/* Do not edit */\n\n"
255 : "#include <stdio.h>\n"
256 : "#include <stdlib.h>\n"
257 : "#include <time.h>\n"
258 : "#include <string.h>\n"
259 : "#include <errno.h>\n"
260 : "#include <limits.h>\n"
261 : "#include <krb5-types.h>\n",
262 : filename);
263 :
264 0 : fprintf (templatefile,
265 : "#include <%s>\n"
266 : "#include <%s>\n"
267 : "#include <der.h>\n"
268 : "#include <der-private.h>\n"
269 : "#include <asn1-template.h>\n",
270 : header, privheader);
271 :
272 :
273 : }
274 :
275 : void
276 : close_generate (void)
277 14 : {
278 14 : fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
279 :
280 14 : if (headerfile)
281 14 : fclose (headerfile);
282 14 : if (privheaderfile)
283 14 : fclose (privheaderfile);
284 14 : if (templatefile)
285 0 : fclose (templatefile);
286 14 : if (logfile)
287 14 : fprintf (logfile, "\n");
288 14 : fclose (logfile);
289 14 : }
290 :
291 : void
292 : gen_assign_defval(const char *var, struct value *val)
293 0 : {
294 0 : switch(val->type) {
295 : case stringvalue:
296 0 : fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue);
297 0 : break;
298 : case integervalue:
299 0 : fprintf(codefile, "%s = %d;\n", var, val->u.integervalue);
300 0 : break;
301 : case booleanvalue:
302 0 : if(val->u.booleanvalue)
303 0 : fprintf(codefile, "%s = TRUE;\n", var);
304 : else
305 0 : fprintf(codefile, "%s = FALSE;\n", var);
306 0 : break;
307 : default:
308 0 : abort();
309 : }
310 0 : }
311 :
312 : void
313 : gen_compare_defval(const char *var, struct value *val)
314 0 : {
315 0 : switch(val->type) {
316 : case stringvalue:
317 0 : fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue);
318 0 : break;
319 : case integervalue:
320 0 : fprintf(codefile, "if(%s != %d)\n", var, val->u.integervalue);
321 0 : break;
322 : case booleanvalue:
323 0 : if(val->u.booleanvalue)
324 0 : fprintf(codefile, "if(!%s)\n", var);
325 : else
326 0 : fprintf(codefile, "if(%s)\n", var);
327 0 : break;
328 : default:
329 0 : abort();
330 : }
331 0 : }
332 :
333 : void
334 : generate_header_of_codefile(const char *name)
335 14 : {
336 : char *filename;
337 :
338 14 : if (codefile != NULL)
339 0 : abort();
340 :
341 14 : asprintf (&filename, "%s_%s.x", STEM, name);
342 14 : if (filename == NULL)
343 0 : errx(1, "malloc");
344 14 : codefile = fopen (filename, "w");
345 14 : if (codefile == NULL)
346 0 : err (1, "fopen %s", filename);
347 14 : fprintf(logfile, "%s ", filename);
348 14 : free(filename);
349 14 : fprintf (codefile,
350 : "/* Generated from %s */\n"
351 : "/* Do not edit */\n\n"
352 : "#include <stdio.h>\n"
353 : "#include <stdlib.h>\n"
354 : "#include <time.h>\n"
355 : "#include <string.h>\n"
356 : "#include <errno.h>\n"
357 : "#include <limits.h>\n"
358 : "#include <krb5-types.h>\n",
359 : orig_filename);
360 :
361 14 : fprintf (codefile,
362 : "#include <%s>\n"
363 : "#include <%s>\n",
364 : header, privheader);
365 14 : fprintf (codefile,
366 : "#include <asn1_err.h>\n"
367 : "#include <der.h>\n"
368 : "#include <der-private.h>\n"
369 : "#include <asn1-template.h>\n"
370 : "#include <parse_units.h>\n\n");
371 :
372 14 : }
373 :
374 : void
375 : close_codefile(void)
376 14 : {
377 14 : if (codefile == NULL)
378 0 : abort();
379 :
380 14 : fclose(codefile);
381 14 : codefile = NULL;
382 14 : }
383 :
384 :
385 : void
386 : generate_constant (const Symbol *s)
387 169 : {
388 169 : switch(s->value->type) {
389 : case booleanvalue:
390 0 : break;
391 : case integervalue:
392 10 : fprintf (headerfile, "enum { %s = %d };\n\n",
393 : s->gen_name, s->value->u.integervalue);
394 10 : break;
395 : case nullvalue:
396 0 : break;
397 : case stringvalue:
398 0 : break;
399 : case objectidentifiervalue: {
400 : struct objid *o, **list;
401 : unsigned int i, len;
402 :
403 159 : if (!one_code_file)
404 0 : generate_header_of_codefile(s->gen_name);
405 :
406 159 : len = 0;
407 1216 : for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
408 1057 : len++;
409 159 : if (len == 0) {
410 0 : printf("s->gen_name: %s",s->gen_name);
411 0 : fflush(stdout);
412 0 : break;
413 : }
414 159 : list = emalloc(sizeof(*list) * len);
415 :
416 159 : i = 0;
417 1216 : for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
418 1057 : list[i++] = o;
419 :
420 159 : fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name);
421 1216 : for (i = len ; i > 0; i--) {
422 1057 : o = list[i - 1];
423 1057 : fprintf(headerfile, "%s(%d) ",
424 : o->label ? o->label : "label-less", o->value);
425 : }
426 :
427 159 : fprintf (headerfile, "} */\n");
428 159 : fprintf (headerfile,
429 : "extern const heim_oid asn1_oid_%s;\n\n",
430 : s->gen_name);
431 :
432 :
433 159 : fprintf (codefile, "static unsigned oid_%s_variable_num[%d] = {",
434 : s->gen_name, len);
435 1216 : for (i = len ; i > 0; i--) {
436 1057 : fprintf(codefile, "%d%s ", list[i - 1]->value, i > 1 ? "," : "");
437 : }
438 159 : fprintf(codefile, "};\n");
439 :
440 159 : fprintf (codefile, "const heim_oid asn1_oid_%s = "
441 : "{ %d, oid_%s_variable_num };\n\n",
442 : s->gen_name, len, s->gen_name);
443 :
444 159 : free(list);
445 :
446 159 : if (!one_code_file)
447 0 : close_codefile();
448 :
449 159 : break;
450 : }
451 : default:
452 0 : abort();
453 : }
454 169 : }
455 :
456 : int
457 : is_primitive_type(int type)
458 1051 : {
459 1051 : switch(type) {
460 : case TInteger:
461 : case TBoolean:
462 : case TOctetString:
463 : case TBitString:
464 : case TEnumerated:
465 : case TGeneralizedTime:
466 : case TGeneralString:
467 : case TTeletexString:
468 : case TOID:
469 : case TUTCTime:
470 : case TUTF8String:
471 : case TPrintableString:
472 : case TIA5String:
473 : case TBMPString:
474 : case TUniversalString:
475 : case TVisibleString:
476 : case TNull:
477 312 : return 1;
478 : default:
479 739 : return 0;
480 : }
481 : }
482 :
483 : static void
484 : space(int level)
485 3325 : {
486 9527 : while(level-- > 0)
487 2877 : fprintf(headerfile, " ");
488 3325 : }
489 :
490 : static const char *
491 : last_member_p(struct member *m)
492 1221 : {
493 1221 : struct member *n = ASN1_TAILQ_NEXT(m, members);
494 1221 : if (n == NULL)
495 245 : return "";
496 976 : if (n->ellipsis && ASN1_TAILQ_NEXT(n, members) == NULL)
497 34 : return "";
498 942 : return ",";
499 : }
500 :
501 : static struct member *
502 : have_ellipsis(Type *t)
503 20 : {
504 : struct member *m;
505 77 : ASN1_TAILQ_FOREACH(m, t->members, members) {
506 62 : if (m->ellipsis)
507 5 : return m;
508 : }
509 15 : return NULL;
510 : }
511 :
512 : static void
513 : define_asn1 (int level, Type *t)
514 2025 : {
515 2025 : switch (t->type) {
516 : case TType:
517 462 : fprintf (headerfile, "%s", t->symbol->name);
518 462 : break;
519 : case TInteger:
520 83 : if(t->members == NULL) {
521 67 : fprintf (headerfile, "INTEGER");
522 67 : if (t->range)
523 32 : fprintf (headerfile, " (%d..%d)",
524 : t->range->min, t->range->max);
525 : } else {
526 : Member *m;
527 16 : fprintf (headerfile, "INTEGER {\n");
528 209 : ASN1_TAILQ_FOREACH(m, t->members, members) {
529 193 : space (level + 1);
530 193 : fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val,
531 : last_member_p(m));
532 : }
533 16 : space(level);
534 16 : fprintf (headerfile, "}");
535 : }
536 83 : break;
537 : case TBoolean:
538 8 : fprintf (headerfile, "BOOLEAN");
539 8 : break;
540 : case TOctetString:
541 96 : fprintf (headerfile, "OCTET STRING");
542 96 : break;
543 : case TEnumerated :
544 : case TBitString: {
545 : Member *m;
546 :
547 22 : space(level);
548 22 : if(t->type == TBitString)
549 22 : fprintf (headerfile, "BIT STRING {\n");
550 : else
551 0 : fprintf (headerfile, "ENUMERATED {\n");
552 111 : ASN1_TAILQ_FOREACH(m, t->members, members) {
553 89 : space(level + 1);
554 89 : fprintf (headerfile, "%s(%d)%s\n", m->name, m->val,
555 : last_member_p(m));
556 : }
557 22 : space(level);
558 22 : fprintf (headerfile, "}");
559 22 : break;
560 : }
561 : case TChoice:
562 : case TSet:
563 : case TSequence: {
564 : Member *m;
565 188 : int max_width = 0;
566 :
567 188 : if(t->type == TChoice)
568 20 : fprintf(headerfile, "CHOICE {\n");
569 168 : else if(t->type == TSet)
570 0 : fprintf(headerfile, "SET {\n");
571 : else
572 168 : fprintf(headerfile, "SEQUENCE {\n");
573 877 : ASN1_TAILQ_FOREACH(m, t->members, members) {
574 689 : if(strlen(m->name) > max_width)
575 368 : max_width = strlen(m->name);
576 : }
577 188 : max_width += 3;
578 188 : if(max_width < 16) max_width = 16;
579 877 : ASN1_TAILQ_FOREACH(m, t->members, members) {
580 689 : int width = max_width;
581 689 : space(level + 1);
582 689 : if (m->ellipsis) {
583 31 : fprintf (headerfile, "...");
584 : } else {
585 658 : width -= fprintf(headerfile, "%s", m->name);
586 658 : fprintf(headerfile, "%*s", width, "");
587 658 : define_asn1(level + 1, m->type);
588 658 : if(m->optional)
589 228 : fprintf(headerfile, " OPTIONAL");
590 : }
591 689 : if(last_member_p(m))
592 689 : fprintf (headerfile, ",");
593 689 : fprintf (headerfile, "\n");
594 : }
595 188 : space(level);
596 188 : fprintf (headerfile, "}");
597 188 : break;
598 : }
599 : case TSequenceOf:
600 54 : fprintf (headerfile, "SEQUENCE OF ");
601 54 : define_asn1 (0, t->subtype);
602 54 : break;
603 : case TSetOf:
604 18 : fprintf (headerfile, "SET OF ");
605 18 : define_asn1 (0, t->subtype);
606 18 : break;
607 : case TGeneralizedTime:
608 6 : fprintf (headerfile, "GeneralizedTime");
609 6 : break;
610 : case TGeneralString:
611 14 : fprintf (headerfile, "GeneralString");
612 14 : break;
613 : case TTeletexString:
614 1 : fprintf (headerfile, "TeletexString");
615 1 : break;
616 : case TTag: {
617 : const char *classnames[] = { "UNIVERSAL ", "APPLICATION ",
618 1002 : "" /* CONTEXT */, "PRIVATE " };
619 1002 : if(t->tag.tagclass != ASN1_C_UNIV)
620 501 : fprintf (headerfile, "[%s%d] ",
621 : classnames[t->tag.tagclass],
622 : t->tag.tagvalue);
623 1002 : if(t->tag.tagenv == TE_IMPLICIT)
624 49 : fprintf (headerfile, "IMPLICIT ");
625 1002 : define_asn1 (level, t->subtype);
626 1002 : break;
627 : }
628 : case TUTCTime:
629 1 : fprintf (headerfile, "UTCTime");
630 1 : break;
631 : case TUTF8String:
632 39 : space(level);
633 39 : fprintf (headerfile, "UTF8String");
634 39 : break;
635 : case TPrintableString:
636 1 : space(level);
637 1 : fprintf (headerfile, "PrintableString");
638 1 : break;
639 : case TIA5String:
640 4 : space(level);
641 4 : fprintf (headerfile, "IA5String");
642 4 : break;
643 : case TBMPString:
644 2 : space(level);
645 2 : fprintf (headerfile, "BMPString");
646 2 : break;
647 : case TUniversalString:
648 1 : space(level);
649 1 : fprintf (headerfile, "UniversalString");
650 1 : break;
651 : case TVisibleString:
652 1 : space(level);
653 1 : fprintf (headerfile, "VisibleString");
654 1 : break;
655 : case TOID :
656 19 : space(level);
657 19 : fprintf(headerfile, "OBJECT IDENTIFIER");
658 19 : break;
659 : case TNull:
660 3 : space(level);
661 3 : fprintf (headerfile, "NULL");
662 3 : break;
663 : default:
664 0 : abort ();
665 : }
666 2025 : }
667 :
668 : static void
669 : getnewbasename(char **newbasename, int typedefp, const char *basename, const char *name)
670 270 : {
671 270 : if (typedefp)
672 226 : *newbasename = strdup(name);
673 : else {
674 44 : if (name[0] == '*')
675 26 : name++;
676 44 : asprintf(newbasename, "%s_%s", basename, name);
677 : }
678 270 : if (*newbasename == NULL)
679 0 : err(1, "malloc");
680 270 : }
681 :
682 : static void
683 : define_type (int level, const char *name, const char *basename, Type *t, int typedefp, int preservep)
684 2417 : {
685 2417 : char *newbasename = NULL;
686 :
687 2417 : switch (t->type) {
688 : case TType:
689 462 : space(level);
690 462 : fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name);
691 462 : break;
692 : case TInteger:
693 475 : space(level);
694 475 : if(t->members) {
695 : Member *m;
696 16 : fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
697 209 : ASN1_TAILQ_FOREACH(m, t->members, members) {
698 193 : space (level + 1);
699 193 : fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val,
700 : last_member_p(m));
701 : }
702 16 : fprintf (headerfile, "} %s;\n", name);
703 459 : } else if (t->range == NULL) {
704 35 : fprintf (headerfile, "heim_integer %s;\n", name);
705 431 : } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
706 7 : fprintf (headerfile, "int %s;\n", name);
707 442 : } else if (t->range->min == 0 && t->range->max == UINT_MAX) {
708 25 : fprintf (headerfile, "unsigned int %s;\n", name);
709 784 : } else if (t->range->min == 0 && t->range->max == INT_MAX) {
710 392 : fprintf (headerfile, "unsigned int %s;\n", name);
711 : } else
712 0 : errx(1, "%s: unsupported range %d -> %d",
713 : name, t->range->min, t->range->max);
714 475 : break;
715 : case TBoolean:
716 8 : space(level);
717 8 : fprintf (headerfile, "int %s;\n", name);
718 8 : break;
719 : case TOctetString:
720 96 : space(level);
721 96 : fprintf (headerfile, "heim_octet_string %s;\n", name);
722 96 : break;
723 : case TBitString: {
724 : Member *m;
725 : Type i;
726 22 : struct range range = { 0, INT_MAX };
727 :
728 22 : i.type = TInteger;
729 22 : i.range = ⦥
730 22 : i.members = NULL;
731 22 : i.constraint = NULL;
732 :
733 22 : space(level);
734 22 : if(ASN1_TAILQ_EMPTY(t->members))
735 12 : fprintf (headerfile, "heim_bit_string %s;\n", name);
736 : else {
737 10 : int pos = 0;
738 10 : getnewbasename(&newbasename, typedefp, basename, name);
739 :
740 10 : fprintf (headerfile, "struct %s {\n", newbasename);
741 99 : ASN1_TAILQ_FOREACH(m, t->members, members) {
742 : char *n;
743 :
744 : /* pad unused */
745 208 : while (pos < m->val) {
746 30 : asprintf (&n, "_unused%d:1", pos);
747 30 : define_type (level + 1, n, newbasename, &i, FALSE, FALSE);
748 30 : free(n);
749 30 : pos++;
750 : }
751 :
752 89 : asprintf (&n, "%s:1", m->gen_name);
753 89 : if (n == NULL)
754 0 : errx(1, "malloc");
755 89 : define_type (level + 1, n, newbasename, &i, FALSE, FALSE);
756 89 : free (n);
757 89 : pos++;
758 : }
759 : /* pad to 32 elements */
760 221 : while (pos < 32) {
761 : char *n;
762 201 : asprintf (&n, "_unused%d:1", pos);
763 201 : define_type (level + 1, n, newbasename, &i, FALSE, FALSE);
764 201 : free(n);
765 201 : pos++;
766 : }
767 :
768 10 : space(level);
769 10 : fprintf (headerfile, "} %s;\n\n", name);
770 : }
771 22 : break;
772 : }
773 : case TEnumerated: {
774 : Member *m;
775 :
776 0 : space(level);
777 0 : fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
778 0 : ASN1_TAILQ_FOREACH(m, t->members, members) {
779 0 : space(level + 1);
780 0 : if (m->ellipsis)
781 0 : fprintf (headerfile, "/* ... */\n");
782 : else
783 0 : fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val,
784 : last_member_p(m));
785 : }
786 0 : space(level);
787 0 : fprintf (headerfile, "} %s;\n\n", name);
788 0 : break;
789 : }
790 : case TSet:
791 : case TSequence: {
792 : Member *m;
793 :
794 168 : getnewbasename(&newbasename, typedefp, basename, name);
795 :
796 168 : space(level);
797 168 : fprintf (headerfile, "struct %s {\n", newbasename);
798 168 : if (t->type == TSequence && preservep) {
799 5 : space(level + 1);
800 5 : fprintf(headerfile, "heim_octet_string _save;\n");
801 : }
802 795 : ASN1_TAILQ_FOREACH(m, t->members, members) {
803 627 : if (m->ellipsis) {
804 : ;
805 601 : } else if (m->optional) {
806 : char *n;
807 :
808 228 : asprintf (&n, "*%s", m->gen_name);
809 228 : if (n == NULL)
810 0 : errx(1, "malloc");
811 228 : define_type (level + 1, n, newbasename, m->type, FALSE, FALSE);
812 228 : free (n);
813 : } else
814 373 : define_type (level + 1, m->gen_name, newbasename, m->type, FALSE, FALSE);
815 : }
816 168 : space(level);
817 168 : fprintf (headerfile, "} %s;\n", name);
818 168 : break;
819 : }
820 : case TSetOf:
821 : case TSequenceOf: {
822 : Type i;
823 72 : struct range range = { 0, INT_MAX };
824 :
825 72 : getnewbasename(&newbasename, typedefp, basename, name);
826 :
827 72 : i.type = TInteger;
828 72 : i.range = ⦥
829 72 : i.members = NULL;
830 72 : i.constraint = NULL;
831 :
832 72 : space(level);
833 72 : fprintf (headerfile, "struct %s {\n", newbasename);
834 72 : define_type (level + 1, "len", newbasename, &i, FALSE, FALSE);
835 72 : define_type (level + 1, "*val", newbasename, t->subtype, FALSE, FALSE);
836 72 : space(level);
837 72 : fprintf (headerfile, "} %s;\n", name);
838 72 : break;
839 : }
840 : case TGeneralizedTime:
841 6 : space(level);
842 6 : fprintf (headerfile, "time_t %s;\n", name);
843 6 : break;
844 : case TGeneralString:
845 14 : space(level);
846 14 : fprintf (headerfile, "heim_general_string %s;\n", name);
847 14 : break;
848 : case TTeletexString:
849 1 : space(level);
850 1 : fprintf (headerfile, "heim_general_string %s;\n", name);
851 1 : break;
852 : case TTag:
853 1002 : define_type (level, name, basename, t->subtype, typedefp, preservep);
854 1002 : break;
855 : case TChoice: {
856 20 : int first = 1;
857 : Member *m;
858 :
859 20 : getnewbasename(&newbasename, typedefp, basename, name);
860 :
861 20 : space(level);
862 20 : fprintf (headerfile, "struct %s {\n", newbasename);
863 20 : if (preservep) {
864 1 : space(level + 1);
865 1 : fprintf(headerfile, "heim_octet_string _save;\n");
866 : }
867 20 : space(level + 1);
868 20 : fprintf (headerfile, "enum {\n");
869 20 : m = have_ellipsis(t);
870 20 : if (m) {
871 5 : space(level + 2);
872 5 : fprintf (headerfile, "%s = 0,\n", m->label);
873 5 : first = 0;
874 : }
875 82 : ASN1_TAILQ_FOREACH(m, t->members, members) {
876 62 : space(level + 2);
877 62 : if (m->ellipsis)
878 5 : fprintf (headerfile, "/* ... */\n");
879 : else
880 57 : fprintf (headerfile, "%s%s%s\n", m->label,
881 : first ? " = 1" : "",
882 : last_member_p(m));
883 62 : first = 0;
884 : }
885 20 : space(level + 1);
886 20 : fprintf (headerfile, "} element;\n");
887 20 : space(level + 1);
888 20 : fprintf (headerfile, "union {\n");
889 82 : ASN1_TAILQ_FOREACH(m, t->members, members) {
890 62 : if (m->ellipsis) {
891 5 : space(level + 2);
892 5 : fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");
893 57 : } else if (m->optional) {
894 : char *n;
895 :
896 0 : asprintf (&n, "*%s", m->gen_name);
897 0 : if (n == NULL)
898 0 : errx(1, "malloc");
899 0 : define_type (level + 2, n, newbasename, m->type, FALSE, FALSE);
900 0 : free (n);
901 : } else
902 57 : define_type (level + 2, m->gen_name, newbasename, m->type, FALSE, FALSE);
903 : }
904 20 : space(level + 1);
905 20 : fprintf (headerfile, "} u;\n");
906 20 : space(level);
907 20 : fprintf (headerfile, "} %s;\n", name);
908 20 : break;
909 : }
910 : case TUTCTime:
911 1 : space(level);
912 1 : fprintf (headerfile, "time_t %s;\n", name);
913 1 : break;
914 : case TUTF8String:
915 39 : space(level);
916 39 : fprintf (headerfile, "heim_utf8_string %s;\n", name);
917 39 : break;
918 : case TPrintableString:
919 1 : space(level);
920 1 : fprintf (headerfile, "heim_printable_string %s;\n", name);
921 1 : break;
922 : case TIA5String:
923 4 : space(level);
924 4 : fprintf (headerfile, "heim_ia5_string %s;\n", name);
925 4 : break;
926 : case TBMPString:
927 2 : space(level);
928 2 : fprintf (headerfile, "heim_bmp_string %s;\n", name);
929 2 : break;
930 : case TUniversalString:
931 1 : space(level);
932 1 : fprintf (headerfile, "heim_universal_string %s;\n", name);
933 1 : break;
934 : case TVisibleString:
935 1 : space(level);
936 1 : fprintf (headerfile, "heim_visible_string %s;\n", name);
937 1 : break;
938 : case TOID :
939 19 : space(level);
940 19 : fprintf (headerfile, "heim_oid %s;\n", name);
941 19 : break;
942 : case TNull:
943 3 : space(level);
944 3 : fprintf (headerfile, "int %s;\n", name);
945 3 : break;
946 : default:
947 0 : abort ();
948 : }
949 2417 : if (newbasename)
950 270 : free(newbasename);
951 2417 : }
952 :
953 : static void
954 : generate_type_header (const Symbol *s)
955 293 : {
956 293 : int preservep = preserve_type(s->name) ? TRUE : FALSE;
957 :
958 293 : fprintf (headerfile, "/*\n");
959 293 : fprintf (headerfile, "%s ::= ", s->name);
960 293 : define_asn1 (0, s->type);
961 293 : fprintf (headerfile, "\n*/\n\n");
962 :
963 293 : fprintf (headerfile, "typedef ");
964 293 : define_type (0, s->gen_name, s->gen_name, s->type, TRUE, preservep);
965 :
966 293 : fprintf (headerfile, "\n");
967 293 : }
968 :
969 : void
970 : generate_type (const Symbol *s)
971 293 : {
972 : FILE *h;
973 :
974 293 : if (!one_code_file)
975 0 : generate_header_of_codefile(s->gen_name);
976 :
977 293 : generate_type_header (s);
978 :
979 293 : if (template_flag)
980 0 : generate_template(s);
981 :
982 293 : if (template_flag == 0 || is_template_compat(s) == 0) {
983 293 : generate_type_encode (s);
984 293 : generate_type_decode (s);
985 293 : generate_type_free (s);
986 293 : generate_type_length (s);
987 293 : generate_type_copy (s);
988 : }
989 293 : generate_type_seq (s);
990 293 : generate_glue (s->type, s->gen_name);
991 :
992 : /* generate prototypes */
993 :
994 293 : if (is_export(s->name))
995 269 : h = headerfile;
996 : else
997 24 : h = privheaderfile;
998 :
999 293 : fprintf (h,
1000 : "int "
1001 : "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
1002 : s->gen_name, s->gen_name);
1003 293 : fprintf (h,
1004 : "int "
1005 : "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n",
1006 : s->gen_name, s->gen_name);
1007 293 : fprintf (h,
1008 : "size_t length_%s(const %s *);\n",
1009 : s->gen_name, s->gen_name);
1010 293 : fprintf (h,
1011 : "int copy_%s (const %s *, %s *);\n",
1012 : s->gen_name, s->gen_name, s->gen_name);
1013 293 : fprintf (h,
1014 : "void free_%s (%s *);\n",
1015 : s->gen_name, s->gen_name);
1016 :
1017 :
1018 293 : fprintf(h, "\n\n");
1019 :
1020 293 : if (!one_code_file) {
1021 0 : fprintf(codefile, "\n\n");
1022 0 : close_codefile();
1023 : }
1024 293 : }
|