1/* $NetBSD: gen.c,v 1.1.1.1 2011/04/13 18:14:40 elric 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 40__RCSID("$NetBSD: gen.c,v 1.1.1.1 2011/04/13 18:14:40 elric Exp $"); 41 42FILE *privheaderfile, *headerfile, *codefile, *logfile, *templatefile; 43 44#define STEM "asn1" 45 46static const char *orig_filename; 47static char *privheader, *header, *template; 48static const char *headerbase = STEM; 49 50/* 51 * list of all IMPORTs 52 */ 53 54struct import { 55 const char *module; 56 struct import *next; 57}; 58 59static struct import *imports = NULL; 60 61void 62add_import (const char *module) 63{ 64 struct import *tmp = emalloc (sizeof(*tmp)); 65 66 tmp->module = module; 67 tmp->next = imports; 68 imports = tmp; 69 70 fprintf (headerfile, "#include <%s_asn1.h>\n", module); 71} 72 73/* 74 * List of all exported symbols 75 */ 76 77struct sexport { 78 const char *name; 79 int defined; 80 struct sexport *next; 81}; 82 83static struct sexport *exports = NULL; 84 85void 86add_export (const char *name) 87{ 88 struct sexport *tmp = emalloc (sizeof(*tmp)); 89 90 tmp->name = name; 91 tmp->next = exports; 92 exports = tmp; 93} 94 95int 96is_export(const char *name) 97{ 98 struct sexport *tmp; 99 100 if (exports == NULL) /* no export list, all exported */ 101 return 1; 102 103 for (tmp = exports; tmp != NULL; tmp = tmp->next) { 104 if (strcmp(tmp->name, name) == 0) { 105 tmp->defined = 1; 106 return 1; 107 } 108 } 109 return 0; 110} 111 112const char * 113get_filename (void) 114{ 115 return orig_filename; 116} 117 118void 119init_generate (const char *filename, const char *base) 120{ 121 char *fn = NULL; 122 123 orig_filename = filename; 124 if (base != NULL) { 125 headerbase = strdup(base); 126 if (headerbase == NULL) 127 errx(1, "strdup"); 128 } 129 130 /* public header file */ 131 if (asprintf(&header, "%s.h", headerbase) < 0 || header == NULL) 132 errx(1, "malloc"); 133 if (asprintf(&fn, "%s.hx", headerbase) < 0 || fn == NULL) 134 errx(1, "malloc"); 135 headerfile = fopen (fn, "w"); 136 if (headerfile == NULL) 137 err (1, "open %s", fn); 138 free(fn); 139 fn = NULL; 140 141 /* private header file */ 142 if (asprintf(&privheader, "%s-priv.h", headerbase) < 0 || privheader == NULL) 143 errx(1, "malloc"); 144 if (asprintf(&fn, "%s-priv.hx", headerbase) < 0 || fn == NULL) 145 errx(1, "malloc"); 146 privheaderfile = fopen (fn, "w"); 147 if (privheaderfile == NULL) 148 err (1, "open %s", fn); 149 free(fn); 150 fn = NULL; 151 152 /* template file */ 153 if (asprintf(&template, "%s-template.c", headerbase) < 0 || template == NULL) 154 errx(1, "malloc"); 155 fprintf (headerfile, 156 "/* Generated from %s */\n" 157 "/* Do not edit */\n\n", 158 filename); 159 fprintf (headerfile, 160 "#ifndef __%s_h__\n" 161 "#define __%s_h__\n\n", headerbase, headerbase); 162 fprintf (headerfile, 163 "#include <stddef.h>\n" 164 "#include <time.h>\n\n"); 165 fprintf (headerfile, 166 "#ifndef __asn1_common_definitions__\n" 167 "#define __asn1_common_definitions__\n\n"); 168 fprintf (headerfile, 169 "typedef struct heim_integer {\n" 170 " size_t length;\n" 171 " void *data;\n" 172 " int negative;\n" 173 "} heim_integer;\n\n"); 174 fprintf (headerfile, 175 "typedef struct heim_octet_string {\n" 176 " size_t length;\n" 177 " void *data;\n" 178 "} heim_octet_string;\n\n"); 179 fprintf (headerfile, 180 "typedef char *heim_general_string;\n\n" 181 ); 182 fprintf (headerfile, 183 "typedef char *heim_utf8_string;\n\n" 184 ); 185 fprintf (headerfile, 186 "typedef struct heim_octet_string heim_printable_string;\n\n" 187 ); 188 fprintf (headerfile, 189 "typedef struct heim_octet_string heim_ia5_string;\n\n" 190 ); 191 fprintf (headerfile, 192 "typedef struct heim_bmp_string {\n" 193 " size_t length;\n" 194 " uint16_t *data;\n" 195 "} heim_bmp_string;\n\n"); 196 fprintf (headerfile, 197 "typedef struct heim_universal_string {\n" 198 " size_t length;\n" 199 " uint32_t *data;\n" 200 "} heim_universal_string;\n\n"); 201 fprintf (headerfile, 202 "typedef char *heim_visible_string;\n\n" 203 ); 204 fprintf (headerfile, 205 "typedef struct heim_oid {\n" 206 " size_t length;\n" 207 " unsigned *components;\n" 208 "} heim_oid;\n\n"); 209 fprintf (headerfile, 210 "typedef struct heim_bit_string {\n" 211 " size_t length;\n" 212 " void *data;\n" 213 "} heim_bit_string;\n\n"); 214 fprintf (headerfile, 215 "typedef struct heim_octet_string heim_any;\n" 216 "typedef struct heim_octet_string heim_any_set;\n\n"); 217 fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \\\n" 218 " do { \\\n" 219 " (BL) = length_##T((S)); \\\n" 220 " (B) = malloc((BL)); \\\n" 221 " if((B) == NULL) { \\\n" 222 " (R) = ENOMEM; \\\n" 223 " } else { \\\n" 224 " (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n" 225 " (S), (L)); \\\n" 226 " if((R) != 0) { \\\n" 227 " free((B)); \\\n" 228 " (B) = NULL; \\\n" 229 " } \\\n" 230 " } \\\n" 231 " } while (0)\n\n", 232 headerfile); 233 fputs("#ifdef _WIN32\n" 234 "#ifndef ASN1_LIB\n" 235 "#define ASN1EXP __declspec(dllimport)\n" 236 "#else\n" 237 "#define ASN1EXP\n" 238 "#endif\n" 239 "#define ASN1CALL __stdcall\n" 240 "#else\n" 241 "#define ASN1EXP\n" 242 "#define ASN1CALL\n" 243 "#endif\n", 244 headerfile); 245 fprintf (headerfile, "struct units;\n\n"); 246 fprintf (headerfile, "#endif\n\n"); 247 if (asprintf(&fn, "%s_files", base) < 0 || fn == NULL) 248 errx(1, "malloc"); 249 logfile = fopen(fn, "w"); 250 if (logfile == NULL) 251 err (1, "open %s", fn); 252 253 /* if one code file, write into the one codefile */ 254 if (one_code_file) 255 return; 256 257 templatefile = fopen (template, "w"); 258 if (templatefile == NULL) 259 err (1, "open %s", template); 260 261 fprintf (templatefile, 262 "/* Generated from %s */\n" 263 "/* Do not edit */\n\n" 264 "#include <stdio.h>\n" 265 "#include <stdlib.h>\n" 266 "#include <time.h>\n" 267 "#include <string.h>\n" 268 "#include <errno.h>\n" 269 "#include <limits.h>\n" 270 "#include <krb5/krb5-types.h>\n", 271 filename); 272 273 fprintf (templatefile, 274 "#include <%s>\n" 275 "#include <%s>\n" 276 "#include <krb5/der.h>\n" 277 "#include <der-private.h>\n" 278 "#include <asn1-template.h>\n", 279 header, privheader); 280 281 282} 283 284void 285close_generate (void) 286{ 287 fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase); 288 289 if (headerfile) 290 fclose (headerfile); 291 if (privheaderfile) 292 fclose (privheaderfile); 293 if (templatefile) 294 fclose (templatefile); 295 if (logfile) 296 fprintf (logfile, "\n"); 297 fclose (logfile); 298} 299 300void 301gen_assign_defval(const char *var, struct value *val) 302{ 303 switch(val->type) { 304 case stringvalue: 305 fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue); 306 break; 307 case integervalue: 308 fprintf(codefile, "%s = %d;\n", var, val->u.integervalue); 309 break; 310 case booleanvalue: 311 if(val->u.booleanvalue) 312 fprintf(codefile, "%s = TRUE;\n", var); 313 else 314 fprintf(codefile, "%s = FALSE;\n", var); 315 break; 316 default: 317 abort(); 318 } 319} 320 321void 322gen_compare_defval(const char *var, struct value *val) 323{ 324 switch(val->type) { 325 case stringvalue: 326 fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue); 327 break; 328 case integervalue: 329 fprintf(codefile, "if(%s != %d)\n", var, val->u.integervalue); 330 break; 331 case booleanvalue: 332 if(val->u.booleanvalue) 333 fprintf(codefile, "if(!%s)\n", var); 334 else 335 fprintf(codefile, "if(%s)\n", var); 336 break; 337 default: 338 abort(); 339 } 340} 341 342void 343generate_header_of_codefile(const char *name) 344{ 345 char *filename = NULL; 346 347 if (codefile != NULL) 348 abort(); 349 350 if (asprintf (&filename, "%s_%s.x", STEM, name) < 0 || filename == NULL) 351 errx(1, "malloc"); 352 codefile = fopen (filename, "w"); 353 if (codefile == NULL) 354 err (1, "fopen %s", filename); 355 fprintf(logfile, "%s ", filename); 356 free(filename); 357 filename = NULL; 358 fprintf (codefile, 359 "/* Generated from %s */\n" 360 "/* Do not edit */\n\n" 361 "#define ASN1_LIB\n\n" 362 "#include <stdio.h>\n" 363 "#include <stdlib.h>\n" 364 "#include <time.h>\n" 365 "#include <string.h>\n" 366 "#include <errno.h>\n" 367 "#include <limits.h>\n" 368 "#include <krb5/krb5-types.h>\n", 369 orig_filename); 370 371 fprintf (codefile, 372 "#include <%s>\n" 373 "#include <%s>\n", 374 header, privheader); 375 fprintf (codefile, 376 "#include <krb5/asn1_err.h>\n" 377 "#include <krb5/der.h>\n" 378 "#include <der-private.h>\n" 379 "#include <asn1-template.h>\n" 380 "#include <krb5/parse_units.h>\n\n"); 381 382} 383 384void 385close_codefile(void) 386{ 387 if (codefile == NULL) 388 abort(); 389 390 fclose(codefile); 391 codefile = NULL; 392} 393 394 395void 396generate_constant (const Symbol *s) 397{ 398 switch(s->value->type) { 399 case booleanvalue: 400 break; 401 case integervalue: 402 fprintf (headerfile, "enum { %s = %d };\n\n", 403 s->gen_name, s->value->u.integervalue); 404 break; 405 case nullvalue: 406 break; 407 case stringvalue: 408 break; 409 case objectidentifiervalue: { 410 struct objid *o, **list; 411 unsigned int i, len; 412 char *gen_upper; 413 414 if (!one_code_file) 415 generate_header_of_codefile(s->gen_name); 416 417 len = 0; 418 for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next) 419 len++; 420 if (len == 0) { 421 printf("s->gen_name: %s",s->gen_name); 422 fflush(stdout); 423 break; 424 } 425 list = emalloc(sizeof(*list) * len); 426 427 i = 0; 428 for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next) 429 list[i++] = o; 430 431 fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name); 432 for (i = len ; i > 0; i--) { 433 o = list[i - 1]; 434 fprintf(headerfile, "%s(%d) ", 435 o->label ? o->label : "label-less", o->value); 436 } 437 438 fprintf (codefile, "static unsigned oid_%s_variable_num[%d] = {", 439 s->gen_name, len); 440 for (i = len ; i > 0; i--) { 441 fprintf(codefile, "%d%s ", list[i - 1]->value, i > 1 ? "," : ""); 442 } 443 fprintf(codefile, "};\n"); 444 445 fprintf (codefile, "const heim_oid asn1_oid_%s = " 446 "{ %d, oid_%s_variable_num };\n\n", 447 s->gen_name, len, s->gen_name); 448 449 free(list); 450 451 /* header file */ 452 453 gen_upper = strdup(s->gen_name); 454 len = strlen(gen_upper); 455 for (i = 0; i < len; i++) 456 gen_upper[i] = toupper((int)s->gen_name[i]); 457 458 fprintf (headerfile, "} */\n"); 459 fprintf (headerfile, 460 "extern ASN1EXP const heim_oid asn1_oid_%s;\n" 461 "#define ASN1_OID_%s (&asn1_oid_%s)\n\n", 462 s->gen_name, 463 gen_upper, 464 s->gen_name); 465 466 free(gen_upper); 467 468 if (!one_code_file) 469 close_codefile(); 470 471 break; 472 } 473 default: 474 abort(); 475 } 476} 477 478int 479is_primitive_type(int type) 480{ 481 switch(type) { 482 case TInteger: 483 case TBoolean: 484 case TOctetString: 485 case TBitString: 486 case TEnumerated: 487 case TGeneralizedTime: 488 case TGeneralString: 489 case TTeletexString: 490 case TOID: 491 case TUTCTime: 492 case TUTF8String: 493 case TPrintableString: 494 case TIA5String: 495 case TBMPString: 496 case TUniversalString: 497 case TVisibleString: 498 case TNull: 499 return 1; 500 default: 501 return 0; 502 } 503} 504 505static void 506space(int level) 507{ 508 while(level-- > 0) 509 fprintf(headerfile, " "); 510} 511 512static const char * 513last_member_p(struct member *m) 514{ 515 struct member *n = ASN1_TAILQ_NEXT(m, members); 516 if (n == NULL) 517 return ""; 518 if (n->ellipsis && ASN1_TAILQ_NEXT(n, members) == NULL) 519 return ""; 520 return ","; 521} 522 523static struct member * 524have_ellipsis(Type *t) 525{ 526 struct member *m; 527 ASN1_TAILQ_FOREACH(m, t->members, members) { 528 if (m->ellipsis) 529 return m; 530 } 531 return NULL; 532} 533 534static void 535define_asn1 (int level, Type *t) 536{ 537 switch (t->type) { 538 case TType: 539 fprintf (headerfile, "%s", t->symbol->name); 540 break; 541 case TInteger: 542 if(t->members == NULL) { 543 fprintf (headerfile, "INTEGER"); 544 if (t->range) 545 fprintf (headerfile, " (%d..%d)", 546 t->range->min, t->range->max); 547 } else { 548 Member *m; 549 fprintf (headerfile, "INTEGER {\n"); 550 ASN1_TAILQ_FOREACH(m, t->members, members) { 551 space (level + 1); 552 fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val, 553 last_member_p(m)); 554 } 555 space(level); 556 fprintf (headerfile, "}"); 557 } 558 break; 559 case TBoolean: 560 fprintf (headerfile, "BOOLEAN"); 561 break; 562 case TOctetString: 563 fprintf (headerfile, "OCTET STRING"); 564 break; 565 case TEnumerated : 566 case TBitString: { 567 Member *m; 568 569 space(level); 570 if(t->type == TBitString) 571 fprintf (headerfile, "BIT STRING {\n"); 572 else 573 fprintf (headerfile, "ENUMERATED {\n"); 574 ASN1_TAILQ_FOREACH(m, t->members, members) { 575 space(level + 1); 576 fprintf (headerfile, "%s(%d)%s\n", m->name, m->val, 577 last_member_p(m)); 578 } 579 space(level); 580 fprintf (headerfile, "}"); 581 break; 582 } 583 case TChoice: 584 case TSet: 585 case TSequence: { 586 Member *m; 587 int max_width = 0; 588 589 if(t->type == TChoice) 590 fprintf(headerfile, "CHOICE {\n"); 591 else if(t->type == TSet) 592 fprintf(headerfile, "SET {\n"); 593 else 594 fprintf(headerfile, "SEQUENCE {\n"); 595 ASN1_TAILQ_FOREACH(m, t->members, members) { 596 if(strlen(m->name) > max_width) 597 max_width = strlen(m->name); 598 } 599 max_width += 3; 600 if(max_width < 16) max_width = 16; 601 ASN1_TAILQ_FOREACH(m, t->members, members) { 602 int width = max_width; 603 space(level + 1); 604 if (m->ellipsis) { 605 fprintf (headerfile, "..."); 606 } else { 607 width -= fprintf(headerfile, "%s", m->name); 608 fprintf(headerfile, "%*s", width, ""); 609 define_asn1(level + 1, m->type); 610 if(m->optional) 611 fprintf(headerfile, " OPTIONAL"); 612 } 613 if(last_member_p(m)) 614 fprintf (headerfile, ","); 615 fprintf (headerfile, "\n"); 616 } 617 space(level); 618 fprintf (headerfile, "}"); 619 break; 620 } 621 case TSequenceOf: 622 fprintf (headerfile, "SEQUENCE OF "); 623 define_asn1 (0, t->subtype); 624 break; 625 case TSetOf: 626 fprintf (headerfile, "SET OF "); 627 define_asn1 (0, t->subtype); 628 break; 629 case TGeneralizedTime: 630 fprintf (headerfile, "GeneralizedTime"); 631 break; 632 case TGeneralString: 633 fprintf (headerfile, "GeneralString"); 634 break; 635 case TTeletexString: 636 fprintf (headerfile, "TeletexString"); 637 break; 638 case TTag: { 639 const char *classnames[] = { "UNIVERSAL ", "APPLICATION ", 640 "" /* CONTEXT */, "PRIVATE " }; 641 if(t->tag.tagclass != ASN1_C_UNIV) 642 fprintf (headerfile, "[%s%d] ", 643 classnames[t->tag.tagclass], 644 t->tag.tagvalue); 645 if(t->tag.tagenv == TE_IMPLICIT) 646 fprintf (headerfile, "IMPLICIT "); 647 define_asn1 (level, t->subtype); 648 break; 649 } 650 case TUTCTime: 651 fprintf (headerfile, "UTCTime"); 652 break; 653 case TUTF8String: 654 space(level); 655 fprintf (headerfile, "UTF8String"); 656 break; 657 case TPrintableString: 658 space(level); 659 fprintf (headerfile, "PrintableString"); 660 break; 661 case TIA5String: 662 space(level); 663 fprintf (headerfile, "IA5String"); 664 break; 665 case TBMPString: 666 space(level); 667 fprintf (headerfile, "BMPString"); 668 break; 669 case TUniversalString: 670 space(level); 671 fprintf (headerfile, "UniversalString"); 672 break; 673 case TVisibleString: 674 space(level); 675 fprintf (headerfile, "VisibleString"); 676 break; 677 case TOID : 678 space(level); 679 fprintf(headerfile, "OBJECT IDENTIFIER"); 680 break; 681 case TNull: 682 space(level); 683 fprintf (headerfile, "NULL"); 684 break; 685 default: 686 abort (); 687 } 688} 689 690static void 691getnewbasename(char **newbasename, int typedefp, const char *basename, const char *name) 692{ 693 if (typedefp) 694 *newbasename = strdup(name); 695 else { 696 if (name[0] == '*') 697 name++; 698 if (asprintf(newbasename, "%s_%s", basename, name) < 0) 699 errx(1, "malloc"); 700 } 701 if (*newbasename == NULL) 702 err(1, "malloc"); 703} 704 705static void 706define_type (int level, const char *name, const char *basename, Type *t, int typedefp, int preservep) 707{ 708 char *newbasename = NULL; 709 710 switch (t->type) { 711 case TType: 712 space(level); 713 fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name); 714 break; 715 case TInteger: 716 space(level); 717 if(t->members) { 718 Member *m; 719 fprintf (headerfile, "enum %s {\n", typedefp ? name : ""); 720 ASN1_TAILQ_FOREACH(m, t->members, members) { 721 space (level + 1); 722 fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val, 723 last_member_p(m)); 724 } 725 fprintf (headerfile, "} %s;\n", name); 726 } else if (t->range == NULL) { 727 fprintf (headerfile, "heim_integer %s;\n", name); 728 } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) { 729 fprintf (headerfile, "int %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 == 0 && t->range->max == INT_MAX) { 733 fprintf (headerfile, "unsigned int %s;\n", name); 734 } else 735 errx(1, "%s: unsupported range %d -> %d", 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 977static void 978generate_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 993void 994generate_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