LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/asn1 - gen.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 1023 1233 83.0 %
Date: 2024-04-21 15:09:00 Functions: 26 29 89.7 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  *
      12             :  * 1. Redistributions of source code must retain the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer.
      14             :  *
      15             :  * 2. Redistributions in binary form must reproduce the above copyright
      16             :  *    notice, this list of conditions and the following disclaimer in the
      17             :  *    documentation and/or other materials provided with the distribution.
      18             :  *
      19             :  * 3. Neither the name of the Institute nor the names of its contributors
      20             :  *    may be used to endorse or promote products derived from this software
      21             :  *    without specific prior written permission.
      22             :  *
      23             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      24             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      25             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      26             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      27             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      28             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      29             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      30             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      31             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      32             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      33             :  * SUCH DAMAGE.
      34             :  */
      35             : 
      36             : #include "gen_locl.h"
      37             : 
      38             : extern const char *enum_prefix;
      39             : extern int prefix_enum;
      40             : 
      41             : RCSID("$Id$");
      42             : 
      43             : FILE *jsonfile, *privheaderfile, *headerfile, *oidsfile, *codefile, *logfile, *templatefile;
      44             : FILE *symsfile;
      45             : 
      46             : #define STEM "asn1"
      47             : 
      48             : static const char *orig_filename;
      49             : static char *privheader, *header, *template;
      50             : static const char *headerbase = STEM;
      51             : 
      52             : /* XXX same as der_length_tag */
      53             : static size_t
      54        7600 : length_tag(unsigned int tag)
      55             : {
      56        7600 :     size_t len = 0;
      57             : 
      58        7600 :     if(tag <= 30)
      59        7128 :         return 1;
      60         190 :     while(tag) {
      61         114 :         tag /= 128;
      62         114 :         len++;
      63             :     }
      64          76 :     return len + 1;
      65             : }
      66             : 
      67             : /*
      68             :  * list of all IMPORTs
      69             :  */
      70             : 
      71             : struct import {
      72             :     const char *module;
      73             :     struct import *next;
      74             : };
      75             : 
      76             : static struct import *imports = NULL;
      77             : 
      78             : void
      79         437 : add_import (const char *module)
      80             : {
      81         437 :     struct import *tmp = emalloc (sizeof(*tmp));
      82             : 
      83         437 :     tmp->module = module;
      84         437 :     tmp->next   = imports;
      85         437 :     imports     = tmp;
      86             : 
      87         437 :     fprintf (headerfile, "#include <%s_asn1.h>\n", module);
      88         437 :     fprintf(jsonfile, "{\"imports\":\"%s\"}\n", module);
      89         437 : }
      90             : 
      91             : /*
      92             :  * List of all exported symbols
      93             :  *
      94             :  * XXX A hash table would be nice here.
      95             :  */
      96             : 
      97             : struct sexport {
      98             :     const char *name;
      99             :     int defined;
     100             :     struct sexport *next;
     101             : };
     102             : 
     103             : static struct sexport *exports = NULL;
     104             : 
     105             : void
     106        1691 : add_export (const char *name)
     107             : {
     108        1691 :     struct sexport *tmp = emalloc (sizeof(*tmp));
     109             : 
     110        1691 :     tmp->name   = name;
     111        1691 :     tmp->next   = exports;
     112        1691 :     exports     = tmp;
     113        1691 : }
     114             : 
     115             : int
     116       38855 : is_export(const char *name)
     117             : {
     118        2045 :     struct sexport *tmp;
     119             : 
     120       38855 :     if (exports == NULL) /* no export list, all exported */
     121       28242 :         return 1;
     122             : 
     123      504146 :     for (tmp = exports; tmp != NULL; tmp = tmp->next) {
     124      501942 :         if (strcmp(tmp->name, name) == 0) {
     125        6840 :             tmp->defined = 1;
     126        6840 :             return 1;
     127             :         }
     128             :     }
     129        2088 :     return 0;
     130             : }
     131             : 
     132             : const char *
     133           0 : get_filename (void)
     134             : {
     135           0 :     return orig_filename;
     136             : }
     137             : 
     138             : void
     139         304 : init_generate (const char *filename, const char *base)
     140             : {
     141         304 :     char *fn = NULL;
     142             : 
     143         304 :     orig_filename = filename;
     144         304 :     if (base != NULL) {
     145         304 :         headerbase = strdup(base);
     146         304 :         if (headerbase == NULL)
     147           0 :             errx(1, "strdup");
     148             :     }
     149             : 
     150             :     /* JSON file */
     151         304 :     if (asprintf(&fn, "%s.json", headerbase) < 0 || fn == NULL)
     152           0 :         errx(1, "malloc");
     153         304 :     jsonfile = fopen(fn, "w");
     154         304 :     if (jsonfile == NULL)
     155           0 :         err(1, "open %s", fn);
     156         304 :     free(fn);
     157         304 :     fn = NULL;
     158             : 
     159             :     /* public header file */
     160         304 :     if (asprintf(&header, "%s.h", headerbase) < 0 || header == NULL)
     161           0 :         errx(1, "malloc");
     162         304 :     if (asprintf(&fn, "%s.h", headerbase) < 0 || fn == NULL)
     163           0 :         errx(1, "malloc");
     164         304 :     headerfile = fopen (fn, "w");
     165         304 :     if (headerfile == NULL)
     166           0 :         err (1, "open %s", fn);
     167         304 :     free(fn);
     168         304 :     fn = NULL;
     169             : 
     170             :     /* private header file */
     171         304 :     if (asprintf(&privheader, "%s-priv.h", headerbase) < 0 || privheader == NULL)
     172           0 :         errx(1, "malloc");
     173         304 :     if (asprintf(&fn, "%s-priv.h", headerbase) < 0 || fn == NULL)
     174           0 :         errx(1, "malloc");
     175         304 :     privheaderfile = fopen (fn, "w");
     176         304 :     if (privheaderfile == NULL)
     177           0 :         err (1, "open %s", fn);
     178         304 :     free(fn);
     179         304 :     fn = NULL;
     180             : 
     181             :     /* template file */
     182         304 :     if (asprintf(&template, "%s-template.c", headerbase) < 0 || template == NULL)
     183           0 :         errx(1, "malloc");
     184         304 :     fprintf (headerfile,
     185             :              "/* Generated from %s */\n"
     186             :              "/* Do not edit */\n\n",
     187             :              filename);
     188         304 :     fprintf (headerfile,
     189             :              "#ifndef __%s_h__\n"
     190             :              "#define __%s_h__\n\n", headerbase, headerbase);
     191         304 :     fprintf (headerfile,
     192             :              "#include <stddef.h>\n"
     193             :              "#include <stdint.h>\n"
     194             :              "#include <time.h>\n\n");
     195         304 :     fprintf (headerfile,
     196             :              "#ifndef __asn1_common_definitions__\n"
     197             :              "#define __asn1_common_definitions__\n\n");
     198         304 :         fprintf (headerfile,
     199             :                  "#ifndef __HEIM_BASE_DATA__\n"
     200             :                  "#define __HEIM_BASE_DATA__ 1\n"
     201             :                  "struct heim_base_data {\n"
     202             :                  "    size_t length;\n"
     203             :                  "    void *data;\n"
     204             :                  "};\n"
     205             :                  "typedef struct heim_base_data heim_octet_string;\n"
     206             :                  "#endif\n\n");
     207         304 :     fprintf (headerfile,
     208             :              "typedef struct heim_integer {\n"
     209             :              "  size_t length;\n"
     210             :              "  void *data;\n"
     211             :              "  int negative;\n"
     212             :              "} heim_integer;\n\n");
     213         304 :     fprintf (headerfile,
     214             :              "typedef char *heim_general_string;\n\n"
     215             :              );
     216         304 :     fprintf (headerfile,
     217             :              "typedef char *heim_utf8_string;\n\n"
     218             :              );
     219         304 :     fprintf (headerfile,
     220             :              "typedef struct heim_base_data heim_printable_string;\n\n"
     221             :              );
     222         304 :     fprintf (headerfile,
     223             :              "typedef struct heim_base_data heim_ia5_string;\n\n"
     224             :              );
     225         304 :     fprintf (headerfile,
     226             :              "typedef struct heim_bmp_string {\n"
     227             :              "  size_t length;\n"
     228             :              "  uint16_t *data;\n"
     229             :              "} heim_bmp_string;\n\n");
     230         304 :     fprintf (headerfile,
     231             :              "typedef struct heim_universal_string {\n"
     232             :              "  size_t length;\n"
     233             :              "  uint32_t *data;\n"
     234             :              "} heim_universal_string;\n\n");
     235         304 :     fprintf (headerfile,
     236             :              "typedef char *heim_visible_string;\n\n"
     237             :              );
     238         304 :     fprintf (headerfile,
     239             :              "typedef struct heim_oid {\n"
     240             :              "  size_t length;\n"
     241             :              "  unsigned *components;\n"
     242             :              "} heim_oid;\n\n");
     243         304 :     fprintf (headerfile,
     244             :              "typedef struct heim_bit_string {\n"
     245             :              "  size_t length;\n"
     246             :              "  void *data;\n"
     247             :              "} heim_bit_string;\n\n");
     248         304 :     fprintf (headerfile,
     249             :              "typedef struct heim_base_data heim_any;\n"
     250             :              "typedef struct heim_base_data heim_any_set;\n"
     251             :              "typedef struct heim_base_data HEIM_ANY;\n"
     252             :              "typedef struct heim_base_data HEIM_ANY_SET;\n\n");
     253             : 
     254         304 :     fprintf (headerfile,
     255             :              "enum asn1_print_flags {\n"
     256             :              "   ASN1_PRINT_INDENT = 1,\n"
     257             :              "};\n\n");
     258         304 :     fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R)                  \\\n"
     259             :           "  do {                                                         \\\n"
     260             :           "    (BL) = length_##T((S));                                    \\\n"
     261             :           "    (B) = calloc(1, (BL));                                     \\\n"
     262             :           "    if((B) == NULL) {                                          \\\n"
     263             :           "      *(L) = 0;                                                \\\n"
     264             :           "      (R) = ENOMEM;                                            \\\n"
     265             :           "    } else {                                                   \\\n"
     266             :           "      (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n"
     267             :           "                       (S), (L));                              \\\n"
     268             :           "      if((R) != 0) {                                           \\\n"
     269             :           "        free((B));                                             \\\n"
     270             :           "        (B) = NULL;                                            \\\n"
     271             :           "        *(L) = 0;                                              \\\n"
     272             :           "      }                                                        \\\n"
     273             :           "    }                                                          \\\n"
     274             :           "  } while (0)\n\n",
     275             :           headerfile);
     276         304 :     fputs("#ifdef _WIN32\n"
     277             :           "#ifndef ASN1_LIB\n"
     278             :           "#define ASN1EXP  __declspec(dllimport)\n"
     279             :           "#else\n"
     280             :           "#define ASN1EXP\n"
     281             :           "#endif\n"
     282             :           "#define ASN1CALL __stdcall\n"
     283             :           "#else\n"
     284             :           "#define ASN1EXP\n"
     285             :           "#define ASN1CALL\n"
     286             :           "#endif\n",
     287             :           headerfile);
     288         304 :     fputs("#ifndef ENOTSUP\n"
     289             :           "/* Very old MSVC CRTs lack ENOTSUP */\n"
     290             :           "#define ENOTSUP EINVAL\n"
     291             :           "#endif\n",
     292             :           headerfile);
     293         304 :     fprintf (headerfile, "struct units;\n\n");
     294         304 :     fprintf (headerfile, "#endif\n\n");
     295         304 :     if (asprintf(&fn, "%s_files", base) < 0 || fn == NULL)
     296           0 :         errx(1, "malloc");
     297         304 :     logfile = fopen(fn, "w");
     298         304 :     if (logfile == NULL)
     299           0 :         err (1, "open %s", fn);
     300         304 :     free(fn);
     301         304 :     fn = NULL;
     302             : 
     303         304 :     if (asprintf(&fn, "%s_oids.c", base) < 0 || fn == NULL)
     304           0 :         errx(1, "malloc");
     305         304 :     oidsfile = fopen(fn, "w");
     306         304 :     if (oidsfile == NULL)
     307           0 :         err (1, "open %s", fn);
     308         304 :     if (asprintf(&fn, "%s_syms.c", base) < 0 || fn == NULL)
     309           0 :         errx(1, "malloc");
     310         304 :     symsfile = fopen(fn, "w");
     311         304 :     if (symsfile == NULL)
     312           0 :         err (1, "open %s", fn);
     313         304 :     free(fn);
     314         304 :     fn = NULL;
     315             : 
     316             :     /* if one code file, write into the one codefile */
     317         304 :     if (one_code_file)
     318         304 :         return;
     319             : 
     320           0 :     templatefile = fopen (template, "w");
     321           0 :     if (templatefile == NULL)
     322           0 :         err (1, "open %s", template);
     323             : 
     324           0 :     fprintf (templatefile,
     325             :              "/* Generated from %s */\n"
     326             :              "/* Do not edit */\n\n"
     327             :              "#include <stdio.h>\n"
     328             :              "#include <stdlib.h>\n"
     329             :              "#include <time.h>\n"
     330             :              "#include <string.h>\n"
     331             :              "#include <errno.h>\n"
     332             :              "#include <limits.h>\n"
     333             :              "#include <asn1_err.h>\n"
     334             :              "#include <%s>\n",
     335             :              filename,
     336             :              type_file_string);
     337             : 
     338           0 :     fprintf (templatefile,
     339             :              "#include <%s>\n"
     340             :              "#include <%s>\n"
     341             :              "#include <der.h>\n"
     342             :              "#include <asn1-template.h>\n",
     343             :              header, privheader);
     344             : 
     345             : 
     346             : }
     347             : 
     348             : void
     349         304 : close_generate (void)
     350             : {
     351         304 :     fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
     352             : 
     353         304 :     if (headerfile && fclose(headerfile) == EOF)
     354           0 :         err(1, "writes to public header file failed");
     355         304 :     if (privheaderfile && fclose(privheaderfile) == EOF)
     356           0 :         err(1, "writes to private header file failed");
     357         304 :     if (templatefile && fclose(templatefile) == EOF)
     358           0 :         err(1, "writes to template file failed");
     359         304 :     if (!jsonfile) abort();
     360         304 :     if (fclose(jsonfile) == EOF)
     361           0 :         err(1, "writes to JSON file failed");
     362         304 :     if (!oidsfile) abort();
     363         304 :     if (fclose(oidsfile) == EOF)
     364           0 :         err(1, "writes to OIDs file failed");
     365         304 :     if (!symsfile) abort();
     366         304 :     if (fclose(symsfile) == EOF)
     367           0 :         err(1, "writes to symbols file failed");
     368         304 :     if (!logfile) abort();
     369         304 :     fprintf(logfile, "\n");
     370         304 :     if (fclose(logfile) == EOF)
     371           0 :         err(1, "writes to log file failed");
     372         304 : }
     373             : 
     374             : void
     375           0 : gen_assign_defval(const char *var, struct value *val)
     376             : {
     377           0 :     switch(val->type) {
     378           0 :     case stringvalue:
     379           0 :         fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue);
     380           0 :         break;
     381           0 :     case integervalue:
     382           0 :         fprintf(codefile, "%s = %lld;\n",
     383           0 :                 var, (long long)val->u.integervalue);
     384           0 :         break;
     385           0 :     case booleanvalue:
     386           0 :         if(val->u.booleanvalue)
     387           0 :             fprintf(codefile, "%s = 1;\n", var);
     388             :         else
     389           0 :             fprintf(codefile, "%s = 0;\n", var);
     390           0 :         break;
     391           0 :     default:
     392           0 :         abort();
     393             :     }
     394           0 : }
     395             : 
     396             : void
     397           0 : gen_compare_defval(const char *var, struct value *val)
     398             : {
     399           0 :     switch(val->type) {
     400           0 :     case stringvalue:
     401           0 :         fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue);
     402           0 :         break;
     403           0 :     case integervalue:
     404           0 :         fprintf(codefile, "if(%s != %lld)\n",
     405           0 :                 var, (long long)val->u.integervalue);
     406           0 :         break;
     407           0 :     case booleanvalue:
     408           0 :         if(val->u.booleanvalue)
     409           0 :             fprintf(codefile, "if(!%s)\n", var);
     410             :         else
     411           0 :             fprintf(codefile, "if(%s)\n", var);
     412           0 :         break;
     413           0 :     default:
     414           0 :         abort();
     415             :     }
     416           0 : }
     417             : 
     418             : void
     419         304 : generate_header_of_codefile(const char *name)
     420             : {
     421         304 :     char *filename = NULL;
     422             : 
     423         304 :     if (codefile != NULL)
     424           0 :         abort();
     425             : 
     426         304 :     if (asprintf (&filename, "%s_%s.c", STEM, name) < 0 || filename == NULL)
     427           0 :         errx(1, "malloc");
     428         304 :     codefile = fopen (filename, "w");
     429         304 :     if (codefile == NULL)
     430           0 :         err (1, "fopen %s", filename);
     431         304 :     if (logfile)
     432         304 :         fprintf(logfile, "%s ", filename);
     433         304 :     free(filename);
     434         304 :     filename = NULL;
     435         304 :     fprintf (codefile,
     436             :              "/* Generated from %s */\n"
     437             :              "/* Do not edit */\n\n"
     438             :              "#if defined(_WIN32) && !defined(ASN1_LIB)\n"
     439             :              "# error \"ASN1_LIB must be defined\"\n"
     440             :              "#endif\n"
     441             :              "#include <stdio.h>\n"
     442             :              "#include <stdlib.h>\n"
     443             :              "#include <time.h>\n"
     444             :              "#include <string.h>\n"
     445             :              "#include <errno.h>\n"
     446             :              "#include <limits.h>\n"
     447             :              "#include <%s>\n",
     448             :              orig_filename,
     449             :              type_file_string);
     450             : 
     451         304 :     fprintf (codefile,
     452             :              "#include \"%s\"\n"
     453             :              "#include \"%s\"\n",
     454             :              header, privheader);
     455         304 :     fprintf (codefile,
     456             :              "#include <asn1_err.h>\n"
     457             :              "#include <der.h>\n"
     458             :              "#include <asn1-template.h>\n\n");
     459             : 
     460         304 :     if (parse_units_flag)
     461         304 :         fprintf (codefile,
     462             :                  "#include <parse_units.h>\n\n");
     463             : 
     464             : #ifdef _WIN32
     465             :     fprintf(codefile, "#pragma warning(disable: 4101)\n\n");
     466             : #endif
     467         304 : }
     468             : 
     469             : void
     470         304 : close_codefile(void)
     471             : {
     472         304 :     if (codefile == NULL)
     473           0 :         abort();
     474             : 
     475         304 :     if (fclose(codefile) == EOF)
     476           0 :         err(1, "writes to source code file failed");
     477         304 :     codefile = NULL;
     478         304 : }
     479             : 
     480             : /* Object identifiers are parsed backwards; this reverses that */
     481             : struct objid **
     482        4921 : objid2list(struct objid *o)
     483             : {
     484         259 :     struct objid *el, **list;
     485         259 :     size_t i, len;
     486             : 
     487       37297 :     for (el = o, len = 0; el; el = el->next)
     488       32376 :         len++;
     489        4921 :     if (len == 0)
     490         270 :         return NULL;
     491        4636 :     list = ecalloc(len + 1, sizeof(*list));
     492             : 
     493       37256 :     for (i = 0; o; o = o->next)
     494       32376 :         list[i++] = o;
     495        4636 :     list[i] = NULL;
     496             : 
     497             :     /* Reverse the list */
     498       19475 :     for (i = 0; i < (len>>1); i++) {
     499       14839 :         el = list[i];
     500       14839 :         list[i] = list[len - (i + 1)];
     501       14839 :         list[len - (i + 1)] = el;
     502             :     }
     503        4392 :     return list;
     504             : }
     505             : 
     506             : void
     507        5529 : generate_constant (const Symbol *s)
     508             : {
     509        5529 :     switch(s->value->type) {
     510           0 :     case booleanvalue:
     511           0 :         break;
     512         912 :     case integervalue:
     513             :         /*
     514             :          * Work around the fact that OpenSSL defines macros for PKIX constants
     515             :          * that we want to generate as enums, which causes conflicts for things
     516             :          * like ub-name (ub_name).
     517             :          */
     518         960 :         fprintf(headerfile,
     519             :                 "#ifdef %s\n"
     520             :                 "#undef %s\n"
     521             :                 "#endif\n"
     522             :                 "enum { %s = %lld };\n\n",
     523         912 :                 s->gen_name, s->gen_name, s->gen_name,
     524         912 :                 (long long)s->value->u.integervalue);
     525         912 :         if (is_export(s->name))
     526         922 :             fprintf(symsfile, "ASN1_SYM_INTVAL(\"%s\", \"%s\", %s, %lld)\n",
     527         874 :                     s->name, s->gen_name, s->gen_name,
     528         874 :                     (long long)s->value->u.integervalue);
     529         912 :         fprintf(jsonfile,
     530             :                 "{\"name\":\"%s\",\"gen_name\":\"%s\",\"type\":\"INTEGER\","
     531             :                 "\"constant\":true,\"exported\":%s,\"value\":%lld}\n",
     532         912 :                 s->name, s->gen_name, is_export(s->name) ? "true" : "false",
     533         912 :                 (long long)s->value->u.integervalue);
     534         864 :         break;
     535           0 :     case nullvalue:
     536           0 :         break;
     537           0 :     case stringvalue:
     538           0 :         break;
     539        4617 :     case objectidentifiervalue: {
     540         243 :         struct objid *o, **list;
     541         243 :         size_t i, len;
     542         243 :         char *gen_upper;
     543             : 
     544        4617 :         if (!one_code_file)
     545           0 :             generate_header_of_codefile(s->gen_name);
     546             : 
     547        4617 :         list = objid2list(s->value->u.objectidentifiervalue);
     548       37065 :         for (len = 0; list && list[len]; len++)
     549             :             ;
     550        4617 :         if (len == 0) {
     551           0 :             errx(1, "Empty OBJECT IDENTIFIER named %s\n", s->name);
     552         243 :             break;
     553             :         }
     554             : 
     555        4617 :         fprintf(jsonfile,
     556             :                 "{\"name\":\"%s\",\"gen_name\":\"%s\","
     557             :                 "\"type\":\"OBJECT IDENTIFIER\","
     558             :                 "\"constant\":true,\"exported\":%s,\"value\":[\n",
     559        9234 :                 s->name, s->gen_name, is_export(s->name) ? "true" : "false");
     560        4617 :         fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name);
     561       37065 :         for (i = 0; i < len; i++) {
     562       32205 :             o = list[i];
     563       32205 :             fprintf(headerfile, "%s(%d) ",
     564       32205 :                     o->label ? o->label : "label-less", o->value);
     565       32205 :             if (o->label == NULL)
     566        9895 :                 fprintf(jsonfile, "%s{\"label\":null,\"value\":%d}",
     567             :                         i ? "," : "", o->value);
     568             :             else
     569       23073 :                 fprintf(jsonfile, "%s{\"label\":\"%s\",\"value\":%d}",
     570             :                         i ? "," : "", o->label, o->value);
     571             :         }
     572        4617 :         fprintf(jsonfile, "]}\n");
     573             : 
     574        4617 :         fprintf (codefile, "static unsigned oid_%s_variable_num[%lu] =  {",
     575        4617 :                  s->gen_name, (unsigned long)len);
     576       37065 :         for (i = 0; list[i]; i++) {
     577       32448 :             fprintf(codefile, "%s %d", i ? "," : "", list[i]->value);
     578             :         }
     579        4617 :         fprintf(codefile, "};\n");
     580             : 
     581        4860 :         fprintf (codefile, "const heim_oid asn1_oid_%s = "
     582             :                  "{ %lu, oid_%s_variable_num };\n\n",
     583        4617 :                  s->gen_name, (unsigned long)len, s->gen_name);
     584             : 
     585        4617 :         fprintf(oidsfile, "DEFINE_OID_WITH_NAME(%s)\n", s->gen_name);
     586        4617 :         if (is_export(s->name))
     587        4860 :             fprintf(symsfile, "ASN1_SYM_OID(\"%s\", \"%s\", %s)\n",
     588        4617 :                     s->name, s->gen_name, s->gen_name);
     589             : 
     590        4617 :         free(list);
     591             : 
     592             :         /* header file */
     593             : 
     594        4617 :         gen_upper = strdup(s->gen_name);
     595        4617 :         len = strlen(gen_upper);
     596       97147 :         for (i = 0; i < len; i++)
     597       92530 :             gen_upper[i] = toupper((unsigned char)s->gen_name[i]);
     598             : 
     599        4617 :         fprintf (headerfile, "} */\n");
     600        4860 :         fprintf (headerfile,
     601             :                  "extern ASN1EXP const heim_oid asn1_oid_%s;\n"
     602             :                  "#define ASN1_OID_%s (&asn1_oid_%s)\n\n",
     603        4374 :                  s->gen_name,
     604             :                  gen_upper,
     605        4617 :                  s->gen_name);
     606             : 
     607        4617 :         free(gen_upper);
     608             : 
     609        4617 :         if (!one_code_file)
     610           0 :             close_codefile();
     611             : 
     612        4374 :         break;
     613             :     }
     614           0 :     default:
     615           0 :         abort();
     616             :     }
     617        5529 : }
     618             : 
     619             : int
     620          57 : is_tagged_type(const Type *t)
     621             : {
     622             :     /*
     623             :      * Start by chasing aliasings like this:
     624             :      *
     625             :      * Type0 ::= ...
     626             :      * Type1 ::= Type0
     627             :      * ..
     628             :      * TypeN ::= TypeN-1
     629             :      *
     630             :      * to <Type0>, then check if <Type0> is tagged.
     631             :      */
     632          60 :     while (t->type == TType) {
     633           0 :         if (t->subtype)
     634           0 :             t = t->subtype;
     635           0 :         else if (t->symbol && t->symbol->type)
     636           0 :             t = t->symbol->type;
     637             :         else
     638           0 :             abort();
     639             : 
     640             :     }
     641          57 :     if (t->type == TTag && t->tag.tagenv == TE_EXPLICIT)
     642          54 :         return 1;
     643           0 :     if (t->type == TTag) {
     644           0 :         if (t->subtype)
     645           0 :             return is_tagged_type(t->subtype);
     646           0 :         if (t->symbol && t->symbol->type)
     647           0 :             return is_tagged_type(t->symbol->type);
     648             :         /* This is the tag */
     649           0 :         return 1;
     650             :     }
     651           0 :     return 0;
     652             : }
     653             : 
     654             : int
     655       21563 : is_primitive_type(const Type *t)
     656             : {
     657             :     /*
     658             :      * Start by chasing aliasings like this:
     659             :      *
     660             :      * Type0 ::= ...
     661             :      * Type1 ::= Type0
     662             :      * ..
     663             :      * TypeN ::= TypeN-1
     664             :      *
     665             :      * to <Type0>, then check if <Type0> is primitive.
     666             :      */
     667       21603 :     while (t->type == TType &&
     668       21603 :            t->symbol &&
     669        2223 :            t->symbol->type) {
     670        1577 :         if (t->symbol->type->type == TType)
     671           0 :             t = t->symbol->type; /* Alias */
     672        1577 :         else if (t->symbol->type->type == TTag &&
     673        1482 :                  t->symbol->type->tag.tagenv == TE_IMPLICIT)
     674             :             /*
     675             :              * IMPLICIT-tagged alias, something like:
     676             :              *
     677             :              * Type0 ::= [0] IMPLICIT ...
     678             :              *
     679             :              * Just recurse.
     680             :              */
     681           0 :             return is_primitive_type(t->symbol->type);
     682             :         else
     683             :             break;
     684             : 
     685             :     }
     686             :     /* EXPLICIT non-UNIVERSAL tags are always constructed */
     687       21603 :     if (t->type == TTag && t->tag.tagclass != ASN1_C_UNIV &&
     688           0 :         t->tag.tagenv == TE_EXPLICIT)
     689           0 :         return 0;
     690       21603 :     if (t->symbol && t->symbol->type) {
     691             :         /* EXPLICIT non-UNIVERSAL tags are constructed */
     692        2356 :         if (t->symbol->type->type == TTag &&
     693        2261 :             t->symbol->type->tag.tagclass != ASN1_C_UNIV &&
     694          19 :             t->symbol->type->tag.tagenv == TE_EXPLICIT)
     695          18 :             return 0;
     696             :         /* EXPLICIT UNIVERSAL tags are constructed if they are SEQUENCE/SET */
     697        2337 :         if (t->symbol->type->type == TTag &&
     698        2242 :             t->symbol->type->tag.tagclass == ASN1_C_UNIV) {
     699        2242 :             switch (t->symbol->type->tag.tagvalue) {
     700         900 :             case UT_Sequence: return 0;
     701         144 :             case UT_Set: return 0;
     702        1140 :             default: return 1;
     703             :             }
     704             :         }
     705             :     }
     706       19342 :     switch(t->type) {
     707        9432 :     case TInteger:
     708             :     case TBoolean:
     709             :     case TOctetString:
     710             :     case TBitString:
     711             :     case TEnumerated:
     712             :     case TGeneralizedTime:
     713             :     case TGeneralString:
     714             :     case TTeletexString:
     715             :     case TOID:
     716             :     case TUTCTime:
     717             :     case TUTF8String:
     718             :     case TPrintableString:
     719             :     case TIA5String:
     720             :     case TBMPString:
     721             :     case TUniversalString:
     722             :     case TVisibleString:
     723             :     case TNull:
     724        9432 :         return 1;
     725         760 :     case TTag:
     726         760 :         return is_primitive_type(t->subtype);
     727        8626 :     default:
     728        8626 :         return 0;
     729             :     }
     730             : }
     731             : 
     732             : static void
     733       85575 : space(int level)
     734             : {
     735      156959 :     while(level-- > 0)
     736       81859 :         fprintf(headerfile, "  ");
     737       83304 : }
     738             : 
     739             : static const char *
     740       56183 : last_member_p(struct member *m)
     741             : {
     742       57095 :     struct member *n = HEIM_TAILQ_NEXT(m, members);
     743       56183 :     if (n == NULL)
     744       10764 :         return "";
     745       45072 :     if (n->ellipsis && HEIM_TAILQ_NEXT(n, members) == NULL)
     746        1464 :         return "";
     747       41904 :     return ",";
     748             : }
     749             : 
     750             : static struct member *
     751        4769 : have_ellipsis(Type *t)
     752             : {
     753         251 :     struct member *m;
     754       21318 :     HEIM_TAILQ_FOREACH(m, t->members, members) {
     755       17252 :         if (m->ellipsis)
     756         666 :             return m;
     757             :     }
     758        3852 :     return NULL;
     759             : }
     760             : 
     761             : static void
     762       50062 : define_asn1 (int level, Type *t)
     763             : {
     764       51490 :     switch (t->type) {
     765       11628 :     case TType:
     766       11628 :         if (!t->symbol && t->typeref.iosclass) {
     767        1282 :             fprintf(headerfile, "%s.&%s",
     768           0 :                     t->typeref.iosclass->symbol->name,
     769           0 :                     t->typeref.field->name);
     770       11628 :         } else if (t->symbol)
     771       11628 :             fprintf(headerfile, "%s", t->symbol->name);
     772             :         else
     773           0 :             abort();
     774       11016 :         break;
     775        2185 :     case TInteger:
     776        2185 :         if(t->members == NULL) {
     777        1672 :             fprintf (headerfile, "INTEGER");
     778        1672 :             if (t->range)
     779        2137 :                 fprintf (headerfile, " (%lld..%lld)",
     780         855 :                          (long long)t->range->min,
     781         855 :                          (long long)t->range->max);
     782             :         } else {
     783          27 :             Member *m;
     784         513 :             fprintf (headerfile, "INTEGER {\n");
     785        6080 :             HEIM_TAILQ_FOREACH(m, t->members, members) {
     786        5567 :                 space (level + 1);
     787        5860 :                 fprintf(headerfile, "%s(%lld)%s\n", m->gen_name,
     788        5567 :                         (long long)m->val, last_member_p(m));
     789             :             }
     790         513 :             space(level);
     791         513 :             fprintf (headerfile, "}");
     792             :         }
     793        2070 :         break;
     794         285 :     case TBoolean:
     795         285 :         fprintf (headerfile, "BOOLEAN");
     796         270 :         break;
     797        2318 :     case TOctetString:
     798        2318 :         fprintf (headerfile, "OCTET STRING");
     799        2196 :         break;
     800         630 :     case TEnumerated:
     801             :     case TBitString: {
     802             :         Member *m;
     803             : 
     804         665 :         space(level);
     805         665 :         if(t->type == TBitString)
     806         665 :             fprintf (headerfile, "BIT STRING {\n");
     807             :         else
     808           0 :             fprintf (headerfile, "ENUMERATED {\n");
     809        3021 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
     810        2356 :             space(level + 1);
     811        2480 :             fprintf(headerfile, "%s(%lld)%s\n", m->name,
     812        2356 :                     (long long)m->val, last_member_p(m));
     813             :         }
     814         665 :         space(level);
     815         665 :         fprintf (headerfile, "}");
     816         630 :         break;
     817             :     }
     818        4769 :     case TChoice:
     819             :     case TSet:
     820             :     case TSequence: {
     821         251 :         Member *m;
     822        4769 :         size_t max_width = 0;
     823             : 
     824        4769 :         if(t->type == TChoice)
     825         589 :             fprintf(headerfile, "CHOICE {\n");
     826        4180 :         else if(t->type == TSet)
     827           0 :             fprintf(headerfile, "SET {\n");
     828             :         else
     829        4180 :             fprintf(headerfile, "SEQUENCE {\n");
     830       22097 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
     831       17328 :             if(strlen(m->name) > max_width)
     832        8838 :                 max_width = strlen(m->name);
     833             :         }
     834        4769 :         max_width += 3;
     835        4769 :         if(max_width < 16) max_width = 16;
     836       22097 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
     837       17328 :             size_t width = max_width;
     838       17328 :             space(level + 1);
     839       17328 :             if (m->ellipsis) {
     840         741 :                 fprintf (headerfile, "...");
     841             :             } else {
     842       16587 :                 width -= fprintf(headerfile, "%s", m->name);
     843       16587 :                 fprintf(headerfile, "%*s", (int)width, "");
     844       16587 :                 define_asn1(level + 1, m->type);
     845       16587 :                 if(m->optional)
     846        5567 :                     fprintf(headerfile, " OPTIONAL");
     847             :             }
     848       17328 :             if(last_member_p(m))
     849       17328 :                 fprintf (headerfile, ",");
     850       17328 :             fprintf (headerfile, "\n");
     851             :         }
     852        4769 :         space(level);
     853        4769 :         fprintf (headerfile, "}");
     854        4518 :         break;
     855             :     }
     856        1406 :     case TSequenceOf:
     857        1406 :         fprintf (headerfile, "SEQUENCE OF ");
     858        1406 :         define_asn1 (0, t->subtype);
     859        1406 :         break;
     860         323 :     case TSetOf:
     861         323 :         fprintf (headerfile, "SET OF ");
     862         323 :         define_asn1 (0, t->subtype);
     863         323 :         break;
     864         171 :     case TGeneralizedTime:
     865         171 :         fprintf (headerfile, "GeneralizedTime");
     866         162 :         break;
     867         266 :     case TGeneralString:
     868         266 :         fprintf (headerfile, "GeneralString");
     869         252 :         break;
     870          19 :     case TTeletexString:
     871          19 :         fprintf (headerfile, "TeletexString");
     872          18 :         break;
     873       25403 :     case TTag: {
     874       25403 :         const char *classnames[] = { "UNIVERSAL ", "APPLICATION ",
     875             :                                      "" /* CONTEXT */, "PRIVATE " };
     876       25403 :         if(t->tag.tagclass != ASN1_C_UNIV)
     877       11609 :             fprintf (headerfile, "[%s%d] ",
     878       10998 :                      classnames[t->tag.tagclass],
     879             :                      t->tag.tagvalue);
     880       25403 :         if(t->tag.tagenv == TE_IMPLICIT)
     881        1596 :             fprintf (headerfile, "IMPLICIT ");
     882       25403 :         define_asn1 (level, t->subtype);
     883       24066 :         break;
     884             :     }
     885          19 :     case TUTCTime:
     886          19 :         fprintf (headerfile, "UTCTime");
     887          18 :         break;
     888         828 :     case TUTF8String:
     889         874 :         space(level);
     890         874 :         fprintf (headerfile, "UTF8String");
     891         828 :         break;
     892          36 :     case TPrintableString:
     893          38 :         space(level);
     894          38 :         fprintf (headerfile, "PrintableString");
     895          36 :         break;
     896         198 :     case TIA5String:
     897         209 :         space(level);
     898         209 :         fprintf (headerfile, "IA5String");
     899         198 :         break;
     900          54 :     case TBMPString:
     901          57 :         space(level);
     902          57 :         fprintf (headerfile, "BMPString");
     903          54 :         break;
     904          18 :     case TUniversalString:
     905          19 :         space(level);
     906          19 :         fprintf (headerfile, "UniversalString");
     907          18 :         break;
     908          36 :     case TVisibleString:
     909          38 :         space(level);
     910          38 :         fprintf (headerfile, "VisibleString");
     911          36 :         break;
     912         666 :     case TOID :
     913         703 :         space(level);
     914         703 :         fprintf(headerfile, "OBJECT IDENTIFIER");
     915         666 :         break;
     916          90 :     case TNull:
     917          95 :         space(level);
     918          95 :         fprintf (headerfile, "NULL");
     919          90 :         break;
     920           0 :     default:
     921           0 :         abort ();
     922             :     }
     923       50062 : }
     924             : 
     925             : static void
     926       12312 : getnewbasename(char **newbasename, int typedefp, const char *basename, const char *name)
     927             : {
     928       12312 :     if (typedefp)
     929       11381 :         *newbasename = strdup(name);
     930             :     else {
     931         931 :         if (name[0] == '*')
     932         608 :             name++;
     933         931 :         if (asprintf(newbasename, "%s_%s", basename, name) < 0)
     934           0 :             errx(1, "malloc");
     935             :     }
     936       12312 :     if (*newbasename == NULL)
     937           0 :         err(1, "malloc");
     938       12312 : }
     939             : 
     940             : typedef enum define_type_options {
     941             :     DEF_TYPE_NONE = 0,
     942             :     DEF_TYPE_PRESERVE = 1,
     943             :     DEF_TYPE_TYPEDEFP = 2,
     944             :     DEF_TYPE_EMIT_NAME = 4
     945             : } define_type_options;
     946             : static void define_type(int, const char *, const char *, Type *, Type *, define_type_options);
     947             : 
     948             : /*
     949             :  * Get the SET/SEQUENCE member pair and CLASS field pair defining an open type.
     950             :  *
     951             :  * There are three cases:
     952             :  *
     953             :  *  - open types embedded in OCTET STRING, with the open type object class
     954             :  *    relation declared via a constraint
     955             :  *
     956             :  *  - open types not embedded in OCTET STRING, which are really more like ANY
     957             :  *    DEFINED BY types, so, HEIM_ANY
     958             :  *
     959             :  *  - open types in a nested structure member where the type ID field is in a
     960             :  *    member of the ancestor structure (this happens in PKIX's `AttributeSet',
     961             :  *    where the open type is essentially a SET OF HEIM_ANY).
     962             :  *
     963             :  * In a type like PKIX's SingleAttribute the type ID member would be the one
     964             :  * named "type" and the open type member would be the one named "value", and
     965             :  * the corresponding fields of the ATTRIBUTE class would be named "id" and
     966             :  * "Type".
     967             :  *
     968             :  * NOTE: We assume a single open type member pair in any SET/SEQUENCE.  In
     969             :  *       principle there could be more pairs and we could iterate them, or
     970             :  *       better yet, we could be given the name of an open type member and then
     971             :  *       just find its related type ID member and fields, then our caller would
     972             :  *       iterate the SET/SEQUENCE type's members looking for open type members
     973             :  *       and would call this function for each one found.
     974             :  */
     975             : void
     976         228 : get_open_type_defn_fields(const Type *t,
     977             :                           Member **typeidmember,
     978             :                           Member **opentypemember,
     979             :                           Field **typeidfield,
     980             :                           Field **opentypefield,
     981             :                           int *is_array_of)
     982             : {
     983          12 :     Member *m;
     984          12 :     Field *junk1, *junk2;
     985         228 :     char *idmembername = NULL;
     986             : 
     987         228 :     if (!typeidfield) typeidfield = &junk1;
     988         228 :     if (!opentypefield) opentypefield = &junk2;
     989             : 
     990         228 :     *typeidfield = *opentypefield = NULL;
     991         228 :     *typeidmember = *opentypemember = NULL;
     992         228 :     *is_array_of = 0;
     993             : 
     994             :     /* Look for the open type member */
     995         494 :     HEIM_TAILQ_FOREACH(m, t->members, members) {
     996         494 :         Type *subtype = m->type;
     997         494 :         Type *sOfType = NULL;
     998             : 
     999         494 :         while (subtype->type == TTag ||
    1000         950 :                subtype->type == TSetOf ||
    1001         432 :                subtype->type == TSequenceOf) {
    1002         494 :             if (subtype->type == TTag && subtype->subtype) {
    1003         418 :                 if (subtype->subtype->type == TOctetString ||
    1004         360 :                     subtype->subtype->type == TBitString)
    1005             :                     break;
    1006         360 :                 subtype = subtype->subtype;
    1007          76 :             } else if (subtype->type == TSetOf || subtype->type == TSequenceOf) {
    1008          76 :                 sOfType = subtype;
    1009          76 :                 if (sOfType->symbol)
    1010           0 :                     break;
    1011          76 :                 if (subtype->subtype)
    1012          76 :                     subtype = subtype->subtype;
    1013             :             } else
    1014             :                 break;
    1015             :         }
    1016             :         /*
    1017             :          * If we traversed through a non-inlined SET OF or SEQUENCE OF type,
    1018             :          * then this cannot be an open type field.
    1019             :          */
    1020         494 :         if (sOfType && sOfType->symbol)
    1021           0 :             continue;
    1022             :         /*
    1023             :          * The type of the field we're interested in has to have an information
    1024             :          * object constraint.
    1025             :          */
    1026         494 :         if (!subtype->constraint)
    1027         266 :             continue;
    1028         228 :         if (subtype->type != TType && subtype->type != TTag)
    1029           0 :             continue;
    1030             :         /*
    1031             :          * Check if it's an ANY-like member or like an OCTET STRING CONTAINING
    1032             :          * member.  Those are the only two possibilities.
    1033             :          */
    1034         228 :         if ((subtype->type == TTag || subtype->type == TType) &&
    1035         228 :             subtype->subtype &&
    1036          38 :             subtype->constraint->ctype == CT_CONTENTS &&
    1037          38 :             subtype->constraint->u.content.type &&
    1038          38 :             subtype->constraint->u.content.type->type == TType &&
    1039          38 :             !subtype->constraint->u.content.type->subtype &&
    1040          38 :             subtype->constraint->u.content.type->constraint &&
    1041          38 :             subtype->constraint->u.content.type->constraint->ctype == CT_TABLE_CONSTRAINT) {
    1042             :             /* Type like OCTET STRING or BIT STRING CONTAINING open type */
    1043          38 :             if (*opentypemember)
    1044           0 :                 errx(1, "Multiple open type members %s and %s for the same "
    1045           0 :                      "field %s?", (*opentypemember)->name, m->name,
    1046           0 :                      (*opentypefield)->name);
    1047          38 :             *opentypemember = m;
    1048          38 :             *opentypefield = subtype->constraint->u.content.type->typeref.field;
    1049          38 :             *is_array_of = sOfType != NULL;
    1050          38 :             idmembername = subtype->constraint->u.content.type->constraint->u.content.crel.membername;
    1051          38 :             break;
    1052         190 :         } else if (subtype->symbol && strcmp(subtype->symbol->name, "HEIM_ANY") == 0) {
    1053             :             /* Open type, but NOT embedded in OCTET STRING or BIT STRING */
    1054         190 :             if (*opentypemember)
    1055           0 :                 errx(1, "Multiple open type members %s and %s for the same "
    1056           0 :                      "field %s?", (*opentypemember)->name, m->name,
    1057           0 :                      (*opentypefield)->name);
    1058         190 :             *opentypemember = m;
    1059         190 :             *opentypefield = subtype->typeref.field;
    1060         190 :             *is_array_of = sOfType != NULL;
    1061         190 :             idmembername = subtype->constraint->u.content.crel.membername;
    1062         190 :             break;
    1063             :         }
    1064             :     }
    1065             : 
    1066         228 :     if (!idmembername)
    1067           0 :         errx(1, "Missing open type id member in %s",
    1068           0 :              t->symbol ? t->symbol->name : "<unknown type>");
    1069             :     /* Look for the type ID member identified in the previous loop */
    1070         228 :     HEIM_TAILQ_FOREACH(m, t->members, members) {
    1071         228 :         if (!m->type->subtype || strcmp(m->name, idmembername) != 0)
    1072           0 :             continue;
    1073         228 :         if (m->type->constraint &&
    1074         228 :             m->type->constraint->ctype == CT_TABLE_CONSTRAINT)
    1075         228 :             *typeidfield = m->type->typeref.field;
    1076           0 :         else if (m->type->subtype->constraint &&
    1077           0 :                  m->type->subtype->constraint->ctype == CT_TABLE_CONSTRAINT)
    1078           0 :             *typeidfield = m->type->subtype->typeref.field;
    1079             :         else
    1080           0 :             continue;
    1081             :         /* This is the type ID field (because there _is_ a subtype) */
    1082         228 :         *typeidmember = m;
    1083         228 :         break;
    1084             :     }
    1085         228 : }
    1086             : 
    1087             : /*
    1088             :  * Generate CHOICE-like struct fields for open types declared via
    1089             :  * X.681/682/683 syntax.
    1090             :  *
    1091             :  * We could support multiple open type members in a SET/SEQUENCE, but for now
    1092             :  * we support only one.
    1093             :  */
    1094             : static void
    1095         114 : define_open_type(int level, const char *newbasename, const char *name, const char *basename, Type *pt, Type *t)
    1096             : {
    1097           6 :     Member *opentypemember, *typeidmember;
    1098           6 :     Field *opentypefield, *typeidfield;
    1099           6 :     ObjectField *of;
    1100         114 :     IOSObjectSet *os = pt->actual_parameter;
    1101           6 :     IOSObject **objects;
    1102           6 :     size_t nobjs, i;
    1103           6 :     int is_array_of_open_type;
    1104             : 
    1105         114 :     get_open_type_defn_fields(pt, &typeidmember, &opentypemember,
    1106             :                               &typeidfield, &opentypefield,
    1107             :                               &is_array_of_open_type);
    1108         114 :     if (!opentypemember || !typeidmember ||
    1109         114 :         !opentypefield  || !typeidfield)
    1110           0 :         errx(1, "Open type specification in %s is incomplete", name);
    1111             : 
    1112         114 :     sort_object_set(os, typeidfield, &objects, &nobjs);
    1113             : 
    1114         114 :     fprintf(headerfile, "struct {\n");
    1115         114 :     fprintf(jsonfile, "{\"opentype\":true,\"arraytype\":%s,",
    1116         114 :             is_array_of_open_type ? "true" : "false");
    1117         114 :     fprintf(jsonfile, "\"classname\":\"%s\",", os->iosclass->symbol->name);
    1118         114 :     fprintf(jsonfile, "\"objectsetname\":\"%s\",", os->symbol->name);
    1119         114 :     fprintf(jsonfile, "\"typeidmember\":\"%s\",", typeidmember->name);
    1120         114 :     fprintf(jsonfile, "\"opentypemember\":\"%s\",", opentypemember->name);
    1121         114 :     fprintf(jsonfile, "\"typeidfield\":\"%s\",", typeidfield->name);
    1122         114 :     fprintf(jsonfile, "\"opentypefield\":\"%s\",", opentypefield->name);
    1123             : 
    1124             :     /* Iterate objects in the object set, gen enum labels */
    1125         114 :     fprintf(headerfile, "enum { choice_%s_iosnumunknown = 0,\n",
    1126             :             newbasename);
    1127         114 :     fprintf(jsonfile, "\"opentypeids\":[");
    1128        1507 :     for (i = 0; i < nobjs; i++) {
    1129        4541 :         HEIM_TAILQ_FOREACH(of, objects[i]->objfields, objfields) {
    1130        3154 :             if (strcmp(of->name, typeidfield->name) != 0)
    1131        1767 :                 continue;
    1132        1387 :             if (!of->value || !of->value->s)
    1133           0 :                 errx(1, "Unknown value in value field %s of object %s",
    1134           0 :                      of->name, objects[i]->symbol->name);
    1135        1387 :             fprintf(headerfile, "choice_%s_iosnum_%s,\n",
    1136        1314 :                     newbasename, of->value->s->gen_name);
    1137        1387 :             fprintf(jsonfile, "\"%s\"", of->value->s->gen_name);
    1138        1486 :             fprintf(jsonfile, "%s", (i + 1) < nobjs ? "," : "");
    1139             :         }
    1140             :     }
    1141         114 :     fprintf(jsonfile, "],\n");
    1142         114 :     fprintf(headerfile, "} element;\n");
    1143             : 
    1144         114 :     if (is_array_of_open_type)
    1145          38 :         fprintf(headerfile, "unsigned int len;\n");
    1146             : 
    1147             :     /* Iterate objects in the object set, gen union arms */
    1148         114 :     fprintf(headerfile, "union {\nvoid *_any;\n");
    1149         114 :     fprintf(jsonfile, "\"members\":[");
    1150        1507 :     for (i = 0; i < nobjs; i++) {
    1151        4541 :         HEIM_TAILQ_FOREACH(of, objects[i]->objfields, objfields) {
    1152        3154 :             char *n = NULL;
    1153             : 
    1154             :             /* XXX Print the type IDs into the jsonfile too pls */
    1155             : 
    1156        3154 :             if (strcmp(of->name, opentypefield->name) != 0)
    1157        1767 :                 continue;
    1158        1387 :             if (!of->type || (!of->type->symbol && of->type->type != TTag) ||
    1159        1387 :                 of->type->tag.tagclass != ASN1_C_UNIV) {
    1160           0 :                 warnx("Ignoring unknown or unset type field %s of object %s",
    1161           0 :                       of->name, objects[i]->symbol->name);
    1162           0 :                 continue;
    1163             :             }
    1164             : 
    1165        1387 :             if (asprintf(&n, "*%s", objects[i]->symbol->gen_name) < 0 || n == NULL)
    1166           0 :                 err(1, "malloc");
    1167        1387 :             define_type(level + 2, n, newbasename, NULL, of->type, DEF_TYPE_NONE);
    1168        1393 :             fprintf(jsonfile, "%s", (i + 1) < nobjs ? "," : "");
    1169        1387 :             free(n);
    1170             :         }
    1171             :     }
    1172         114 :     fprintf(jsonfile, "]}\n");
    1173         114 :     if (is_array_of_open_type) {
    1174          38 :         fprintf(headerfile, "} *val;\n} _ioschoice_%s;\n", opentypemember->gen_name);
    1175             :     } else {
    1176          76 :         fprintf(headerfile, "} u;\n");
    1177          76 :         fprintf(headerfile, "} _ioschoice_%s;\n", opentypemember->gen_name);
    1178             :     }
    1179         114 :     free(objects);
    1180         114 : }
    1181             : 
    1182             : static const char * const tagclassnames[] = {
    1183             :     "UNIVERSAL", "APPLICATION", "CONTEXT", "PRIVATE"
    1184             : };
    1185             : 
    1186             : static void
    1187       62510 : define_type(int level, const char *name, const char *basename,
    1188             :             Type *pt, Type *t, define_type_options opts)
    1189             : {
    1190       62510 :     const char *label_prefix = NULL;
    1191       62510 :     const char *label_prefix_sep = NULL;
    1192       62510 :     char *newbasename = NULL;
    1193             : 
    1194      121730 :     fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
    1195             :             "\"is_type\":true,\"exported\":%s,\"typedef\":%s,",
    1196             :             basename, name,
    1197       62510 :             t->symbol && is_export(t->symbol->name) ? "true" : "false",
    1198       62510 :             (opts & DEF_TYPE_TYPEDEFP) ? "true" : "false");
    1199             : 
    1200       62510 :     switch (t->type) {
    1201       12330 :     case TType:
    1202       13015 :         space(level);
    1203       13015 :         if (!t->symbol && t->actual_parameter) {
    1204           0 :             define_open_type(level, newbasename, name, basename, t, t);
    1205       13015 :         } else if (!t->symbol && pt->actual_parameter) {
    1206           0 :             define_open_type(level, newbasename, name, basename, pt, t);
    1207       13015 :         } else if (t->symbol) {
    1208       13015 :             fprintf(headerfile, "%s %s;\n", t->symbol->gen_name, name);
    1209       16305 :             fprintf(jsonfile, "\"ttype\":\"%s\","
    1210       13015 :                     "\"alias\":true\n", t->symbol->gen_name);
    1211             :         } else
    1212           0 :             abort();
    1213       12330 :         break;
    1214       11818 :     case TInteger:
    1215       11818 :         if (t->symbol && t->symbol->emitted_definition)
    1216           0 :             break;
    1217             : 
    1218       11818 :         space(level);
    1219       11818 :         if(t->members) {
    1220          27 :             Member *m;
    1221             : 
    1222         513 :             label_prefix = prefix_enum ? name : (enum_prefix ? enum_prefix : "");
    1223         513 :             label_prefix_sep = prefix_enum ? "_" : "";
    1224         513 :             fprintf (headerfile, "enum %s {\n", (opts & DEF_TYPE_TYPEDEFP) ? name : "");
    1225         513 :             fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"enum\","
    1226             :                     "\"members\":[\n");
    1227        6080 :             HEIM_TAILQ_FOREACH(m, t->members, members) {
    1228        5567 :                 space (level + 1);
    1229        5567 :                 fprintf(headerfile, "%s%s%s = %lld%s\n",
    1230             :                         label_prefix, label_prefix_sep,
    1231        5567 :                         m->gen_name, (long long)m->val, last_member_p(m));
    1232        5860 :                 fprintf(jsonfile, "{\"%s%s%s\":%lld}%s\n",
    1233             :                         label_prefix, label_prefix_sep,
    1234        5567 :                         m->gen_name, (long long)m->val, last_member_p(m));
    1235             :             }
    1236         513 :             fprintf(headerfile, "} %s;\n", name);
    1237         513 :             fprintf(jsonfile, "]");
    1238       11305 :         } else if (t->range == NULL) {
    1239         817 :             fprintf(headerfile, "heim_integer %s;\n", name);
    1240         817 :             fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"heim_integer\"");
    1241       10488 :         } else if (t->range->min < 0 &&
    1242         189 :                    (t->range->min < INT_MIN || t->range->max > INT_MAX)) {
    1243          19 :             fprintf(headerfile, "int64_t %s;\n", name);
    1244          19 :             fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"int64_t\"");
    1245       10469 :         } else if (t->range->min < 0) {
    1246         171 :             fprintf (headerfile, "int %s;\n", name);
    1247         171 :             fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"int\"");
    1248       10298 :         } else if (t->range->max > UINT_MAX) {
    1249           0 :             fprintf (headerfile, "uint64_t %s;\n", name);
    1250           0 :             fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"uint64_t\"");
    1251             :         } else {
    1252       10298 :             fprintf (headerfile, "unsigned int %s;\n", name);
    1253       10298 :             fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"unsigned int\"");
    1254             :         }
    1255       11196 :         break;
    1256         270 :     case TBoolean:
    1257         285 :         space(level);
    1258         285 :         fprintf (headerfile, "int %s;\n", name);
    1259         285 :         fprintf(jsonfile, "\"ttype\":\"BOOLEAN\",\"ctype\":\"unsigned int\"");
    1260         270 :         break;
    1261        2196 :     case TOctetString:
    1262        2318 :         space(level);
    1263        2318 :         fprintf (headerfile, "heim_octet_string %s;\n", name);
    1264        2318 :         fprintf(jsonfile, "\"ttype\":\"OCTET STRING\",\"ctype\":\"heim_octet_string\"");
    1265        2196 :         break;
    1266         665 :     case TBitString: {
    1267          35 :         Member *m;
    1268          35 :         Type i;
    1269         665 :         struct range range = { 0, UINT_MAX };
    1270         665 :         size_t max_memno = 0;
    1271          35 :         size_t bitset_size;
    1272             : 
    1273         665 :         if (t->symbol && t->symbol->emitted_definition)
    1274           0 :             break;
    1275         665 :         memset(&i, 0, sizeof(i));
    1276             : 
    1277             :         /*
    1278             :          * range.max implies the size of the base unsigned integer used for the
    1279             :          * bitfield members.  If it's less than or equal to UINT_MAX, then that
    1280             :          * will be unsigned int, otherwise it will be uint64_t.
    1281             :          *
    1282             :          * We could just use uint64_t, yes, but for now, and in case that any
    1283             :          * projects were exposing the BIT STRING types' C representations in
    1284             :          * ABIs prior to this compiler supporting BIT STRING with larger
    1285             :          * members, we stick to this.
    1286             :          */
    1287        3021 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
    1288        2356 :             if (m->val > max_memno)
    1289        1998 :                 max_memno = m->val;
    1290             :         }
    1291         665 :         if (max_memno > 63)
    1292           0 :             range.max = INT64_MAX;
    1293             :         else
    1294         665 :             range.max = 1ULL << max_memno;
    1295             : 
    1296         665 :         i.type = TInteger;
    1297         665 :         i.range = &range;
    1298         665 :         i.members = NULL;
    1299         665 :         i.constraint = NULL;
    1300             : 
    1301         665 :         space(level);
    1302         665 :         fprintf(jsonfile, "\"ttype\":\"BIT STRING\",");
    1303         665 :         if(HEIM_TAILQ_EMPTY(t->members)) {
    1304         418 :             fprintf (headerfile, "heim_bit_string %s;\n", name);
    1305         418 :             fprintf(jsonfile, "\"ctype\":\"heim_bit_string\"");
    1306             :         } else {
    1307         247 :             int64_t pos = 0;
    1308         247 :             getnewbasename(&newbasename, (opts & DEF_TYPE_TYPEDEFP) || level == 0, basename, name);
    1309             : 
    1310         247 :             fprintf (headerfile, "struct %s {\n", newbasename);
    1311         247 :             fprintf(jsonfile, "\"ctype\":\"struct %s\",\"members\":[\n", newbasename);
    1312        2603 :             HEIM_TAILQ_FOREACH(m, t->members, members) {
    1313        2356 :                 char *n = NULL;
    1314             : 
    1315             :                 /*
    1316             :                  * pad unused bits beween declared members (hopefully this
    1317             :                  * forces the compiler to give us an obvious layout)
    1318             :                  */
    1319        2774 :                 while (pos < m->val) {
    1320         418 :                     if (asprintf (&n, "_unused%lld:1", (long long)pos) < 0 ||
    1321         418 :                         n == NULL)
    1322           0 :                         err(1, "malloc");
    1323         418 :                     define_type(level + 1, n, newbasename, NULL, &i, DEF_TYPE_EMIT_NAME);
    1324         418 :                     fprintf(jsonfile, ",");
    1325         418 :                     free(n);
    1326         418 :                     pos++;
    1327             :                 }
    1328             : 
    1329        2356 :                 n = NULL;
    1330        2356 :                 if (asprintf (&n, "%s:1", m->gen_name) < 0 || n == NULL)
    1331           0 :                     errx(1, "malloc");
    1332        2356 :                 define_type(level + 1, n, newbasename, NULL, &i, DEF_TYPE_EMIT_NAME);
    1333        2467 :                 fprintf(jsonfile, "%s", last_member_p(m));
    1334        2356 :                 free (n);
    1335        2356 :                 n = NULL;
    1336        2356 :                 pos++;
    1337             :             }
    1338             :             /* pad unused tail (ditto) */
    1339         247 :             bitset_size = max_memno;
    1340         247 :             if (max_memno > 31)
    1341           0 :                 bitset_size += 64 - (max_memno % 64);
    1342             :             else
    1343         234 :                 bitset_size = 32;
    1344         247 :             if (pos < bitset_size)
    1345         209 :                 fprintf(jsonfile, ",");
    1346        5377 :             while (pos < bitset_size) {
    1347        5130 :                 char *n = NULL;
    1348        5130 :                 if (asprintf (&n, "_unused%lld:1", (long long)pos) < 0 ||
    1349        5130 :                     n == NULL)
    1350           0 :                     errx(1, "malloc");
    1351        5130 :                 define_type(level + 1, n, newbasename, NULL, &i, DEF_TYPE_EMIT_NAME);
    1352        5141 :                 fprintf(jsonfile, "%s", (pos + 1) < bitset_size ? "," : "");
    1353        5130 :                 free(n);
    1354        5130 :                 pos++;
    1355             :             }
    1356             : 
    1357         247 :             space(level);
    1358         481 :             fprintf(headerfile, "}%s%s;\n\n",
    1359         234 :                     (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
    1360         247 :                     (opts & DEF_TYPE_EMIT_NAME) ? name : "");
    1361         269 :             fprintf(jsonfile, "]");
    1362             :         }
    1363         630 :         break;
    1364             :     }
    1365           0 :     case TEnumerated: {
    1366           0 :         Member *m;
    1367             : 
    1368           0 :         if (t->symbol && t->symbol->emitted_definition)
    1369           0 :             break;
    1370             : 
    1371           0 :         label_prefix = prefix_enum ? name : (enum_prefix ? enum_prefix : "");
    1372           0 :         label_prefix_sep = prefix_enum ? "_" : "";
    1373           0 :         space(level);
    1374           0 :         fprintf (headerfile, "enum %s {\n", (opts & DEF_TYPE_TYPEDEFP) ? name : "");
    1375           0 :         fprintf(jsonfile, "\"ctype\":\"enum %s\",\"extensible\":%s,\"members\":[\n",
    1376           0 :                 (opts & DEF_TYPE_TYPEDEFP) ? name : "", have_ellipsis(t) ? "true" : "false");
    1377           0 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
    1378           0 :             space(level + 1);
    1379           0 :             if (m->ellipsis) {
    1380           0 :                 fprintf (headerfile, "/* ... */\n");
    1381             :             } else {
    1382           0 :                 fprintf(headerfile, "%s%s%s = %lld%s\n",
    1383             :                         label_prefix, label_prefix_sep,
    1384           0 :                         m->gen_name, (long long)m->val, last_member_p(m));
    1385           0 :                 fprintf(jsonfile, "{\"%s%s%s\":%lld%s}\n",
    1386             :                         label_prefix, label_prefix_sep,
    1387           0 :                         m->gen_name, (long long)m->val, last_member_p(m));
    1388             :             }
    1389             :         }
    1390           0 :         space(level);
    1391           0 :         fprintf(headerfile, "}%s%s;\n\n",
    1392           0 :                 (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
    1393           0 :                 (opts & DEF_TYPE_EMIT_NAME) ? name : "");
    1394           0 :         fprintf(jsonfile, "]");
    1395           0 :         break;
    1396             :     }
    1397        4180 :     case TSet:
    1398             :     case TSequence: {
    1399         220 :         Member *m;
    1400         220 :         struct decoration deco;
    1401        4180 :         ssize_t more_deco = -1;
    1402        4180 :         int decorated = 0;
    1403             : 
    1404        4180 :         getnewbasename(&newbasename, (opts & DEF_TYPE_TYPEDEFP) || level == 0, basename, name);
    1405             : 
    1406        4180 :         space(level);
    1407             : 
    1408        4180 :         fprintf (headerfile, "struct %s {\n", newbasename);
    1409        8360 :         fprintf(jsonfile, "\"ttype\":\"%s\",\"extensible\":%s,"
    1410             :                 "\"ctype\":\"struct %s\"",
    1411        4180 :                 t->type == TSet ? "SET" : "SEQUENCE",
    1412        4180 :                 have_ellipsis(t) ? "true" : "false", newbasename);
    1413        4180 :         if (t->type == TSequence && (opts & DEF_TYPE_PRESERVE)) {
    1414         114 :             space(level + 1);
    1415         114 :             fprintf(headerfile, "heim_octet_string _save;\n");
    1416         114 :             fprintf(jsonfile, ",\"preserve\":true");
    1417             :         }
    1418        4180 :         fprintf(jsonfile, ",\"members\":[\n");
    1419       19646 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
    1420       15466 :             if (m->ellipsis) {
    1421             :                 ;
    1422       14820 :             } else if (m->optional || m->defval) {
    1423        5776 :                 char *n = NULL, *defval = NULL;
    1424         304 :                 const char *namep, *defvalp;
    1425             : 
    1426        5776 :                 if (m->defval) {
    1427         209 :                     switch (m->defval->type) {
    1428           0 :                     case stringvalue:
    1429           0 :                         if (asprintf(&defval, "\"%s\"", m->defval->u.stringvalue) < 0 || defval == NULL)
    1430           0 :                             errx(1, "malloc");
    1431           0 :                         defvalp = defval;
    1432           0 :                         break;
    1433          95 :                     case integervalue:
    1434          95 :                         if (asprintf(&defval, "%lld", (long long)m->defval->u.integervalue) < 0 || defval == NULL)
    1435           0 :                             errx(1, "malloc");
    1436          90 :                         defvalp = defval;
    1437          90 :                         break;
    1438         114 :                     case booleanvalue:
    1439         114 :                         defvalp = m->defval->u.booleanvalue ? "true" : "false";
    1440         108 :                         break;
    1441           0 :                     default:
    1442           0 :                         abort();
    1443             :                     }
    1444             :                 } else
    1445        5274 :                     defvalp = "null";
    1446             : 
    1447        5776 :                 if (m->optional) {
    1448        5567 :                     if (asprintf(&n, "*%s", m->gen_name) < 0 || n == NULL)
    1449           0 :                         errx(1, "malloc");
    1450        5274 :                     namep = n;
    1451             :                 } else
    1452         209 :                     namep = m->gen_name;
    1453             : 
    1454        5776 :                 fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
    1455             :                         "\"optional\":%s,\"defval\":%s,\"type\":",
    1456        5776 :                         m->name, m->gen_name, m->optional ? "true" : "false", defvalp);
    1457        5776 :                 define_type(level + 1, namep, newbasename, t, m->type, DEF_TYPE_EMIT_NAME);
    1458        5988 :                 fprintf(jsonfile, "}%s", last_member_p(m));
    1459        5776 :                 free (n);
    1460        5776 :                 free (defval);
    1461             :             } else {
    1462        9044 :                 fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
    1463             :                         "\"optional\":false,\"type\":", m->name, m->gen_name);
    1464        9044 :                 define_type(level + 1, m->gen_name, newbasename, t, m->type, DEF_TYPE_EMIT_NAME);
    1465        9762 :                 fprintf(jsonfile, "}%s", last_member_p(m));
    1466             :             }
    1467             :         }
    1468        4180 :         fprintf(jsonfile, "]");
    1469        4180 :         if (t->actual_parameter && t->actual_parameter->objects) {
    1470         114 :             fprintf(jsonfile, ",\"opentype\":");
    1471         114 :             define_open_type(level, newbasename, name, basename, t, t);
    1472             :         }
    1473        4256 :         while (decorate_type(newbasename, &deco, &more_deco)) {
    1474          76 :             decorated++;
    1475          76 :             space(level + 1);
    1476          76 :             fprintf(headerfile, "%s %s%s;\n", deco.field_type,
    1477          76 :                     deco.opt ? "*" : "", deco.field_name);
    1478          76 :             if (deco.first)
    1479          57 :                 fprintf(jsonfile, ",\"decorate\":[");
    1480        1020 :             fprintf(jsonfile, "%s{"
    1481             :                     "\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s,"
    1482             :                     "\"external\":%s,\"pointer\":%s,\"void_star\":%s,"
    1483             :                     "\"struct_star\":%s,"
    1484             :                     "\"copy_function\":\"%s\","
    1485             :                     "\"free_function\":\"%s\",\"header_name\":%s%s%s"
    1486             :                     "}",
    1487          76 :                     deco.first ? "" : ",",
    1488             :                     deco.field_type, deco.field_name,
    1489         149 :                     deco.opt ? "true" : "false", deco.ext ? "true" : "false",
    1490         151 :                     deco.ptr ? "true" : "false", deco.void_star ? "true" : "false",
    1491          76 :                     deco.struct_star ? "true" : "false",
    1492          76 :                     deco.copy_function_name ? deco.copy_function_name : "",
    1493          76 :                     deco.free_function_name ? deco.free_function_name : "",
    1494          72 :                     deco.header_name && deco.header_name[0] == '"' ? "" : "\"",
    1495          72 :                     deco.header_name ? deco.header_name : "",
    1496          76 :                     deco.header_name && deco.header_name[0] == '"' ? "" : "\""
    1497             :                     );
    1498             :         }
    1499        4180 :         if (decorated)
    1500         292 :             fprintf(jsonfile, "]");
    1501        4180 :         space(level);
    1502        8348 :         fprintf(headerfile, "}%s%s;\n",
    1503        3960 :                 (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
    1504        4180 :                 (opts & DEF_TYPE_EMIT_NAME) ? name : "");
    1505        4180 :         free(deco.field_type);
    1506        4180 :         break;
    1507             :     }
    1508        1729 :     case TSetOf:
    1509             :     case TSequenceOf: {
    1510          91 :         Type i;
    1511        1729 :         struct range range = { 0, UINT_MAX };
    1512             : 
    1513        1762 :         getnewbasename(&newbasename, (opts & DEF_TYPE_TYPEDEFP) || level == 0, basename, name);
    1514             : 
    1515        1729 :         memset(&i, 0, sizeof(i));
    1516        1729 :         i.type = TInteger;
    1517        1729 :         i.range = &range;
    1518             : 
    1519        1729 :         space(level);
    1520        1729 :         fprintf (headerfile, "struct %s {\n", newbasename);
    1521        1729 :         fprintf(jsonfile, "\"ttype\":\"%s\",\"ctype\":\"struct %s\",\"members\":[",
    1522        1729 :                 t->type == TSetOf ? "SET OF" : "SEQUENCE OF", newbasename);
    1523        1729 :         define_type(level + 1, "len", newbasename, t, &i, DEF_TYPE_NONE);
    1524        1729 :         fprintf(jsonfile, ",");
    1525        1729 :         define_type(level + 1, "*val", newbasename, t, t->subtype, DEF_TYPE_NONE | DEF_TYPE_EMIT_NAME);
    1526        1729 :         space(level);
    1527        3425 :         fprintf(headerfile, "}%s%s;\n",
    1528        1638 :                 (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
    1529        1729 :                 (opts & DEF_TYPE_EMIT_NAME) ? name : "");
    1530        1729 :         fprintf(jsonfile, "]");
    1531        1729 :         break;
    1532             :     }
    1533         162 :     case TGeneralizedTime:
    1534         171 :         space(level);
    1535         171 :         fprintf (headerfile, "time_t %s;\n", name);
    1536         171 :         fprintf(jsonfile, "\"ttype\":\"GeneralizedTime\",\"ctype\":\"time_t\"");
    1537         162 :         break;
    1538         252 :     case TGeneralString:
    1539         266 :         space(level);
    1540         266 :         fprintf (headerfile, "heim_general_string %s;\n", name);
    1541         266 :         fprintf(jsonfile, "\"ttype\":\"GeneralString\",\"ctype\":\"heim_general_string\"");
    1542         252 :         break;
    1543          18 :     case TTeletexString:
    1544          19 :         space(level);
    1545          19 :         fprintf (headerfile, "heim_general_string %s;\n", name);
    1546          19 :         fprintf(jsonfile, "\"ttype\":\"TeletexString\",\"ctype\":\"heim_general_string\"");
    1547          18 :         break;
    1548       25403 :     case TTag:
    1549       25403 :         if (t->implicit_choice) {
    1550          38 :             fprintf(jsonfile, "\"desired_tagenv\":\"IMPLICIT\",");
    1551             :         }
    1552       28077 :         fprintf(jsonfile, "\"tagclass\":\"%s\",\"tagvalue\":%d,\"tagenv\":\"%s\",\n",
    1553       25403 :                 tagclassnames[t->tag.tagclass], t->tag.tagvalue,
    1554       25403 :                 t->tag.tagenv == TE_EXPLICIT ? "EXPLICIT" : "IMPLICIT");
    1555       25403 :         fprintf(jsonfile, "\"ttype\":\n");
    1556       25403 :         define_type(level, name, basename, t, t->subtype, opts);
    1557       25403 :         break;
    1558         589 :     case TChoice: {
    1559          31 :         struct decoration deco;
    1560         589 :         ssize_t more_deco = -1;
    1561         589 :         int decorated = 0;
    1562         589 :         int first = 1;
    1563          31 :         Member *m;
    1564             : 
    1565         589 :         getnewbasename(&newbasename, (opts & DEF_TYPE_TYPEDEFP) || level == 0, basename, name);
    1566             : 
    1567         589 :         space(level);
    1568         589 :         fprintf (headerfile, "struct %s {\n", newbasename);
    1569         589 :         fprintf(jsonfile, "\"ttype\":\"CHOICE\",\"ctype\":\"struct %s\"",
    1570             :                 newbasename);
    1571         589 :         if ((opts & DEF_TYPE_PRESERVE)) {
    1572          19 :             space(level + 1);
    1573          19 :             fprintf(headerfile, "heim_octet_string _save;\n");
    1574          19 :             fprintf(jsonfile, ",\"preserve\":true");
    1575             :         }
    1576         589 :         space(level + 1);
    1577         589 :         fprintf (headerfile, "enum %s_enum {\n", newbasename);
    1578         589 :         m = have_ellipsis(t);
    1579         589 :         if (m) {
    1580          95 :             space(level + 2);
    1581          95 :             fprintf (headerfile, "%s = 0,\n", m->label);
    1582          95 :             first = 0;
    1583             :         }
    1584         615 :         fprintf(jsonfile, ",\"extensible\":%s", m ? "true" : "false");
    1585        2451 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
    1586        1862 :             space(level + 2);
    1587        1862 :             if (m->ellipsis)
    1588          95 :                 fprintf (headerfile, "/* ... */\n");
    1589             :             else
    1590        1901 :                 fprintf (headerfile, "%s%s%s\n", m->label,
    1591             :                          first ? " = 1" : "",
    1592             :                          last_member_p(m));
    1593        1862 :             first = 0;
    1594             :         }
    1595         589 :         space(level + 1);
    1596         589 :         fprintf (headerfile, "} element;\n");
    1597         589 :         space(level + 1);
    1598         589 :         fprintf (headerfile, "union {\n");
    1599         589 :         fprintf(jsonfile, ",\"members\":[\n");
    1600        2451 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
    1601        1862 :             if (m->ellipsis) {
    1602          95 :                 space(level + 2);
    1603          95 :                 fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");
    1604        1767 :             } else if (m->optional) {
    1605           0 :                 char *n = NULL;
    1606             : 
    1607           0 :                 if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL)
    1608           0 :                     errx(1, "malloc");
    1609           0 :                 fprintf(jsonfile, "{\"optional\":");
    1610           0 :                 define_type(level + 2, n, newbasename, t, m->type, DEF_TYPE_EMIT_NAME);
    1611           0 :                 fprintf(jsonfile, "}%s", last_member_p(m));
    1612           0 :                 free (n);
    1613             :             } else {
    1614        1767 :                 define_type(level + 2, m->gen_name, newbasename, t, m->type, DEF_TYPE_EMIT_NAME);
    1615        1839 :                 fprintf(jsonfile, "%s", last_member_p(m));
    1616             :             }
    1617             :         }
    1618         589 :         space(level + 1);
    1619         589 :         fprintf (headerfile, "} u;\n");
    1620         589 :         fprintf(jsonfile, "]");
    1621             : 
    1622         589 :         while (decorate_type(newbasename, &deco, &more_deco)) {
    1623           0 :             decorated++;
    1624           0 :             space(level + 1);
    1625           0 :             fprintf(headerfile, "%s %s%s;\n", deco.field_type,
    1626           0 :                     deco.opt ? "*" : "", deco.field_name);
    1627           0 :             if (deco.first)
    1628           0 :                 fprintf(jsonfile, ",\"decorate\":[");
    1629          31 :             fprintf(jsonfile, "%s{"
    1630             :                     "\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s,"
    1631             :                     "\"external\":%s,\"pointer\":%s,\"void_star\":%s,"
    1632             :                     "\"struct_star\":%s,"
    1633             :                     "\"copy_function\":\"%s\","
    1634             :                     "\"free_function\":\"%s\",\"header_name\":%s%s%s"
    1635             :                     "}",
    1636           0 :                     deco.first ? "" : ",",
    1637             :                     deco.field_type, deco.field_name,
    1638           0 :                     deco.opt ? "true" : "false", deco.ext ? "true" : "false",
    1639           0 :                     deco.ptr ? "true" : "false", deco.void_star ? "true" : "false",
    1640           0 :                     deco.struct_star ? "true" : "false",
    1641           0 :                     deco.copy_function_name ? deco.copy_function_name : "",
    1642           0 :                     deco.free_function_name ? deco.free_function_name : "",
    1643           0 :                     deco.header_name && deco.header_name[0] == '"' ? "" : "\"",
    1644           0 :                     deco.header_name ? deco.header_name : "",
    1645           0 :                     deco.header_name && deco.header_name[0] == '"' ? "" : "\""
    1646             :                     );
    1647             :         }
    1648         589 :         if (decorated)
    1649          35 :             fprintf(jsonfile, "]");
    1650             : 
    1651         589 :         space(level);
    1652        1174 :         fprintf(headerfile, "}%s%s;\n",
    1653         558 :                 (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
    1654         589 :                 (opts & DEF_TYPE_EMIT_NAME) ? name : "");
    1655         589 :         break;
    1656             :     }
    1657          18 :     case TUTCTime:
    1658          19 :         space(level);
    1659          19 :         fprintf (headerfile, "time_t %s;\n", name);
    1660          19 :         fprintf(jsonfile, "\"ttype\":\"UTCTime\",\"ctype\":\"time_t\"");
    1661          18 :         break;
    1662         828 :     case TUTF8String:
    1663         874 :         space(level);
    1664         874 :         fprintf (headerfile, "heim_utf8_string %s;\n", name);
    1665         874 :         fprintf(jsonfile, "\"ttype\":\"UTF8String\",\"ctype\":\"heim_utf8_string\"");
    1666         828 :         break;
    1667          36 :     case TPrintableString:
    1668          38 :         space(level);
    1669          38 :         fprintf (headerfile, "heim_printable_string %s;\n", name);
    1670          38 :         fprintf(jsonfile, "\"ttype\":\"PrintableString\",\"ctype\":\"heim_printable_string\"");
    1671          36 :         break;
    1672         198 :     case TIA5String:
    1673         209 :         space(level);
    1674         209 :         fprintf (headerfile, "heim_ia5_string %s;\n", name);
    1675         209 :         fprintf(jsonfile, "\"ttype\":\"IA5String\",\"ctype\":\"heim_ia5_string\"");
    1676         198 :         break;
    1677          54 :     case TBMPString:
    1678          57 :         space(level);
    1679          57 :         fprintf (headerfile, "heim_bmp_string %s;\n", name);
    1680          57 :         fprintf(jsonfile, "\"ttype\":\"BMPString\",\"ctype\":\"heim_bmp_string\"");
    1681          54 :         break;
    1682          18 :     case TUniversalString:
    1683          19 :         space(level);
    1684          19 :         fprintf (headerfile, "heim_universal_string %s;\n", name);
    1685          19 :         fprintf(jsonfile, "\"ttype\":\"UniversalString\",\"ctype\":\"heim_universal_string\"");
    1686          18 :         break;
    1687          36 :     case TVisibleString:
    1688          38 :         space(level);
    1689          38 :         fprintf (headerfile, "heim_visible_string %s;\n", name);
    1690          38 :         fprintf(jsonfile, "\"ttype\":\"VisibleString\",\"ctype\":\"heim_visible_string\"");
    1691          36 :         break;
    1692         666 :     case TOID :
    1693         703 :         space(level);
    1694         703 :         fprintf (headerfile, "heim_oid %s;\n", name);
    1695         703 :         fprintf(jsonfile, "\"ttype\":\"OBJECT IDENTIFIER\",\"ctype\":\"heim_oid\"");
    1696         666 :         break;
    1697          90 :     case TNull:
    1698          95 :         space(level);
    1699          95 :         fprintf (headerfile, "int %s;\n", name);
    1700          95 :         fprintf(jsonfile, "\"ttype\":\"NULL\",\"ctype\":\"int\"");
    1701          90 :         break;
    1702           0 :     default:
    1703           0 :         abort ();
    1704             :     }
    1705       62510 :     fprintf(jsonfile, "}\n");
    1706       62510 :     free(newbasename);
    1707       62510 : }
    1708             : 
    1709             : static void
    1710       14858 : declare_type(const Symbol *s, Type *t, int typedefp)
    1711             : {
    1712       14858 :     char *newbasename = NULL;
    1713             : 
    1714       14858 :     if (typedefp)
    1715        7771 :         fprintf(headerfile, "typedef ");
    1716             : 
    1717       14858 :     switch (t->type) {
    1718         627 :     case TType:
    1719         627 :         define_type(0, s->gen_name, s->gen_name, NULL, s->type,
    1720             :                     DEF_TYPE_PRESERVE | DEF_TYPE_TYPEDEFP |
    1721         627 :                     (s->emitted_declaration ? 0 : DEF_TYPE_EMIT_NAME));
    1722         627 :         if (template_flag && !s->emitted_declaration)
    1723         627 :             generate_template_type_forward(s->gen_name);
    1724         627 :         emitted_declaration(s);
    1725        9324 :         return;
    1726        1577 :     case TInteger:
    1727             :     case TBoolean:
    1728             :     case TOctetString:
    1729             :     case TBitString: 
    1730             :     case TEnumerated: 
    1731             :     case TGeneralizedTime:
    1732             :     case TGeneralString:
    1733             :     case TTeletexString:
    1734             :     case TUTCTime:
    1735             :     case TUTF8String:
    1736             :     case TPrintableString:
    1737             :     case TIA5String:
    1738             :     case TBMPString:
    1739             :     case TUniversalString:
    1740             :     case TVisibleString:
    1741             :     case TOID :
    1742             :     case TNull:
    1743        1577 :         define_type(0, s->gen_name, s->gen_name, NULL, s->type,
    1744             :                     DEF_TYPE_PRESERVE | DEF_TYPE_TYPEDEFP |
    1745        1577 :                      (s->emitted_declaration ? 0 : DEF_TYPE_EMIT_NAME));
    1746        1577 :         if (template_flag && !s->emitted_declaration)
    1747        1444 :             generate_template_type_forward(s->gen_name);
    1748        1577 :         emitted_declaration(s);
    1749        1577 :         emitted_definition(s);
    1750        1577 :         return;
    1751        7087 :     case TTag:
    1752        7087 :         if (!s->emitted_declaration)
    1753        7087 :             declare_type(s, t->subtype, FALSE);
    1754        7087 :         emitted_declaration(s);
    1755        7087 :         return;
    1756        5274 :     default:
    1757        5567 :         break;
    1758             :     }
    1759             : 
    1760        5567 :     switch (t->type) {
    1761        3952 :     case TSet:
    1762             :     case TSequence: {
    1763         208 :         struct decoration deco;
    1764        3952 :         ssize_t more_deco = -1;
    1765             : 
    1766        3952 :         getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
    1767        3952 :         fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
    1768        4028 :         while (decorate_type(newbasename, &deco, &more_deco)) {
    1769          76 :             if (deco.header_name)
    1770           0 :                 fprintf(headerfile, "#include %s\n", deco.header_name);
    1771          76 :             free(deco.field_type);
    1772             :         }
    1773        3952 :         break;
    1774             :     }
    1775        1102 :     case TSetOf:
    1776             :     case TSequenceOf:
    1777        1102 :         getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
    1778        1102 :         fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
    1779        1044 :         break;
    1780         513 :     case TChoice: {
    1781          27 :         struct decoration deco;
    1782         513 :         ssize_t more_deco = -1;
    1783             : 
    1784         513 :         getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
    1785         513 :         fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
    1786         513 :         while (decorate_type(newbasename, &deco, &more_deco)) {
    1787           0 :             if (deco.header_name)
    1788           0 :                 fprintf(headerfile, "#include %s\n", deco.header_name);
    1789           0 :             free(deco.field_type);
    1790             :         }
    1791         513 :         break;
    1792             :     }
    1793           0 :     default:
    1794           0 :         abort ();
    1795             :     }
    1796        5567 :     free(newbasename);
    1797        5567 :     emitted_declaration(s);
    1798             : }
    1799             : 
    1800             : static void generate_subtypes_header_helper(const Member *m);
    1801             : static void generate_type_header(const Symbol *);
    1802             : 
    1803             : static void
    1804       25460 : generate_subtypes_header_helper(const Member *m)
    1805             : {
    1806        1340 :     Member *sm;
    1807        1340 :     Symbol *s;
    1808             : 
    1809       25460 :     if (m->ellipsis)
    1810         864 :         return;
    1811       24548 :     if (m->type->symbol && (s = getsym(m->type->symbol->name)) &&
    1812        2641 :         !s->emitted_definition) {
    1813             :         /* A field of some named type; recurse */
    1814         627 :         if (!m->optional && !m->defval)
    1815         570 :             generate_type_header(s);
    1816         627 :         return;
    1817             :     }
    1818       23921 :     if (!m->type->subtype && !m->type->members)
    1819        1908 :         return;
    1820       21907 :     if (m->type->type == TTag &&
    1821       32724 :         m->type->subtype && m->type->subtype->symbol &&
    1822       11438 :         (s = getsym(m->type->subtype->symbol->name))) {
    1823       11438 :         if (!m->optional && !m->defval)
    1824        7562 :             generate_type_header(s);
    1825       11438 :         return;
    1826             :     }
    1827       10469 :     if (m->type->subtype) {
    1828       10450 :         switch (m->type->subtype->type) {
    1829          90 :         case TSet:
    1830             :         case TSequence:
    1831             :         case TChoice:
    1832          95 :             break;
    1833        9810 :         default:
    1834        9810 :             return;
    1835             :         }
    1836             :         /* A field of some anonymous (inlined) structured type */
    1837         513 :         HEIM_TAILQ_FOREACH(sm, m->type->subtype->members, members) {
    1838         418 :             generate_subtypes_header_helper(sm);
    1839             :         }
    1840             :     }
    1841         114 :     if (m->type->members) {
    1842          57 :         HEIM_TAILQ_FOREACH(sm, m->type->members, members) {
    1843          38 :             generate_subtypes_header_helper(sm);
    1844             :         }
    1845             :     }
    1846             : }
    1847             : 
    1848             : static void
    1849       14991 : generate_subtypes_header(const Symbol *s)
    1850             : {
    1851       14991 :     Type *t = s->type;
    1852         789 :     Member *m;
    1853             : 
    1854             :     /*
    1855             :      * Recurse down structured types to make sure top-level types get
    1856             :      * defined before they are referenced.
    1857             :      *
    1858             :      * We'll take care to skip OPTIONAL member fields of constructed types so
    1859             :      * that we can have circular types like:
    1860             :      *
    1861             :      *  Foo ::= SEQUENCE {
    1862             :      *    bar Bar OPTIONAL
    1863             :      *  }
    1864             :      *
    1865             :      *  Bar ::= SEQUENCE {
    1866             :      *    foo Foo OPTIONAL
    1867             :      *  }
    1868             :      *
    1869             :      * not unlike XDR, which uses `*' to mean "optional", except in XDR it's
    1870             :      * called a "pointer".  With some care we should be able to eventually
    1871             :      * support the silly XDR linked list example:
    1872             :      *
    1873             :      *  ListOfFoo ::= SEQUENCE {
    1874             :      *    someField SomeType,
    1875             :      *    next ListOfFoo OPTIONAL
    1876             :      *  }
    1877             :      *
    1878             :      * Not that anyone needs it -- just use a SEQUENCE OF and be done.
    1879             :      */
    1880             : 
    1881       21565 :     while (t->type == TTag && t->subtype) {
    1882       14155 :         switch (t->subtype->type) {
    1883        6574 :         case TTag:
    1884             :         case TSet:
    1885             :         case TSequence:
    1886             :         case TChoice:
    1887        6574 :             t = t->subtype;
    1888        6574 :             continue;
    1889        7182 :         default:
    1890        7182 :             break;
    1891             :         }
    1892        7182 :         break;
    1893             :     }
    1894             : 
    1895       14991 :     switch (t->type) {
    1896        7182 :     default: return;
    1897         513 :     case TType: {
    1898          27 :         Symbol *s2;
    1899         513 :         if (t->symbol && (s2 = getsym(t->symbol->name)) != s)
    1900         513 :             generate_type_header(s2);
    1901         486 :         return;
    1902             :     }
    1903        6534 :     case TSet:
    1904             :     case TSequence:
    1905             :     case TChoice:
    1906        6897 :         break;
    1907             :     }
    1908             : 
    1909       31901 :     HEIM_TAILQ_FOREACH(m, t->members, members) {
    1910       25004 :         generate_subtypes_header_helper(m);
    1911             :     }
    1912             : }
    1913             : 
    1914             : static void
    1915       16416 : generate_type_header (const Symbol *s)
    1916             : {
    1917       16416 :     Type *t = s->type;
    1918             : 
    1919       16416 :     if (!s->type)
    1920        1350 :         return;
    1921             : 
    1922             :     /*
    1923             :      * Recurse down the types of member fields of `s' to make sure that
    1924             :      * referenced types have had their definitions emitted already if the
    1925             :      * member fields are not OPTIONAL/DEFAULTed.
    1926             :      */
    1927       14991 :     generate_subtypes_header(s);
    1928       14991 :     if (!s->emitted_asn1) {
    1929        7771 :         fprintf(headerfile, "/*\n");
    1930        7771 :         fprintf(headerfile, "%s ::= ", s->name);
    1931        7771 :         define_asn1 (0, s->type);
    1932        7771 :         fprintf(headerfile, "\n*/\n\n");
    1933        7771 :         emitted_asn1(s);
    1934             :     }
    1935             : 
    1936             :     /*
    1937             :      * Emit enums for the outermost tag of this type.  These are needed for
    1938             :      * dealing with IMPLICIT tags so we know what to rewrite the tag to when
    1939             :      * decoding.
    1940             :      *
    1941             :      * See gen_encode.c and gen_decode.c for a complete explanation.  Short
    1942             :      * version: we need to change the prototypes of the length/encode/decode
    1943             :      * functions to take an optional IMPLICIT tag to use instead of the type's
    1944             :      * outermost tag, but for now we hack it, and to do that we need to know
    1945             :      * the type's outermost tag outside the context of the bodies of the codec
    1946             :      * functions we generate for it.  Using an enum means no extra space is
    1947             :      * needed in stripped objects.
    1948             :      */
    1949       14991 :     if (!s->emitted_tag_enums) {
    1950        8113 :         while (t->type == TType && s->type->symbol && s->type->symbol->type) {
    1951         342 :             if (t->subtype)
    1952           0 :                 t = t->subtype;
    1953             :             else
    1954         751 :                 t = s->type->symbol->type;
    1955             :         }
    1956             : 
    1957        7771 :         if (t->type == TType && t->symbol &&
    1958         171 :             strcmp(t->symbol->name, "HEIM_ANY") != 0) {
    1959             :             /*
    1960             :              * This type is ultimately an alias of an imported type, so we don't
    1961             :              * know its outermost tag here.
    1962             :              */
    1963         160 :             fprintf(headerfile,
    1964             :                     "enum { asn1_tag_length_%s = asn1_tag_length_%s,\n"
    1965             :                     "       asn1_tag_class_%s = asn1_tag_class_%s,\n"
    1966             :                     "       asn1_tag_tag_%s = asn1_tag_tag_%s };\n",
    1967         144 :                     s->gen_name, s->type->symbol->gen_name,
    1968         144 :                     s->gen_name, s->type->symbol->gen_name,
    1969         152 :                     s->gen_name, s->type->symbol->gen_name);
    1970         152 :             emitted_tag_enums(s);
    1971        7619 :         } else if (t->type != TType) {
    1972             :             /* This type's outermost tag is known here */
    1973       15600 :             fprintf(headerfile,
    1974             :                     "enum { asn1_tag_length_%s = %lu,\n"
    1975             :                     "       asn1_tag_class_%s = %d,\n"
    1976             :                     "       asn1_tag_tag_%s = %d };\n",
    1977        7600 :                     s->gen_name, (unsigned long)length_tag(s->type->tag.tagvalue),
    1978        7200 :                     s->gen_name, s->type->tag.tagclass,
    1979        7600 :                     s->gen_name, s->type->tag.tagvalue);
    1980        7600 :             emitted_tag_enums(s);
    1981             :         }
    1982             :     }
    1983             : 
    1984       14991 :     if (s->emitted_definition)
    1985        8334 :         return;
    1986             : 
    1987        6194 :     if (is_export(s->name))
    1988        6254 :         fprintf(symsfile, "ASN1_SYM_TYPE(\"%s\", \"%s\", %s)\n",
    1989        5928 :                 s->name, s->gen_name, s->gen_name);
    1990             : 
    1991        6194 :     if (!s->emitted_declaration) {
    1992           0 :         fprintf(headerfile, "typedef ");
    1993           0 :         define_type(0, s->gen_name, s->gen_name, NULL, s->type,
    1994             :                     DEF_TYPE_TYPEDEFP | DEF_TYPE_EMIT_NAME |
    1995           0 :                     (preserve_type(s->name) ? DEF_TYPE_PRESERVE : 0));
    1996        6194 :     } else if (s->type->type == TType) {
    1997             :         /* This is a type alias and we've already declared it */
    1998        5681 :     } else if (s->type->type == TTag &&
    1999        5168 :                s->type->subtype != NULL &&
    2000        5168 :                s->type->subtype->symbol != NULL) {
    2001             :         /* This is a type alias and we've already declared it */
    2002             :     } else {
    2003        5853 :         define_type(0, s->gen_name, s->gen_name, NULL, s->type,
    2004             :                     DEF_TYPE_TYPEDEFP |
    2005        5567 :                     (preserve_type(s->name) ? DEF_TYPE_PRESERVE : 0));
    2006             :     }
    2007        6194 :     fprintf(headerfile, "\n");
    2008             : 
    2009        6194 :     emitted_definition(s);
    2010             : }
    2011             : 
    2012             : void
    2013        7771 : generate_type_header_forwards(const Symbol *s)
    2014             : {
    2015        7771 :     declare_type(s, s->type, TRUE);
    2016        7771 :     fprintf(headerfile, "\n");
    2017        7771 :     if (template_flag)
    2018        6859 :         generate_template_type_forward(s->gen_name);
    2019        7771 : }
    2020             : 
    2021             : void
    2022        7771 : generate_type (const Symbol *s)
    2023             : {
    2024         409 :     FILE *h;
    2025         409 :     const char * exp;
    2026             : 
    2027        7771 :     if (!one_code_file)
    2028           0 :         generate_header_of_codefile(s->gen_name);
    2029             : 
    2030        7771 :     generate_type_header(s);
    2031             : 
    2032        7771 :     if (template_flag)
    2033        6859 :         generate_template(s);
    2034             : 
    2035        7771 :     if (template_flag == 0 || is_template_compat(s) == 0) {
    2036         912 :         generate_type_encode (s);
    2037         912 :         generate_type_decode (s);
    2038         912 :         generate_type_free (s);
    2039         912 :         generate_type_length (s);
    2040         912 :         generate_type_copy (s);
    2041         912 :         generate_type_print_stub(s);
    2042             :     }
    2043        7771 :     generate_type_seq (s);
    2044        7771 :     generate_glue (s->type, s->gen_name);
    2045             : 
    2046             :     /* generate prototypes */
    2047             : 
    2048        7771 :     if (is_export(s->name)) {
    2049        7296 :         h = headerfile;
    2050        7296 :         exp = "ASN1EXP ";
    2051             :     } else {
    2052         475 :         h = privheaderfile;
    2053         475 :         exp = "";
    2054             :     }
    2055             : 
    2056        8180 :     fprintf (h,
    2057             :              "%sint    ASN1CALL "
    2058             :              "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
    2059             :              exp,
    2060        7771 :              s->gen_name, s->gen_name);
    2061        8180 :     fprintf (h,
    2062             :              "%sint    ASN1CALL "
    2063             :              "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n",
    2064             :              exp,
    2065        7771 :              s->gen_name, s->gen_name);
    2066        8180 :     fprintf (h,
    2067             :              "%ssize_t ASN1CALL length_%s(const %s *);\n",
    2068             :              exp,
    2069        7771 :              s->gen_name, s->gen_name);
    2070        8180 :     fprintf (h,
    2071             :              "%sint    ASN1CALL copy_%s  (const %s *, %s *);\n",
    2072             :              exp,
    2073        7771 :              s->gen_name, s->gen_name, s->gen_name);
    2074        8180 :     fprintf (h,
    2075             :              "%svoid   ASN1CALL free_%s  (%s *);\n",
    2076             :              exp,
    2077        7771 :              s->gen_name, s->gen_name);
    2078             : 
    2079        8180 :     fprintf(h,
    2080             :             "%schar * ASN1CALL print_%s (const %s *, int);\n",
    2081             :             exp,
    2082        7771 :             s->gen_name, s->gen_name);
    2083             : 
    2084        7771 :     fprintf(h, "\n\n");
    2085             : 
    2086        7771 :     if (!one_code_file) {
    2087           0 :         fprintf(codefile, "\n\n");
    2088           0 :         close_codefile();
    2089             :     }
    2090        7771 : }

Generated by: LCOV version 1.14