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 = %" PRId64 ";\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 != %" PRId64 ")\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 = %" PRId64 " };\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, " (%" PRId64 "..%" PRId64 ")", 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 <= INT64_MAX) { 727 fprintf (headerfile, "int64_t %s;\n", name); 728 } else if (t->range->min >= 0 && t->range->max > UINT_MAX) { 729 fprintf (headerfile, "uint64_t %s;\n", name); 730 } else if (t->range->min >= 0 && t->range->max <= UINT_MAX) { 731 fprintf (headerfile, "unsigned int %s;\n", name); 732 } else if (t->range->min >= INT_MIN && t->range->max <= INT_MAX) { 733 fprintf (headerfile, "int %s;\n", name); 734 } else 735 errx(1, "%s: unsupported range %" PRId64 " -> %" PRId64 "", 736 name, t->range->min, t->range->max); 737 break; 738 case TBoolean: 739 space(level); 740 fprintf (headerfile, "int %s;\n", name); 741 break; 742 case TOctetString: 743 space(level); 744 fprintf (headerfile, "heim_octet_string %s;\n", name); 745 break; 746 case TBitString: { 747 Member *m; 748 Type i; 749 struct range range = { 0, INT_MAX }; 750 751 i.type = TInteger; 752 i.range = ⦥ 753 i.members = NULL; 754 i.constraint = NULL; 755 756 space(level); 757 if(ASN1_TAILQ_EMPTY(t->members)) 758 fprintf (headerfile, "heim_bit_string %s;\n", name); 759 else { 760 int pos = 0; 761 getnewbasename(&newbasename, typedefp, basename, name); 762 763 fprintf (headerfile, "struct %s {\n", newbasename); 764 ASN1_TAILQ_FOREACH(m, t->members, members) { 765 char *n = NULL; 766 767 /* pad unused */ 768 while (pos < m->val) { 769 if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL) 770 errx(1, "malloc"); 771 define_type (level + 1, n, newbasename, &i, FALSE, FALSE); 772 free(n); 773 pos++; 774 } 775 776 n = NULL; 777 if (asprintf (&n, "%s:1", m->gen_name) < 0 || n == NULL) 778 errx(1, "malloc"); 779 define_type (level + 1, n, newbasename, &i, FALSE, FALSE); 780 free (n); 781 n = NULL; 782 pos++; 783 } 784 /* pad to 32 elements */ 785 while (pos < 32) { 786 char *n = NULL; 787 if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL) 788 errx(1, "malloc"); 789 define_type (level + 1, n, newbasename, &i, FALSE, FALSE); 790 free(n); 791 pos++; 792 } 793 794 space(level); 795 fprintf (headerfile, "} %s;\n\n", name); 796 } 797 break; 798 } 799 case TEnumerated: { 800 Member *m; 801 802 space(level); 803 fprintf (headerfile, "enum %s {\n", typedefp ? name : ""); 804 ASN1_TAILQ_FOREACH(m, t->members, members) { 805 space(level + 1); 806 if (m->ellipsis) 807 fprintf (headerfile, "/* ... */\n"); 808 else 809 fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val, 810 last_member_p(m)); 811 } 812 space(level); 813 fprintf (headerfile, "} %s;\n\n", name); 814 break; 815 } 816 case TSet: 817 case TSequence: { 818 Member *m; 819 820 getnewbasename(&newbasename, typedefp, basename, name); 821 822 space(level); 823 fprintf (headerfile, "struct %s {\n", newbasename); 824 if (t->type == TSequence && preservep) { 825 space(level + 1); 826 fprintf(headerfile, "heim_octet_string _save;\n"); 827 } 828 ASN1_TAILQ_FOREACH(m, t->members, members) { 829 if (m->ellipsis) { 830 ; 831 } else if (m->optional) { 832 char *n = NULL; 833 834 if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL) 835 errx(1, "malloc"); 836 define_type (level + 1, n, newbasename, m->type, FALSE, FALSE); 837 free (n); 838 } else 839 define_type (level + 1, m->gen_name, newbasename, m->type, FALSE, FALSE); 840 } 841 space(level); 842 fprintf (headerfile, "} %s;\n", name); 843 break; 844 } 845 case TSetOf: 846 case TSequenceOf: { 847 Type i; 848 struct range range = { 0, INT_MAX }; 849 850 getnewbasename(&newbasename, typedefp, basename, name); 851 852 i.type = TInteger; 853 i.range = ⦥ 854 i.members = NULL; 855 i.constraint = NULL; 856 857 space(level); 858 fprintf (headerfile, "struct %s {\n", newbasename); 859 define_type (level + 1, "len", newbasename, &i, FALSE, FALSE); 860 define_type (level + 1, "*val", newbasename, t->subtype, FALSE, FALSE); 861 space(level); 862 fprintf (headerfile, "} %s;\n", name); 863 break; 864 } 865 case TGeneralizedTime: 866 space(level); 867 fprintf (headerfile, "time_t %s;\n", name); 868 break; 869 case TGeneralString: 870 space(level); 871 fprintf (headerfile, "heim_general_string %s;\n", name); 872 break; 873 case TTeletexString: 874 space(level); 875 fprintf (headerfile, "heim_general_string %s;\n", name); 876 break; 877 case TTag: 878 define_type (level, name, basename, t->subtype, typedefp, preservep); 879 break; 880 case TChoice: { 881 int first = 1; 882 Member *m; 883 884 getnewbasename(&newbasename, typedefp, basename, name); 885 886 space(level); 887 fprintf (headerfile, "struct %s {\n", newbasename); 888 if (preservep) { 889 space(level + 1); 890 fprintf(headerfile, "heim_octet_string _save;\n"); 891 } 892 space(level + 1); 893 fprintf (headerfile, "enum {\n"); 894 m = have_ellipsis(t); 895 if (m) { 896 space(level + 2); 897 fprintf (headerfile, "%s = 0,\n", m->label); 898 first = 0; 899 } 900 ASN1_TAILQ_FOREACH(m, t->members, members) { 901 space(level + 2); 902 if (m->ellipsis) 903 fprintf (headerfile, "/* ... */\n"); 904 else 905 fprintf (headerfile, "%s%s%s\n", m->label, 906 first ? " = 1" : "", 907 last_member_p(m)); 908 first = 0; 909 } 910 space(level + 1); 911 fprintf (headerfile, "} element;\n"); 912 space(level + 1); 913 fprintf (headerfile, "union {\n"); 914 ASN1_TAILQ_FOREACH(m, t->members, members) { 915 if (m->ellipsis) { 916 space(level + 2); 917 fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n"); 918 } else if (m->optional) { 919 char *n = NULL; 920 921 if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL) 922 errx(1, "malloc"); 923 define_type (level + 2, n, newbasename, m->type, FALSE, FALSE); 924 free (n); 925 } else 926 define_type (level + 2, m->gen_name, newbasename, m->type, FALSE, FALSE); 927 } 928 space(level + 1); 929 fprintf (headerfile, "} u;\n"); 930 space(level); 931 fprintf (headerfile, "} %s;\n", name); 932 break; 933 } 934 case TUTCTime: 935 space(level); 936 fprintf (headerfile, "time_t %s;\n", name); 937 break; 938 case TUTF8String: 939 space(level); 940 fprintf (headerfile, "heim_utf8_string %s;\n", name); 941 break; 942 case TPrintableString: 943 space(level); 944 fprintf (headerfile, "heim_printable_string %s;\n", name); 945 break; 946 case TIA5String: 947 space(level); 948 fprintf (headerfile, "heim_ia5_string %s;\n", name); 949 break; 950 case TBMPString: 951 space(level); 952 fprintf (headerfile, "heim_bmp_string %s;\n", name); 953 break; 954 case TUniversalString: 955 space(level); 956 fprintf (headerfile, "heim_universal_string %s;\n", name); 957 break; 958 case TVisibleString: 959 space(level); 960 fprintf (headerfile, "heim_visible_string %s;\n", name); 961 break; 962 case TOID : 963 space(level); 964 fprintf (headerfile, "heim_oid %s;\n", name); 965 break; 966 case TNull: 967 space(level); 968 fprintf (headerfile, "int %s;\n", name); 969 break; 970 default: 971 abort (); 972 } 973 if (newbasename) 974 free(newbasename); 975 } 976 977 static void 978 generate_type_header (const Symbol *s) 979 { 980 int preservep = preserve_type(s->name) ? TRUE : FALSE; 981 982 fprintf (headerfile, "/*\n"); 983 fprintf (headerfile, "%s ::= ", s->name); 984 define_asn1 (0, s->type); 985 fprintf (headerfile, "\n*/\n\n"); 986 987 fprintf (headerfile, "typedef "); 988 define_type (0, s->gen_name, s->gen_name, s->type, TRUE, preservep); 989 990 fprintf (headerfile, "\n"); 991 } 992 993 void 994 generate_type (const Symbol *s) 995 { 996 FILE *h; 997 const char * exp; 998 999 if (!one_code_file) 1000 generate_header_of_codefile(s->gen_name); 1001 1002 generate_type_header (s); 1003 1004 if (template_flag) 1005 generate_template(s); 1006 1007 if (template_flag == 0 || is_template_compat(s) == 0) { 1008 generate_type_encode (s); 1009 generate_type_decode (s); 1010 generate_type_free (s); 1011 generate_type_length (s); 1012 generate_type_copy (s); 1013 } 1014 generate_type_seq (s); 1015 generate_glue (s->type, s->gen_name); 1016 1017 /* generate prototypes */ 1018 1019 if (is_export(s->name)) { 1020 h = headerfile; 1021 exp = "ASN1EXP "; 1022 } else { 1023 h = privheaderfile; 1024 exp = ""; 1025 } 1026 1027 fprintf (h, 1028 "%sint ASN1CALL " 1029 "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n", 1030 exp, 1031 s->gen_name, s->gen_name); 1032 fprintf (h, 1033 "%sint ASN1CALL " 1034 "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n", 1035 exp, 1036 s->gen_name, s->gen_name); 1037 fprintf (h, 1038 "%ssize_t ASN1CALL length_%s(const %s *);\n", 1039 exp, 1040 s->gen_name, s->gen_name); 1041 fprintf (h, 1042 "%sint ASN1CALL copy_%s (const %s *, %s *);\n", 1043 exp, 1044 s->gen_name, s->gen_name, s->gen_name); 1045 fprintf (h, 1046 "%svoid ASN1CALL free_%s (%s *);\n", 1047 exp, 1048 s->gen_name, s->gen_name); 1049 1050 fprintf(h, "\n\n"); 1051 1052 if (!one_code_file) { 1053 fprintf(codefile, "\n\n"); 1054 close_codefile(); 1055 } 1056 } 1057