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