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 { 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 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 { 86 struct sexport *tmp = emalloc (sizeof(*tmp)); 87 88 tmp->name = name; 89 tmp->next = exports; 90 exports = tmp; 91 } 92 93 int 94 is_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 110 const char * 111 get_filename (void) 112 { 113 return orig_filename; 114 } 115 116 void 117 init_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 "typedef struct heim_integer {\n" 168 " size_t length;\n" 169 " void *data;\n" 170 " int negative;\n" 171 "} heim_integer;\n\n"); 172 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 fprintf (headerfile, 178 "typedef char *heim_general_string;\n\n" 179 ); 180 fprintf (headerfile, 181 "typedef char *heim_utf8_string;\n\n" 182 ); 183 fprintf (headerfile, 184 "typedef struct heim_octet_string heim_printable_string;\n\n" 185 ); 186 fprintf (headerfile, 187 "typedef struct heim_octet_string heim_ia5_string;\n\n" 188 ); 189 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 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 fprintf (headerfile, 200 "typedef char *heim_visible_string;\n\n" 201 ); 202 fprintf (headerfile, 203 "typedef struct heim_oid {\n" 204 " size_t length;\n" 205 " unsigned *components;\n" 206 "} heim_oid;\n\n"); 207 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 fprintf (headerfile, 213 "typedef struct heim_octet_string heim_any;\n" 214 "typedef struct heim_octet_string heim_any_set;\n\n"); 215 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 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 fprintf (headerfile, "struct units;\n\n"); 244 fprintf (headerfile, "#endif\n\n"); 245 if (asprintf(&fn, "%s_files", base) < 0 || fn == NULL) 246 errx(1, "malloc"); 247 logfile = fopen(fn, "w"); 248 if (logfile == NULL) 249 err (1, "open %s", fn); 250 251 /* if one code file, write into the one codefile */ 252 if (one_code_file) 253 return; 254 255 templatefile = fopen (template, "w"); 256 if (templatefile == NULL) 257 err (1, "open %s", template); 258 259 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 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 close_generate (void) 284 { 285 fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase); 286 287 if (headerfile) 288 fclose (headerfile); 289 if (privheaderfile) 290 fclose (privheaderfile); 291 if (templatefile) 292 fclose (templatefile); 293 if (logfile) 294 fprintf (logfile, "\n"); 295 fclose (logfile); 296 } 297 298 void 299 gen_assign_defval(const char *var, struct value *val) 300 { 301 switch(val->type) { 302 case stringvalue: 303 fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue); 304 break; 305 case integervalue: 306 fprintf(codefile, "%s = %d;\n", var, val->u.integervalue); 307 break; 308 case booleanvalue: 309 if(val->u.booleanvalue) 310 fprintf(codefile, "%s = TRUE;\n", var); 311 else 312 fprintf(codefile, "%s = FALSE;\n", var); 313 break; 314 default: 315 abort(); 316 } 317 } 318 319 void 320 gen_compare_defval(const char *var, struct value *val) 321 { 322 switch(val->type) { 323 case stringvalue: 324 fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue); 325 break; 326 case integervalue: 327 fprintf(codefile, "if(%s != %d)\n", var, val->u.integervalue); 328 break; 329 case booleanvalue: 330 if(val->u.booleanvalue) 331 fprintf(codefile, "if(!%s)\n", var); 332 else 333 fprintf(codefile, "if(%s)\n", var); 334 break; 335 default: 336 abort(); 337 } 338 } 339 340 void 341 generate_header_of_codefile(const char *name) 342 { 343 char *filename = NULL; 344 345 if (codefile != NULL) 346 abort(); 347 348 if (asprintf (&filename, "%s_%s.x", STEM, name) < 0 || filename == NULL) 349 errx(1, "malloc"); 350 codefile = fopen (filename, "w"); 351 if (codefile == NULL) 352 err (1, "fopen %s", filename); 353 fprintf(logfile, "%s ", filename); 354 free(filename); 355 filename = NULL; 356 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 fprintf (codefile, 370 "#include <%s>\n" 371 "#include <%s>\n", 372 header, privheader); 373 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 } 381 382 void 383 close_codefile(void) 384 { 385 if (codefile == NULL) 386 abort(); 387 388 fclose(codefile); 389 codefile = NULL; 390 } 391 392 393 void 394 generate_constant (const Symbol *s) 395 { 396 switch(s->value->type) { 397 case booleanvalue: 398 break; 399 case integervalue: 400 fprintf (headerfile, "enum { %s = %d };\n\n", 401 s->gen_name, s->value->u.integervalue); 402 break; 403 case nullvalue: 404 break; 405 case stringvalue: 406 break; 407 case objectidentifiervalue: { 408 struct objid *o, **list; 409 unsigned int i, len; 410 char *gen_upper; 411 412 if (!one_code_file) 413 generate_header_of_codefile(s->gen_name); 414 415 len = 0; 416 for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next) 417 len++; 418 if (len == 0) { 419 printf("s->gen_name: %s",s->gen_name); 420 fflush(stdout); 421 break; 422 } 423 list = emalloc(sizeof(*list) * len); 424 425 i = 0; 426 for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next) 427 list[i++] = o; 428 429 fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name); 430 for (i = len ; i > 0; i--) { 431 o = list[i - 1]; 432 fprintf(headerfile, "%s(%d) ", 433 o->label ? o->label : "label-less", o->value); 434 } 435 436 fprintf (codefile, "static unsigned oid_%s_variable_num[%d] = {", 437 s->gen_name, len); 438 for (i = len ; i > 0; i--) { 439 fprintf(codefile, "%d%s ", list[i - 1]->value, i > 1 ? "," : ""); 440 } 441 fprintf(codefile, "};\n"); 442 443 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 free(list); 448 449 /* header file */ 450 451 gen_upper = strdup(s->gen_name); 452 len = strlen(gen_upper); 453 for (i = 0; i < len; i++) 454 gen_upper[i] = toupper((int)s->gen_name[i]); 455 456 fprintf (headerfile, "} */\n"); 457 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 free(gen_upper); 465 466 if (!one_code_file) 467 close_codefile(); 468 469 break; 470 } 471 default: 472 abort(); 473 } 474 } 475 476 int 477 is_primitive_type(int type) 478 { 479 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 return 1; 498 default: 499 return 0; 500 } 501 } 502 503 static void 504 space(int level) 505 { 506 while(level-- > 0) 507 fprintf(headerfile, " "); 508 } 509 510 static const char * 511 last_member_p(struct member *m) 512 { 513 struct member *n = ASN1_TAILQ_NEXT(m, members); 514 if (n == NULL) 515 return ""; 516 if (n->ellipsis && ASN1_TAILQ_NEXT(n, members) == NULL) 517 return ""; 518 return ","; 519 } 520 521 static struct member * 522 have_ellipsis(Type *t) 523 { 524 struct member *m; 525 ASN1_TAILQ_FOREACH(m, t->members, members) { 526 if (m->ellipsis) 527 return m; 528 } 529 return NULL; 530 } 531 532 static void 533 define_asn1 (int level, Type *t) 534 { 535 switch (t->type) { 536 case TType: 537 fprintf (headerfile, "%s", t->symbol->name); 538 break; 539 case TInteger: 540 if(t->members == NULL) { 541 fprintf (headerfile, "INTEGER"); 542 if (t->range) 543 fprintf (headerfile, " (%d..%d)", 544 t->range->min, t->range->max); 545 } else { 546 Member *m; 547 fprintf (headerfile, "INTEGER {\n"); 548 ASN1_TAILQ_FOREACH(m, t->members, members) { 549 space (level + 1); 550 fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val, 551 last_member_p(m)); 552 } 553 space(level); 554 fprintf (headerfile, "}"); 555 } 556 break; 557 case TBoolean: 558 fprintf (headerfile, "BOOLEAN"); 559 break; 560 case TOctetString: 561 fprintf (headerfile, "OCTET STRING"); 562 break; 563 case TEnumerated : 564 case TBitString: { 565 Member *m; 566 567 space(level); 568 if(t->type == TBitString) 569 fprintf (headerfile, "BIT STRING {\n"); 570 else 571 fprintf (headerfile, "ENUMERATED {\n"); 572 ASN1_TAILQ_FOREACH(m, t->members, members) { 573 space(level + 1); 574 fprintf (headerfile, "%s(%d)%s\n", m->name, m->val, 575 last_member_p(m)); 576 } 577 space(level); 578 fprintf (headerfile, "}"); 579 break; 580 } 581 case TChoice: 582 case TSet: 583 case TSequence: { 584 Member *m; 585 int max_width = 0; 586 587 if(t->type == TChoice) 588 fprintf(headerfile, "CHOICE {\n"); 589 else if(t->type == TSet) 590 fprintf(headerfile, "SET {\n"); 591 else 592 fprintf(headerfile, "SEQUENCE {\n"); 593 ASN1_TAILQ_FOREACH(m, t->members, members) { 594 if(strlen(m->name) > max_width) 595 max_width = strlen(m->name); 596 } 597 max_width += 3; 598 if(max_width < 16) max_width = 16; 599 ASN1_TAILQ_FOREACH(m, t->members, members) { 600 int width = max_width; 601 space(level + 1); 602 if (m->ellipsis) { 603 fprintf (headerfile, "..."); 604 } else { 605 width -= fprintf(headerfile, "%s", m->name); 606 fprintf(headerfile, "%*s", width, ""); 607 define_asn1(level + 1, m->type); 608 if(m->optional) 609 fprintf(headerfile, " OPTIONAL"); 610 } 611 if(last_member_p(m)) 612 fprintf (headerfile, ","); 613 fprintf (headerfile, "\n"); 614 } 615 space(level); 616 fprintf (headerfile, "}"); 617 break; 618 } 619 case TSequenceOf: 620 fprintf (headerfile, "SEQUENCE OF "); 621 define_asn1 (0, t->subtype); 622 break; 623 case TSetOf: 624 fprintf (headerfile, "SET OF "); 625 define_asn1 (0, t->subtype); 626 break; 627 case TGeneralizedTime: 628 fprintf (headerfile, "GeneralizedTime"); 629 break; 630 case TGeneralString: 631 fprintf (headerfile, "GeneralString"); 632 break; 633 case TTeletexString: 634 fprintf (headerfile, "TeletexString"); 635 break; 636 case TTag: { 637 const char *classnames[] = { "UNIVERSAL ", "APPLICATION ", 638 "" /* CONTEXT */, "PRIVATE " }; 639 if(t->tag.tagclass != ASN1_C_UNIV) 640 fprintf (headerfile, "[%s%d] ", 641 classnames[t->tag.tagclass], 642 t->tag.tagvalue); 643 if(t->tag.tagenv == TE_IMPLICIT) 644 fprintf (headerfile, "IMPLICIT "); 645 define_asn1 (level, t->subtype); 646 break; 647 } 648 case TUTCTime: 649 fprintf (headerfile, "UTCTime"); 650 break; 651 case TUTF8String: 652 space(level); 653 fprintf (headerfile, "UTF8String"); 654 break; 655 case TPrintableString: 656 space(level); 657 fprintf (headerfile, "PrintableString"); 658 break; 659 case TIA5String: 660 space(level); 661 fprintf (headerfile, "IA5String"); 662 break; 663 case TBMPString: 664 space(level); 665 fprintf (headerfile, "BMPString"); 666 break; 667 case TUniversalString: 668 space(level); 669 fprintf (headerfile, "UniversalString"); 670 break; 671 case TVisibleString: 672 space(level); 673 fprintf (headerfile, "VisibleString"); 674 break; 675 case TOID : 676 space(level); 677 fprintf(headerfile, "OBJECT IDENTIFIER"); 678 break; 679 case TNull: 680 space(level); 681 fprintf (headerfile, "NULL"); 682 break; 683 default: 684 abort (); 685 } 686 } 687 688 static void 689 getnewbasename(char **newbasename, int typedefp, const char *basename, const char *name) 690 { 691 if (typedefp) 692 *newbasename = strdup(name); 693 else { 694 if (name[0] == '*') 695 name++; 696 if (asprintf(newbasename, "%s_%s", basename, name) < 0) 697 errx(1, "malloc"); 698 } 699 if (*newbasename == NULL) 700 err(1, "malloc"); 701 } 702 703 static void 704 define_type (int level, const char *name, const char *basename, Type *t, int typedefp, int preservep) 705 { 706 char *newbasename = NULL; 707 708 switch (t->type) { 709 case TType: 710 space(level); 711 fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name); 712 break; 713 case TInteger: 714 space(level); 715 if(t->members) { 716 Member *m; 717 fprintf (headerfile, "enum %s {\n", typedefp ? name : ""); 718 ASN1_TAILQ_FOREACH(m, t->members, members) { 719 space (level + 1); 720 fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val, 721 last_member_p(m)); 722 } 723 fprintf (headerfile, "} %s;\n", name); 724 } else if (t->range == NULL) { 725 fprintf (headerfile, "heim_integer %s;\n", name); 726 } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) { 727 fprintf (headerfile, "int %s;\n", name); 728 } else if (t->range->min == 0 && t->range->max == UINT_MAX) { 729 fprintf (headerfile, "unsigned int %s;\n", name); 730 } else if (t->range->min == 0 && t->range->max == INT_MAX) { 731 fprintf (headerfile, "unsigned int %s;\n", name); 732 } else 733 errx(1, "%s: unsupported range %d -> %d", 734 name, t->range->min, t->range->max); 735 break; 736 case TBoolean: 737 space(level); 738 fprintf (headerfile, "int %s;\n", name); 739 break; 740 case TOctetString: 741 space(level); 742 fprintf (headerfile, "heim_octet_string %s;\n", name); 743 break; 744 case TBitString: { 745 Member *m; 746 Type i; 747 struct range range = { 0, INT_MAX }; 748 749 i.type = TInteger; 750 i.range = ⦥ 751 i.members = NULL; 752 i.constraint = NULL; 753 754 space(level); 755 if(ASN1_TAILQ_EMPTY(t->members)) 756 fprintf (headerfile, "heim_bit_string %s;\n", name); 757 else { 758 int pos = 0; 759 getnewbasename(&newbasename, typedefp, basename, name); 760 761 fprintf (headerfile, "struct %s {\n", newbasename); 762 ASN1_TAILQ_FOREACH(m, t->members, members) { 763 char *n = NULL; 764 765 /* pad unused */ 766 while (pos < m->val) { 767 if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL) 768 errx(1, "malloc"); 769 define_type (level + 1, n, newbasename, &i, FALSE, FALSE); 770 free(n); 771 pos++; 772 } 773 774 n = NULL; 775 if (asprintf (&n, "%s:1", m->gen_name) < 0 || n == NULL) 776 errx(1, "malloc"); 777 define_type (level + 1, n, newbasename, &i, FALSE, FALSE); 778 free (n); 779 n = NULL; 780 pos++; 781 } 782 /* pad to 32 elements */ 783 while (pos < 32) { 784 char *n = NULL; 785 if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL) 786 errx(1, "malloc"); 787 define_type (level + 1, n, newbasename, &i, FALSE, FALSE); 788 free(n); 789 pos++; 790 } 791 792 space(level); 793 fprintf (headerfile, "} %s;\n\n", name); 794 } 795 break; 796 } 797 case TEnumerated: { 798 Member *m; 799 800 space(level); 801 fprintf (headerfile, "enum %s {\n", typedefp ? name : ""); 802 ASN1_TAILQ_FOREACH(m, t->members, members) { 803 space(level + 1); 804 if (m->ellipsis) 805 fprintf (headerfile, "/* ... */\n"); 806 else 807 fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val, 808 last_member_p(m)); 809 } 810 space(level); 811 fprintf (headerfile, "} %s;\n\n", name); 812 break; 813 } 814 case TSet: 815 case TSequence: { 816 Member *m; 817 818 getnewbasename(&newbasename, typedefp, basename, name); 819 820 space(level); 821 fprintf (headerfile, "struct %s {\n", newbasename); 822 if (t->type == TSequence && preservep) { 823 space(level + 1); 824 fprintf(headerfile, "heim_octet_string _save;\n"); 825 } 826 ASN1_TAILQ_FOREACH(m, t->members, members) { 827 if (m->ellipsis) { 828 ; 829 } else if (m->optional) { 830 char *n = NULL; 831 832 if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL) 833 errx(1, "malloc"); 834 define_type (level + 1, n, newbasename, m->type, FALSE, FALSE); 835 free (n); 836 } else 837 define_type (level + 1, m->gen_name, newbasename, m->type, FALSE, FALSE); 838 } 839 space(level); 840 fprintf (headerfile, "} %s;\n", name); 841 break; 842 } 843 case TSetOf: 844 case TSequenceOf: { 845 Type i; 846 struct range range = { 0, INT_MAX }; 847 848 getnewbasename(&newbasename, typedefp, basename, name); 849 850 i.type = TInteger; 851 i.range = ⦥ 852 i.members = NULL; 853 i.constraint = NULL; 854 855 space(level); 856 fprintf (headerfile, "struct %s {\n", newbasename); 857 define_type (level + 1, "len", newbasename, &i, FALSE, FALSE); 858 define_type (level + 1, "*val", newbasename, t->subtype, FALSE, FALSE); 859 space(level); 860 fprintf (headerfile, "} %s;\n", name); 861 break; 862 } 863 case TGeneralizedTime: 864 space(level); 865 fprintf (headerfile, "time_t %s;\n", name); 866 break; 867 case TGeneralString: 868 space(level); 869 fprintf (headerfile, "heim_general_string %s;\n", name); 870 break; 871 case TTeletexString: 872 space(level); 873 fprintf (headerfile, "heim_general_string %s;\n", name); 874 break; 875 case TTag: 876 define_type (level, name, basename, t->subtype, typedefp, preservep); 877 break; 878 case TChoice: { 879 int first = 1; 880 Member *m; 881 882 getnewbasename(&newbasename, typedefp, basename, name); 883 884 space(level); 885 fprintf (headerfile, "struct %s {\n", newbasename); 886 if (preservep) { 887 space(level + 1); 888 fprintf(headerfile, "heim_octet_string _save;\n"); 889 } 890 space(level + 1); 891 fprintf (headerfile, "enum {\n"); 892 m = have_ellipsis(t); 893 if (m) { 894 space(level + 2); 895 fprintf (headerfile, "%s = 0,\n", m->label); 896 first = 0; 897 } 898 ASN1_TAILQ_FOREACH(m, t->members, members) { 899 space(level + 2); 900 if (m->ellipsis) 901 fprintf (headerfile, "/* ... */\n"); 902 else 903 fprintf (headerfile, "%s%s%s\n", m->label, 904 first ? " = 1" : "", 905 last_member_p(m)); 906 first = 0; 907 } 908 space(level + 1); 909 fprintf (headerfile, "} element;\n"); 910 space(level + 1); 911 fprintf (headerfile, "union {\n"); 912 ASN1_TAILQ_FOREACH(m, t->members, members) { 913 if (m->ellipsis) { 914 space(level + 2); 915 fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n"); 916 } else if (m->optional) { 917 char *n = NULL; 918 919 if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL) 920 errx(1, "malloc"); 921 define_type (level + 2, n, newbasename, m->type, FALSE, FALSE); 922 free (n); 923 } else 924 define_type (level + 2, m->gen_name, newbasename, m->type, FALSE, FALSE); 925 } 926 space(level + 1); 927 fprintf (headerfile, "} u;\n"); 928 space(level); 929 fprintf (headerfile, "} %s;\n", name); 930 break; 931 } 932 case TUTCTime: 933 space(level); 934 fprintf (headerfile, "time_t %s;\n", name); 935 break; 936 case TUTF8String: 937 space(level); 938 fprintf (headerfile, "heim_utf8_string %s;\n", name); 939 break; 940 case TPrintableString: 941 space(level); 942 fprintf (headerfile, "heim_printable_string %s;\n", name); 943 break; 944 case TIA5String: 945 space(level); 946 fprintf (headerfile, "heim_ia5_string %s;\n", name); 947 break; 948 case TBMPString: 949 space(level); 950 fprintf (headerfile, "heim_bmp_string %s;\n", name); 951 break; 952 case TUniversalString: 953 space(level); 954 fprintf (headerfile, "heim_universal_string %s;\n", name); 955 break; 956 case TVisibleString: 957 space(level); 958 fprintf (headerfile, "heim_visible_string %s;\n", name); 959 break; 960 case TOID : 961 space(level); 962 fprintf (headerfile, "heim_oid %s;\n", name); 963 break; 964 case TNull: 965 space(level); 966 fprintf (headerfile, "int %s;\n", name); 967 break; 968 default: 969 abort (); 970 } 971 if (newbasename) 972 free(newbasename); 973 } 974 975 static void 976 generate_type_header (const Symbol *s) 977 { 978 int preservep = preserve_type(s->name) ? TRUE : FALSE; 979 980 fprintf (headerfile, "/*\n"); 981 fprintf (headerfile, "%s ::= ", s->name); 982 define_asn1 (0, s->type); 983 fprintf (headerfile, "\n*/\n\n"); 984 985 fprintf (headerfile, "typedef "); 986 define_type (0, s->gen_name, s->gen_name, s->type, TRUE, preservep); 987 988 fprintf (headerfile, "\n"); 989 } 990 991 void 992 generate_type (const Symbol *s) 993 { 994 FILE *h; 995 const char * exp; 996 997 if (!one_code_file) 998 generate_header_of_codefile(s->gen_name); 999 1000 generate_type_header (s); 1001 1002 if (template_flag) 1003 generate_template(s); 1004 1005 if (template_flag == 0 || is_template_compat(s) == 0) { 1006 generate_type_encode (s); 1007 generate_type_decode (s); 1008 generate_type_free (s); 1009 generate_type_length (s); 1010 generate_type_copy (s); 1011 } 1012 generate_type_seq (s); 1013 generate_glue (s->type, s->gen_name); 1014 1015 /* generate prototypes */ 1016 1017 if (is_export(s->name)) { 1018 h = headerfile; 1019 exp = "ASN1EXP "; 1020 } else { 1021 h = privheaderfile; 1022 exp = ""; 1023 } 1024 1025 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 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 fprintf (h, 1036 "%ssize_t ASN1CALL length_%s(const %s *);\n", 1037 exp, 1038 s->gen_name, s->gen_name); 1039 fprintf (h, 1040 "%sint ASN1CALL copy_%s (const %s *, %s *);\n", 1041 exp, 1042 s->gen_name, s->gen_name, s->gen_name); 1043 fprintf (h, 1044 "%svoid ASN1CALL free_%s (%s *);\n", 1045 exp, 1046 s->gen_name, s->gen_name); 1047 1048 fprintf(h, "\n\n"); 1049 1050 if (!one_code_file) { 1051 fprintf(codefile, "\n\n"); 1052 close_codefile(); 1053 } 1054 } 1055