LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/asn1 - gen_template.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 630 817 77.1 %
Date: 2024-06-13 04:01:37 Functions: 52 52 100.0 %

          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 - 2010 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             : /*
      37             :  * Currently we generate C source code defining constant arrays of structures
      38             :  * containing a sort of a "byte-coded" template of an ASN.1 compiler to be
      39             :  * interpreted at run-time.
      40             :  */
      41             : 
      42             : #include "gen_locl.h"
      43             : #include <vis.h>
      44             : #include <vis-extras.h>
      45             : 
      46             : static const char *symbol_name(const char *, const Type *);
      47             : static void generate_template_type(const char *, const char **, const char *, const char *, const char *,
      48             :                                    Type *, int, int, int);
      49             : 
      50             : static const char *
      51        6412 : ttype_symbol(const char *basename, const Type *t)
      52             : {
      53        6412 :     return t->symbol->gen_name;
      54             : }
      55             : 
      56             : static const char *
      57        1708 : integer_symbol(const char *basename, const Type *t)
      58             : {
      59        1708 :     if (t->members)
      60             :         /*
      61             :          * XXX enum foo -- compute the size either from inspecting the members
      62             :          * and applying the ABI's rules for enum size, OR infer the field
      63             :          * size from a template by using the offsetof field.  The latter is
      64             :          * hard to do though.
      65             :          */
      66         336 :         return "int";
      67        1372 :     else if (t->range == NULL)
      68         770 :         return "heim_integer";
      69         756 :     else if (t->range->min < 0 &&
      70         308 :              (t->range->min < INT_MIN || t->range->max > INT_MAX))
      71           0 :         return "int64_t";
      72         602 :     else if (t->range->min < 0)
      73         154 :         return "int";
      74         448 :     else if (t->range->max > UINT_MAX)
      75           0 :         return "uint64_t";
      76             :     else
      77         448 :         return "unsigned";
      78             : }
      79             : 
      80             : static const char *
      81         280 : boolean_symbol(const char *basename, const Type *t)
      82             : {
      83         280 :     return "int";
      84             : }
      85             : 
      86             : 
      87             : static const char *
      88        2562 : octetstring_symbol(const char *basename, const Type *t)
      89             : {
      90        2562 :     return "heim_octet_string";
      91             : }
      92             : 
      93             : static const char *
      94          56 : sequence_symbol(const char *basename, const Type *t)
      95             : {
      96          56 :     return basename;
      97             : }
      98             : 
      99             : static const char *
     100         224 : time_symbol(const char *basename, const Type *t)
     101             : {
     102         224 :     return "time_t";
     103             : }
     104             : 
     105             : static const char *
     106        3822 : tag_symbol(const char *basename, const Type *t)
     107             : {
     108        3822 :     return symbol_name(basename, t->subtype);
     109             : }
     110             : 
     111             : static const char *
     112         322 : generalstring_symbol(const char *basename, const Type *t)
     113             : {
     114         322 :     return "heim_general_string";
     115             : }
     116             : 
     117             : static const char *
     118          42 : printablestring_symbol(const char *basename, const Type *t)
     119             : {
     120          42 :     return "heim_printable_string";
     121             : }
     122             : 
     123             : static const char *
     124         266 : ia5string_symbol(const char *basename, const Type *t)
     125             : {
     126         266 :     return "heim_ia5_string";
     127             : }
     128             : 
     129             : static const char *
     130          28 : teletexstring_symbol(const char *basename, const Type *t)
     131             : {
     132          28 :     return "heim_general_string";
     133             : }
     134             : 
     135             : static const char *
     136          56 : visiblestring_symbol(const char *basename, const Type *t)
     137             : {
     138          56 :     return "heim_visible_string";
     139             : }
     140             : 
     141             : static const char *
     142         896 : utf8string_symbol(const char *basename, const Type *t)
     143             : {
     144         896 :     return "heim_utf8_string";
     145             : }
     146             : 
     147             : static const char *
     148          70 : bmpstring_symbol(const char *basename, const Type *t)
     149             : {
     150          70 :     return "heim_bmp_string";
     151             : }
     152             : 
     153             : static const char *
     154          28 : universalstring_symbol(const char *basename, const Type *t)
     155             : {
     156          28 :     return "heim_universal_string";
     157             : }
     158             : 
     159             : static const char *
     160         672 : oid_symbol(const char *basename, const Type *t)
     161             : {
     162         672 :     return "heim_oid";
     163             : }
     164             : 
     165             : static const char *
     166         420 : bitstring_symbol(const char *basename, const Type *t)
     167             : {
     168         420 :     if (t->members)
     169         420 :         return basename;
     170           0 :     return "heim_bit_string";
     171             : }
     172             : 
     173             : 
     174             : 
     175             : /* Keep this sorted by `type' so we can just index this by type */
     176             : const struct {
     177             :     enum typetype type;
     178             :     const char *(*symbol_name)(const char *, const Type *);
     179             :     int is_struct;
     180             : } types[] =  {
     181             :     { TBitString, bitstring_symbol, 0 },
     182             :     { TBoolean, boolean_symbol, 0 },
     183             :     { TChoice, sequence_symbol, 1 },
     184             :     { TEnumerated, integer_symbol, 0 },
     185             :     { TGeneralString, generalstring_symbol, 0 },
     186             :     { TTeletexString, teletexstring_symbol, 0 },
     187             :     { TGeneralizedTime, time_symbol, 0 },
     188             :     { TIA5String, ia5string_symbol, 0 },
     189             :     { TInteger, integer_symbol, 0 },
     190             :     { TNull, integer_symbol, 1 },
     191             :     { TOID, oid_symbol, 0 },
     192             :     { TOctetString, octetstring_symbol, 0 },
     193             :     { TPrintableString, printablestring_symbol, 0 },
     194             :     { TSequence, sequence_symbol, 1 },
     195             :     { TSequenceOf, tag_symbol, 1 },
     196             :     { TSet, sequence_symbol, 1 },
     197             :     { TSetOf, tag_symbol, 1 },
     198             :     { TTag, tag_symbol, 1 },
     199             :     { TType, ttype_symbol, 1 },
     200             :     { TUTCTime, time_symbol, 0 },
     201             :     { TUTF8String, utf8string_symbol, 0 },
     202             :     { TBMPString, bmpstring_symbol, 0 },
     203             :     { TUniversalString, universalstring_symbol, 0 },
     204             :     { TVisibleString, visiblestring_symbol, 0 },
     205             : };
     206             : 
     207             : static FILE *
     208       68670 : get_code_file(void)
     209             : {
     210       68670 :     if (!one_code_file)
     211           0 :         return templatefile;
     212       68670 :     return codefile;
     213             : }
     214             : 
     215             : 
     216             : static int
     217        5026 : is_supported_type_p(const Type *t)
     218             : {
     219       10052 :     return t->type >= 0 && t->type <= TVisibleString &&
     220        5026 :         types[t->type].type == t->type;
     221             : }
     222             : 
     223             : int
     224        5026 : is_template_compat (const Symbol *s)
     225             : {
     226        5026 :     return is_supported_type_p(s->type);
     227             : }
     228             : 
     229             : static const char *
     230       17864 : symbol_name(const char *basename, const Type *t)
     231             : {
     232       35728 :     if (t->type >= 0 && t->type <= TVisibleString &&
     233       17864 :         types[t->type].type == t->type)
     234       17864 :         return (types[t->type].symbol_name)(basename, t);
     235           0 :     if (t->type >= 0 && t->type <= TVisibleString)
     236           0 :         errx(1, "types[] is not sorted");
     237           0 :     errx(1, "unknown der type: %d\n", t->type);
     238             :     return NULL;
     239             : }
     240             : 
     241             : 
     242             : static char *
     243       32284 : partial_offset(const char *basetype, const char *name, int need_offset, int isstruct)
     244             : {
     245             :     char *str;
     246       32284 :     if (name == NULL || need_offset == 0)
     247       22722 :         return strdup("0");
     248        9562 :     if (asprintf(&str, "offsetof(%s%s, %s)", isstruct ? "struct " : "", basetype, name) < 0 || str == NULL)
     249           0 :         errx(1, "malloc");
     250        9562 :     return str;
     251             : }
     252             : 
     253             : struct template {
     254             :     char *line;
     255             :     char *tt;
     256             :     char *offset;
     257             :     char *ptr;
     258             :     HEIM_TAILQ_ENTRY(template) members;
     259             : };
     260             : 
     261             : HEIM_TAILQ_HEAD(templatehead, template);
     262             : 
     263             : struct tlist {
     264             :     char *name;
     265             :     char *header;
     266             :     struct templatehead template;
     267             :     HEIM_TAILQ_ENTRY(tlist) tmembers;
     268             : };
     269             : 
     270             : HEIM_TAILQ_HEAD(tlisthead, tlist);
     271             : 
     272             : static void tlist_header(struct tlist *, const char *, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
     273             : static struct template *
     274             :     add_line(struct templatehead *, const char *, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
     275             : static int tlist_cmp(const struct tlist *, const struct tlist *);
     276             : 
     277             : static void add_line_pointer(struct templatehead *, const char *, const char *, const char *, ...)
     278             :     __attribute__ ((__format__ (__printf__, 4, 5)));
     279             : static void add_line_string(struct templatehead *, const char *, const char *, const char *, ...)
     280             :     __attribute__ ((__format__ (__printf__, 4, 5)));
     281             : static void add_line_pointer_reference(struct templatehead *, const char *, const char *, const char *, ...)
     282             :     __attribute__ ((__format__ (__printf__, 4, 5)));
     283             : 
     284             : 
     285             : static struct tlisthead tlistmaster = HEIM_TAILQ_HEAD_INITIALIZER(tlistmaster);
     286             : static unsigned long numdups = 0;
     287             : 
     288             : static struct tlist *
     289       23128 : tlist_new(const char *name)
     290             : {
     291       23128 :     struct tlist *tl = calloc(1, sizeof(*tl));
     292       23128 :     tl->name = strdup(name);
     293       23128 :     HEIM_TAILQ_INIT(&tl->template);
     294       23128 :     return tl;
     295             : }
     296             : 
     297             : static void
     298       23128 : tlist_header(struct tlist *t, const char *fmt, ...)
     299             : {
     300             :     va_list ap;
     301       23128 :     va_start(ap, fmt);
     302       23128 :     if (vasprintf(&t->header, fmt, ap) < 0 || t->header == NULL)
     303           0 :         errx(1, "malloc");
     304       23128 :     va_end(ap);
     305       23128 : }
     306             : 
     307             : static unsigned long
     308       22722 : tlist_count(struct tlist *tl)
     309             : {
     310       22722 :     unsigned int count = 0;
     311             :     struct template *q;
     312             : 
     313       65128 :     HEIM_TAILQ_FOREACH(q, &tl->template, members) {
     314       42406 :         count++;
     315             :     }
     316       22722 :     return count;
     317             : }
     318             : 
     319             : static void
     320       14406 : tlist_add(struct tlist *tl)
     321             : {
     322       14406 :     HEIM_TAILQ_INSERT_TAIL(&tlistmaster, tl, tmembers);
     323       14406 : }
     324             : 
     325             : static void
     326       14406 : tlist_print(struct tlist *tl)
     327             : {
     328             :     struct template *q;
     329       14406 :     unsigned int i = 1;
     330       14406 :     FILE *f = get_code_file();
     331             : 
     332       14406 :     fprintf(f, "const struct asn1_template asn1_%s[] = {\n", tl->name);
     333       14406 :     fprintf(f, "/* 0 */ %s,\n", tl->header);
     334       54292 :     HEIM_TAILQ_FOREACH(q, &tl->template, members) {
     335       39886 :         int last = (HEIM_TAILQ_LAST(&tl->template, templatehead) == q);
     336       39886 :         fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");
     337             :     }
     338       14406 :     fprintf(f, "};\n");
     339       14406 : }
     340             : 
     341             : static struct tlist *
     342        9660 : tlist_find_by_name(const char *name)
     343             : {
     344             :     struct tlist *ql;
     345      384608 :     HEIM_TAILQ_FOREACH(ql, &tlistmaster, tmembers) {
     346      384608 :         if (strcmp(ql->name, name) == 0)
     347        9660 :             return ql;
     348             :     }
     349           0 :     return NULL;
     350             : }
     351             : 
     352             : static int
     353        4830 : tlist_cmp_name(const char *tname, const char *qname)
     354             : {
     355        4830 :     struct tlist *tl = tlist_find_by_name(tname);
     356        4830 :     struct tlist *ql = tlist_find_by_name(qname);
     357        4830 :     if (tl == NULL)
     358           0 :         return 1;
     359        4830 :     if (ql == NULL)
     360           0 :         return -1;
     361        4830 :     return tlist_cmp(tl, ql);
     362             : }
     363             : 
     364             : static int
     365     1771798 : tlist_cmp(const struct tlist *tl, const struct tlist *ql)
     366             : {
     367             :     int ret;
     368             :     struct template *t, *q;
     369             : 
     370     1771798 :     if (tl == ql)
     371        4830 :         return 0;
     372     1766968 :     ret = strcmp(tl->header, ql->header);
     373     1766968 :     if (ret != 0) return ret;
     374             : 
     375       21630 :     q = HEIM_TAILQ_FIRST(&ql->template);
     376       30338 :     HEIM_TAILQ_FOREACH(t, &tl->template, members) {
     377       21616 :         if (q == NULL) return 1;
     378             : 
     379       21616 :         if (t->ptr == NULL || q->ptr == NULL) {
     380       11326 :             ret = strcmp(t->line, q->line);
     381       11326 :             if (ret != 0) return ret;
     382             :         } else {
     383       10290 :             ret = strcmp(t->tt, q->tt);
     384       10290 :             if (ret != 0) return ret;
     385             : 
     386        4858 :             ret = strcmp(t->offset, q->offset);
     387        4858 :             if (ret != 0) return ret;
     388             : 
     389        9688 :             if ((ret = strcmp(t->ptr, q->ptr)) != 0 ||
     390        4830 :                 (ret = tlist_cmp_name(t->ptr, q->ptr)) != 0)
     391          28 :                 return ret;
     392             :         }
     393        8708 :         q = HEIM_TAILQ_NEXT(q, members);
     394             :     }
     395        8722 :     if (q != NULL) return -1;
     396        8722 :     return 0;
     397             : }
     398             : 
     399             : 
     400             : static const char *
     401       23058 : tlist_find_dup(const struct tlist *tl)
     402             : {
     403             :     struct tlist *ql;
     404             : 
     405     1781304 :     HEIM_TAILQ_FOREACH(ql, &tlistmaster, tmembers) {
     406     1766968 :         if (tlist_cmp(ql, tl) == 0) {
     407        8722 :             numdups++;
     408        8722 :             return ql->name;
     409             :         }
     410             :     }
     411       14336 :     return NULL;
     412             : }
     413             : 
     414             : 
     415             : /*
     416             :  * Add an entry to a template.
     417             :  */
     418             : 
     419             : static struct template *
     420       51562 : add_line(struct templatehead *t, const char *fmt, ...)
     421             : {
     422       51562 :     struct template *q = calloc(1, sizeof(*q));
     423             :     va_list ap;
     424       51562 :     va_start(ap, fmt);
     425       51562 :     if (vasprintf(&q->line, fmt, ap) < 0 || q->line == NULL)
     426           0 :         errx(1, "malloc");
     427       51562 :     va_end(ap);
     428       51562 :     HEIM_TAILQ_INSERT_TAIL(t, q, members);
     429       51562 :     return q;
     430             : }
     431             : 
     432             : /*
     433             :  * Add an entry to a template, with the pointer field being a symbol name of a
     434             :  * template (i.e., an array, which decays to a pointer as usual in C).
     435             :  */
     436             : static void
     437       22274 : add_line_pointer(struct templatehead *t,
     438             :                  const char *ptr,
     439             :                  const char *offset,
     440             :                  const char *ttfmt,
     441             :                  ...)
     442             : {
     443             :     struct template *q;
     444             :     va_list ap;
     445       22274 :     char *tt = NULL;
     446             : 
     447       22274 :     va_start(ap, ttfmt);
     448       22274 :     if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL)
     449           0 :         errx(1, "malloc");
     450       22274 :     va_end(ap);
     451             : 
     452       22274 :     if (ptr[0] == '&')
     453          14 :         q = add_line(t, "{ %s, %s, %s }", tt, offset, ptr);
     454             :     else
     455       22260 :         q = add_line(t, "{ %s, %s, asn1_%s }", tt, offset, ptr);
     456       22274 :     q->tt = tt;
     457       22274 :     q->offset = strdup(offset);
     458       22274 :     q->ptr = strdup(ptr);
     459       22274 : }
     460             : 
     461             : /*
     462             :  * Add an entry to a template where the pointer field is a string literal.
     463             :  */
     464             : static void
     465       12600 : add_line_string(struct templatehead *t,
     466             :                 const char *str,
     467             :                 const char *offset,
     468             :                 const char *ttfmt,
     469             :                 ...)
     470             : {
     471             :     struct template *q;
     472             :     va_list ap;
     473       12600 :     char *tt = NULL;
     474             : 
     475       12600 :     va_start(ap, ttfmt);
     476       12600 :     if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL)
     477           0 :         errx(1, "malloc");
     478       12600 :     va_end(ap);
     479             : 
     480       12600 :     q = add_line(t, "{ %s, %s, \"%s\" }", tt, offset, str);
     481       12600 :     q->tt = tt;
     482       12600 :     q->offset = strdup(offset);
     483       12600 :     q->ptr = strdup(str);
     484       12600 : }
     485             : 
     486             : /*
     487             :  * Add an entry to a template, with the pointer field being a reference to
     488             :  * named object of a type other than a template or other array type.
     489             :  */
     490             : static void
     491        1428 : add_line_pointer_reference(struct templatehead *t,
     492             :                            const char *ptr,
     493             :                            const char *offset,
     494             :                            const char *ttfmt,
     495             :                            ...)
     496             : {
     497             :     struct template *q;
     498             :     va_list ap;
     499        1428 :     char *tt = NULL;
     500             : 
     501        1428 :     va_start(ap, ttfmt);
     502        1428 :     if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL)
     503           0 :         errx(1, "malloc");
     504        1428 :     va_end(ap);
     505             : 
     506        1428 :     q = add_line(t, "{ %s, %s, (const void *)&asn1_%s }", tt, offset, ptr);
     507        1428 :     q->tt = tt;
     508        1428 :     q->offset = strdup(offset);
     509        1428 :     q->ptr = strdup(ptr);
     510        1428 : }
     511             : 
     512             : static int
     513       12446 : use_extern(const Symbol *s)
     514             : {
     515       12446 :     if (s->type == NULL)
     516        1064 :         return 1;
     517       11382 :     return 0;
     518             : }
     519             : 
     520             : static int
     521       21364 : is_struct(const Type *t, int isstruct)
     522             : {
     523       21364 :     if (t->type == TType)
     524        5810 :         return 0;
     525       15554 :     if (t->type == TSequence || t->type == TSet || t->type == TChoice)
     526        2996 :         return 1;
     527       12558 :     if (t->type == TTag)
     528        3668 :         return is_struct(t->subtype, isstruct);
     529             : 
     530       17780 :     if (t->type >= 0 && t->type <= TVisibleString &&
     531        8890 :         types[t->type].type == t->type) {
     532        8890 :         if (types[t->type].is_struct == 0)
     533        7364 :             return 0;
     534        1526 :         return isstruct;
     535             :     }
     536           0 :     if (t->type >= 0 && t->type <= TVisibleString)
     537           0 :         errx(1, "types[] is not sorted");
     538           0 :     errx(1, "unknown der type: %d\n", t->type);
     539             :     return isstruct;
     540             : }
     541             : 
     542             : static const Type *
     543          56 : compact_tag(const Type *t)
     544             : {
     545         112 :     while (t->type == TTag)
     546           0 :         t = t->subtype;
     547          56 :     return t;
     548             : }
     549             : 
     550             : static void
     551         154 : defval(struct templatehead *temp, Member *m)
     552             : {
     553         154 :     switch (m->defval->type) {
     554          84 :     case booleanvalue:
     555          84 :         add_line(temp, "{ A1_OP_DEFVAL|A1_DV_BOOLEAN, ~0, (void *)(uintptr_t)%u }",
     556          84 :                  m->defval->u.booleanvalue);
     557          84 :         break;
     558           0 :     case nullvalue:
     559           0 :         add_line(temp, "{ A1_OP_DEFVAL|A1_DV_NULL, ~0, (void *)(uintptr_t)0 }");
     560           0 :         break;
     561          70 :     case integervalue: {
     562          70 :         const char *dv = "A1_DV_INTEGER";
     563          70 :         Type *t = m->type;
     564             : 
     565             :         for (;;) {
     566         434 :             if (t->range)
     567          28 :                 break;
     568         224 :             if (t->type == TInteger && t->members)
     569          42 :                 break;
     570         182 :             if (t->type == TEnumerated)
     571           0 :                 break;
     572         182 :             if (t->subtype)
     573          98 :                 t = t->subtype;
     574          84 :             else if (t->symbol && t->symbol->type)
     575          84 :                 t = t->symbol->type;
     576             :             else
     577           0 :                 errx(1, "DEFAULT values for unconstrained INTEGER members not supported");
     578             :         }
     579             : 
     580          70 :         if (t->members)
     581          42 :             dv = "A1_DV_INTEGER32"; /* XXX Enum size assumptions!  No good! */
     582          42 :         else if (t->range && t->range->min < 0 &&
     583          28 :                  (t->range->min < INT_MIN || t->range->max > INT_MAX))
     584           0 :             dv = "A1_DV_INTEGER64";
     585          28 :         else if (t->range && t->range->min < 0)
     586          14 :             dv = "A1_DV_INTEGER32";
     587          14 :         else if (t->range && t->range->max > UINT_MAX)
     588           0 :             dv = "A1_DV_INTEGER64";
     589             :         else
     590          14 :             dv = "A1_DV_INTEGER32";
     591          70 :         add_line(temp, "{ A1_OP_DEFVAL|%s, ~0, (void *)(uintptr_t)%llu }",
     592          70 :                  dv, (long long)m->defval->u.integervalue);
     593          70 :         break;
     594             :     }
     595           0 :     case stringvalue: {
     596             :         char *quoted;
     597             : 
     598           0 :         if (rk_strasvis(&quoted, m->defval->u.stringvalue,
     599             :                         VIS_CSTYLE | VIS_NL, "\"") < 0)
     600           0 :             err(1, "Could not quote a string");
     601           0 :         add_line(temp, "{ A1_OP_DEFVAL|A1_DV_UTF8STRING, ~0, (void *)(uintptr_t)\"%s\" }",
     602             :                  quoted);
     603           0 :         free(quoted);
     604           0 :         break;
     605             :     }
     606           0 :     case objectidentifiervalue: {
     607             :         struct objid *o;
     608           0 :         size_t sz = sizeof("{ }");
     609             :         char *s, *p;
     610             :         int len;
     611             : 
     612           0 :         for (o = m->defval->u.objectidentifiervalue; o != NULL; o = o->next) {
     613           0 :             if ((len = snprintf(0, 0, " %d", o->value)) < 0)
     614           0 :                 err(1, "Could not format integer");
     615           0 :             sz += len;
     616             :         }
     617             : 
     618           0 :         if ((p = s = malloc(sz)) == NULL)
     619           0 :                 err(1, "Could not allocate string");
     620             : 
     621           0 :         len = snprintf(p, sz, "{");
     622           0 :         sz -= len;
     623           0 :         p += len;
     624           0 :         for (o = m->defval->u.objectidentifiervalue; o != NULL; o = o->next) {
     625           0 :             if ((len = snprintf(p, sz, " %d", o->value)) < 0 || len > sz - 1)
     626           0 :                 err(1, "Could not format integer");
     627           0 :             sz -= len;
     628           0 :             p += len;
     629             :         }
     630           0 :         if ((len = snprintf(p, sz, " }")) >= sz)
     631           0 :             abort();
     632           0 :         sz -= len;
     633           0 :         if (sz != 0)
     634           0 :             abort();
     635             : 
     636           0 :         add_line(temp, "{ A1_OP_DEFVAL|A1_DV_INTEGER, ~0, (void *)(uintptr_t)\"%s\" }", s);
     637           0 :         free(s);
     638           0 :         break;
     639             :     }
     640           0 :     default: abort();
     641             :     }
     642         154 : }
     643             : 
     644             : int
     645        6944 : objid_cmp(struct objid *oida, struct objid *oidb)
     646             : {
     647             :     struct objid *p;
     648             :     size_t ai, bi, alen, blen;
     649             :     int avals[20];
     650             :     int bvals[20];
     651             :     int c;
     652             : 
     653             :     /*
     654             :      * Our OID values are backwards here.  Comparing them is hard.
     655             :      */
     656             : 
     657       46410 :     for (p = oida, alen = 0;
     658       32522 :          p && alen < sizeof(avals)/sizeof(avals[0]);
     659       32522 :          p = p->next)
     660       32522 :         avals[alen++] = p->value;
     661       49070 :     for (p = oidb, blen = 0;
     662       35182 :          p && blen < sizeof(bvals)/sizeof(bvals[0]);
     663       35182 :          p = p->next)
     664       35182 :         bvals[blen++] = p->value;
     665        6944 :     if (alen >= sizeof(avals)/sizeof(avals[0]) ||
     666             :         blen >= sizeof(bvals)/sizeof(bvals[0]))
     667           0 :         err(1, "OIDs with more components than %llu not supported",
     668             :             (unsigned long long)sizeof(avals)/sizeof(avals[0]));
     669             : 
     670       33614 :     for (ai = 0, bi = 0; ai < alen && bi < blen;)
     671       26670 :         if ((c = avals[(alen-1)-(ai++)] - bvals[(blen-1)-(bi++)]))
     672        6944 :             return c;
     673             : 
     674           0 :     if (ai == alen && bi == blen)
     675           0 :         return 0;
     676           0 :     if (ai == alen)
     677           0 :         return 1;
     678           0 :     return -1;
     679             : }
     680             : 
     681             : int
     682        6944 : object_cmp(const void *va, const void *vb)
     683             : {
     684        6944 :     const IOSObject *oa = *(const IOSObject * const *)va;
     685        6944 :     const IOSObject *ob = *(const IOSObject * const *)vb;
     686             : 
     687        6944 :     switch (oa->typeidf->value->type) {
     688           0 :     case booleanvalue:
     689           0 :         return oa->typeidf->value->u.booleanvalue -
     690           0 :             ob->typeidf->value->u.booleanvalue;
     691           0 :     case nullvalue:
     692           0 :         return 0;
     693           0 :     case integervalue:
     694           0 :         return oa->typeidf->value->u.integervalue -
     695           0 :             ob->typeidf->value->u.integervalue;
     696           0 :     case stringvalue:
     697           0 :         return strcmp(oa->typeidf->value->u.stringvalue,
     698           0 :             ob->typeidf->value->u.stringvalue);
     699        6944 :     case objectidentifiervalue: {
     700        6944 :         return objid_cmp(oa->typeidf->value->u.objectidentifiervalue,
     701        6944 :             ob->typeidf->value->u.objectidentifiervalue);
     702             :     }
     703           0 :     default:
     704           0 :             abort();
     705             :             return -1;
     706             :     }
     707             : }
     708             : 
     709             : void
     710         224 : sort_object_set(IOSObjectSet *os,       /* Object set to sort fields of */
     711             :                 Field *typeidfield,     /* Field to sort by */
     712             :                 IOSObject ***objectsp,  /* Output: array of objects */
     713             :                 size_t *nobjsp)         /* Output: count of objects */
     714             : {
     715             :     IOSObject **objects;
     716             :     IOSObject *o;
     717         224 :     size_t i, nobjs = 0;
     718             : 
     719         224 :     *objectsp = NULL;
     720             : 
     721        2674 :     HEIM_TAILQ_FOREACH(o, os->objects, objects) {
     722        2450 :         ObjectField *typeidobjf = NULL;
     723             :         ObjectField *of;
     724             : 
     725        8190 :         HEIM_TAILQ_FOREACH(of, o->objfields, objfields) {
     726        5740 :             if (strcmp(of->name, typeidfield->name) == 0)
     727        2450 :                 typeidobjf = of;
     728             :         }
     729        2450 :         if (!typeidobjf) {
     730           0 :             warnx("Ignoring incomplete object specification of %s "
     731             :                   "(missing type ID field)",
     732           0 :                   o->symbol ? o->symbol->name : "<unknown>");
     733           0 :             continue;
     734             :         }
     735        2450 :         o->typeidf = typeidobjf;
     736        2450 :         nobjs++;
     737             :     }
     738         224 :     *nobjsp = nobjs;
     739             : 
     740         224 :     if (nobjs == 0)
     741           0 :         return;
     742             : 
     743         224 :     if ((objects = calloc(nobjs, sizeof(*objects))) == NULL)
     744           0 :         err(1, "Out of memory");
     745         224 :     *objectsp = objects;
     746             : 
     747         224 :     i = 0;
     748        2674 :     HEIM_TAILQ_FOREACH(o, os->objects, objects) {
     749        2450 :         ObjectField *typeidobjf = NULL;
     750             :         ObjectField *of;
     751             : 
     752        8190 :         HEIM_TAILQ_FOREACH(of, o->objfields, objfields) {
     753        5740 :             if (strcmp(of->name, typeidfield->name) == 0)
     754        2450 :                 typeidobjf = of;
     755             :         }
     756        2450 :         if (typeidobjf)
     757        2450 :             objects[i++] = o;
     758             :     }
     759         224 :     qsort(objects, nobjs, sizeof(*objects), object_cmp);
     760             : }
     761             : 
     762             : static void
     763          84 : template_object_set(IOSObjectSet *os, Field *typeidfield, Field *opentypefield)
     764             : {
     765          84 :     IOSObject **objects = NULL;
     766             :     IOSObject *o;
     767             :     struct tlist *tl;
     768             :     size_t nobjs, i;
     769             : 
     770          84 :     if (os->symbol->emitted_template)
     771          14 :         return;
     772             : 
     773          70 :     sort_object_set(os, typeidfield, &objects, &nobjs);
     774             : 
     775          70 :     tl = tlist_new(os->symbol->name);
     776          70 :     add_line(&tl->template, "{ A1_OP_NAME, 0, \"%s\" }", os->symbol->name);
     777         784 :     for (i = 0; i < nobjs; i++) {
     778         714 :         ObjectField *typeidobjf = NULL, *opentypeobjf = NULL;
     779             :         ObjectField *of;
     780         714 :         char *s = NULL;
     781             : 
     782         714 :         o = objects[i];
     783             : 
     784        2422 :         HEIM_TAILQ_FOREACH(of, o->objfields, objfields) {
     785        1708 :             if (strcmp(of->name, typeidfield->name) == 0)
     786         714 :                 typeidobjf = of;
     787         994 :             else if (strcmp(of->name, opentypefield->name) == 0)
     788         714 :                 opentypeobjf = of;
     789             :         }
     790         714 :         if (!typeidobjf)
     791           0 :             continue; /* We've warned about this one already when sorting */
     792         714 :         if (!opentypeobjf) {
     793           0 :             warnx("Ignoring incomplete object specification of %s "
     794             :                   "(missing open type field)",
     795           0 :                   o->symbol ? o->symbol->name : "<unknown>");
     796           0 :             continue;
     797             :         }
     798             : 
     799         714 :         add_line(&tl->template, "{ A1_OP_NAME, 0, \"%s\" }", o->symbol->name);
     800             :         /*
     801             :          * Some of this logic could stand to move into sanity checks of object
     802             :          * definitions in asn1parse.y.
     803             :          */
     804         714 :         switch (typeidobjf->value->type) {
     805           0 :         case integervalue:
     806           0 :             add_line(&tl->template,
     807             :                      "{ A1_OP_OPENTYPE_ID | A1_OTI_IS_INTEGER, 0, (void *)(uintptr_t)%lld }",
     808           0 :                      (long long)typeidobjf->value->u.integervalue);
     809           0 :             break;
     810         714 :         case objectidentifiervalue:
     811         714 :             if (asprintf(&s, "oid_%s",
     812        1428 :                          typeidobjf->value->s->gen_name) == -1 || !s)
     813           0 :                 err(1, "Out of memory");
     814         714 :             add_line_pointer_reference(&tl->template, s, "0", "A1_OP_OPENTYPE_ID");
     815         714 :             free(s);
     816         714 :             s = NULL;
     817         714 :             break;
     818           0 :         default:
     819           0 :             errx(1, "Only integer and OID types supported "
     820             :                  "for open type type-ID fields");
     821             :         }
     822             : 
     823         714 :         if (asprintf(&s, "sizeof(%s)",
     824        1428 :                      opentypeobjf->type->symbol->gen_name) == -1 || !s)
     825           0 :             err(1, "Out of memory");
     826        1428 :         add_line_pointer_reference(&tl->template,
     827         714 :                                    opentypeobjf->type->symbol->gen_name, s,
     828             :                                    "A1_OP_OPENTYPE");
     829         714 :         free(s);
     830             :     }
     831          70 :     free(objects);
     832             : 
     833          70 :     tlist_header(tl, "{ 0, 0, ((void *)(uintptr_t)%zu) }", nobjs);
     834          70 :     tlist_print(tl);
     835          70 :     tlist_add(tl);
     836          70 :     os->symbol->emitted_template = 1;
     837             : }
     838             : 
     839             : static void
     840          84 : template_open_type(struct templatehead *temp,
     841             :                    const char *basetype,
     842             :                    const Type *t,
     843             :                    size_t typeididx,
     844             :                    size_t opentypeidx,
     845             :                    Field *typeidfield,
     846             :                    Field *opentypefield,
     847             :                    Member *m,
     848             :                    int is_array_of_open_type)
     849             : {
     850          84 :     char *s = NULL;
     851             : 
     852          84 :     if (typeididx >= 1<<10 || opentypeidx >= 1<<10)
     853           0 :         errx(1, "SET/SEQUENCE with too many members (%s)", basetype);
     854             : 
     855          84 :     if (asprintf(&s, "offsetof(%s, _ioschoice_%s)",
     856          84 :                  basetype, m->gen_name) == -1 || !s)
     857           0 :         err(1, "Out of memory");
     858             : 
     859          84 :     template_object_set(t->actual_parameter, typeidfield, opentypefield);
     860          84 :     add_line_pointer(temp, t->actual_parameter->symbol->gen_name, s,
     861             :                      /*
     862             :                       * We always sort object sets for now as we can't import
     863             :                       * values yet, so they must all be known.
     864             :                       */
     865             :                      "A1_OP_OPENTYPE_OBJSET | A1_OS_IS_SORTED |%s | (%llu << 10) | %llu",
     866             :                      is_array_of_open_type ? "A1_OS_OT_IS_ARRAY" : "0",
     867             :                      (unsigned long long)opentypeidx,
     868             :                      (unsigned long long)typeididx);
     869          84 :     free(s);
     870          84 : }
     871             : 
     872             : static void
     873        2660 : template_names(struct templatehead *temp, const char *basetype, const Type *t)
     874             : {
     875             :     Member *m;
     876             : 
     877        2660 :     add_line_string(temp, basetype, "0", "A1_OP_NAME");
     878       12600 :     HEIM_TAILQ_FOREACH(m, t->members, members) {
     879        9940 :         add_line_string(temp, m->name, "0", "A1_OP_NAME");
     880             :     }
     881        2660 : }
     882             : 
     883             : static void
     884       32256 : template_members(struct templatehead *temp,
     885             :                  const char *basetype,
     886             :                  const char *name,
     887             :                  const Type *t,
     888             :                  int optional,
     889             :                  int defaulted,
     890             :                  int implicit,
     891             :                  int isstruct,
     892             :                  int need_offset)
     893             : {
     894       32256 :     char *poffset = NULL;
     895             : 
     896       32256 :     if (optional && t->type != TTag && t->type != TType)
     897           0 :         errx(1, "%s...%s is optional and not a (TTag or TType)", basetype, name);
     898             : 
     899       32256 :     poffset = partial_offset(basetype, name, need_offset, isstruct);
     900             : 
     901       32256 :     switch (t->type) {
     902        7420 :     case TType:
     903        7420 :         if (use_extern(t->symbol)) {
     904        1064 :             add_line(temp, "{ A1_OP_TYPE_EXTERN %s%s%s, %s, &asn1_extern_%s}",
     905             :                      optional  ? "|A1_FLAG_OPTIONAL" : "",
     906             :                      defaulted ? "|A1_FLAG_DEFAULT" : "",
     907             :                      implicit  ? "|A1_FLAG_IMPLICIT" : "",
     908        1064 :                      poffset, t->symbol->gen_name);
     909             :         } else {
     910        6356 :             add_line_pointer(temp, t->symbol->gen_name, poffset,
     911             :                              "A1_OP_TYPE %s%s%s",
     912             :                              optional  ? "|A1_FLAG_OPTIONAL" : "",
     913             :                              defaulted ? "|A1_FLAG_DEFAULT" : "",
     914             :                              implicit  ? "|A1_FLAG_IMPLICIT" : "");
     915             : 
     916             :         }
     917        7420 :         break;
     918        1288 :     case TEnumerated:
     919             :     case TInteger: {
     920        1288 :         char *varname = NULL;
     921        1288 :         char *itype = NULL;
     922             : 
     923        1288 :         if (t->members)
     924         336 :             itype = "IMEMBER";
     925         952 :         else if (t->range == NULL)
     926         546 :             itype = "HEIM_INTEGER";
     927         504 :         else if (t->range->min < 0 &&
     928         196 :                  (t->range->min < INT_MIN || t->range->max > INT_MAX))
     929           0 :             itype = "INTEGER64";
     930         406 :         else if (t->range->min < 0)
     931          98 :             itype = "INTEGER";
     932         308 :         else if (t->range->max > UINT_MAX)
     933           0 :             itype = "UNSIGNED64";
     934             :         else
     935         308 :             itype = "UNSIGNED";
     936             : 
     937             :         /*
     938             :          * If `t->members' then we should generate a template for those
     939             :          * members.
     940             :          *
     941             :          * We don't know the name of this field, and the type may not have a
     942             :          * name.  If it has no name, we should generate a name for it, and if
     943             :          * it does have a name, use it, to name a template for its members.
     944             :          *
     945             :          * Then we could use that in _asn1_print() to pretty-print values of
     946             :          * enumerations.
     947             :          */
     948        1624 :         if (t->members && t->symbol) {
     949             :             struct tlist *tl;
     950             :             Member *m;
     951         336 :             size_t nmemb = 0;
     952             : 
     953         672 :             if (asprintf(&varname, "%s_enum_names", t->symbol->gen_name) == -1 ||
     954         336 :                 varname == NULL)
     955           0 :                 err(1, "Out of memory");
     956             : 
     957         336 :             tl = tlist_new(varname);
     958             :             /*
     959             :              * XXX We're going to assume that t->members is sorted in
     960             :              * numerically ascending order in the module source.  We should
     961             :              * really sort it here.
     962             :              */
     963        4312 :             HEIM_TAILQ_FOREACH(m, t->members, members) {
     964        3976 :                 if (m->val > UINT32_MAX)
     965           0 :                     errx(1, "Cannot handle %s type %s with named bit %s "
     966             :                          "larger than 63",
     967           0 :                          t->type == TEnumerated ? "ENUMERATED" : "INTEGER",
     968             :                          name, m->gen_name);
     969        7952 :                 add_line(&tl->template,
     970        3976 :                          "{ A1_OP_NAME, %d, \"%s\" }", (int)m->val, m->name);
     971        3976 :                 nmemb++;
     972             :             }
     973         336 :             tlist_header(tl, "{ 0, 0, ((void *)(uintptr_t)%zu) }", nmemb);
     974             :             /* XXX Accidentally O(N^2)? */
     975         336 :             if (!tlist_find_dup(tl)) {
     976         336 :                 tlist_print(tl);
     977         336 :                 tlist_add(tl);
     978             :             }
     979         336 :             add_line(temp, "{ A1_PARSE_T(A1T_%s), %s, asn1_%s }", itype, poffset, varname);
     980             :         } else {
     981         952 :             add_line(temp, "{ A1_PARSE_T(A1T_%s), %s, NULL }", itype, poffset);
     982             :         }
     983        1288 :         break;
     984             :     }
     985         182 :     case TGeneralString:
     986         182 :         add_line(temp, "{ A1_PARSE_T(A1T_GENERAL_STRING), %s, NULL }", poffset);
     987         182 :         break;
     988          14 :     case TTeletexString:
     989          14 :         add_line(temp, "{ A1_PARSE_T(A1T_TELETEX_STRING), %s, NULL }", poffset);
     990          14 :         break;
     991          28 :     case TPrintableString:
     992          28 :         add_line(temp, "{ A1_PARSE_T(A1T_PRINTABLE_STRING), %s, NULL }", poffset);
     993          28 :         break;
     994        1484 :     case TOctetString:
     995        1484 :         add_line(temp, "{ A1_PARSE_T(A1T_OCTET_STRING), %s, NULL }", poffset);
     996        1484 :         break;
     997         154 :     case TIA5String:
     998         154 :         add_line(temp, "{ A1_PARSE_T(A1T_IA5_STRING), %s, NULL }", poffset);
     999         154 :         break;
    1000          42 :     case TBMPString:
    1001          42 :         add_line(temp, "{ A1_PARSE_T(A1T_BMP_STRING), %s, NULL }", poffset);
    1002          42 :         break;
    1003          14 :     case TUniversalString:
    1004          14 :         add_line(temp, "{ A1_PARSE_T(A1T_UNIVERSAL_STRING), %s, NULL }", poffset);
    1005          14 :         break;
    1006          28 :     case TVisibleString:
    1007          28 :         add_line(temp, "{ A1_PARSE_T(A1T_VISIBLE_STRING), %s, NULL }", poffset);
    1008          28 :         break;
    1009         588 :     case TUTF8String:
    1010         588 :         add_line(temp, "{ A1_PARSE_T(A1T_UTF8_STRING), %s, NULL }", poffset);
    1011         588 :         break;
    1012         126 :     case TGeneralizedTime:
    1013         126 :         add_line(temp, "{ A1_PARSE_T(A1T_GENERALIZED_TIME), %s, NULL }", poffset);
    1014         126 :         break;
    1015          14 :     case TUTCTime:
    1016          14 :         add_line(temp, "{ A1_PARSE_T(A1T_UTC_TIME), %s, NULL }", poffset);
    1017          14 :         break;
    1018         182 :     case TBoolean:
    1019         182 :         add_line(temp, "{ A1_PARSE_T(A1T_BOOLEAN), %s, NULL }", poffset);
    1020         182 :         break;
    1021         462 :     case TOID:
    1022         462 :         add_line(temp, "{ A1_PARSE_T(A1T_OID), %s, NULL }", poffset);
    1023         462 :         break;
    1024          56 :     case TNull:
    1025          56 :         break;
    1026         350 :     case TBitString: {
    1027             :         struct templatehead template;
    1028             :         struct template *q;
    1029             :         Member *m;
    1030         350 :         size_t count = 0, i;
    1031         350 :         char *bname = NULL;
    1032         350 :         FILE *f = get_code_file();
    1033             :         static unsigned long bmember_counter = 0;
    1034             : 
    1035         350 :         HEIM_TAILQ_INIT(&template);
    1036             : 
    1037         350 :         if (HEIM_TAILQ_EMPTY(t->members)) {
    1038         210 :             add_line(temp, "{ A1_PARSE_T(A1T_HEIM_BIT_STRING), %s, NULL }", poffset);
    1039         210 :             break;
    1040             :         }
    1041             : 
    1042         140 :         if (asprintf(&bname, "bmember_%s_%lu", name ? name : "", bmember_counter++) < 0 || bname == NULL)
    1043           0 :             errx(1, "malloc");
    1044         140 :         output_name(bname);
    1045             : 
    1046        1372 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
    1047        1232 :             if (m->val > UINT32_MAX)
    1048           0 :                 errx(1, "Cannot handle BIT STRING type %s with named bit %s "
    1049             :                      "larger than 63", name, m->gen_name);
    1050        1232 :             add_line(&template, "{ 0, %d, \"%s\" }", (int)m->val, m->gen_name);
    1051             :         }
    1052             : 
    1053        1372 :         HEIM_TAILQ_FOREACH(q, &template, members) {
    1054        1232 :             count++;
    1055             :         }
    1056             : 
    1057         140 :         fprintf(f, "static const struct asn1_template asn1_%s_%s[] = {\n", basetype, bname);
    1058         140 :         fprintf(f, "/* 0 */ { 0%s, sizeof(%s), ((void *)(uintptr_t)%lu) },\n",
    1059         140 :                 rfc1510_bitstring ? "|A1_HBF_RFC1510" : "",
    1060             :                 basetype, (unsigned long)count);
    1061         140 :         i = 1;
    1062        1372 :         HEIM_TAILQ_FOREACH(q, &template, members) {
    1063        1232 :             int last = (HEIM_TAILQ_LAST(&template, templatehead) == q);
    1064        1232 :             fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");
    1065             :         }
    1066         140 :         fprintf(f, "};\n");
    1067             : 
    1068         140 :         add_line(temp, "{ A1_OP_BMEMBER, %s, asn1_%s_%s }", poffset, basetype, bname);
    1069             : 
    1070         140 :         free(bname);
    1071             : 
    1072         140 :         break;
    1073             :     }
    1074           0 :     case TSet: {
    1075           0 :         Member *opentypemember = NULL;
    1076           0 :         Member *typeidmember = NULL;
    1077           0 :         Field *opentypefield = NULL;
    1078           0 :         Field *typeidfield = NULL;
    1079             :         Member *m;
    1080             :         struct decoration deco;
    1081           0 :         ssize_t more_deco = -1;
    1082           0 :         size_t i = 0, typeididx = 0, opentypeidx = 0;
    1083           0 :         int is_array_of_open_type = 0;
    1084             : 
    1085           0 :         if (isstruct && t->actual_parameter)
    1086           0 :             get_open_type_defn_fields(t, &typeidmember, &opentypemember,
    1087             :                                       &typeidfield, &opentypefield,
    1088             :                                       &is_array_of_open_type);
    1089             : 
    1090           0 :         fprintf(get_code_file(), "/* tset: members isstruct: %d */\n", isstruct);
    1091             : 
    1092           0 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
    1093           0 :             char *newbasename = NULL;
    1094             : 
    1095           0 :             if (m->ellipsis)
    1096           0 :                 continue;
    1097             : 
    1098           0 :             if (typeidmember == m) typeididx = i;
    1099           0 :             if (opentypemember == m) opentypeidx = i;
    1100             : 
    1101           0 :             if (name) {
    1102           0 :                 if (asprintf(&newbasename, "%s_%s", basetype, name) < 0)
    1103           0 :                     errx(1, "malloc");
    1104             :             } else
    1105           0 :                 newbasename = strdup(basetype);
    1106           0 :             if (newbasename == NULL)
    1107           0 :                 errx(1, "malloc");
    1108             : 
    1109           0 :             if (m->defval)
    1110           0 :                 defval(temp, m);
    1111             : 
    1112           0 :             template_members(temp, newbasename, m->gen_name, m->type, m->optional, m->defval ? 1 : 0, 0, isstruct, 1);
    1113             : 
    1114           0 :             free(newbasename);
    1115           0 :             i++;
    1116             :         }
    1117             : 
    1118           0 :         if (isstruct && t->actual_parameter)
    1119           0 :             template_open_type(temp, basetype, t, typeididx, opentypeidx,
    1120             :                                typeidfield, opentypefield, opentypemember,
    1121             :                                is_array_of_open_type);
    1122             : 
    1123           0 :         while (decorate_type(basetype, &deco, &more_deco)) {
    1124             :             char *poffset2;
    1125             : 
    1126           0 :             poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
    1127             : 
    1128           0 :             if (deco.ext) {
    1129           0 :                 char *ptr = NULL;
    1130             : 
    1131             :                 /* Decorated with external C type */
    1132           0 :                 if (asprintf(&ptr, "&asn1_extern_%s_%s",
    1133           0 :                              basetype, deco.field_name) == -1 || ptr == NULL)
    1134           0 :                     err(1, "out of memory");
    1135           0 :                 add_line_pointer(temp, ptr, poffset2,
    1136             :                                  "A1_OP_TYPE_DECORATE_EXTERN %s",
    1137           0 :                                  deco.opt ? "|A1_FLAG_OPTIONAL" : "");
    1138           0 :                 free(ptr);
    1139             :             } else
    1140             :                 /* Decorated with a templated ASN.1 type */
    1141           0 :                 add_line_pointer(temp, deco.field_type, poffset2,
    1142             :                                  "A1_OP_TYPE_DECORATE %s",
    1143           0 :                                  deco.opt ? "|A1_FLAG_OPTIONAL" : "");
    1144           0 :             free(poffset2);
    1145           0 :             free(deco.field_type);
    1146             :         }
    1147             : 
    1148           0 :         if (isstruct)
    1149           0 :             template_names(temp, basetype, t);
    1150           0 :         break;
    1151             :     }
    1152        2660 :     case TSequence: {
    1153        2660 :         Member *opentypemember = NULL;
    1154        2660 :         Member *typeidmember = NULL;
    1155        2660 :         Field *opentypefield = NULL;
    1156        2660 :         Field *typeidfield = NULL;
    1157             :         Member *m;
    1158             :         struct decoration deco;
    1159        2660 :         ssize_t more_deco = -1;
    1160        2660 :         size_t i = 0, typeididx = 0, opentypeidx = 0;
    1161        2660 :         int is_array_of_open_type = 0;
    1162             : 
    1163        2660 :         if (isstruct && t->actual_parameter)
    1164          84 :             get_open_type_defn_fields(t, &typeidmember, &opentypemember,
    1165             :                                       &typeidfield, &opentypefield,
    1166             :                                       &is_array_of_open_type);
    1167             : 
    1168        2660 :         fprintf(get_code_file(), "/* tsequence: members isstruct: %d */\n", isstruct);
    1169             : 
    1170       12600 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
    1171        9940 :             char *newbasename = NULL;
    1172             : 
    1173        9940 :             if (m->ellipsis)
    1174         406 :                 continue;
    1175             : 
    1176        9534 :             if (typeidmember == m) typeididx = i;
    1177        9534 :             if (opentypemember == m) opentypeidx = i;
    1178             : 
    1179        9534 :             if (name) {
    1180          56 :                 if (asprintf(&newbasename, "%s_%s", basetype, name) < 0)
    1181           0 :                     errx(1, "malloc");
    1182             :             } else
    1183        9478 :                 newbasename = strdup(basetype);
    1184        9534 :             if (newbasename == NULL)
    1185           0 :                 errx(1, "malloc");
    1186             : 
    1187        9534 :             if (m->defval)
    1188         154 :                 defval(temp, m);
    1189             :             
    1190        9534 :             template_members(temp, newbasename, m->gen_name, m->type, m->optional, m->defval ? 1 : 0, 0, isstruct, 1);
    1191             : 
    1192        9534 :             free(newbasename);
    1193        9534 :             i++;
    1194             :         }
    1195             : 
    1196        2660 :         if (isstruct && t->actual_parameter)
    1197          84 :             template_open_type(temp, basetype, t, typeididx, opentypeidx,
    1198             :                                typeidfield, opentypefield, opentypemember,
    1199             :                                is_array_of_open_type);
    1200             : 
    1201        5348 :         while (decorate_type(basetype, &deco, &more_deco)) {
    1202             :             char *poffset2;
    1203             : 
    1204          28 :             poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
    1205             : 
    1206          28 :             if (deco.ext) {
    1207          14 :                 char *ptr = NULL;
    1208             : 
    1209             :                 /* Decorated with external C type */
    1210          14 :                 if (asprintf(&ptr, "&asn1_extern_%s_%s",
    1211          14 :                              basetype, deco.field_name) == -1 || ptr == NULL)
    1212           0 :                     err(1, "out of memory");
    1213          14 :                 add_line_pointer(temp, ptr, poffset2,
    1214             :                                  "A1_OP_TYPE_DECORATE_EXTERN %s",
    1215          14 :                                  deco.opt ? "|A1_FLAG_OPTIONAL" : "");
    1216          14 :                 free(ptr);
    1217             :             } else
    1218             :                 /* Decorated with a templated ASN.1 type */
    1219          14 :                 add_line_pointer(temp, deco.field_type, poffset2,
    1220             :                                  "A1_OP_TYPE_DECORATE %s",
    1221          14 :                                  deco.opt ? "|A1_FLAG_OPTIONAL" : "");
    1222          28 :             free(poffset2);
    1223          28 :             free(deco.field_type);
    1224             :         }
    1225             : 
    1226        2660 :         if (isstruct)
    1227        2660 :             template_names(temp, basetype, t);
    1228        2660 :         break;
    1229             :     }
    1230       15806 :     case TTag: {
    1231       15806 :         char *tname = NULL, *elname = NULL;
    1232             :         const char *sename, *dupname;
    1233       15806 :         int subtype_is_struct = is_struct(t->subtype, isstruct);
    1234             :         static unsigned long tag_counter = 0;
    1235       15806 :         int tagimplicit = 0;
    1236       38682 :         int prim = !(t->tag.tagclass != ASN1_C_UNIV &&
    1237       25382 :                      t->tag.tagenv == TE_EXPLICIT) &&
    1238        9576 :             is_primitive_type(t->subtype);
    1239             : 
    1240       15806 :         if (t->tag.tagenv == TE_IMPLICIT) {
    1241        1050 :             Type *t2 = t->subtype ? t->subtype : t->symbol->type;
    1242             : 
    1243        2394 :             while (t2->type == TType && (t2->subtype || t2->symbol->type))
    1244         294 :                 t2 = t2->subtype ? t2->subtype : t2->symbol->type;
    1245        1050 :             if (t2->type != TChoice)
    1246        1022 :                 tagimplicit = 1;
    1247             :         }
    1248             : 
    1249       15806 :         fprintf(get_code_file(), "/* template_members: %s %s %s */\n", basetype, implicit ? "imp" : "exp", tagimplicit ? "imp" : "exp");
    1250             : 
    1251       15806 :         if (subtype_is_struct)
    1252        3640 :             sename = basetype;
    1253             :         else
    1254       12166 :             sename = symbol_name(basetype, t->subtype);
    1255             : 
    1256       15806 :         if (asprintf(&tname, "tag_%s_%lu", name ? name : "", tag_counter++) < 0 || tname == NULL)
    1257           0 :             errx(1, "malloc");
    1258       15806 :         output_name(tname);
    1259             : 
    1260       15806 :         if (asprintf(&elname, "%s_%s", basetype, tname) < 0 || elname == NULL)
    1261           0 :             errx(1, "malloc");
    1262             : 
    1263       15806 :         generate_template_type(elname, &dupname, NULL, sename, name,
    1264       15806 :                                t->subtype, 0, subtype_is_struct, 0);
    1265             : 
    1266       47418 :         add_line_pointer(temp, dupname, poffset,
    1267             :                          "A1_TAG_T(%s,%s,%s)%s%s%s",
    1268       15806 :                          classname(t->tag.tagclass),
    1269             :                          prim  ? "PRIM" : "CONS",
    1270       15806 :                          valuename(t->tag.tagclass, t->tag.tagvalue),
    1271             :                          optional    ? "|A1_FLAG_OPTIONAL" : "",
    1272             :                          defaulted   ? "|A1_FLAG_DEFAULT" : "",
    1273             :                          tagimplicit ? "|A1_FLAG_IMPLICIT" : "");
    1274             : 
    1275       15806 :         free(tname);
    1276       15806 :         free(elname);
    1277             : 
    1278       15806 :         break;
    1279             :     }
    1280        1050 :     case TSetOf:
    1281             :     case TSequenceOf: {
    1282        1050 :         const char *type = NULL, *tname, *dupname;
    1283        1050 :         char *sename = NULL, *elname = NULL;
    1284        1050 :         int subtype_is_struct = is_struct(t->subtype, 0);
    1285             :         static unsigned long seof_counter = 0;
    1286             : 
    1287        1050 :         if (name && subtype_is_struct) {
    1288          14 :             tname = "seofTstruct";
    1289          28 :             if (asprintf(&sename, "%s_%s_val", basetype, name) < 0)
    1290           0 :                 errx(1, "malloc");
    1291        1036 :         } else if (subtype_is_struct) {
    1292          14 :             tname = "seofTstruct";
    1293          14 :             if (asprintf(&sename, "%s_val", symbol_name(basetype, t->subtype)) < 0)
    1294           0 :                 errx(1, "malloc");
    1295             :         } else {
    1296        1022 :             if (name)
    1297         392 :                 tname = name;
    1298             :             else
    1299         630 :                 tname = "seofTstruct";
    1300        1022 :             sename = strdup(symbol_name(basetype, t->subtype));
    1301             :         }
    1302        1050 :         if (sename == NULL)
    1303           0 :             errx(1, "malloc");
    1304             : 
    1305        1050 :         if (t->type == TSetOf) type = "A1_OP_SETOF";
    1306         812 :         else if (t->type == TSequenceOf) type = "A1_OP_SEQOF";
    1307           0 :         else abort();
    1308             : 
    1309        1050 :         if (asprintf(&elname, "%s_%s_%lu", basetype, tname, seof_counter++) < 0 || elname == NULL)
    1310           0 :             errx(1, "malloc");
    1311             : 
    1312        1050 :         generate_template_type(elname, &dupname, NULL, sename, NULL, t->subtype,
    1313             :                                0, subtype_is_struct, need_offset);
    1314             : 
    1315        1050 :         add_line(temp, "{ %s, %s, asn1_%s }", type, poffset, dupname);
    1316        1050 :         free(sename);
    1317        1050 :         break;
    1318             :     }
    1319         308 :     case TChoice: {
    1320             :         struct decoration deco;
    1321         308 :         ssize_t more_deco = -1;
    1322             :         struct templatehead template;
    1323             :         struct template *q;
    1324         308 :         size_t count = 0, i;
    1325         308 :         char *tname = NULL;
    1326         308 :         FILE *f = get_code_file();
    1327             :         Member *m;
    1328         308 :         int ellipsis = 0;
    1329             :         char *e;
    1330             :         static unsigned long choice_counter = 0;
    1331             : 
    1332         308 :         HEIM_TAILQ_INIT(&template);
    1333             : 
    1334         308 :         if (asprintf(&tname, "asn1_choice_%s_%s%lu",
    1335         308 :                      basetype, name ? name : "", choice_counter++) < 0 || tname == NULL)
    1336           0 :             errx(1, "malloc");
    1337             : 
    1338        1204 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
    1339             :             const char *dupname;
    1340         896 :             char *elname = NULL;
    1341         896 :             char *newbasename = NULL;
    1342             :             int subtype_is_struct;
    1343             : 
    1344         896 :             if (m->ellipsis) {
    1345          56 :                 ellipsis = 1;
    1346          56 :                 continue;
    1347             :             }
    1348             : 
    1349         840 :             subtype_is_struct = is_struct(m->type, 0);
    1350             : 
    1351         840 :             if (asprintf(&elname, "%s_choice_%s", basetype, m->gen_name) < 0 || elname == NULL)
    1352           0 :                 errx(1, "malloc");
    1353             : 
    1354         840 :             if (subtype_is_struct) {
    1355          28 :                 if (asprintf(&newbasename, "%s_%s", basetype, m->gen_name) < 0)
    1356           0 :                     errx(1, "malloc");
    1357             :             } else
    1358         812 :                 newbasename = strdup(basetype);
    1359             : 
    1360         840 :             if (newbasename == NULL)
    1361           0 :                 errx(1, "malloc");
    1362             : 
    1363             : 
    1364         840 :             generate_template_type(elname, &dupname, NULL,
    1365         840 :                                    symbol_name(newbasename, m->type),
    1366         840 :                                    NULL, m->type, 0, subtype_is_struct, 1);
    1367             : 
    1368         840 :             add_line(&template, "{ %s, offsetof(%s%s, u.%s), asn1_%s }",
    1369             :                      m->label, isstruct ? "struct " : "",
    1370             :                      basetype, m->gen_name,
    1371             :                      dupname);
    1372             : 
    1373         840 :             free(elname);
    1374         840 :             free(newbasename);
    1375             :         }
    1376             : 
    1377        1204 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
    1378         896 :             add_line(&template, "{ 0, 0, \"%s\" }", m->name);
    1379             :         }
    1380             : 
    1381         308 :         e = NULL;
    1382         308 :         if (ellipsis) {
    1383          56 :             if (asprintf(&e, "offsetof(%s%s, u.asn1_ellipsis)", isstruct ? "struct " : "", basetype) < 0 || e == NULL)
    1384           0 :                 errx(1, "malloc");
    1385             :         }
    1386             : 
    1387        2044 :         HEIM_TAILQ_FOREACH(q, &template, members) {
    1388        1736 :             count++;
    1389             :         }
    1390             : 
    1391         308 :         fprintf(f, "static const struct asn1_template %s[] = {\n", tname);
    1392         616 :         fprintf(f, "/* 0 */ { %s, offsetof(%s%s, element), ((void *)(uintptr_t)%lu) },\n",
    1393         308 :                 e ? e : "0", isstruct ? "struct " : "", basetype, (unsigned long)count);
    1394         308 :         i = 1;
    1395        2044 :         HEIM_TAILQ_FOREACH(q, &template, members) {
    1396        1736 :             int last = (HEIM_TAILQ_LAST(&template, templatehead) == q);
    1397        1736 :             fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");
    1398             :         }
    1399         308 :         fprintf(f, "};\n");
    1400             : 
    1401         308 :         add_line(temp, "{ A1_OP_CHOICE, %s, %s }", poffset, tname);
    1402             : 
    1403         616 :         while (decorate_type(basetype, &deco, &more_deco)) {
    1404             :             char *poffset2;
    1405             : 
    1406           0 :             poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
    1407             : 
    1408           0 :             if (deco.ext) {
    1409           0 :                 char *ptr = NULL;
    1410             : 
    1411             :                 /* Decorated with external C type */
    1412           0 :                 if (asprintf(&ptr, "&asn1_extern_%s_%s",
    1413           0 :                              basetype, deco.field_name) == -1 || ptr == NULL)
    1414           0 :                     err(1, "out of memory");
    1415           0 :                 add_line_pointer(temp, ptr, poffset2,
    1416             :                                  "A1_OP_TYPE_DECORATE_EXTERN %s",
    1417           0 :                                  deco.opt ? "|A1_FLAG_OPTIONAL" : "");
    1418           0 :                 free(ptr);
    1419             :             } else
    1420             :                 /* Decorated with a templated ASN.1 type */
    1421           0 :                 add_line_pointer(temp, deco.field_type, poffset2,
    1422             :                                  "A1_OP_TYPE_DECORATE %s",
    1423           0 :                                  deco.opt ? "|A1_FLAG_OPTIONAL" : "");
    1424           0 :             free(poffset2);
    1425           0 :             free(deco.field_type);
    1426             :         }
    1427             : 
    1428         308 :         free(e);
    1429         308 :         free(tname);
    1430         308 :         break;
    1431             :     }
    1432           0 :     default:
    1433           0 :         abort ();
    1434             :     }
    1435       32256 :     if (poffset)
    1436       32256 :         free(poffset);
    1437       32256 : }
    1438             : 
    1439             : static void
    1440         616 : gen_extern_stubs(FILE *f, const char *name)
    1441             : {
    1442         616 :     fprintf(f,
    1443             :             "static const struct asn1_type_func asn1_extern_%s = {\n"
    1444             :             "\t(asn1_type_encode)encode_%s,\n"
    1445             :             "\t(asn1_type_decode)decode_%s,\n"
    1446             :             "\t(asn1_type_length)length_%s,\n"
    1447             :             "\t(asn1_type_copy)copy_%s,\n"
    1448             :             "\t(asn1_type_release)free_%s,\n"
    1449             :             "\t(asn1_type_print)print_%s,\n"
    1450             :             "\tsizeof(%s)\n"
    1451             :             "};\n",
    1452             :             name, name, name, name,
    1453             :             name, name, name, name);
    1454         616 : }
    1455             : 
    1456             : void
    1457         784 : gen_template_import(const Symbol *s)
    1458             : {
    1459         784 :     FILE *f = get_code_file();
    1460             : 
    1461         784 :     if (template_flag == 0)
    1462         168 :         return;
    1463             : 
    1464         616 :     gen_extern_stubs(f, s->gen_name);
    1465             : }
    1466             : 
    1467             : void
    1468        6538 : generate_template_type_forward(const char *name)
    1469             : {
    1470        6538 :     fprintf(get_code_file(), "extern const struct asn1_template asn1_%s[];\n", name);
    1471        6538 : }
    1472             : 
    1473             : void
    1474          70 : generate_template_objectset_forwards(const Symbol *s)
    1475             : {
    1476          70 :     if (!template_flag)
    1477           0 :         return;
    1478          70 :     fprintf(get_code_file(), "extern const struct asn1_template asn1_%s[];\n",
    1479             :             s->gen_name);
    1480             : }
    1481             : 
    1482             : static void
    1483       22722 : generate_template_type(const char *varname,
    1484             :                        const char **dupname,
    1485             :                        const char *symname,
    1486             :                        const char *basetype,
    1487             :                        const char *name,
    1488             :                        Type *type,
    1489             :                        int optional,
    1490             :                        int isstruct,
    1491             :                        int need_offset)
    1492             : {
    1493             :     struct tlist *tl;
    1494             :     const char *d;
    1495       22722 :     char *szt = NULL;
    1496       22722 :     int have_ellipsis = 0;
    1497       22722 :     int implicit = 0;
    1498             :     int n;
    1499             : 
    1500       22722 :     tl = tlist_new(varname);
    1501             : 
    1502       22722 :     if (type->type == TTag && type->tag.tagenv == TE_IMPLICIT) {
    1503         378 :         Type *t = type->subtype ? type->subtype : type->symbol->type;
    1504             : 
    1505         784 :         while (t->type == TType && (t->subtype || t->symbol->type))
    1506          28 :             t = t->subtype ? t->subtype : t->symbol->type;
    1507         378 :         if (t->type != TChoice)
    1508         364 :             implicit = (type->tag.tagenv == TE_IMPLICIT);
    1509             :     }
    1510             : 
    1511       22722 :     template_members(&tl->template, basetype, name, type, optional, 0,
    1512             :                      implicit, isstruct, need_offset);
    1513             : 
    1514             :     /* if its a sequence or set type, check if there is a ellipsis */
    1515       22722 :     if (type->type == TSequence || type->type == TSet) {
    1516             :         Member *m;
    1517       12600 :         HEIM_TAILQ_FOREACH(m, type->members, members) {
    1518        9940 :             if (m->ellipsis)
    1519         406 :                 have_ellipsis = 1;
    1520             :         }
    1521             :     }
    1522             : 
    1523       22722 :     if (isstruct)
    1524        3696 :         if (name)
    1525         756 :             n = asprintf(&szt, "struct %s_%s", basetype, name);
    1526             :         else
    1527        2940 :             n = asprintf(&szt, "struct %s", basetype);
    1528             :     else
    1529       19026 :         n = asprintf(&szt, "%s", basetype);
    1530       22722 :     if (n < 0 || szt == NULL)
    1531           0 :         errx(1, "malloc");
    1532             : 
    1533       22722 :     if (HEIM_TAILQ_EMPTY(&tl->template) && compact_tag(type)->type != TNull)
    1534           0 :         errx(1, "Tag %s...%s with no content ?", basetype, name ? name : "");
    1535             : 
    1536       22722 :     fprintf(get_code_file(), "/* generate_template_type: %s */\n", tl->name);
    1537             : 
    1538       22820 :     tlist_header(tl, "{ 0%s%s, sizeof(%s), ((void *)(uintptr_t)%lu) }",
    1539        5026 :                  (symname && preserve_type(symname)) ? "|A1_HF_PRESERVE" : "",
    1540             :                  have_ellipsis ? "|A1_HF_ELLIPSIS" : "", szt, tlist_count(tl));
    1541             : 
    1542       22722 :     free(szt);
    1543             : 
    1544             :     /* XXX Accidentally O(N^2)? */
    1545       22722 :     d = tlist_find_dup(tl);
    1546       22722 :     if (d) {
    1547             : #if 0
    1548             :         if (strcmp(d, tl->name) == 0)
    1549             :             errx(1, "found dup of ourself: %s", d);
    1550             : #endif
    1551        8722 :         *dupname = d;
    1552             :     } else {
    1553       14000 :         *dupname = tl->name;
    1554       14000 :         tlist_print(tl);
    1555       14000 :         tlist_add(tl);
    1556             :     }
    1557       22722 : }
    1558             : 
    1559             : 
    1560             : void
    1561        5026 : generate_template(const Symbol *s)
    1562             : {
    1563        5026 :     FILE *f = get_code_file();
    1564             :     const char *dupname;
    1565             :     struct decoration deco;
    1566        5026 :     ssize_t more_deco = -1;
    1567             : 
    1568        5026 :     if (use_extern(s)) {
    1569           0 :         gen_extern_stubs(f, s->gen_name);
    1570           0 :         return;
    1571             :     }
    1572             : 
    1573       10080 :     while (decorate_type(s->gen_name, &deco, &more_deco)) {
    1574          28 :         if (!deco.ext)
    1575          14 :             continue;
    1576          14 :         if (deco.void_star && deco.header_name)
    1577           0 :             fprintf(f, "#include %s\n", deco.header_name);
    1578          42 :         fprintf(f,
    1579             :                 "static const struct asn1_type_func asn1_extern_%s_%s = {\n"
    1580             :                 "\t(asn1_type_encode)0,\n"
    1581             :                 "\t(asn1_type_decode)0,\n"
    1582             :                 "\t(asn1_type_length)0,\n"
    1583             :                 "\t(asn1_type_copy)%s,\n"
    1584             :                 "\t(asn1_type_release)%s,\n"
    1585             :                 "\t(asn1_type_print)0,\n"
    1586             :                 "\tsizeof(%s)\n"
    1587             :                 "};\n", s->gen_name, deco.field_name,
    1588          14 :                 deco.copy_function_name && deco.copy_function_name[0] ?
    1589             :                 deco.copy_function_name : "0",
    1590          14 :                 deco.free_function_name && deco.free_function_name[0] ?
    1591             :                 deco.free_function_name : "0",
    1592          14 :                 deco.void_star ? "void *" : deco.field_type);
    1593          14 :         free(deco.field_type);
    1594             :     }
    1595             : 
    1596        5026 :     generate_template_type(s->gen_name, &dupname, s->name, s->gen_name, NULL, s->type, 0, 0, 1);
    1597             : 
    1598        5026 :     fprintf(f,
    1599             :             "\n"
    1600             :             "int ASN1CALL\n"
    1601             :             "decode_%s(const unsigned char *p, size_t len, %s *data, size_t *size)\n"
    1602             :             "{\n"
    1603             :             "    memset(data, 0, sizeof(*data));\n"
    1604             :             "    return _asn1_decode_top(asn1_%s, 0|%s, p, len, data, size);\n"
    1605             :             "}\n"
    1606             :             "\n",
    1607             :             s->gen_name,
    1608             :             s->gen_name,
    1609             :             dupname,
    1610        5026 :             support_ber ? "A1_PF_ALLOW_BER" : "0");
    1611             : 
    1612        5026 :     fprintf(f,
    1613             :             "\n"
    1614             :             "int ASN1CALL\n"
    1615             :             "encode_%s(unsigned char *p, size_t len, const %s *data, size_t *size)\n"
    1616             :             "{\n"
    1617             :             "    return _asn1_encode%s(asn1_%s, p, len, data, size);\n"
    1618             :             "}\n"
    1619             :             "\n",
    1620             :             s->gen_name,
    1621             :             s->gen_name,
    1622             :             fuzzer_string,
    1623             :             dupname);
    1624             : 
    1625        5026 :     fprintf(f,
    1626             :             "\n"
    1627             :             "size_t ASN1CALL\n"
    1628             :             "length_%s(const %s *data)\n"
    1629             :             "{\n"
    1630             :             "    return _asn1_length%s(asn1_%s, data);\n"
    1631             :             "}\n"
    1632             :             "\n",
    1633             :             s->gen_name,
    1634             :             s->gen_name,
    1635             :             fuzzer_string,
    1636             :             dupname);
    1637             : 
    1638             : 
    1639        5026 :     fprintf(f,
    1640             :             "\n"
    1641             :             "void ASN1CALL\n"
    1642             :             "free_%s(%s *data)\n"
    1643             :             "{\n"
    1644             :             "    _asn1_free_top(asn1_%s, data);\n"
    1645             :             "}\n"
    1646             :             "\n",
    1647             :             s->gen_name,
    1648             :             s->gen_name,
    1649             :             dupname);
    1650             : 
    1651        5026 :     fprintf(f,
    1652             :             "\n"
    1653             :             "int ASN1CALL\n"
    1654             :             "copy_%s(const %s *from, %s *to)\n"
    1655             :             "{\n"
    1656             :             "    return _asn1_copy_top(asn1_%s, from, to);\n"
    1657             :             "}\n"
    1658             :             "\n",
    1659             :             s->gen_name,
    1660             :             s->gen_name,
    1661             :             s->gen_name,
    1662             :             dupname);
    1663             : 
    1664        5026 :     fprintf(f,
    1665             :             "\n"
    1666             :             "char * ASN1CALL\n"
    1667             :             "print_%s(const %s *data, int flags)\n"
    1668             :             "{\n"
    1669             :             "    return _asn1_print_top(asn1_%s, flags, data);\n"
    1670             :             "}\n"
    1671             :             "\n",
    1672             :             s->gen_name,
    1673             :             s->gen_name,
    1674             :             dupname);
    1675             : }

Generated by: LCOV version 1.13