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