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