root/source4/heimdal/lib/asn1/gen.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. add_import
  2. get_filename
  3. init_generate
  4. close_generate
  5. gen_assign_defval
  6. gen_compare_defval
  7. generate_header_of_codefile
  8. close_codefile
  9. generate_constant
  10. space
  11. last_member_p
  12. have_ellipsis
  13. define_asn1
  14. define_type
  15. generate_type_header
  16. generate_type

   1 /*
   2  * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
   3  * (Royal Institute of Technology, Stockholm, Sweden).
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  *
  13  * 2. Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in the
  15  *    documentation and/or other materials provided with the distribution.
  16  *
  17  * 3. Neither the name of the Institute nor the names of its contributors
  18  *    may be used to endorse or promote products derived from this software
  19  *    without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31  * SUCH DAMAGE.
  32  */
  33 
  34 #include "gen_locl.h"
  35 
  36 RCSID("$Id$");
  37 
  38 FILE *headerfile, *codefile, *logfile;
  39 
  40 #define STEM "asn1"
  41 
  42 static const char *orig_filename;
  43 static char *header;
  44 static const char *headerbase = STEM;
  45 
  46 /*
  47  * list of all IMPORTs
  48  */
  49 
  50 struct import {
  51     const char *module;
  52     struct import *next;
  53 };
  54 
  55 static struct import *imports = NULL;
  56 
  57 void
  58 add_import (const char *module)
     /* [<][>][^][v][top][bottom][index][help] */
  59 {
  60     struct import *tmp = emalloc (sizeof(*tmp));
  61 
  62     tmp->module = module;
  63     tmp->next   = imports;
  64     imports     = tmp;
  65 
  66     fprintf (headerfile, "#include <%s_asn1.h>\n", module);
  67 }
  68 
  69 const char *
  70 get_filename (void)
     /* [<][>][^][v][top][bottom][index][help] */
  71 {
  72     return orig_filename;
  73 }
  74 
  75 void
  76 init_generate (const char *filename, const char *base)
     /* [<][>][^][v][top][bottom][index][help] */
  77 {
  78     char *fn;
  79 
  80     orig_filename = filename;
  81     if (base != NULL) {
  82         headerbase = strdup(base);
  83         if (headerbase == NULL)
  84             errx(1, "strdup");
  85     }
  86     asprintf(&header, "%s.h", headerbase);
  87     if (header == NULL)
  88         errx(1, "malloc");
  89     headerfile = fopen (header, "w");
  90     if (headerfile == NULL)
  91         err (1, "open %s", header);
  92     fprintf (headerfile,
  93              "/* Generated from %s */\n"
  94              "/* Do not edit */\n\n",
  95              filename);
  96     fprintf (headerfile,
  97              "#ifndef __%s_h__\n"
  98              "#define __%s_h__\n\n", headerbase, headerbase);
  99     fprintf (headerfile,
 100              "#include <stddef.h>\n"
 101              "#include <time.h>\n\n");
 102     fprintf (headerfile,
 103              "#ifndef __asn1_common_definitions__\n"
 104              "#define __asn1_common_definitions__\n\n");
 105     fprintf (headerfile,
 106              "typedef struct heim_integer {\n"
 107              "  size_t length;\n"
 108              "  void *data;\n"
 109              "  int negative;\n"
 110              "} heim_integer;\n\n");
 111     fprintf (headerfile,
 112              "typedef struct heim_octet_string {\n"
 113              "  size_t length;\n"
 114              "  void *data;\n"
 115              "} heim_octet_string;\n\n");
 116     fprintf (headerfile,
 117              "typedef char *heim_general_string;\n\n"
 118              );
 119     fprintf (headerfile,
 120              "typedef char *heim_utf8_string;\n\n"
 121              );
 122     fprintf (headerfile,
 123              "typedef char *heim_printable_string;\n\n"
 124              );
 125     fprintf (headerfile,
 126              "typedef char *heim_ia5_string;\n\n"
 127              );
 128     fprintf (headerfile,
 129              "typedef struct heim_bmp_string {\n"
 130              "  size_t length;\n"
 131              "  uint16_t *data;\n"
 132              "} heim_bmp_string;\n\n");
 133     fprintf (headerfile,
 134              "typedef struct heim_universal_string {\n"
 135              "  size_t length;\n"
 136              "  uint32_t *data;\n"
 137              "} heim_universal_string;\n\n");
 138     fprintf (headerfile,
 139              "typedef char *heim_visible_string;\n\n"
 140              );
 141     fprintf (headerfile,
 142              "typedef struct heim_oid {\n"
 143              "  size_t length;\n"
 144              "  unsigned *components;\n"
 145              "} heim_oid;\n\n");
 146     fprintf (headerfile,
 147              "typedef struct heim_bit_string {\n"
 148              "  size_t length;\n"
 149              "  void *data;\n"
 150              "} heim_bit_string;\n\n");
 151     fprintf (headerfile,
 152              "typedef struct heim_octet_string heim_any;\n"
 153              "typedef struct heim_octet_string heim_any_set;\n\n");
 154     fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R)                  \\\n"
 155           "  do {                                                         \\\n"
 156           "    (BL) = length_##T((S));                                    \\\n"
 157           "    (B) = malloc((BL));                                        \\\n"
 158           "    if((B) == NULL) {                                          \\\n"
 159           "      (R) = ENOMEM;                                            \\\n"
 160           "    } else {                                                   \\\n"
 161           "      (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n"
 162           "                       (S), (L));                              \\\n"
 163           "      if((R) != 0) {                                           \\\n"
 164           "        free((B));                                             \\\n"
 165           "        (B) = NULL;                                            \\\n"
 166           "      }                                                        \\\n"
 167           "    }                                                          \\\n"
 168           "  } while (0)\n\n",
 169           headerfile);
 170     fprintf (headerfile, "struct units;\n\n");
 171     fprintf (headerfile, "#endif\n\n");
 172     asprintf(&fn, "%s_files", base);
 173     if (fn == NULL)
 174         errx(1, "malloc");
 175     logfile = fopen(fn, "w");
 176     if (logfile == NULL)
 177         err (1, "open %s", fn);
 178 }
 179 
 180 void
 181 close_generate (void)
     /* [<][>][^][v][top][bottom][index][help] */
 182 {
 183     fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
 184 
 185     fclose (headerfile);
 186     fprintf (logfile, "\n");
 187     fclose (logfile);
 188 }
 189 
 190 void
 191 gen_assign_defval(const char *var, struct value *val)
     /* [<][>][^][v][top][bottom][index][help] */
 192 {
 193     switch(val->type) {
 194     case stringvalue:
 195         fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue);
 196         break;
 197     case integervalue:
 198         fprintf(codefile, "%s = %d;\n", var, val->u.integervalue);
 199         break;
 200     case booleanvalue:
 201         if(val->u.booleanvalue)
 202             fprintf(codefile, "%s = TRUE;\n", var);
 203         else
 204             fprintf(codefile, "%s = FALSE;\n", var);
 205         break;
 206     default:
 207         abort();
 208     }
 209 }
 210 
 211 void
 212 gen_compare_defval(const char *var, struct value *val)
     /* [<][>][^][v][top][bottom][index][help] */
 213 {
 214     switch(val->type) {
 215     case stringvalue:
 216         fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue);
 217         break;
 218     case integervalue:
 219         fprintf(codefile, "if(%s != %d)\n", var, val->u.integervalue);
 220         break;
 221     case booleanvalue:
 222         if(val->u.booleanvalue)
 223             fprintf(codefile, "if(!%s)\n", var);
 224         else
 225             fprintf(codefile, "if(%s)\n", var);
 226         break;
 227     default:
 228         abort();
 229     }
 230 }
 231 
 232 static void
 233 generate_header_of_codefile(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 234 {
 235     char *filename;
 236 
 237     if (codefile != NULL)
 238         abort();
 239 
 240     asprintf (&filename, "%s_%s.x", STEM, name);
 241     if (filename == NULL)
 242         errx(1, "malloc");
 243     codefile = fopen (filename, "w");
 244     if (codefile == NULL)
 245         err (1, "fopen %s", filename);
 246     fprintf(logfile, "%s ", filename);
 247     free(filename);
 248     fprintf (codefile,
 249              "/* Generated from %s */\n"
 250              "/* Do not edit */\n\n"
 251              "#include <stdio.h>\n"
 252              "#include <stdlib.h>\n"
 253              "#include <time.h>\n"
 254              "#include <string.h>\n"
 255              "#include <errno.h>\n"
 256              "#include <limits.h>\n"
 257              "#include <krb5-types.h>\n",
 258              orig_filename);
 259 
 260     fprintf (codefile,
 261              "#include <%s.h>\n",
 262              headerbase);
 263     fprintf (codefile,
 264              "#include <asn1_err.h>\n"
 265              "#include <der.h>\n"
 266              "#include <parse_units.h>\n\n");
 267 
 268 }
 269 
 270 static void
 271 close_codefile(void)
     /* [<][>][^][v][top][bottom][index][help] */
 272 {
 273     if (codefile == NULL)
 274         abort();
 275 
 276     fclose(codefile);
 277     codefile = NULL;
 278 }
 279 
 280 
 281 void
 282 generate_constant (const Symbol *s)
     /* [<][>][^][v][top][bottom][index][help] */
 283 {
 284     switch(s->value->type) {
 285     case booleanvalue:
 286         break;
 287     case integervalue:
 288         fprintf (headerfile, "enum { %s = %d };\n\n",
 289                  s->gen_name, s->value->u.integervalue);
 290         break;
 291     case nullvalue:
 292         break;
 293     case stringvalue:
 294         break;
 295     case objectidentifiervalue: {
 296         struct objid *o, **list;
 297         unsigned int i, len;
 298 
 299         generate_header_of_codefile(s->gen_name);
 300 
 301         len = 0;
 302         for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
 303             len++;
 304         if (len == 0) {
 305             printf("s->gen_name: %s",s->gen_name);
 306             fflush(stdout);
 307             break;
 308         }
 309         list = emalloc(sizeof(*list) * len);
 310 
 311         i = 0;
 312         for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
 313             list[i++] = o;
 314 
 315         fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name);
 316         for (i = len ; i > 0; i--) {
 317             o = list[i - 1];
 318             fprintf(headerfile, "%s(%d) ",
 319                     o->label ? o->label : "label-less", o->value);
 320         }
 321 
 322         fprintf (headerfile, "} */\n");
 323         fprintf (headerfile, "const heim_oid *oid_%s(void);\n\n",
 324                  s->gen_name);
 325 
 326         fprintf (codefile, "static unsigned oid_%s_variable_num[%d] =  {",
 327                  s->gen_name, len);
 328         for (i = len ; i > 0; i--) {
 329             fprintf(codefile, "%d%s ", list[i - 1]->value, i > 1 ? "," : "");
 330         }
 331         fprintf(codefile, "};\n");
 332 
 333         fprintf (codefile, "static const heim_oid oid_%s_variable = "
 334                  "{ %d, oid_%s_variable_num };\n\n",
 335                  s->gen_name, len, s->gen_name);
 336 
 337         fprintf (codefile, "const heim_oid *oid_%s(void)\n"
 338                  "{\n"
 339                  "return &oid_%s_variable;\n"
 340                  "}\n\n",
 341                  s->gen_name, s->gen_name);
 342 
 343         close_codefile();
 344 
 345         break;
 346     }
 347     default:
 348         abort();
 349     }
 350 }
 351 
 352 static void
 353 space(int level)
     /* [<][>][^][v][top][bottom][index][help] */
 354 {
 355     while(level-- > 0)
 356         fprintf(headerfile, "  ");
 357 }
 358 
 359 static const char *
 360 last_member_p(struct member *m)
     /* [<][>][^][v][top][bottom][index][help] */
 361 {
 362     struct member *n = ASN1_TAILQ_NEXT(m, members);
 363     if (n == NULL)
 364         return "";
 365     if (n->ellipsis && ASN1_TAILQ_NEXT(n, members) == NULL)
 366         return "";
 367     return ",";
 368 }
 369 
 370 static struct member *
 371 have_ellipsis(Type *t)
     /* [<][>][^][v][top][bottom][index][help] */
 372 {
 373     struct member *m;
 374     ASN1_TAILQ_FOREACH(m, t->members, members) {
 375         if (m->ellipsis)
 376             return m;
 377     }
 378     return NULL;
 379 }
 380 
 381 static void
 382 define_asn1 (int level, Type *t)
     /* [<][>][^][v][top][bottom][index][help] */
 383 {
 384     switch (t->type) {
 385     case TType:
 386         fprintf (headerfile, "%s", t->symbol->name);
 387         break;
 388     case TInteger:
 389         if(t->members == NULL) {
 390             fprintf (headerfile, "INTEGER");
 391             if (t->range)
 392                 fprintf (headerfile, " (%d..%d)",
 393                          t->range->min, t->range->max);
 394         } else {
 395             Member *m;
 396             fprintf (headerfile, "INTEGER {\n");
 397             ASN1_TAILQ_FOREACH(m, t->members, members) {
 398                 space (level + 1);
 399                 fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val,
 400                         last_member_p(m));
 401             }
 402             space(level);
 403             fprintf (headerfile, "}");
 404         }
 405         break;
 406     case TBoolean:
 407         fprintf (headerfile, "BOOLEAN");
 408         break;
 409     case TOctetString:
 410         fprintf (headerfile, "OCTET STRING");
 411         break;
 412     case TEnumerated :
 413     case TBitString: {
 414         Member *m;
 415 
 416         space(level);
 417         if(t->type == TBitString)
 418             fprintf (headerfile, "BIT STRING {\n");
 419         else
 420             fprintf (headerfile, "ENUMERATED {\n");
 421         ASN1_TAILQ_FOREACH(m, t->members, members) {
 422             space(level + 1);
 423             fprintf (headerfile, "%s(%d)%s\n", m->name, m->val,
 424                      last_member_p(m));
 425         }
 426         space(level);
 427         fprintf (headerfile, "}");
 428         break;
 429     }
 430     case TChoice:
 431     case TSet:
 432     case TSequence: {
 433         Member *m;
 434         int max_width = 0;
 435 
 436         if(t->type == TChoice)
 437             fprintf(headerfile, "CHOICE {\n");
 438         else if(t->type == TSet)
 439             fprintf(headerfile, "SET {\n");
 440         else
 441             fprintf(headerfile, "SEQUENCE {\n");
 442         ASN1_TAILQ_FOREACH(m, t->members, members) {
 443             if(strlen(m->name) > max_width)
 444                 max_width = strlen(m->name);
 445         }
 446         max_width += 3;
 447         if(max_width < 16) max_width = 16;
 448         ASN1_TAILQ_FOREACH(m, t->members, members) {
 449             int width = max_width;
 450             space(level + 1);
 451             if (m->ellipsis) {
 452                 fprintf (headerfile, "...");
 453             } else {
 454                 width -= fprintf(headerfile, "%s", m->name);
 455                 fprintf(headerfile, "%*s", width, "");
 456                 define_asn1(level + 1, m->type);
 457                 if(m->optional)
 458                     fprintf(headerfile, " OPTIONAL");
 459             }
 460             if(last_member_p(m))
 461                 fprintf (headerfile, ",");
 462             fprintf (headerfile, "\n");
 463         }
 464         space(level);
 465         fprintf (headerfile, "}");
 466         break;
 467     }
 468     case TSequenceOf:
 469         fprintf (headerfile, "SEQUENCE OF ");
 470         define_asn1 (0, t->subtype);
 471         break;
 472     case TSetOf:
 473         fprintf (headerfile, "SET OF ");
 474         define_asn1 (0, t->subtype);
 475         break;
 476     case TGeneralizedTime:
 477         fprintf (headerfile, "GeneralizedTime");
 478         break;
 479     case TGeneralString:
 480         fprintf (headerfile, "GeneralString");
 481         break;
 482     case TTag: {
 483         const char *classnames[] = { "UNIVERSAL ", "APPLICATION ",
 484                                      "" /* CONTEXT */, "PRIVATE " };
 485         if(t->tag.tagclass != ASN1_C_UNIV)
 486             fprintf (headerfile, "[%s%d] ",
 487                      classnames[t->tag.tagclass],
 488                      t->tag.tagvalue);
 489         if(t->tag.tagenv == TE_IMPLICIT)
 490             fprintf (headerfile, "IMPLICIT ");
 491         define_asn1 (level, t->subtype);
 492         break;
 493     }
 494     case TUTCTime:
 495         fprintf (headerfile, "UTCTime");
 496         break;
 497     case TUTF8String:
 498         space(level);
 499         fprintf (headerfile, "UTF8String");
 500         break;
 501     case TPrintableString:
 502         space(level);
 503         fprintf (headerfile, "PrintableString");
 504         break;
 505     case TIA5String:
 506         space(level);
 507         fprintf (headerfile, "IA5String");
 508         break;
 509     case TBMPString:
 510         space(level);
 511         fprintf (headerfile, "BMPString");
 512         break;
 513     case TUniversalString:
 514         space(level);
 515         fprintf (headerfile, "UniversalString");
 516         break;
 517     case TVisibleString:
 518         space(level);
 519         fprintf (headerfile, "VisibleString");
 520         break;
 521     case TOID :
 522         space(level);
 523         fprintf(headerfile, "OBJECT IDENTIFIER");
 524         break;
 525     case TNull:
 526         space(level);
 527         fprintf (headerfile, "NULL");
 528         break;
 529     default:
 530         abort ();
 531     }
 532 }
 533 
 534 static void
 535 define_type (int level, const char *name, Type *t, int typedefp, int preservep)
     /* [<][>][^][v][top][bottom][index][help] */
 536 {
 537     switch (t->type) {
 538     case TType:
 539         space(level);
 540         fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name);
 541         break;
 542     case TInteger:
 543         space(level);
 544         if(t->members) {
 545             Member *m;
 546             fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
 547             ASN1_TAILQ_FOREACH(m, t->members, members) {
 548                 space (level + 1);
 549                 fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val,
 550                         last_member_p(m));
 551             }
 552             fprintf (headerfile, "} %s;\n", name);
 553         } else if (t->range == NULL) {
 554             fprintf (headerfile, "heim_integer %s;\n", name);
 555         } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
 556             fprintf (headerfile, "int %s;\n", name);
 557         } else if (t->range->min == 0 && t->range->max == UINT_MAX) {
 558             fprintf (headerfile, "unsigned int %s;\n", name);
 559         } else if (t->range->min == 0 && t->range->max == INT_MAX) {
 560             fprintf (headerfile, "unsigned int %s;\n", name);
 561         } else
 562             errx(1, "%s: unsupported range %d -> %d",
 563                  name, t->range->min, t->range->max);
 564         break;
 565     case TBoolean:
 566         space(level);
 567         fprintf (headerfile, "int %s;\n", name);
 568         break;
 569     case TOctetString:
 570         space(level);
 571         fprintf (headerfile, "heim_octet_string %s;\n", name);
 572         break;
 573     case TBitString: {
 574         Member *m;
 575         Type i;
 576         struct range range = { 0, INT_MAX };
 577 
 578         i.type = TInteger;
 579         i.range = &range;
 580         i.members = NULL;
 581         i.constraint = NULL;
 582 
 583         space(level);
 584         if(ASN1_TAILQ_EMPTY(t->members))
 585             fprintf (headerfile, "heim_bit_string %s;\n", name);
 586         else {
 587             fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
 588             ASN1_TAILQ_FOREACH(m, t->members, members) {
 589                 char *n;
 590                 
 591                 asprintf (&n, "%s:1", m->gen_name);
 592                 if (n == NULL)
 593                     errx(1, "malloc");
 594                 define_type (level + 1, n, &i, FALSE, FALSE);
 595                 free (n);
 596             }
 597             space(level);
 598             fprintf (headerfile, "} %s;\n\n", name);
 599         }
 600         break;
 601     }
 602     case TEnumerated: {
 603         Member *m;
 604 
 605         space(level);
 606         fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
 607         ASN1_TAILQ_FOREACH(m, t->members, members) {
 608             space(level + 1);
 609             if (m->ellipsis)
 610                 fprintf (headerfile, "/* ... */\n");
 611             else
 612                 fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val,
 613                          last_member_p(m));
 614         }
 615         space(level);
 616         fprintf (headerfile, "} %s;\n\n", name);
 617         break;
 618     }
 619     case TSet:
 620     case TSequence: {
 621         Member *m;
 622 
 623         space(level);
 624         fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
 625         if (t->type == TSequence && preservep) {
 626             space(level + 1);
 627             fprintf(headerfile, "heim_octet_string _save;\n");
 628         }
 629         ASN1_TAILQ_FOREACH(m, t->members, members) {
 630             if (m->ellipsis) {
 631                 ;
 632             } else if (m->optional) {
 633                 char *n;
 634 
 635                 asprintf (&n, "*%s", m->gen_name);
 636                 if (n == NULL)
 637                     errx(1, "malloc");
 638                 define_type (level + 1, n, m->type, FALSE, FALSE);
 639                 free (n);
 640             } else
 641                 define_type (level + 1, m->gen_name, m->type, FALSE, FALSE);
 642         }
 643         space(level);
 644         fprintf (headerfile, "} %s;\n", name);
 645         break;
 646     }
 647     case TSetOf:
 648     case TSequenceOf: {
 649         Type i;
 650         struct range range = { 0, INT_MAX };
 651 
 652         i.type = TInteger;
 653         i.range = &range;
 654         i.members = NULL;
 655         i.constraint = NULL;
 656 
 657         space(level);
 658         fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
 659         define_type (level + 1, "len", &i, FALSE, FALSE);
 660         define_type (level + 1, "*val", t->subtype, FALSE, FALSE);
 661         space(level);
 662         fprintf (headerfile, "} %s;\n", name);
 663         break;
 664     }
 665     case TGeneralizedTime:
 666         space(level);
 667         fprintf (headerfile, "time_t %s;\n", name);
 668         break;
 669     case TGeneralString:
 670         space(level);
 671         fprintf (headerfile, "heim_general_string %s;\n", name);
 672         break;
 673     case TTag:
 674         define_type (level, name, t->subtype, typedefp, preservep);
 675         break;
 676     case TChoice: {
 677         int first = 1;
 678         Member *m;
 679 
 680         space(level);
 681         fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
 682         if (preservep) {
 683             space(level + 1);
 684             fprintf(headerfile, "heim_octet_string _save;\n");
 685         }
 686         space(level + 1);
 687         fprintf (headerfile, "enum {\n");
 688         m = have_ellipsis(t);
 689         if (m) {
 690             space(level + 2);
 691             fprintf (headerfile, "%s = 0,\n", m->label);
 692             first = 0;
 693         }
 694         ASN1_TAILQ_FOREACH(m, t->members, members) {
 695             space(level + 2);
 696             if (m->ellipsis)
 697                 fprintf (headerfile, "/* ... */\n");
 698             else
 699                 fprintf (headerfile, "%s%s%s\n", m->label,
 700                          first ? " = 1" : "",
 701                          last_member_p(m));
 702             first = 0;
 703         }
 704         space(level + 1);
 705         fprintf (headerfile, "} element;\n");
 706         space(level + 1);
 707         fprintf (headerfile, "union {\n");
 708         ASN1_TAILQ_FOREACH(m, t->members, members) {
 709             if (m->ellipsis) {
 710                 space(level + 2);
 711                 fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");
 712             } else if (m->optional) {
 713                 char *n;
 714 
 715                 asprintf (&n, "*%s", m->gen_name);
 716                 if (n == NULL)
 717                     errx(1, "malloc");
 718                 define_type (level + 2, n, m->type, FALSE, FALSE);
 719                 free (n);
 720             } else
 721                 define_type (level + 2, m->gen_name, m->type, FALSE, FALSE);
 722         }
 723         space(level + 1);
 724         fprintf (headerfile, "} u;\n");
 725         space(level);
 726         fprintf (headerfile, "} %s;\n", name);
 727         break;
 728     }
 729     case TUTCTime:
 730         space(level);
 731         fprintf (headerfile, "time_t %s;\n", name);
 732         break;
 733     case TUTF8String:
 734         space(level);
 735         fprintf (headerfile, "heim_utf8_string %s;\n", name);
 736         break;
 737     case TPrintableString:
 738         space(level);
 739         fprintf (headerfile, "heim_printable_string %s;\n", name);
 740         break;
 741     case TIA5String:
 742         space(level);
 743         fprintf (headerfile, "heim_ia5_string %s;\n", name);
 744         break;
 745     case TBMPString:
 746         space(level);
 747         fprintf (headerfile, "heim_bmp_string %s;\n", name);
 748         break;
 749     case TUniversalString:
 750         space(level);
 751         fprintf (headerfile, "heim_universal_string %s;\n", name);
 752         break;
 753     case TVisibleString:
 754         space(level);
 755         fprintf (headerfile, "heim_visible_string %s;\n", name);
 756         break;
 757     case TOID :
 758         space(level);
 759         fprintf (headerfile, "heim_oid %s;\n", name);
 760         break;
 761     case TNull:
 762         space(level);
 763         fprintf (headerfile, "int %s;\n", name);
 764         break;
 765     default:
 766         abort ();
 767     }
 768 }
 769 
 770 static void
 771 generate_type_header (const Symbol *s)
     /* [<][>][^][v][top][bottom][index][help] */
 772 {
 773     int preservep = preserve_type(s->name) ? TRUE : FALSE;
 774 
 775     fprintf (headerfile, "/*\n");
 776     fprintf (headerfile, "%s ::= ", s->name);
 777     define_asn1 (0, s->type);
 778     fprintf (headerfile, "\n*/\n\n");
 779 
 780     fprintf (headerfile, "typedef ");
 781     define_type (0, s->gen_name, s->type, TRUE, preservep);
 782 
 783     fprintf (headerfile, "\n");
 784 }
 785 
 786 
 787 void
 788 generate_type (const Symbol *s)
     /* [<][>][^][v][top][bottom][index][help] */
 789 {
 790     generate_header_of_codefile(s->gen_name);
 791 
 792     generate_type_header (s);
 793     generate_type_encode (s);
 794     generate_type_decode (s);
 795     generate_type_free (s);
 796     generate_type_length (s);
 797     generate_type_copy (s);
 798     generate_type_seq (s);
 799     generate_glue (s->type, s->gen_name);
 800     fprintf(headerfile, "\n\n");
 801     close_codefile();
 802 }

/* [<][>][^][v][top][bottom][index][help] */