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