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 vadcx-master-patch-75612 fe003de8 Lines: 702 897 78.3 %
Date: 2024-02-29 22:57:05 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        8721 : ttype_symbol(const char *basename, const Type *t)
      52             : {
      53        8721 :     return t->symbol->gen_name;
      54             : }
      55             : 
      56             : static const char *
      57        2337 : integer_symbol(const char *basename, const Type *t)
      58             : {
      59        2337 :     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         450 :         return "int";
      67        1862 :     else if (t->range == NULL)
      68         990 :         return "heim_integer";
      69         817 :     else if (t->range->min < 0 &&
      70         209 :              (t->range->min < INT_MIN || t->range->max > INT_MAX))
      71           0 :         return "int64_t";
      72         817 :     else if (t->range->min < 0)
      73         198 :         return "int";
      74         608 :     else if (t->range->max > UINT_MAX)
      75           0 :         return "uint64_t";
      76             :     else
      77         608 :         return "unsigned";
      78             : }
      79             : 
      80             : static const char *
      81         380 : boolean_symbol(const char *basename, const Type *t)
      82             : {
      83         380 :     return "int";
      84             : }
      85             : 
      86             : 
      87             : static const char *
      88        3553 : octetstring_symbol(const char *basename, const Type *t)
      89             : {
      90        3553 :     return "heim_octet_string";
      91             : }
      92             : 
      93             : static const char *
      94          76 : sequence_symbol(const char *basename, const Type *t)
      95             : {
      96          76 :     return basename;
      97             : }
      98             : 
      99             : static const char *
     100         304 : time_symbol(const char *basename, const Type *t)
     101             : {
     102         304 :     return "time_t";
     103             : }
     104             : 
     105             : static const char *
     106        5225 : tag_symbol(const char *basename, const Type *t)
     107             : {
     108        5225 :     return symbol_name(basename, t->subtype);
     109             : }
     110             : 
     111             : static const char *
     112         437 : generalstring_symbol(const char *basename, const Type *t)
     113             : {
     114         437 :     return "heim_general_string";
     115             : }
     116             : 
     117             : static const char *
     118          57 : printablestring_symbol(const char *basename, const Type *t)
     119             : {
     120          57 :     return "heim_printable_string";
     121             : }
     122             : 
     123             : static const char *
     124         361 : ia5string_symbol(const char *basename, const Type *t)
     125             : {
     126         361 :     return "heim_ia5_string";
     127             : }
     128             : 
     129             : static const char *
     130          38 : teletexstring_symbol(const char *basename, const Type *t)
     131             : {
     132          38 :     return "heim_general_string";
     133             : }
     134             : 
     135             : static const char *
     136          76 : visiblestring_symbol(const char *basename, const Type *t)
     137             : {
     138          76 :     return "heim_visible_string";
     139             : }
     140             : 
     141             : static const char *
     142        1216 : utf8string_symbol(const char *basename, const Type *t)
     143             : {
     144        1216 :     return "heim_utf8_string";
     145             : }
     146             : 
     147             : static const char *
     148          95 : bmpstring_symbol(const char *basename, const Type *t)
     149             : {
     150          95 :     return "heim_bmp_string";
     151             : }
     152             : 
     153             : static const char *
     154          38 : universalstring_symbol(const char *basename, const Type *t)
     155             : {
     156          38 :     return "heim_universal_string";
     157             : }
     158             : 
     159             : static const char *
     160         912 : oid_symbol(const char *basename, const Type *t)
     161             : {
     162         912 :     return "heim_oid";
     163             : }
     164             : 
     165             : static const char *
     166         570 : bitstring_symbol(const char *basename, const Type *t)
     167             : {
     168         570 :     if (t->members)
     169         570 :         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       93727 : get_code_file(void)
     209             : {
     210       89930 :     if (!one_code_file)
     211           0 :         return templatefile;
     212       93727 :     return codefile;
     213             : }
     214             : 
     215             : 
     216             : static int
     217        6859 : is_supported_type_p(const Type *t)
     218             : {
     219       13718 :     return t->type >= 0 && t->type <= TVisibleString &&
     220        6859 :         types[t->type].type == t->type;
     221             : }
     222             : 
     223             : int
     224        6859 : is_template_compat (const Symbol *s)
     225             : {
     226        6859 :     return is_supported_type_p(s->type);
     227             : }
     228             : 
     229             : static const char *
     230       24396 : symbol_name(const char *basename, const Type *t)
     231             : {
     232       24396 :     if (t->type >= 0 && t->type <= TVisibleString &&
     233       24396 :         types[t->type].type == t->type)
     234       24396 :         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       44042 : partial_offset(const char *basetype, const char *name, int need_offset, int isstruct)
     244             : {
     245        2318 :     char *str;
     246       44042 :     if (name == NULL || need_offset == 0)
     247       31008 :         return strdup("0");
     248       13720 :     if (asprintf(&str, "offsetof(%s%s, %s)", isstruct ? "struct " : "", basetype, name) < 0 || str == NULL)
     249           0 :         errx(1, "malloc");
     250       12348 :     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       31578 : tlist_new(const char *name)
     290             : {
     291       31578 :     struct tlist *tl = calloc(1, sizeof(*tl));
     292       31578 :     tl->name = strdup(name);
     293       31578 :     HEIM_TAILQ_INIT(&tl->template);
     294       31578 :     return tl;
     295             : }
     296             : 
     297             : static void
     298       31578 : tlist_header(struct tlist *t, const char *fmt, ...)
     299             : {
     300        1662 :     va_list ap;
     301       31578 :     va_start(ap, fmt);
     302       31578 :     if (vasprintf(&t->header, fmt, ap) < 0 || t->header == NULL)
     303           0 :         errx(1, "malloc");
     304       31578 :     va_end(ap);
     305       31578 : }
     306             : 
     307             : static unsigned long
     308       31008 : tlist_count(struct tlist *tl)
     309             : {
     310       31008 :     unsigned int count = 0;
     311        1632 :     struct template *q;
     312             : 
     313       88844 :     HEIM_TAILQ_FOREACH(q, &tl->template, members) {
     314       57836 :         count++;
     315             :     }
     316       31008 :     return count;
     317             : }
     318             : 
     319             : static void
     320       19665 : tlist_add(struct tlist *tl)
     321             : {
     322       19665 :     HEIM_TAILQ_INSERT_TAIL(&tlistmaster, tl, tmembers);
     323       19660 : }
     324             : 
     325             : static void
     326       19665 : tlist_print(struct tlist *tl)
     327             : {
     328        1035 :     struct template *q;
     329       19665 :     unsigned int i = 1;
     330       19665 :     FILE *f = get_code_file();
     331             : 
     332       19665 :     fprintf(f, "const struct asn1_template asn1_%s[] = {\n", tl->name);
     333       19665 :     fprintf(f, "/* 0 */ %s,\n", tl->header);
     334       74062 :     HEIM_TAILQ_FOREACH(q, &tl->template, members) {
     335       54397 :         int last = (HEIM_TAILQ_LAST(&tl->template, templatehead) == q);
     336       56228 :         fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");
     337             :     }
     338       19665 :     fprintf(f, "};\n");
     339       19665 : }
     340             : 
     341             : static struct tlist *
     342       13186 : tlist_find_by_name(const char *name)
     343             : {
     344         694 :     struct tlist *ql;
     345      524704 :     HEIM_TAILQ_FOREACH(ql, &tlistmaster, tmembers) {
     346      524704 :         if (strcmp(ql->name, name) == 0)
     347       13186 :             return ql;
     348             :     }
     349           0 :     return NULL;
     350             : }
     351             : 
     352             : static int
     353        6593 : tlist_cmp_name(const char *tname, const char *qname)
     354             : {
     355        6593 :     struct tlist *tl = tlist_find_by_name(tname);
     356        6593 :     struct tlist *ql = tlist_find_by_name(qname);
     357        6593 :     if (tl == NULL)
     358           0 :         return 1;
     359        6593 :     if (ql == NULL)
     360           0 :         return -1;
     361        6593 :     return tlist_cmp(tl, ql);
     362             : }
     363             : 
     364             : static int
     365     2442773 : tlist_cmp(const struct tlist *tl, const struct tlist *ql)
     366             : {
     367      128567 :     int ret;
     368      128567 :     struct template *t, *q;
     369             : 
     370     2442773 :     if (tl == ql)
     371        6246 :         return 0;
     372     2436180 :     ret = strcmp(tl->header, ql->header);
     373     2436180 :     if (ret != 0) return ret;
     374             : 
     375       29697 :     q = HEIM_TAILQ_FIRST(&ql->template);
     376       41591 :     HEIM_TAILQ_FOREACH(t, &tl->template, members) {
     377       29678 :         if (q == NULL) return 1;
     378             : 
     379       29678 :         if (t->ptr == NULL || q->ptr == NULL) {
     380       15656 :             ret = strcmp(t->line, q->line);
     381       15656 :             if (ret != 0) return ret;
     382             :         } else {
     383       14022 :             ret = strcmp(t->tt, q->tt);
     384       14022 :             if (ret != 0) return ret;
     385             : 
     386        6631 :             ret = strcmp(t->offset, q->offset);
     387        6631 :             if (ret != 0) return ret;
     388             : 
     389       12877 :             if ((ret = strcmp(t->ptr, q->ptr)) != 0 ||
     390        6593 :                 (ret = tlist_cmp_name(t->ptr, q->ptr)) != 0)
     391          38 :                 return ret;
     392             :         }
     393       11894 :         q = HEIM_TAILQ_NEXT(q, members);
     394             :     }
     395       11913 :     if (q != NULL) return -1;
     396       11286 :     return 0;
     397             : }
     398             : 
     399             : 
     400             : static const char *
     401       31483 : tlist_find_dup(const struct tlist *tl)
     402             : {
     403        1657 :     struct tlist *ql;
     404             : 
     405     2455750 :     HEIM_TAILQ_FOREACH(ql, &tlistmaster, tmembers) {
     406     2436180 :         if (tlist_cmp(ql, tl) == 0) {
     407       11913 :             numdups++;
     408       11913 :             return ql->name;
     409             :         }
     410             :     }
     411       18540 :     return NULL;
     412             : }
     413             : 
     414             : 
     415             : /*
     416             :  * Add an entry to a template.
     417             :  */
     418             : 
     419             : static struct template *
     420       70319 : add_line(struct templatehead *t, const char *fmt, ...)
     421             : {
     422       70319 :     struct template *q = calloc(1, sizeof(*q));
     423        3701 :     va_list ap;
     424       70319 :     va_start(ap, fmt);
     425       70319 :     if (vasprintf(&q->line, fmt, ap) < 0 || q->line == NULL)
     426           0 :         errx(1, "malloc");
     427       70319 :     va_end(ap);
     428       70319 :     HEIM_TAILQ_INSERT_TAIL(t, q, members);
     429       70319 :     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       30381 : add_line_pointer(struct templatehead *t,
     438             :                  const char *ptr,
     439             :                  const char *offset,
     440             :                  const char *ttfmt,
     441             :                  ...)
     442             : {
     443        1599 :     struct template *q;
     444        1599 :     va_list ap;
     445       30381 :     char *tt = NULL;
     446             : 
     447       30381 :     va_start(ap, ttfmt);
     448       30381 :     if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL)
     449           0 :         errx(1, "malloc");
     450       30381 :     va_end(ap);
     451             : 
     452       30381 :     if (ptr[0] == '&')
     453          19 :         q = add_line(t, "{ %s, %s, %s }", tt, offset, ptr);
     454             :     else
     455       30362 :         q = add_line(t, "{ %s, %s, asn1_%s }", tt, offset, ptr);
     456       30381 :     q->tt = tt;
     457       30381 :     q->offset = strdup(offset);
     458       30381 :     q->ptr = strdup(ptr);
     459       30381 : }
     460             : 
     461             : /*
     462             :  * Add an entry to a template where the pointer field is a string literal.
     463             :  */
     464             : static void
     465       17176 : add_line_string(struct templatehead *t,
     466             :                 const char *str,
     467             :                 const char *offset,
     468             :                 const char *ttfmt,
     469             :                 ...)
     470             : {
     471         904 :     struct template *q;
     472         904 :     va_list ap;
     473       17176 :     char *tt = NULL;
     474             : 
     475       17176 :     va_start(ap, ttfmt);
     476       17176 :     if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL)
     477           0 :         errx(1, "malloc");
     478       17176 :     va_end(ap);
     479             : 
     480       17176 :     q = add_line(t, "{ %s, %s, \"%s\" }", tt, offset, str);
     481       17176 :     q->tt = tt;
     482       17176 :     q->offset = strdup(offset);
     483       17176 :     q->ptr = strdup(str);
     484       17176 : }
     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        1938 : add_line_pointer_reference(struct templatehead *t,
     492             :                            const char *ptr,
     493             :                            const char *offset,
     494             :                            const char *ttfmt,
     495             :                            ...)
     496             : {
     497         102 :     struct template *q;
     498         102 :     va_list ap;
     499        1938 :     char *tt = NULL;
     500             : 
     501        1938 :     va_start(ap, ttfmt);
     502        1938 :     if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL)
     503           0 :         errx(1, "malloc");
     504        1938 :     va_end(ap);
     505             : 
     506        1938 :     q = add_line(t, "{ %s, %s, (const void *)&asn1_%s }", tt, offset, ptr);
     507        1938 :     q->tt = tt;
     508        1938 :     q->offset = strdup(offset);
     509        1938 :     q->ptr = strdup(ptr);
     510        1938 : }
     511             : 
     512             : static int
     513       16948 : use_extern(const Symbol *s)
     514             : {
     515       16948 :     if (s->type == NULL)
     516        1444 :         return 1;
     517       14688 :     return 0;
     518             : }
     519             : 
     520             : static int
     521       28901 : is_struct(const Type *t, int isstruct)
     522             : {
     523       29165 :     if (t->type == TType)
     524        7488 :         return 0;
     525       21261 :     if (t->type == TSequence || t->type == TSet || t->type == TChoice)
     526        3870 :         return 1;
     527       17176 :     if (t->type == TTag)
     528        5016 :         return is_struct(t->subtype, isstruct);
     529             : 
     530       12160 :     if (t->type >= 0 && t->type <= TVisibleString &&
     531       12160 :         types[t->type].type == t->type) {
     532       12160 :         if (types[t->type].is_struct == 0)
     533        9558 :             return 0;
     534        2071 :         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          72 : compact_tag(const Type *t)
     544             : {
     545          76 :     while (t->type == TTag)
     546           0 :         t = t->subtype;
     547          76 :     return t;
     548             : }
     549             : 
     550             : static void
     551         209 : defval(struct templatehead *temp, Member *m)
     552             : {
     553         209 :     switch (m->defval->type) {
     554         114 :     case booleanvalue:
     555         114 :         add_line(temp, "{ A1_OP_DEFVAL|A1_DV_BOOLEAN, ~0, (void *)(uintptr_t)%u }",
     556         108 :                  m->defval->u.booleanvalue);
     557         114 :         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          95 :     case integervalue: {
     562          95 :         const char *dv = "A1_DV_INTEGER";
     563          95 :         Type *t = m->type;
     564             : 
     565          18 :         for (;;) {
     566         342 :             if (t->range)
     567          36 :                 break;
     568         304 :             if (t->type == TInteger && t->members)
     569          54 :                 break;
     570         247 :             if (t->type == TEnumerated)
     571           0 :                 break;
     572         247 :             if (t->subtype)
     573         126 :                 t = t->subtype;
     574         114 :             else if (t->symbol && t->symbol->type)
     575         108 :                 t = t->symbol->type;
     576             :             else
     577           0 :                 errx(1, "DEFAULT values for unconstrained INTEGER members not supported");
     578             :         }
     579             : 
     580          95 :         if (t->members)
     581          54 :             dv = "A1_DV_INTEGER32"; /* XXX Enum size assumptions!  No good! */
     582          38 :         else if (t->range && t->range->min < 0 &&
     583          19 :                  (t->range->min < INT_MIN || t->range->max > INT_MAX))
     584           0 :             dv = "A1_DV_INTEGER64";
     585          38 :         else if (t->range && t->range->min < 0)
     586          18 :             dv = "A1_DV_INTEGER32";
     587          19 :         else if (t->range && t->range->max > UINT_MAX)
     588           0 :             dv = "A1_DV_INTEGER64";
     589             :         else
     590          19 :             dv = "A1_DV_INTEGER32";
     591          95 :         add_line(temp, "{ A1_OP_DEFVAL|%s, ~0, (void *)(uintptr_t)%llu }",
     592          95 :                  dv, (long long)m->defval->u.integervalue);
     593          95 :         break;
     594             :     }
     595           0 :     case stringvalue: {
     596           0 :         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           0 :         struct objid *o;
     608           0 :         size_t sz = sizeof("{ }");
     609           0 :         char *s, *p;
     610           0 :         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         209 : }
     643             : 
     644             : int
     645        9424 : objid_cmp(struct objid *oida, struct objid *oidb)
     646             : {
     647         496 :     struct objid *p;
     648         496 :     size_t ai, bi, alen, blen;
     649         496 :     int avals[20];
     650         496 :     int bvals[20];
     651         496 :     int c;
     652             : 
     653             :     /*
     654             :      * Our OID values are backwards here.  Comparing them is hard.
     655             :      */
     656             : 
     657        9424 :     for (p = oida, alen = 0;
     658       53561 :          p && alen < sizeof(avals)/sizeof(avals[0]);
     659       44137 :          p = p->next)
     660       44137 :         avals[alen++] = p->value;
     661        8928 :     for (p = oidb, blen = 0;
     662       57171 :          p && blen < sizeof(bvals)/sizeof(bvals[0]);
     663       47747 :          p = p->next)
     664       47747 :         bvals[blen++] = p->value;
     665        9424 :     if (alen >= sizeof(avals)/sizeof(avals[0]) ||
     666         496 :         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       36195 :     for (ai = 0, bi = 0; ai < alen && bi < blen;)
     671       36195 :         if ((c = avals[(alen-1)-(ai++)] - bvals[(blen-1)-(bi++)]))
     672        9424 :             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        9424 : object_cmp(const void *va, const void *vb)
     683             : {
     684        9424 :     const IOSObject *oa = *(const IOSObject * const *)va;
     685        9424 :     const IOSObject *ob = *(const IOSObject * const *)vb;
     686             : 
     687        9424 :     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        9424 :     case objectidentifiervalue: {
     700        9424 :         return objid_cmp(oa->typeidf->value->u.objectidentifiervalue,
     701        9424 :             ob->typeidf->value->u.objectidentifiervalue);
     702             :     }
     703           0 :     default:
     704           0 :             abort();
     705             :             return -1;
     706             :     }
     707             : }
     708             : 
     709             : void
     710         304 : 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          16 :     IOSObject **objects;
     716          16 :     IOSObject *o;
     717         304 :     size_t i, nobjs = 0;
     718             : 
     719         304 :     *objectsp = NULL;
     720             : 
     721        3629 :     HEIM_TAILQ_FOREACH(o, os->objects, objects) {
     722        3325 :         ObjectField *typeidobjf = NULL;
     723         175 :         ObjectField *of;
     724             : 
     725       11115 :         HEIM_TAILQ_FOREACH(of, o->objfields, objfields) {
     726        7790 :             if (strcmp(of->name, typeidfield->name) == 0)
     727        3325 :                 typeidobjf = of;
     728             :         }
     729        3325 :         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        3325 :         o->typeidf = typeidobjf;
     736        3325 :         nobjs++;
     737             :     }
     738         304 :     *nobjsp = nobjs;
     739             : 
     740         304 :     if (nobjs == 0)
     741           0 :         return;
     742             : 
     743         304 :     if ((objects = calloc(nobjs, sizeof(*objects))) == NULL)
     744           0 :         err(1, "Out of memory");
     745         304 :     *objectsp = objects;
     746             : 
     747         304 :     i = 0;
     748        3629 :     HEIM_TAILQ_FOREACH(o, os->objects, objects) {
     749        3325 :         ObjectField *typeidobjf = NULL;
     750         175 :         ObjectField *of;
     751             : 
     752       11115 :         HEIM_TAILQ_FOREACH(of, o->objfields, objfields) {
     753        7790 :             if (strcmp(of->name, typeidfield->name) == 0)
     754        3325 :                 typeidobjf = of;
     755             :         }
     756        3325 :         if (typeidobjf)
     757        3325 :             objects[i++] = o;
     758             :     }
     759         304 :     qsort(objects, nobjs, sizeof(*objects), object_cmp);
     760             : }
     761             : 
     762             : static void
     763         114 : template_object_set(IOSObjectSet *os, Field *typeidfield, Field *opentypefield)
     764             : {
     765         114 :     IOSObject **objects = NULL;
     766           6 :     IOSObject *o;
     767           6 :     struct tlist *tl;
     768           6 :     size_t nobjs, i;
     769             : 
     770         114 :     if (os->symbol->emitted_template)
     771          19 :         return;
     772             : 
     773          95 :     sort_object_set(os, typeidfield, &objects, &nobjs);
     774             : 
     775          95 :     tl = tlist_new(os->symbol->name);
     776          95 :     add_line(&tl->template, "{ A1_OP_NAME, 0, \"%s\" }", os->symbol->name);
     777        1069 :     for (i = 0; i < nobjs; i++) {
     778         969 :         ObjectField *typeidobjf = NULL, *opentypeobjf = NULL;
     779          51 :         ObjectField *of;
     780         969 :         char *s = NULL;
     781             : 
     782         969 :         o = objects[i];
     783             : 
     784        3287 :         HEIM_TAILQ_FOREACH(of, o->objfields, objfields) {
     785        2318 :             if (strcmp(of->name, typeidfield->name) == 0)
     786         918 :                 typeidobjf = of;
     787        1349 :             else if (strcmp(of->name, opentypefield->name) == 0)
     788         969 :                 opentypeobjf = of;
     789             :         }
     790         969 :         if (!typeidobjf)
     791           0 :             continue; /* We've warned about this one already when sorting */
     792         969 :         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         969 :         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         969 :         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         969 :         case objectidentifiervalue:
     811         969 :             if (asprintf(&s, "oid_%s",
     812        1938 :                          typeidobjf->value->s->gen_name) == -1 || !s)
     813           0 :                 err(1, "Out of memory");
     814         969 :             add_line_pointer_reference(&tl->template, s, "0", "A1_OP_OPENTYPE_ID");
     815         969 :             free(s);
     816         969 :             s = NULL;
     817         969 :             break;
     818           0 :         default:
     819           0 :             errx(1, "Only integer and OID types supported "
     820             :                  "for open type type-ID fields");
     821             :         }
     822             : 
     823         969 :         if (asprintf(&s, "sizeof(%s)",
     824        1938 :                      opentypeobjf->type->symbol->gen_name) == -1 || !s)
     825           0 :             err(1, "Out of memory");
     826         969 :         add_line_pointer_reference(&tl->template,
     827         969 :                                    opentypeobjf->type->symbol->gen_name, s,
     828             :                                    "A1_OP_OPENTYPE");
     829         969 :         free(s);
     830             :     }
     831          95 :     free(objects);
     832             : 
     833          95 :     tlist_header(tl, "{ 0, 0, ((void *)(uintptr_t)%zu) }", nobjs);
     834          95 :     tlist_print(tl);
     835          95 :     tlist_add(tl);
     836          95 :     os->symbol->emitted_template = 1;
     837             : }
     838             : 
     839             : static void
     840         114 : 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         114 :     char *s = NULL;
     851             : 
     852         114 :     if (typeididx >= 1<<10 || opentypeidx >= 1<<10)
     853           0 :         errx(1, "SET/SEQUENCE with too many members (%s)", basetype);
     854             : 
     855         114 :     if (asprintf(&s, "offsetof(%s, _ioschoice_%s)",
     856         114 :                  basetype, m->gen_name) == -1 || !s)
     857           0 :         err(1, "Out of memory");
     858             : 
     859         114 :     template_object_set(t->actual_parameter, typeidfield, opentypefield);
     860         118 :     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         114 :     free(s);
     870         114 : }
     871             : 
     872             : static void
     873        3629 : template_names(struct templatehead *temp, const char *basetype, const Type *t)
     874             : {
     875         191 :     Member *m;
     876             : 
     877        3629 :     add_line_string(temp, basetype, "0", "A1_OP_NAME");
     878       17176 :     HEIM_TAILQ_FOREACH(m, t->members, members) {
     879       13547 :         add_line_string(temp, m->name, "0", "A1_OP_NAME");
     880             :     }
     881        3629 : }
     882             : 
     883             : static void
     884       44004 : 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       44004 :     char *poffset = NULL;
     895             : 
     896       44004 :     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       44004 :     poffset = partial_offset(basetype, name, need_offset, isstruct);
     900             : 
     901       44004 :     switch (t->type) {
     902       10089 :     case TType:
     903       10089 :         if (use_extern(t->symbol)) {
     904        1669 :             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        1368 :                      poffset, t->symbol->gen_name);
     909             :         } else {
     910        9994 :             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        9558 :         break;
     918        1767 :     case TEnumerated:
     919             :     case TInteger: {
     920        1767 :         char *varname = NULL;
     921        1767 :         char *itype = NULL;
     922             : 
     923        1767 :         if (t->members)
     924         450 :             itype = "IMEMBER";
     925        1292 :         else if (t->range == NULL)
     926         702 :             itype = "HEIM_INTEGER";
     927         551 :         else if (t->range->min < 0 &&
     928         133 :                  (t->range->min < INT_MIN || t->range->max > INT_MAX))
     929           0 :             itype = "INTEGER64";
     930         551 :         else if (t->range->min < 0)
     931         126 :             itype = "INTEGER";
     932         418 :         else if (t->range->max > UINT_MAX)
     933           0 :             itype = "UNSIGNED64";
     934             :         else
     935         418 :             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        2242 :         if (t->members && t->symbol) {
     949          25 :             struct tlist *tl;
     950          25 :             Member *m;
     951         475 :             size_t nmemb = 0;
     952             : 
     953         475 :             if (asprintf(&varname, "%s_enum_names", t->symbol->gen_name) == -1 ||
     954         475 :                 varname == NULL)
     955           0 :                 err(1, "Out of memory");
     956             : 
     957         475 :             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        5928 :             HEIM_TAILQ_FOREACH(m, t->members, members) {
     964        5453 :                 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        5453 :                 add_line(&tl->template,
     970        5166 :                          "{ A1_OP_NAME, %d, \"%s\" }", (int)m->val, m->name);
     971        5453 :                 nmemb++;
     972             :             }
     973         475 :             tlist_header(tl, "{ 0, 0, ((void *)(uintptr_t)%zu) }", nmemb);
     974             :             /* XXX Accidentally O(N^2)? */
     975         475 :             if (!tlist_find_dup(tl)) {
     976         475 :                 tlist_print(tl);
     977         475 :                 tlist_add(tl);
     978             :             }
     979         475 :             add_line(temp, "{ A1_PARSE_T(A1T_%s), %s, asn1_%s }", itype, poffset, varname);
     980             :         } else {
     981        1292 :             add_line(temp, "{ A1_PARSE_T(A1T_%s), %s, NULL }", itype, poffset);
     982             :         }
     983        1767 :         break;
     984             :     }
     985         247 :     case TGeneralString:
     986         247 :         add_line(temp, "{ A1_PARSE_T(A1T_GENERAL_STRING), %s, NULL }", poffset);
     987         247 :         break;
     988          19 :     case TTeletexString:
     989          19 :         add_line(temp, "{ A1_PARSE_T(A1T_TELETEX_STRING), %s, NULL }", poffset);
     990          19 :         break;
     991          38 :     case TPrintableString:
     992          38 :         add_line(temp, "{ A1_PARSE_T(A1T_PRINTABLE_STRING), %s, NULL }", poffset);
     993          38 :         break;
     994        2052 :     case TOctetString:
     995        2052 :         add_line(temp, "{ A1_PARSE_T(A1T_OCTET_STRING), %s, NULL }", poffset);
     996        2052 :         break;
     997         209 :     case TIA5String:
     998         209 :         add_line(temp, "{ A1_PARSE_T(A1T_IA5_STRING), %s, NULL }", poffset);
     999         209 :         break;
    1000          57 :     case TBMPString:
    1001          57 :         add_line(temp, "{ A1_PARSE_T(A1T_BMP_STRING), %s, NULL }", poffset);
    1002          57 :         break;
    1003          19 :     case TUniversalString:
    1004          19 :         add_line(temp, "{ A1_PARSE_T(A1T_UNIVERSAL_STRING), %s, NULL }", poffset);
    1005          19 :         break;
    1006          38 :     case TVisibleString:
    1007          38 :         add_line(temp, "{ A1_PARSE_T(A1T_VISIBLE_STRING), %s, NULL }", poffset);
    1008          38 :         break;
    1009         798 :     case TUTF8String:
    1010         798 :         add_line(temp, "{ A1_PARSE_T(A1T_UTF8_STRING), %s, NULL }", poffset);
    1011         798 :         break;
    1012         171 :     case TGeneralizedTime:
    1013         171 :         add_line(temp, "{ A1_PARSE_T(A1T_GENERALIZED_TIME), %s, NULL }", poffset);
    1014         171 :         break;
    1015          19 :     case TUTCTime:
    1016          19 :         add_line(temp, "{ A1_PARSE_T(A1T_UTC_TIME), %s, NULL }", poffset);
    1017          19 :         break;
    1018         247 :     case TBoolean:
    1019         247 :         add_line(temp, "{ A1_PARSE_T(A1T_BOOLEAN), %s, NULL }", poffset);
    1020         247 :         break;
    1021         627 :     case TOID:
    1022         627 :         add_line(temp, "{ A1_PARSE_T(A1T_OID), %s, NULL }", poffset);
    1023         627 :         break;
    1024          72 :     case TNull:
    1025          72 :         break;
    1026         475 :     case TBitString: {
    1027          25 :         struct templatehead template;
    1028          25 :         struct template *q;
    1029          25 :         Member *m;
    1030         475 :         size_t count = 0, i;
    1031         475 :         char *bname = NULL;
    1032         475 :         FILE *f = get_code_file();
    1033          25 :         static unsigned long bmember_counter = 0;
    1034             : 
    1035         475 :         HEIM_TAILQ_INIT(&template);
    1036             : 
    1037         475 :         if (HEIM_TAILQ_EMPTY(t->members)) {
    1038         285 :             add_line(temp, "{ A1_PARSE_T(A1T_HEIM_BIT_STRING), %s, NULL }", poffset);
    1039         285 :             break;
    1040             :         }
    1041             : 
    1042         200 :         if (asprintf(&bname, "bmember_%s_%lu", name ? name : "", bmember_counter++) < 0 || bname == NULL)
    1043           0 :             errx(1, "malloc");
    1044         190 :         output_name(bname);
    1045             : 
    1046        1862 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
    1047        1672 :             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        1672 :             add_line(&template, "{ 0, %d, \"%s\" }", (int)m->val, m->gen_name);
    1051             :         }
    1052             : 
    1053        1862 :         HEIM_TAILQ_FOREACH(q, &template, members) {
    1054        1672 :             count++;
    1055             :         }
    1056             : 
    1057         190 :         fprintf(f, "static const struct asn1_template asn1_%s_%s[] = {\n", basetype, bname);
    1058         200 :         fprintf(f, "/* 0 */ { 0%s, sizeof(%s), ((void *)(uintptr_t)%lu) },\n",
    1059         190 :                 rfc1510_bitstring ? "|A1_HBF_RFC1510" : "",
    1060             :                 basetype, (unsigned long)count);
    1061         190 :         i = 1;
    1062        1862 :         HEIM_TAILQ_FOREACH(q, &template, members) {
    1063        1672 :             int last = (HEIM_TAILQ_LAST(&template, templatehead) == q);
    1064        1750 :             fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");
    1065             :         }
    1066         190 :         fprintf(f, "};\n");
    1067             : 
    1068         190 :         add_line(temp, "{ A1_OP_BMEMBER, %s, asn1_%s_%s }", poffset, basetype, bname);
    1069             : 
    1070         190 :         free(bname);
    1071             : 
    1072         190 :         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           0 :         Member *m;
    1080           0 :         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           0 :             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        3629 :     case TSequence: {
    1153        3629 :         Member *opentypemember = NULL;
    1154        3629 :         Member *typeidmember = NULL;
    1155        3629 :         Field *opentypefield = NULL;
    1156        3629 :         Field *typeidfield = NULL;
    1157         191 :         Member *m;
    1158         191 :         struct decoration deco;
    1159        3629 :         ssize_t more_deco = -1;
    1160        3629 :         size_t i = 0, typeididx = 0, opentypeidx = 0;
    1161        3629 :         int is_array_of_open_type = 0;
    1162             : 
    1163        3629 :         if (isstruct && t->actual_parameter)
    1164         114 :             get_open_type_defn_fields(t, &typeidmember, &opentypemember,
    1165             :                                       &typeidfield, &opentypefield,
    1166             :                                       &is_array_of_open_type);
    1167             : 
    1168        3820 :         fprintf(get_code_file(), "/* tsequence: members isstruct: %d */\n", isstruct);
    1169             : 
    1170       17176 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
    1171       13547 :             char *newbasename = NULL;
    1172             : 
    1173       13547 :             if (m->ellipsis)
    1174         551 :                 continue;
    1175             : 
    1176       12996 :             if (typeidmember == m) typeididx = i;
    1177       12996 :             if (opentypemember == m) opentypeidx = i;
    1178             : 
    1179       12996 :             if (name) {
    1180          76 :                 if (asprintf(&newbasename, "%s_%s", basetype, name) < 0)
    1181           0 :                     errx(1, "malloc");
    1182             :             } else
    1183       12920 :                 newbasename = strdup(basetype);
    1184       12996 :             if (newbasename == NULL)
    1185           0 :                 errx(1, "malloc");
    1186             : 
    1187       12996 :             if (m->defval)
    1188         209 :                 defval(temp, m);
    1189             :             
    1190       12996 :             template_members(temp, newbasename, m->gen_name, m->type, m->optional, m->defval ? 1 : 0, 0, isstruct, 1);
    1191             : 
    1192       12996 :             free(newbasename);
    1193       12996 :             i++;
    1194             :         }
    1195             : 
    1196        3629 :         if (isstruct && t->actual_parameter)
    1197         114 :             template_open_type(temp, basetype, t, typeididx, opentypeidx,
    1198             :                                typeidfield, opentypefield, opentypemember,
    1199             :                                is_array_of_open_type);
    1200             : 
    1201        3667 :         while (decorate_type(basetype, &deco, &more_deco)) {
    1202           2 :             char *poffset2;
    1203             : 
    1204          38 :             poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
    1205             : 
    1206          38 :             if (deco.ext) {
    1207          19 :                 char *ptr = NULL;
    1208             : 
    1209             :                 /* Decorated with external C type */
    1210          19 :                 if (asprintf(&ptr, "&asn1_extern_%s_%s",
    1211          19 :                              basetype, deco.field_name) == -1 || ptr == NULL)
    1212           0 :                     err(1, "out of memory");
    1213          19 :                 add_line_pointer(temp, ptr, poffset2,
    1214             :                                  "A1_OP_TYPE_DECORATE_EXTERN %s",
    1215          19 :                                  deco.opt ? "|A1_FLAG_OPTIONAL" : "");
    1216          19 :                 free(ptr);
    1217             :             } else
    1218             :                 /* Decorated with a templated ASN.1 type */
    1219          19 :                 add_line_pointer(temp, deco.field_type, poffset2,
    1220             :                                  "A1_OP_TYPE_DECORATE %s",
    1221          19 :                                  deco.opt ? "|A1_FLAG_OPTIONAL" : "");
    1222          38 :             free(poffset2);
    1223          38 :             free(deco.field_type);
    1224             :         }
    1225             : 
    1226        3629 :         if (isstruct)
    1227        3629 :             template_names(temp, basetype, t);
    1228        3629 :         break;
    1229             :     }
    1230       21584 :     case TTag: {
    1231       21584 :         char *tname = NULL, *elname = NULL;
    1232        1136 :         const char *sename, *dupname;
    1233       21584 :         int subtype_is_struct = is_struct(t->subtype, isstruct);
    1234        1136 :         static unsigned long tag_counter = 0;
    1235       21584 :         int tagimplicit = 0;
    1236       52820 :         int prim = !(t->tag.tagclass != ASN1_C_UNIV &&
    1237       34656 :                      t->tag.tagenv == TE_EXPLICIT) &&
    1238       13072 :             is_primitive_type(t->subtype);
    1239             : 
    1240       21584 :         if (t->tag.tagenv == TE_IMPLICIT) {
    1241        1425 :             Type *t2 = t->subtype;
    1242             : 
    1243        1899 :             while (t2->type == TType && (t2->subtype || t2->symbol->type))
    1244         399 :                 t2 = t2->subtype ? t2->subtype : t2->symbol->type;
    1245        1425 :             if (t2->type != TChoice)
    1246        1314 :                 tagimplicit = 1;
    1247             :         }
    1248             : 
    1249       22720 :         fprintf(get_code_file(), "/* template_members: %s %s %s */\n", basetype, implicit ? "imp" : "exp", tagimplicit ? "imp" : "exp");
    1250             : 
    1251       21584 :         if (subtype_is_struct)
    1252        4698 :             sename = basetype;
    1253             :         else
    1254       16625 :             sename = symbol_name(basetype, t->subtype);
    1255             : 
    1256       22720 :         if (asprintf(&tname, "tag_%s_%lu", name ? name : "", tag_counter++) < 0 || tname == NULL)
    1257           0 :             errx(1, "malloc");
    1258       21584 :         output_name(tname);
    1259             : 
    1260       21584 :         if (asprintf(&elname, "%s_%s", basetype, tname) < 0 || elname == NULL)
    1261           0 :             errx(1, "malloc");
    1262             : 
    1263       21584 :         generate_template_type(elname, &dupname, NULL, sename, name,
    1264       21584 :                                t->subtype, 0, subtype_is_struct, 0);
    1265             : 
    1266       66943 :         add_line_pointer(temp, dupname, poffset,
    1267             :                          "A1_TAG_T(%s,%s,%s)%s%s%s",
    1268       21584 :                          classname(t->tag.tagclass),
    1269             :                          prim  ? "PRIM" : "CONS",
    1270       21584 :                          valuename(t->tag.tagclass, t->tag.tagvalue),
    1271             :                          optional    ? "|A1_FLAG_OPTIONAL" : "",
    1272             :                          defaulted   ? "|A1_FLAG_DEFAULT" : "",
    1273             :                          tagimplicit ? "|A1_FLAG_IMPLICIT" : "");
    1274             : 
    1275       21584 :         free(tname);
    1276       21584 :         free(elname);
    1277             : 
    1278       21584 :         break;
    1279             :     }
    1280        1425 :     case TSetOf:
    1281             :     case TSequenceOf: {
    1282        1425 :         const char *type = NULL, *tname, *dupname;
    1283        1425 :         char *sename = NULL, *elname = NULL;
    1284        1425 :         int subtype_is_struct = is_struct(t->subtype, 0);
    1285          75 :         static unsigned long seof_counter = 0;
    1286             : 
    1287        1425 :         if (name && subtype_is_struct) {
    1288          19 :             tname = "seofTstruct";
    1289          19 :             if (asprintf(&sename, "%s_%s_val", basetype, name) < 0)
    1290           0 :                 errx(1, "malloc");
    1291        1406 :         } else if (subtype_is_struct) {
    1292          19 :             tname = "seofTstruct";
    1293          19 :             if (asprintf(&sename, "%s_val", symbol_name(basetype, t->subtype)) < 0)
    1294           0 :                 errx(1, "malloc");
    1295             :         } else {
    1296        1387 :             if (name)
    1297         504 :                 tname = name;
    1298             :             else
    1299         855 :                 tname = "seofTstruct";
    1300        1387 :             sename = strdup(symbol_name(basetype, t->subtype));
    1301             :         }
    1302        1425 :         if (sename == NULL)
    1303           0 :             errx(1, "malloc");
    1304             : 
    1305        1425 :         if (t->type == TSetOf) type = "A1_OP_SETOF";
    1306        1102 :         else if (t->type == TSequenceOf) type = "A1_OP_SEQOF";
    1307           0 :         else abort();
    1308             : 
    1309        1425 :         if (asprintf(&elname, "%s_%s_%lu", basetype, tname, seof_counter++) < 0 || elname == NULL)
    1310           0 :             errx(1, "malloc");
    1311             : 
    1312        1425 :         generate_template_type(elname, &dupname, NULL, sename, NULL, t->subtype,
    1313             :                                0, subtype_is_struct, need_offset);
    1314             : 
    1315        1425 :         add_line(temp, "{ %s, %s, asn1_%s }", type, poffset, dupname);
    1316        1425 :         free(sename);
    1317        1425 :         break;
    1318             :     }
    1319         418 :     case TChoice: {
    1320          22 :         struct decoration deco;
    1321         418 :         ssize_t more_deco = -1;
    1322          22 :         struct templatehead template;
    1323          22 :         struct template *q;
    1324         418 :         size_t count = 0, i;
    1325         418 :         char *tname = NULL;
    1326         418 :         FILE *f = get_code_file();
    1327          22 :         Member *m;
    1328         418 :         int ellipsis = 0;
    1329          22 :         char *e;
    1330          22 :         static unsigned long choice_counter = 0;
    1331             : 
    1332         418 :         HEIM_TAILQ_INIT(&template);
    1333             : 
    1334         440 :         if (asprintf(&tname, "asn1_choice_%s_%s%lu",
    1335         418 :                      basetype, name ? name : "", choice_counter++) < 0 || tname == NULL)
    1336           0 :             errx(1, "malloc");
    1337             : 
    1338        1634 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
    1339          64 :             const char *dupname;
    1340        1216 :             char *elname = NULL;
    1341        1216 :             char *newbasename = NULL;
    1342          64 :             int subtype_is_struct;
    1343             : 
    1344        1216 :             if (m->ellipsis) {
    1345          76 :                 ellipsis = 1;
    1346          76 :                 continue;
    1347             :             }
    1348             : 
    1349        1140 :             subtype_is_struct = is_struct(m->type, 0);
    1350             : 
    1351        1140 :             if (asprintf(&elname, "%s_choice_%s", basetype, m->gen_name) < 0 || elname == NULL)
    1352           0 :                 errx(1, "malloc");
    1353             : 
    1354        1140 :             if (subtype_is_struct) {
    1355          38 :                 if (asprintf(&newbasename, "%s_%s", basetype, m->gen_name) < 0)
    1356           0 :                     errx(1, "malloc");
    1357             :             } else
    1358        1102 :                 newbasename = strdup(basetype);
    1359             : 
    1360        1140 :             if (newbasename == NULL)
    1361           0 :                 errx(1, "malloc");
    1362             : 
    1363             : 
    1364        1140 :             generate_template_type(elname, &dupname, NULL,
    1365        1080 :                                    symbol_name(newbasename, m->type),
    1366        1140 :                                    NULL, m->type, 0, subtype_is_struct, 1);
    1367             : 
    1368        1200 :             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        1140 :             free(elname);
    1374        1140 :             free(newbasename);
    1375             :         }
    1376             : 
    1377        1634 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
    1378        1216 :             add_line(&template, "{ 0, 0, \"%s\" }", m->name);
    1379             :         }
    1380             : 
    1381         418 :         e = NULL;
    1382         418 :         if (ellipsis) {
    1383          80 :             if (asprintf(&e, "offsetof(%s%s, u.asn1_ellipsis)", isstruct ? "struct " : "", basetype) < 0 || e == NULL)
    1384           0 :                 errx(1, "malloc");
    1385             :         }
    1386             : 
    1387        2774 :         HEIM_TAILQ_FOREACH(q, &template, members) {
    1388        2356 :             count++;
    1389             :         }
    1390             : 
    1391         418 :         fprintf(f, "static const struct asn1_template %s[] = {\n", tname);
    1392         814 :         fprintf(f, "/* 0 */ { %s, offsetof(%s%s, element), ((void *)(uintptr_t)%lu) },\n",
    1393         418 :                 e ? e : "0", isstruct ? "struct " : "", basetype, (unsigned long)count);
    1394         418 :         i = 1;
    1395        2774 :         HEIM_TAILQ_FOREACH(q, &template, members) {
    1396        2356 :             int last = (HEIM_TAILQ_LAST(&template, templatehead) == q);
    1397        2458 :             fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");
    1398             :         }
    1399         418 :         fprintf(f, "};\n");
    1400             : 
    1401         418 :         add_line(temp, "{ A1_OP_CHOICE, %s, %s }", poffset, tname);
    1402             : 
    1403         418 :         while (decorate_type(basetype, &deco, &more_deco)) {
    1404           0 :             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         418 :         free(e);
    1429         418 :         free(tname);
    1430         418 :         break;
    1431             :     }
    1432           0 :     default:
    1433           0 :         abort ();
    1434             :     }
    1435       44004 :     if (poffset)
    1436       44004 :         free(poffset);
    1437       44004 : }
    1438             : 
    1439             : static void
    1440         836 : gen_extern_stubs(FILE *f, const char *name)
    1441             : {
    1442         836 :     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         836 : }
    1455             : 
    1456             : void
    1457        1064 : gen_template_import(const Symbol *s)
    1458             : {
    1459        1064 :     FILE *f = get_code_file();
    1460             : 
    1461        1064 :     if (template_flag == 0)
    1462         216 :         return;
    1463             : 
    1464         836 :     gen_extern_stubs(f, s->gen_name);
    1465             : }
    1466             : 
    1467             : void
    1468        8930 : generate_template_type_forward(const char *name)
    1469             : {
    1470        9400 :     fprintf(get_code_file(), "extern const struct asn1_template asn1_%s[];\n", name);
    1471        8930 : }
    1472             : 
    1473             : void
    1474          95 : generate_template_objectset_forwards(const Symbol *s)
    1475             : {
    1476          95 :     if (!template_flag)
    1477           0 :         return;
    1478          95 :     fprintf(get_code_file(), "extern const struct asn1_template asn1_%s[];\n",
    1479          95 :             s->gen_name);
    1480             : }
    1481             : 
    1482             : static void
    1483       31008 : 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        1632 :     struct tlist *tl;
    1494        1632 :     const char *d;
    1495       31008 :     char *szt = NULL;
    1496       31008 :     int have_ellipsis = 0;
    1497       31008 :     int implicit = 0;
    1498        1632 :     int n;
    1499             : 
    1500       31008 :     tl = tlist_new(varname);
    1501             : 
    1502       31008 :     if (type->type == TTag && type->tag.tagenv == TE_IMPLICIT) {
    1503         513 :         Type *t = type->subtype ? type->subtype : type->symbol->type;
    1504             : 
    1505         551 :         while (t->type == TType && (t->subtype || t->symbol->type))
    1506          38 :             t = t->subtype ? t->subtype : t->symbol->type;
    1507         513 :         if (t->type != TChoice)
    1508         494 :             implicit = (type->tag.tagenv == TE_IMPLICIT);
    1509             :     }
    1510             : 
    1511       31008 :     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       31008 :     if (type->type == TSequence || type->type == TSet) {
    1516         191 :         Member *m;
    1517       17176 :         HEIM_TAILQ_FOREACH(m, type->members, members) {
    1518       13547 :             if (m->ellipsis)
    1519         551 :                 have_ellipsis = 1;
    1520             :         }
    1521             :     }
    1522             : 
    1523       31008 :     if (isstruct)
    1524        5035 :         if (name)
    1525        1026 :             n = asprintf(&szt, "struct %s_%s", basetype, name);
    1526             :         else
    1527        4009 :             n = asprintf(&szt, "struct %s", basetype);
    1528             :     else
    1529       25973 :         n = asprintf(&szt, "%s", basetype);
    1530       31008 :     if (n < 0 || szt == NULL)
    1531           0 :         errx(1, "malloc");
    1532             : 
    1533       31012 :     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       32640 :     fprintf(get_code_file(), "/* generate_template_type: %s */\n", tl->name);
    1537             : 
    1538       41104 :     tlist_header(tl, "{ 0%s%s, sizeof(%s), ((void *)(uintptr_t)%lu) }",
    1539        6859 :                  (symname && preserve_type(symname)) ? "|A1_HF_PRESERVE" : "",
    1540             :                  have_ellipsis ? "|A1_HF_ELLIPSIS" : "", szt, tlist_count(tl));
    1541             : 
    1542       31008 :     free(szt);
    1543             : 
    1544             :     /* XXX Accidentally O(N^2)? */
    1545       31008 :     d = tlist_find_dup(tl);
    1546       31008 :     if (d) {
    1547             : #if 0
    1548             :         if (strcmp(d, tl->name) == 0)
    1549             :             errx(1, "found dup of ourself: %s", d);
    1550             : #endif
    1551       11913 :         *dupname = d;
    1552             :     } else {
    1553       19095 :         *dupname = tl->name;
    1554       19095 :         tlist_print(tl);
    1555       19095 :         tlist_add(tl);
    1556             :     }
    1557       31008 : }
    1558             : 
    1559             : 
    1560             : void
    1561        6859 : generate_template(const Symbol *s)
    1562             : {
    1563        6859 :     FILE *f = get_code_file();
    1564         361 :     const char *dupname;
    1565         361 :     struct decoration deco;
    1566        6859 :     ssize_t more_deco = -1;
    1567             : 
    1568        6859 :     if (use_extern(s)) {
    1569           0 :         gen_extern_stubs(f, s->gen_name);
    1570           0 :         return;
    1571             :     }
    1572             : 
    1573        6897 :     while (decorate_type(s->gen_name, &deco, &more_deco)) {
    1574          38 :         if (!deco.ext)
    1575          19 :             continue;
    1576          19 :         if (deco.void_star && deco.header_name)
    1577           0 :             fprintf(f, "#include %s\n", deco.header_name);
    1578          54 :         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          19 :                 "};\n", s->gen_name, deco.field_name,
    1588          19 :                 deco.copy_function_name && deco.copy_function_name[0] ?
    1589             :                 deco.copy_function_name : "0",
    1590          19 :                 deco.free_function_name && deco.free_function_name[0] ?
    1591             :                 deco.free_function_name : "0",
    1592          19 :                 deco.void_star ? "void *" : deco.field_type);
    1593          19 :         free(deco.field_type);
    1594             :     }
    1595             : 
    1596        6859 :     generate_template_type(s->gen_name, &dupname, s->name, s->gen_name, NULL, s->type, 0, 0, 1);
    1597             : 
    1598        7581 :     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        6859 :             s->gen_name,
    1608        6859 :             s->gen_name,
    1609             :             dupname,
    1610        6859 :             support_ber ? "A1_PF_ALLOW_BER" : "0");
    1611             : 
    1612        7220 :     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        6859 :             s->gen_name,
    1621        6859 :             s->gen_name,
    1622             :             fuzzer_string,
    1623             :             dupname);
    1624             : 
    1625        7220 :     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        6859 :             s->gen_name,
    1634        6859 :             s->gen_name,
    1635             :             fuzzer_string,
    1636             :             dupname);
    1637             : 
    1638             : 
    1639        7220 :     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        6859 :             s->gen_name,
    1648        6859 :             s->gen_name,
    1649             :             dupname);
    1650             : 
    1651        7220 :     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        6859 :             s->gen_name,
    1660        6498 :             s->gen_name,
    1661        6859 :             s->gen_name,
    1662             :             dupname);
    1663             : 
    1664        6859 :     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        6859 :             s->gen_name,
    1673        6859 :             s->gen_name,
    1674             :             dupname);
    1675             : }

Generated by: LCOV version 1.14