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