155682Smarkm/* 2233294Sstas * Copyright (c) 1997 - 2005 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 755682Smarkm * 8233294Sstas * Redistribution and use in source and binary forms, with or without 9233294Sstas * modification, are permitted provided that the following conditions 10233294Sstas * are met: 1155682Smarkm * 12233294Sstas * 1. Redistributions of source code must retain the above copyright 13233294Sstas * notice, this list of conditions and the following disclaimer. 1455682Smarkm * 15233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 16233294Sstas * notice, this list of conditions and the following disclaimer in the 17233294Sstas * documentation and/or other materials provided with the distribution. 1855682Smarkm * 19233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 20233294Sstas * may be used to endorse or promote products derived from this software 21233294Sstas * without specific prior written permission. 22233294Sstas * 23233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33233294Sstas * SUCH DAMAGE. 3455682Smarkm */ 3555682Smarkm 3655682Smarkm#include "gen_locl.h" 3755682Smarkm 38233294SstasRCSID("$Id$"); 3955682Smarkm 40233294SstasFILE *privheaderfile, *headerfile, *codefile, *logfile, *templatefile; 4155682Smarkm 4255682Smarkm#define STEM "asn1" 4355682Smarkm 4472445Sassarstatic const char *orig_filename; 45233294Sstasstatic char *privheader, *header, *template; 46178825Sdfrstatic const char *headerbase = STEM; 4755682Smarkm 4890926Snectar/* 4990926Snectar * list of all IMPORTs 5090926Snectar */ 5190926Snectar 5290926Snectarstruct import { 5390926Snectar const char *module; 5490926Snectar struct import *next; 5590926Snectar}; 5690926Snectar 5790926Snectarstatic struct import *imports = NULL; 5890926Snectar 5990926Snectarvoid 6090926Snectaradd_import (const char *module) 6190926Snectar{ 6290926Snectar struct import *tmp = emalloc (sizeof(*tmp)); 6390926Snectar 6490926Snectar tmp->module = module; 6590926Snectar tmp->next = imports; 6690926Snectar imports = tmp; 67178825Sdfr 68178825Sdfr fprintf (headerfile, "#include <%s_asn1.h>\n", module); 6990926Snectar} 7090926Snectar 71233294Sstas/* 72233294Sstas * List of all exported symbols 73233294Sstas */ 74233294Sstas 75233294Sstasstruct sexport { 76233294Sstas const char *name; 77233294Sstas int defined; 78233294Sstas struct sexport *next; 79233294Sstas}; 80233294Sstas 81233294Sstasstatic struct sexport *exports = NULL; 82233294Sstas 83233294Sstasvoid 84233294Sstasadd_export (const char *name) 85233294Sstas{ 86233294Sstas struct sexport *tmp = emalloc (sizeof(*tmp)); 87233294Sstas 88233294Sstas tmp->name = name; 89233294Sstas tmp->next = exports; 90233294Sstas exports = tmp; 91233294Sstas} 92233294Sstas 93233294Sstasint 94233294Sstasis_export(const char *name) 95233294Sstas{ 96233294Sstas struct sexport *tmp; 97233294Sstas 98233294Sstas if (exports == NULL) /* no export list, all exported */ 99233294Sstas return 1; 100233294Sstas 101233294Sstas for (tmp = exports; tmp != NULL; tmp = tmp->next) { 102233294Sstas if (strcmp(tmp->name, name) == 0) { 103233294Sstas tmp->defined = 1; 104233294Sstas return 1; 105233294Sstas } 106233294Sstas } 107233294Sstas return 0; 108233294Sstas} 109233294Sstas 11072445Sassarconst char * 111178825Sdfrget_filename (void) 11272445Sassar{ 11372445Sassar return orig_filename; 11472445Sassar} 11572445Sassar 11655682Smarkmvoid 11772445Sassarinit_generate (const char *filename, const char *base) 11855682Smarkm{ 119233294Sstas char *fn = NULL; 120178825Sdfr 12155682Smarkm orig_filename = filename; 122178825Sdfr if (base != NULL) { 123178825Sdfr headerbase = strdup(base); 124178825Sdfr if (headerbase == NULL) 125178825Sdfr errx(1, "strdup"); 126178825Sdfr } 127233294Sstas 128233294Sstas /* public header file */ 129233294Sstas if (asprintf(&header, "%s.h", headerbase) < 0 || header == NULL) 130178825Sdfr errx(1, "malloc"); 131233294Sstas if (asprintf(&fn, "%s.hx", headerbase) < 0 || fn == NULL) 132233294Sstas errx(1, "malloc"); 133233294Sstas headerfile = fopen (fn, "w"); 13455682Smarkm if (headerfile == NULL) 135233294Sstas err (1, "open %s", fn); 136233294Sstas free(fn); 137233294Sstas fn = NULL; 138233294Sstas 139233294Sstas /* private header file */ 140233294Sstas if (asprintf(&privheader, "%s-priv.h", headerbase) < 0 || privheader == NULL) 141233294Sstas errx(1, "malloc"); 142233294Sstas if (asprintf(&fn, "%s-priv.hx", headerbase) < 0 || fn == NULL) 143233294Sstas errx(1, "malloc"); 144233294Sstas privheaderfile = fopen (fn, "w"); 145233294Sstas if (privheaderfile == NULL) 146233294Sstas err (1, "open %s", fn); 147233294Sstas free(fn); 148233294Sstas fn = NULL; 149233294Sstas 150233294Sstas /* template file */ 151233294Sstas if (asprintf(&template, "%s-template.c", headerbase) < 0 || template == NULL) 152233294Sstas errx(1, "malloc"); 15355682Smarkm fprintf (headerfile, 15455682Smarkm "/* Generated from %s */\n" 15555682Smarkm "/* Do not edit */\n\n", 15655682Smarkm filename); 157233294Sstas fprintf (headerfile, 15855682Smarkm "#ifndef __%s_h__\n" 15955682Smarkm "#define __%s_h__\n\n", headerbase, headerbase); 160233294Sstas fprintf (headerfile, 16155682Smarkm "#include <stddef.h>\n" 16255682Smarkm "#include <time.h>\n\n"); 16355682Smarkm fprintf (headerfile, 16455682Smarkm "#ifndef __asn1_common_definitions__\n" 16555682Smarkm "#define __asn1_common_definitions__\n\n"); 16655682Smarkm fprintf (headerfile, 167178825Sdfr "typedef struct heim_integer {\n" 16855682Smarkm " size_t length;\n" 16955682Smarkm " void *data;\n" 170178825Sdfr " int negative;\n" 171178825Sdfr "} heim_integer;\n\n"); 17255682Smarkm fprintf (headerfile, 173178825Sdfr "typedef struct heim_octet_string {\n" 174178825Sdfr " size_t length;\n" 175178825Sdfr " void *data;\n" 176178825Sdfr "} heim_octet_string;\n\n"); 177178825Sdfr fprintf (headerfile, 178178825Sdfr "typedef char *heim_general_string;\n\n" 17955682Smarkm ); 18090926Snectar fprintf (headerfile, 181178825Sdfr "typedef char *heim_utf8_string;\n\n" 182178825Sdfr ); 183178825Sdfr fprintf (headerfile, 184233294Sstas "typedef struct heim_octet_string heim_printable_string;\n\n" 185178825Sdfr ); 186178825Sdfr fprintf (headerfile, 187233294Sstas "typedef struct heim_octet_string heim_ia5_string;\n\n" 188178825Sdfr ); 189178825Sdfr fprintf (headerfile, 190178825Sdfr "typedef struct heim_bmp_string {\n" 19190926Snectar " size_t length;\n" 192178825Sdfr " uint16_t *data;\n" 193178825Sdfr "} heim_bmp_string;\n\n"); 194178825Sdfr fprintf (headerfile, 195178825Sdfr "typedef struct heim_universal_string {\n" 196178825Sdfr " size_t length;\n" 197178825Sdfr " uint32_t *data;\n" 198178825Sdfr "} heim_universal_string;\n\n"); 199178825Sdfr fprintf (headerfile, 200178825Sdfr "typedef char *heim_visible_string;\n\n" 201178825Sdfr ); 202178825Sdfr fprintf (headerfile, 203178825Sdfr "typedef struct heim_oid {\n" 204178825Sdfr " size_t length;\n" 20590926Snectar " unsigned *components;\n" 206178825Sdfr "} heim_oid;\n\n"); 207178825Sdfr fprintf (headerfile, 208178825Sdfr "typedef struct heim_bit_string {\n" 209178825Sdfr " size_t length;\n" 210178825Sdfr " void *data;\n" 211178825Sdfr "} heim_bit_string;\n\n"); 212178825Sdfr fprintf (headerfile, 213178825Sdfr "typedef struct heim_octet_string heim_any;\n" 214178825Sdfr "typedef struct heim_octet_string heim_any_set;\n\n"); 215103423Snectar fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \\\n" 216103423Snectar " do { \\\n" 217103423Snectar " (BL) = length_##T((S)); \\\n" 218103423Snectar " (B) = malloc((BL)); \\\n" 219103423Snectar " if((B) == NULL) { \\\n" 220103423Snectar " (R) = ENOMEM; \\\n" 221103423Snectar " } else { \\\n" 222103423Snectar " (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n" 223103423Snectar " (S), (L)); \\\n" 224103423Snectar " if((R) != 0) { \\\n" 225103423Snectar " free((B)); \\\n" 226103423Snectar " (B) = NULL; \\\n" 227103423Snectar " } \\\n" 228103423Snectar " } \\\n" 229103423Snectar " } while (0)\n\n", 230103423Snectar headerfile); 231233294Sstas fputs("#ifdef _WIN32\n" 232233294Sstas "#ifndef ASN1_LIB\n" 233233294Sstas "#define ASN1EXP __declspec(dllimport)\n" 234233294Sstas "#else\n" 235233294Sstas "#define ASN1EXP\n" 236233294Sstas "#endif\n" 237233294Sstas "#define ASN1CALL __stdcall\n" 238233294Sstas "#else\n" 239233294Sstas "#define ASN1EXP\n" 240233294Sstas "#define ASN1CALL\n" 241233294Sstas "#endif\n", 242233294Sstas headerfile); 243178825Sdfr fprintf (headerfile, "struct units;\n\n"); 24455682Smarkm fprintf (headerfile, "#endif\n\n"); 245233294Sstas if (asprintf(&fn, "%s_files", base) < 0 || fn == NULL) 246178825Sdfr errx(1, "malloc"); 247178825Sdfr logfile = fopen(fn, "w"); 24855682Smarkm if (logfile == NULL) 249178825Sdfr err (1, "open %s", fn); 250233294Sstas 251233294Sstas /* if one code file, write into the one codefile */ 252233294Sstas if (one_code_file) 253233294Sstas return; 254233294Sstas 255233294Sstas templatefile = fopen (template, "w"); 256233294Sstas if (templatefile == NULL) 257233294Sstas err (1, "open %s", template); 258233294Sstas 259233294Sstas fprintf (templatefile, 260233294Sstas "/* Generated from %s */\n" 261233294Sstas "/* Do not edit */\n\n" 262233294Sstas "#include <stdio.h>\n" 263233294Sstas "#include <stdlib.h>\n" 264233294Sstas "#include <time.h>\n" 265233294Sstas "#include <string.h>\n" 266233294Sstas "#include <errno.h>\n" 267233294Sstas "#include <limits.h>\n" 268233294Sstas "#include <krb5-types.h>\n", 269233294Sstas filename); 270233294Sstas 271233294Sstas fprintf (templatefile, 272233294Sstas "#include <%s>\n" 273233294Sstas "#include <%s>\n" 274233294Sstas "#include <der.h>\n" 275233294Sstas "#include <der-private.h>\n" 276233294Sstas "#include <asn1-template.h>\n", 277233294Sstas header, privheader); 278233294Sstas 279233294Sstas 28055682Smarkm} 28155682Smarkm 28255682Smarkmvoid 28372445Sassarclose_generate (void) 28455682Smarkm{ 28555682Smarkm fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase); 28655682Smarkm 287233294Sstas if (headerfile) 288233294Sstas fclose (headerfile); 289233294Sstas if (privheaderfile) 290233294Sstas fclose (privheaderfile); 291233294Sstas if (templatefile) 292233294Sstas fclose (templatefile); 293233294Sstas if (logfile) 294233294Sstas fprintf (logfile, "\n"); 295233294Sstas fclose (logfile); 29655682Smarkm} 29755682Smarkm 29855682Smarkmvoid 299178825Sdfrgen_assign_defval(const char *var, struct value *val) 300178825Sdfr{ 301178825Sdfr switch(val->type) { 302178825Sdfr case stringvalue: 303178825Sdfr fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue); 304178825Sdfr break; 305178825Sdfr case integervalue: 306178825Sdfr fprintf(codefile, "%s = %d;\n", var, val->u.integervalue); 307178825Sdfr break; 308178825Sdfr case booleanvalue: 309178825Sdfr if(val->u.booleanvalue) 310178825Sdfr fprintf(codefile, "%s = TRUE;\n", var); 311178825Sdfr else 312178825Sdfr fprintf(codefile, "%s = FALSE;\n", var); 313178825Sdfr break; 314178825Sdfr default: 315178825Sdfr abort(); 316178825Sdfr } 317178825Sdfr} 318178825Sdfr 319178825Sdfrvoid 320178825Sdfrgen_compare_defval(const char *var, struct value *val) 321178825Sdfr{ 322178825Sdfr switch(val->type) { 323178825Sdfr case stringvalue: 324178825Sdfr fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue); 325178825Sdfr break; 326178825Sdfr case integervalue: 327178825Sdfr fprintf(codefile, "if(%s != %d)\n", var, val->u.integervalue); 328178825Sdfr break; 329178825Sdfr case booleanvalue: 330178825Sdfr if(val->u.booleanvalue) 331178825Sdfr fprintf(codefile, "if(!%s)\n", var); 332178825Sdfr else 333178825Sdfr fprintf(codefile, "if(%s)\n", var); 334178825Sdfr break; 335178825Sdfr default: 336178825Sdfr abort(); 337178825Sdfr } 338178825Sdfr} 339178825Sdfr 340233294Sstasvoid 341178825Sdfrgenerate_header_of_codefile(const char *name) 342178825Sdfr{ 343233294Sstas char *filename = NULL; 344178825Sdfr 345178825Sdfr if (codefile != NULL) 346178825Sdfr abort(); 347178825Sdfr 348233294Sstas if (asprintf (&filename, "%s_%s.x", STEM, name) < 0 || filename == NULL) 349178825Sdfr errx(1, "malloc"); 350178825Sdfr codefile = fopen (filename, "w"); 351178825Sdfr if (codefile == NULL) 352178825Sdfr err (1, "fopen %s", filename); 353178825Sdfr fprintf(logfile, "%s ", filename); 354178825Sdfr free(filename); 355233294Sstas filename = NULL; 356233294Sstas fprintf (codefile, 357178825Sdfr "/* Generated from %s */\n" 358178825Sdfr "/* Do not edit */\n\n" 359233294Sstas "#define ASN1_LIB\n\n" 360178825Sdfr "#include <stdio.h>\n" 361178825Sdfr "#include <stdlib.h>\n" 362178825Sdfr "#include <time.h>\n" 363178825Sdfr "#include <string.h>\n" 364178825Sdfr "#include <errno.h>\n" 365178825Sdfr "#include <limits.h>\n" 366178825Sdfr "#include <krb5-types.h>\n", 367178825Sdfr orig_filename); 368178825Sdfr 369178825Sdfr fprintf (codefile, 370233294Sstas "#include <%s>\n" 371233294Sstas "#include <%s>\n", 372233294Sstas header, privheader); 373178825Sdfr fprintf (codefile, 374178825Sdfr "#include <asn1_err.h>\n" 375178825Sdfr "#include <der.h>\n" 376233294Sstas "#include <der-private.h>\n" 377233294Sstas "#include <asn1-template.h>\n" 378178825Sdfr "#include <parse_units.h>\n\n"); 379178825Sdfr 380178825Sdfr} 381178825Sdfr 382233294Sstasvoid 383178825Sdfrclose_codefile(void) 384178825Sdfr{ 385178825Sdfr if (codefile == NULL) 386178825Sdfr abort(); 387178825Sdfr 388178825Sdfr fclose(codefile); 389178825Sdfr codefile = NULL; 390178825Sdfr} 391178825Sdfr 392178825Sdfr 393178825Sdfrvoid 39455682Smarkmgenerate_constant (const Symbol *s) 39555682Smarkm{ 396178825Sdfr switch(s->value->type) { 397178825Sdfr case booleanvalue: 398178825Sdfr break; 399178825Sdfr case integervalue: 400178825Sdfr fprintf (headerfile, "enum { %s = %d };\n\n", 401178825Sdfr s->gen_name, s->value->u.integervalue); 402178825Sdfr break; 403178825Sdfr case nullvalue: 404178825Sdfr break; 405178825Sdfr case stringvalue: 406178825Sdfr break; 407178825Sdfr case objectidentifiervalue: { 408178825Sdfr struct objid *o, **list; 409233294Sstas unsigned int i, len; 410233294Sstas char *gen_upper; 411178825Sdfr 412233294Sstas if (!one_code_file) 413233294Sstas generate_header_of_codefile(s->gen_name); 414178825Sdfr 415178825Sdfr len = 0; 416178825Sdfr for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next) 417178825Sdfr len++; 418233294Sstas if (len == 0) { 419233294Sstas printf("s->gen_name: %s",s->gen_name); 420233294Sstas fflush(stdout); 421233294Sstas break; 422233294Sstas } 423178825Sdfr list = emalloc(sizeof(*list) * len); 424178825Sdfr 425178825Sdfr i = 0; 426178825Sdfr for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next) 427178825Sdfr list[i++] = o; 428178825Sdfr 429178825Sdfr fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name); 430233294Sstas for (i = len ; i > 0; i--) { 431233294Sstas o = list[i - 1]; 432178825Sdfr fprintf(headerfile, "%s(%d) ", 433178825Sdfr o->label ? o->label : "label-less", o->value); 434178825Sdfr } 435178825Sdfr 436178825Sdfr fprintf (codefile, "static unsigned oid_%s_variable_num[%d] = {", 437178825Sdfr s->gen_name, len); 438233294Sstas for (i = len ; i > 0; i--) { 439233294Sstas fprintf(codefile, "%d%s ", list[i - 1]->value, i > 1 ? "," : ""); 440178825Sdfr } 441178825Sdfr fprintf(codefile, "};\n"); 442178825Sdfr 443233294Sstas fprintf (codefile, "const heim_oid asn1_oid_%s = " 444233294Sstas "{ %d, oid_%s_variable_num };\n\n", 445178825Sdfr s->gen_name, len, s->gen_name); 446178825Sdfr 447233294Sstas free(list); 448178825Sdfr 449233294Sstas /* header file */ 450178825Sdfr 451233294Sstas gen_upper = strdup(s->gen_name); 452233294Sstas len = strlen(gen_upper); 453233294Sstas for (i = 0; i < len; i++) 454233294Sstas gen_upper[i] = toupper((int)s->gen_name[i]); 455233294Sstas 456233294Sstas fprintf (headerfile, "} */\n"); 457233294Sstas fprintf (headerfile, 458233294Sstas "extern ASN1EXP const heim_oid asn1_oid_%s;\n" 459233294Sstas "#define ASN1_OID_%s (&asn1_oid_%s)\n\n", 460233294Sstas s->gen_name, 461233294Sstas gen_upper, 462233294Sstas s->gen_name); 463233294Sstas 464233294Sstas free(gen_upper); 465233294Sstas 466233294Sstas if (!one_code_file) 467233294Sstas close_codefile(); 468233294Sstas 469178825Sdfr break; 470178825Sdfr } 471178825Sdfr default: 472178825Sdfr abort(); 473178825Sdfr } 47455682Smarkm} 47555682Smarkm 476233294Sstasint 477233294Sstasis_primitive_type(int type) 478233294Sstas{ 479233294Sstas switch(type) { 480233294Sstas case TInteger: 481233294Sstas case TBoolean: 482233294Sstas case TOctetString: 483233294Sstas case TBitString: 484233294Sstas case TEnumerated: 485233294Sstas case TGeneralizedTime: 486233294Sstas case TGeneralString: 487233294Sstas case TTeletexString: 488233294Sstas case TOID: 489233294Sstas case TUTCTime: 490233294Sstas case TUTF8String: 491233294Sstas case TPrintableString: 492233294Sstas case TIA5String: 493233294Sstas case TBMPString: 494233294Sstas case TUniversalString: 495233294Sstas case TVisibleString: 496233294Sstas case TNull: 497233294Sstas return 1; 498233294Sstas default: 499233294Sstas return 0; 500233294Sstas } 501233294Sstas} 502233294Sstas 50355682Smarkmstatic void 50455682Smarkmspace(int level) 50555682Smarkm{ 50655682Smarkm while(level-- > 0) 50755682Smarkm fprintf(headerfile, " "); 50855682Smarkm} 50955682Smarkm 510178825Sdfrstatic const char * 511178825Sdfrlast_member_p(struct member *m) 512178825Sdfr{ 513178825Sdfr struct member *n = ASN1_TAILQ_NEXT(m, members); 514178825Sdfr if (n == NULL) 515178825Sdfr return ""; 516178825Sdfr if (n->ellipsis && ASN1_TAILQ_NEXT(n, members) == NULL) 517178825Sdfr return ""; 518178825Sdfr return ","; 519178825Sdfr} 520178825Sdfr 521178825Sdfrstatic struct member * 522178825Sdfrhave_ellipsis(Type *t) 523178825Sdfr{ 524178825Sdfr struct member *m; 525178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 526178825Sdfr if (m->ellipsis) 527178825Sdfr return m; 528178825Sdfr } 529178825Sdfr return NULL; 530178825Sdfr} 531178825Sdfr 53255682Smarkmstatic void 53355682Smarkmdefine_asn1 (int level, Type *t) 53455682Smarkm{ 53555682Smarkm switch (t->type) { 53655682Smarkm case TType: 53755682Smarkm fprintf (headerfile, "%s", t->symbol->name); 53855682Smarkm break; 53955682Smarkm case TInteger: 540178825Sdfr if(t->members == NULL) { 541178825Sdfr fprintf (headerfile, "INTEGER"); 542178825Sdfr if (t->range) 543178825Sdfr fprintf (headerfile, " (%d..%d)", 544178825Sdfr t->range->min, t->range->max); 545178825Sdfr } else { 546178825Sdfr Member *m; 547178825Sdfr fprintf (headerfile, "INTEGER {\n"); 548178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 549178825Sdfr space (level + 1); 550233294Sstas fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val, 551178825Sdfr last_member_p(m)); 552178825Sdfr } 553178825Sdfr space(level); 554178825Sdfr fprintf (headerfile, "}"); 555178825Sdfr } 55655682Smarkm break; 557178825Sdfr case TBoolean: 558178825Sdfr fprintf (headerfile, "BOOLEAN"); 55972445Sassar break; 56055682Smarkm case TOctetString: 56155682Smarkm fprintf (headerfile, "OCTET STRING"); 56255682Smarkm break; 563178825Sdfr case TEnumerated : 56455682Smarkm case TBitString: { 56555682Smarkm Member *m; 56655682Smarkm 56755682Smarkm space(level); 568178825Sdfr if(t->type == TBitString) 569178825Sdfr fprintf (headerfile, "BIT STRING {\n"); 570178825Sdfr else 571178825Sdfr fprintf (headerfile, "ENUMERATED {\n"); 572178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 57355682Smarkm space(level + 1); 574233294Sstas fprintf (headerfile, "%s(%d)%s\n", m->name, m->val, 575178825Sdfr last_member_p(m)); 57655682Smarkm } 57755682Smarkm space(level); 57855682Smarkm fprintf (headerfile, "}"); 57955682Smarkm break; 58055682Smarkm } 581178825Sdfr case TChoice: 582178825Sdfr case TSet: 58355682Smarkm case TSequence: { 58455682Smarkm Member *m; 58555682Smarkm int max_width = 0; 58655682Smarkm 587178825Sdfr if(t->type == TChoice) 588178825Sdfr fprintf(headerfile, "CHOICE {\n"); 589178825Sdfr else if(t->type == TSet) 590178825Sdfr fprintf(headerfile, "SET {\n"); 591178825Sdfr else 592178825Sdfr fprintf(headerfile, "SEQUENCE {\n"); 593178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 594178825Sdfr if(strlen(m->name) > max_width) 595178825Sdfr max_width = strlen(m->name); 59655682Smarkm } 597178825Sdfr max_width += 3; 59855682Smarkm if(max_width < 16) max_width = 16; 599178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 600178825Sdfr int width = max_width; 60155682Smarkm space(level + 1); 602178825Sdfr if (m->ellipsis) { 603178825Sdfr fprintf (headerfile, "..."); 604178825Sdfr } else { 605178825Sdfr width -= fprintf(headerfile, "%s", m->name); 606178825Sdfr fprintf(headerfile, "%*s", width, ""); 607178825Sdfr define_asn1(level + 1, m->type); 608178825Sdfr if(m->optional) 609178825Sdfr fprintf(headerfile, " OPTIONAL"); 610178825Sdfr } 611178825Sdfr if(last_member_p(m)) 61255682Smarkm fprintf (headerfile, ","); 61355682Smarkm fprintf (headerfile, "\n"); 61455682Smarkm } 61555682Smarkm space(level); 61655682Smarkm fprintf (headerfile, "}"); 61755682Smarkm break; 61855682Smarkm } 619178825Sdfr case TSequenceOf: 62055682Smarkm fprintf (headerfile, "SEQUENCE OF "); 62155682Smarkm define_asn1 (0, t->subtype); 62255682Smarkm break; 623178825Sdfr case TSetOf: 624178825Sdfr fprintf (headerfile, "SET OF "); 625178825Sdfr define_asn1 (0, t->subtype); 626178825Sdfr break; 62755682Smarkm case TGeneralizedTime: 62855682Smarkm fprintf (headerfile, "GeneralizedTime"); 62955682Smarkm break; 63055682Smarkm case TGeneralString: 63155682Smarkm fprintf (headerfile, "GeneralString"); 63255682Smarkm break; 633233294Sstas case TTeletexString: 634233294Sstas fprintf (headerfile, "TeletexString"); 635233294Sstas break; 636178825Sdfr case TTag: { 637233294Sstas const char *classnames[] = { "UNIVERSAL ", "APPLICATION ", 638178825Sdfr "" /* CONTEXT */, "PRIVATE " }; 639178825Sdfr if(t->tag.tagclass != ASN1_C_UNIV) 640233294Sstas fprintf (headerfile, "[%s%d] ", 641178825Sdfr classnames[t->tag.tagclass], 642178825Sdfr t->tag.tagvalue); 643178825Sdfr if(t->tag.tagenv == TE_IMPLICIT) 644178825Sdfr fprintf (headerfile, "IMPLICIT "); 64555682Smarkm define_asn1 (level, t->subtype); 64655682Smarkm break; 647178825Sdfr } 648178825Sdfr case TUTCTime: 649178825Sdfr fprintf (headerfile, "UTCTime"); 650178825Sdfr break; 651178825Sdfr case TUTF8String: 652178825Sdfr space(level); 653178825Sdfr fprintf (headerfile, "UTF8String"); 654178825Sdfr break; 655178825Sdfr case TPrintableString: 656178825Sdfr space(level); 657178825Sdfr fprintf (headerfile, "PrintableString"); 658178825Sdfr break; 659178825Sdfr case TIA5String: 660178825Sdfr space(level); 661178825Sdfr fprintf (headerfile, "IA5String"); 662178825Sdfr break; 663178825Sdfr case TBMPString: 664178825Sdfr space(level); 665178825Sdfr fprintf (headerfile, "BMPString"); 666178825Sdfr break; 667178825Sdfr case TUniversalString: 668178825Sdfr space(level); 669178825Sdfr fprintf (headerfile, "UniversalString"); 670178825Sdfr break; 671178825Sdfr case TVisibleString: 672178825Sdfr space(level); 673178825Sdfr fprintf (headerfile, "VisibleString"); 674178825Sdfr break; 675178825Sdfr case TOID : 676178825Sdfr space(level); 677178825Sdfr fprintf(headerfile, "OBJECT IDENTIFIER"); 678178825Sdfr break; 679178825Sdfr case TNull: 680178825Sdfr space(level); 681178825Sdfr fprintf (headerfile, "NULL"); 682178825Sdfr break; 68355682Smarkm default: 68455682Smarkm abort (); 68555682Smarkm } 68655682Smarkm} 68755682Smarkm 68855682Smarkmstatic void 689233294Sstasgetnewbasename(char **newbasename, int typedefp, const char *basename, const char *name) 69055682Smarkm{ 691233294Sstas if (typedefp) 692233294Sstas *newbasename = strdup(name); 693233294Sstas else { 694233294Sstas if (name[0] == '*') 695233294Sstas name++; 696233294Sstas if (asprintf(newbasename, "%s_%s", basename, name) < 0) 697233294Sstas errx(1, "malloc"); 698233294Sstas } 699233294Sstas if (*newbasename == NULL) 700233294Sstas err(1, "malloc"); 701233294Sstas} 702233294Sstas 703233294Sstasstatic void 704233294Sstasdefine_type (int level, const char *name, const char *basename, Type *t, int typedefp, int preservep) 705233294Sstas{ 706233294Sstas char *newbasename = NULL; 707233294Sstas 70855682Smarkm switch (t->type) { 70955682Smarkm case TType: 71055682Smarkm space(level); 71155682Smarkm fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name); 71255682Smarkm break; 71355682Smarkm case TInteger: 71455682Smarkm space(level); 715178825Sdfr if(t->members) { 71672445Sassar Member *m; 71772445Sassar fprintf (headerfile, "enum %s {\n", typedefp ? name : ""); 718178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 71972445Sassar space (level + 1); 720233294Sstas fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val, 721178825Sdfr last_member_p(m)); 72272445Sassar } 72372445Sassar fprintf (headerfile, "} %s;\n", name); 724178825Sdfr } else if (t->range == NULL) { 725178825Sdfr fprintf (headerfile, "heim_integer %s;\n", name); 726178825Sdfr } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) { 727178825Sdfr fprintf (headerfile, "int %s;\n", name); 728178825Sdfr } else if (t->range->min == 0 && t->range->max == UINT_MAX) { 729178825Sdfr fprintf (headerfile, "unsigned int %s;\n", name); 730178825Sdfr } else if (t->range->min == 0 && t->range->max == INT_MAX) { 731178825Sdfr fprintf (headerfile, "unsigned int %s;\n", name); 732178825Sdfr } else 733233294Sstas errx(1, "%s: unsupported range %d -> %d", 734178825Sdfr name, t->range->min, t->range->max); 73555682Smarkm break; 736178825Sdfr case TBoolean: 73755682Smarkm space(level); 738178825Sdfr fprintf (headerfile, "int %s;\n", name); 73955682Smarkm break; 74055682Smarkm case TOctetString: 74155682Smarkm space(level); 742178825Sdfr fprintf (headerfile, "heim_octet_string %s;\n", name); 74355682Smarkm break; 74455682Smarkm case TBitString: { 74555682Smarkm Member *m; 74655682Smarkm Type i; 747178825Sdfr struct range range = { 0, INT_MAX }; 74855682Smarkm 749178825Sdfr i.type = TInteger; 750178825Sdfr i.range = ⦥ 751178825Sdfr i.members = NULL; 752178825Sdfr i.constraint = NULL; 753178825Sdfr 75455682Smarkm space(level); 755233294Sstas if(ASN1_TAILQ_EMPTY(t->members)) 756178825Sdfr fprintf (headerfile, "heim_bit_string %s;\n", name); 757178825Sdfr else { 758233294Sstas int pos = 0; 759233294Sstas getnewbasename(&newbasename, typedefp, basename, name); 760233294Sstas 761233294Sstas fprintf (headerfile, "struct %s {\n", newbasename); 762178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 763233294Sstas char *n = NULL; 764233294Sstas 765233294Sstas /* pad unused */ 766233294Sstas while (pos < m->val) { 767233294Sstas if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL) 768233294Sstas errx(1, "malloc"); 769233294Sstas define_type (level + 1, n, newbasename, &i, FALSE, FALSE); 770233294Sstas free(n); 771233294Sstas pos++; 772233294Sstas } 773233294Sstas 774233294Sstas n = NULL; 775233294Sstas if (asprintf (&n, "%s:1", m->gen_name) < 0 || n == NULL) 776178825Sdfr errx(1, "malloc"); 777233294Sstas define_type (level + 1, n, newbasename, &i, FALSE, FALSE); 778178825Sdfr free (n); 779233294Sstas n = NULL; 780233294Sstas pos++; 781178825Sdfr } 782233294Sstas /* pad to 32 elements */ 783233294Sstas while (pos < 32) { 784233294Sstas char *n = NULL; 785233294Sstas if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL) 786233294Sstas errx(1, "malloc"); 787233294Sstas define_type (level + 1, n, newbasename, &i, FALSE, FALSE); 788233294Sstas free(n); 789233294Sstas pos++; 790233294Sstas } 791233294Sstas 792178825Sdfr space(level); 793178825Sdfr fprintf (headerfile, "} %s;\n\n", name); 79455682Smarkm } 79555682Smarkm break; 79655682Smarkm } 79790926Snectar case TEnumerated: { 79890926Snectar Member *m; 79990926Snectar 80090926Snectar space(level); 80190926Snectar fprintf (headerfile, "enum %s {\n", typedefp ? name : ""); 802178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 80390926Snectar space(level + 1); 804178825Sdfr if (m->ellipsis) 805178825Sdfr fprintf (headerfile, "/* ... */\n"); 806178825Sdfr else 807178825Sdfr fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val, 808178825Sdfr last_member_p(m)); 80990926Snectar } 81090926Snectar space(level); 81190926Snectar fprintf (headerfile, "} %s;\n\n", name); 81290926Snectar break; 81390926Snectar } 814178825Sdfr case TSet: 81555682Smarkm case TSequence: { 81655682Smarkm Member *m; 81755682Smarkm 818233294Sstas getnewbasename(&newbasename, typedefp, basename, name); 819233294Sstas 82055682Smarkm space(level); 821233294Sstas fprintf (headerfile, "struct %s {\n", newbasename); 822178825Sdfr if (t->type == TSequence && preservep) { 823178825Sdfr space(level + 1); 824178825Sdfr fprintf(headerfile, "heim_octet_string _save;\n"); 825178825Sdfr } 826178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 827178825Sdfr if (m->ellipsis) { 828178825Sdfr ; 829178825Sdfr } else if (m->optional) { 830233294Sstas char *n = NULL; 83155682Smarkm 832233294Sstas if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL) 833178825Sdfr errx(1, "malloc"); 834233294Sstas define_type (level + 1, n, newbasename, m->type, FALSE, FALSE); 83555682Smarkm free (n); 83655682Smarkm } else 837233294Sstas define_type (level + 1, m->gen_name, newbasename, m->type, FALSE, FALSE); 83855682Smarkm } 83955682Smarkm space(level); 84055682Smarkm fprintf (headerfile, "} %s;\n", name); 84155682Smarkm break; 84255682Smarkm } 843178825Sdfr case TSetOf: 84455682Smarkm case TSequenceOf: { 84555682Smarkm Type i; 846178825Sdfr struct range range = { 0, INT_MAX }; 84755682Smarkm 848233294Sstas getnewbasename(&newbasename, typedefp, basename, name); 849233294Sstas 850178825Sdfr i.type = TInteger; 851178825Sdfr i.range = ⦥ 852178825Sdfr i.members = NULL; 853178825Sdfr i.constraint = NULL; 85455682Smarkm 85555682Smarkm space(level); 856233294Sstas fprintf (headerfile, "struct %s {\n", newbasename); 857233294Sstas define_type (level + 1, "len", newbasename, &i, FALSE, FALSE); 858233294Sstas define_type (level + 1, "*val", newbasename, t->subtype, FALSE, FALSE); 85955682Smarkm space(level); 86055682Smarkm fprintf (headerfile, "} %s;\n", name); 86155682Smarkm break; 86255682Smarkm } 86355682Smarkm case TGeneralizedTime: 86455682Smarkm space(level); 86555682Smarkm fprintf (headerfile, "time_t %s;\n", name); 86655682Smarkm break; 86755682Smarkm case TGeneralString: 86855682Smarkm space(level); 869178825Sdfr fprintf (headerfile, "heim_general_string %s;\n", name); 87055682Smarkm break; 871233294Sstas case TTeletexString: 872233294Sstas space(level); 873233294Sstas fprintf (headerfile, "heim_general_string %s;\n", name); 874233294Sstas break; 875178825Sdfr case TTag: 876233294Sstas define_type (level, name, basename, t->subtype, typedefp, preservep); 87755682Smarkm break; 878178825Sdfr case TChoice: { 879178825Sdfr int first = 1; 880178825Sdfr Member *m; 881178825Sdfr 882233294Sstas getnewbasename(&newbasename, typedefp, basename, name); 883233294Sstas 884178825Sdfr space(level); 885233294Sstas fprintf (headerfile, "struct %s {\n", newbasename); 886178825Sdfr if (preservep) { 887178825Sdfr space(level + 1); 888178825Sdfr fprintf(headerfile, "heim_octet_string _save;\n"); 889178825Sdfr } 890178825Sdfr space(level + 1); 891178825Sdfr fprintf (headerfile, "enum {\n"); 892178825Sdfr m = have_ellipsis(t); 893178825Sdfr if (m) { 894178825Sdfr space(level + 2); 895233294Sstas fprintf (headerfile, "%s = 0,\n", m->label); 896178825Sdfr first = 0; 897178825Sdfr } 898178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 899178825Sdfr space(level + 2); 900178825Sdfr if (m->ellipsis) 901178825Sdfr fprintf (headerfile, "/* ... */\n"); 902178825Sdfr else 903233294Sstas fprintf (headerfile, "%s%s%s\n", m->label, 904233294Sstas first ? " = 1" : "", 905178825Sdfr last_member_p(m)); 906178825Sdfr first = 0; 907178825Sdfr } 908178825Sdfr space(level + 1); 909178825Sdfr fprintf (headerfile, "} element;\n"); 910178825Sdfr space(level + 1); 911178825Sdfr fprintf (headerfile, "union {\n"); 912178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 913178825Sdfr if (m->ellipsis) { 914178825Sdfr space(level + 2); 915178825Sdfr fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n"); 916178825Sdfr } else if (m->optional) { 917233294Sstas char *n = NULL; 918178825Sdfr 919233294Sstas if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL) 920178825Sdfr errx(1, "malloc"); 921233294Sstas define_type (level + 2, n, newbasename, m->type, FALSE, FALSE); 922178825Sdfr free (n); 923178825Sdfr } else 924233294Sstas define_type (level + 2, m->gen_name, newbasename, m->type, FALSE, FALSE); 925178825Sdfr } 926178825Sdfr space(level + 1); 927178825Sdfr fprintf (headerfile, "} u;\n"); 928178825Sdfr space(level); 929178825Sdfr fprintf (headerfile, "} %s;\n", name); 930178825Sdfr break; 931178825Sdfr } 932178825Sdfr case TUTCTime: 933178825Sdfr space(level); 934178825Sdfr fprintf (headerfile, "time_t %s;\n", name); 935178825Sdfr break; 936178825Sdfr case TUTF8String: 937178825Sdfr space(level); 938178825Sdfr fprintf (headerfile, "heim_utf8_string %s;\n", name); 939178825Sdfr break; 940178825Sdfr case TPrintableString: 941178825Sdfr space(level); 942178825Sdfr fprintf (headerfile, "heim_printable_string %s;\n", name); 943178825Sdfr break; 944178825Sdfr case TIA5String: 945178825Sdfr space(level); 946178825Sdfr fprintf (headerfile, "heim_ia5_string %s;\n", name); 947178825Sdfr break; 948178825Sdfr case TBMPString: 949178825Sdfr space(level); 950178825Sdfr fprintf (headerfile, "heim_bmp_string %s;\n", name); 951178825Sdfr break; 952178825Sdfr case TUniversalString: 953178825Sdfr space(level); 954178825Sdfr fprintf (headerfile, "heim_universal_string %s;\n", name); 955178825Sdfr break; 956178825Sdfr case TVisibleString: 957178825Sdfr space(level); 958178825Sdfr fprintf (headerfile, "heim_visible_string %s;\n", name); 959178825Sdfr break; 960178825Sdfr case TOID : 961178825Sdfr space(level); 962178825Sdfr fprintf (headerfile, "heim_oid %s;\n", name); 963178825Sdfr break; 964178825Sdfr case TNull: 965178825Sdfr space(level); 966178825Sdfr fprintf (headerfile, "int %s;\n", name); 967178825Sdfr break; 96855682Smarkm default: 96955682Smarkm abort (); 97055682Smarkm } 971233294Sstas if (newbasename) 972233294Sstas free(newbasename); 97355682Smarkm} 97455682Smarkm 97555682Smarkmstatic void 97655682Smarkmgenerate_type_header (const Symbol *s) 97755682Smarkm{ 978178825Sdfr int preservep = preserve_type(s->name) ? TRUE : FALSE; 979178825Sdfr 98055682Smarkm fprintf (headerfile, "/*\n"); 98155682Smarkm fprintf (headerfile, "%s ::= ", s->name); 98255682Smarkm define_asn1 (0, s->type); 98355682Smarkm fprintf (headerfile, "\n*/\n\n"); 98455682Smarkm 98555682Smarkm fprintf (headerfile, "typedef "); 986233294Sstas define_type (0, s->gen_name, s->gen_name, s->type, TRUE, preservep); 98755682Smarkm 98855682Smarkm fprintf (headerfile, "\n"); 98955682Smarkm} 99055682Smarkm 99155682Smarkmvoid 99255682Smarkmgenerate_type (const Symbol *s) 99355682Smarkm{ 994233294Sstas FILE *h; 995233294Sstas const char * exp; 99655682Smarkm 997233294Sstas if (!one_code_file) 998233294Sstas generate_header_of_codefile(s->gen_name); 999233294Sstas 100055682Smarkm generate_type_header (s); 1001233294Sstas 1002233294Sstas if (template_flag) 1003233294Sstas generate_template(s); 1004233294Sstas 1005233294Sstas if (template_flag == 0 || is_template_compat(s) == 0) { 1006233294Sstas generate_type_encode (s); 1007233294Sstas generate_type_decode (s); 1008233294Sstas generate_type_free (s); 1009233294Sstas generate_type_length (s); 1010233294Sstas generate_type_copy (s); 1011233294Sstas } 1012178825Sdfr generate_type_seq (s); 1013178825Sdfr generate_glue (s->type, s->gen_name); 1014233294Sstas 1015233294Sstas /* generate prototypes */ 1016233294Sstas 1017233294Sstas if (is_export(s->name)) { 1018233294Sstas h = headerfile; 1019233294Sstas exp = "ASN1EXP "; 1020233294Sstas } else { 1021233294Sstas h = privheaderfile; 1022233294Sstas exp = ""; 1023233294Sstas } 1024233294Sstas 1025233294Sstas fprintf (h, 1026233294Sstas "%sint ASN1CALL " 1027233294Sstas "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n", 1028233294Sstas exp, 1029233294Sstas s->gen_name, s->gen_name); 1030233294Sstas fprintf (h, 1031233294Sstas "%sint ASN1CALL " 1032233294Sstas "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n", 1033233294Sstas exp, 1034233294Sstas s->gen_name, s->gen_name); 1035233294Sstas fprintf (h, 1036233294Sstas "%ssize_t ASN1CALL length_%s(const %s *);\n", 1037233294Sstas exp, 1038233294Sstas s->gen_name, s->gen_name); 1039233294Sstas fprintf (h, 1040233294Sstas "%sint ASN1CALL copy_%s (const %s *, %s *);\n", 1041233294Sstas exp, 1042233294Sstas s->gen_name, s->gen_name, s->gen_name); 1043233294Sstas fprintf (h, 1044233294Sstas "%svoid ASN1CALL free_%s (%s *);\n", 1045233294Sstas exp, 1046233294Sstas s->gen_name, s->gen_name); 1047233294Sstas 1048233294Sstas fprintf(h, "\n\n"); 1049233294Sstas 1050233294Sstas if (!one_code_file) { 1051233294Sstas fprintf(codefile, "\n\n"); 1052233294Sstas close_codefile(); 1053233294Sstas } 105455682Smarkm} 1055