LCOV - code coverage report
Current view: top level - source4/heimdal/lib/asn1 - gen_template.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 7 420 1.7 %
Date: 2021-09-23 10:06:22 Functions: 2 42 4.8 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  *
      12             :  * 1. Redistributions of source code must retain the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer.
      14             :  *
      15             :  * 2. Redistributions in binary form must reproduce the above copyright
      16             :  *    notice, this list of conditions and the following disclaimer in the
      17             :  *    documentation and/or other materials provided with the distribution.
      18             :  *
      19             :  * 3. Neither the name of the Institute nor the names of its contributors
      20             :  *    may be used to endorse or promote products derived from this software
      21             :  *    without specific prior written permission.
      22             :  *
      23             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      24             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      25             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      26             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      27             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      28             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      29             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      30             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      31             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      32             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      33             :  * SUCH DAMAGE.
      34             :  */
      35             : 
      36             : #include "gen_locl.h"
      37             : 
      38             : static const char *symbol_name(const char *, const Type *);
      39             : static void generate_template_type(const char *, const char **, const char *, const char *, const char *,
      40             :                                    Type *, int, int, int);
      41             : 
      42             : static const char *
      43           0 : ttype_symbol(const char *basename, const Type *t)
      44             : {
      45           0 :     return t->symbol->gen_name;
      46             : }
      47             : 
      48             : static const char *
      49           0 : integer_symbol(const char *basename, const Type *t)
      50             : {
      51           0 :     if (t->members)
      52           0 :         return "int"; /* XXX enum foo */
      53           0 :     else if (t->range == NULL)
      54           0 :         return "heim_integer";
      55           0 :     else if (t->range->min == INT_MIN && t->range->max == INT_MAX)
      56           0 :         return "int";
      57           0 :     else if (t->range->min == 0 && t->range->max == UINT_MAX)
      58           0 :         return "unsigned";
      59           0 :     else if (t->range->min == 0 && t->range->max == INT_MAX)
      60           0 :         return "unsigned";
      61             :     else {
      62           0 :         abort();
      63             :         UNREACHABLE(return NULL);
      64             :     }
      65             : }
      66             : 
      67             : static const char *
      68           0 : boolean_symbol(const char *basename, const Type *t)
      69             : {
      70           0 :     return "int";
      71             : }
      72             : 
      73             : 
      74             : static const char *
      75           0 : octetstring_symbol(const char *basename, const Type *t)
      76             : {
      77           0 :     return "heim_octet_string";
      78             : }
      79             : 
      80             : static const char *
      81           0 : sequence_symbol(const char *basename, const Type *t)
      82             : {
      83           0 :     return basename;
      84             : }
      85             : 
      86             : static const char *
      87           0 : time_symbol(const char *basename, const Type *t)
      88             : {
      89           0 :     return "time_t";
      90             : }
      91             : 
      92             : static const char *
      93           0 : tag_symbol(const char *basename, const Type *t)
      94             : {
      95           0 :     return symbol_name(basename, t->subtype);
      96             : }
      97             : 
      98             : static const char *
      99           0 : generalstring_symbol(const char *basename, const Type *t)
     100             : {
     101           0 :     return "heim_general_string";
     102             : }
     103             : 
     104             : static const char *
     105           0 : printablestring_symbol(const char *basename, const Type *t)
     106             : {
     107           0 :     return "heim_printable_string";
     108             : }
     109             : 
     110             : static const char *
     111           0 : ia5string_symbol(const char *basename, const Type *t)
     112             : {
     113           0 :     return "heim_ia5_string";
     114             : }
     115             : 
     116             : static const char *
     117           0 : visiblestring_symbol(const char *basename, const Type *t)
     118             : {
     119           0 :     return "heim_visible_string";
     120             : }
     121             : 
     122             : static const char *
     123           0 : utf8string_symbol(const char *basename, const Type *t)
     124             : {
     125           0 :     return "heim_utf8_string";
     126             : }
     127             : 
     128             : static const char *
     129           0 : bmpstring_symbol(const char *basename, const Type *t)
     130             : {
     131           0 :     return "heim_bmp_string";
     132             : }
     133             : 
     134             : static const char *
     135           0 : universalstring_symbol(const char *basename, const Type *t)
     136             : {
     137           0 :     return "heim_universal_string";
     138             : }
     139             : 
     140             : static const char *
     141           0 : oid_symbol(const char *basename, const Type *t)
     142             : {
     143           0 :     return "heim_oid";
     144             : }
     145             : 
     146             : static const char *
     147           0 : bitstring_symbol(const char *basename, const Type *t)
     148             : {
     149           0 :     if (t->members)
     150           0 :         return basename;
     151           0 :     return "heim_bit_string";
     152             : }
     153             : 
     154             : 
     155             : 
     156             : struct {
     157             :     enum typetype type;
     158             :     const char *(*symbol_name)(const char *, const Type *);
     159             :     int is_struct;
     160             : } types[] =  {
     161             :     { TBMPString, bmpstring_symbol, 0 },
     162             :     { TBitString, bitstring_symbol, 0 },
     163             :     { TBoolean, boolean_symbol, 0 },
     164             :     { TGeneralString, generalstring_symbol, 0 },
     165             :     { TGeneralizedTime, time_symbol, 0 },
     166             :     { TIA5String, ia5string_symbol, 0 },
     167             :     { TInteger, integer_symbol, 0 },
     168             :     { TOID, oid_symbol, 0 },
     169             :     { TOctetString, octetstring_symbol, 0 },
     170             :     { TPrintableString, printablestring_symbol, 0 },
     171             :     { TSequence, sequence_symbol, 1 },
     172             :     { TSequenceOf, tag_symbol, 1 },
     173             :     { TSetOf, tag_symbol, 1 },
     174             :     { TTag, tag_symbol, 1 },
     175             :     { TType, ttype_symbol, 1 },
     176             :     { TUTCTime, time_symbol, 0 },
     177             :     { TUniversalString, universalstring_symbol, 0 },
     178             :     { TVisibleString,  visiblestring_symbol, 0 },
     179             :     { TUTF8String, utf8string_symbol, 0 },
     180             :     { TChoice, sequence_symbol, 1 },
     181             :     { TNull, integer_symbol, 1 }
     182             : };
     183             : 
     184             : static FILE *
     185         810 : get_code_file(void)
     186             : {
     187         855 :     if (!one_code_file)
     188           0 :         return templatefile;
     189         855 :     return codefile;
     190             : }
     191             : 
     192             : 
     193             : static int
     194           0 : is_supported_type_p(const Type *t)
     195             : {
     196             :     size_t i;
     197             : 
     198           0 :     for (i = 0; i < sizeof(types)/sizeof(types[0]); i++)
     199           0 :         if (t->type == types[i].type)
     200           0 :             return 1;
     201           0 :     return 0;
     202             : }
     203             : 
     204             : int
     205           0 : is_template_compat (const Symbol *s)
     206             : {
     207           0 :     return is_supported_type_p(s->type);
     208             : }
     209             : 
     210             : static const char *
     211           0 : symbol_name(const char *basename, const Type *t)
     212             : {
     213             :     size_t i;
     214             : 
     215           0 :     for (i = 0; i < sizeof(types)/sizeof(types[0]); i++)
     216           0 :         if (t->type == types[i].type)
     217           0 :             return (types[i].symbol_name)(basename, t);
     218           0 :     printf("unknown der type: %d\n", t->type);
     219           0 :     exit(1);
     220             : }
     221             : 
     222             : 
     223             : static char *
     224           0 : partial_offset(const char *basetype, const char *name, int need_offset)
     225             : {
     226             :     char *str;
     227           0 :     if (name == NULL || need_offset == 0)
     228           0 :         return strdup("0");
     229           0 :     if (asprintf(&str, "offsetof(struct %s, %s)", basetype, name) < 0 || str == NULL)
     230           0 :         errx(1, "malloc");
     231           0 :     return str;
     232             : }
     233             : 
     234             : struct template {
     235             :     char *line;
     236             :     char *tt;
     237             :     char *offset;
     238             :     char *ptr;
     239             :     ASN1_TAILQ_ENTRY(template) members;
     240             : };
     241             : 
     242             : ASN1_TAILQ_HEAD(templatehead, template);
     243             : 
     244             : struct tlist {
     245             :     char *name;
     246             :     char *header;
     247             :     struct templatehead template;
     248             :     ASN1_TAILQ_ENTRY(tlist) tmembers;
     249             : };
     250             : 
     251             : ASN1_TAILQ_HEAD(tlisthead, tlist);
     252             : 
     253             : static void tlist_header(struct tlist *, const char *, ...) __attribute__((__format__(__printf__, 2, 3)));
     254             : static struct template *
     255             :     add_line(struct templatehead *, const char *, ...) __attribute__((__format__(__printf__, 2, 3)));
     256             : static int tlist_cmp(const struct tlist *, const struct tlist *);
     257             : 
     258             : static void add_line_pointer(struct templatehead *, const char *, const char *, const char *, ...)
     259             :     __attribute__((__format__(__printf__, 4, 5)));
     260             : 
     261             : 
     262             : static struct tlisthead tlistmaster = ASN1_TAILQ_HEAD_INITIALIZER(tlistmaster);
     263             : static unsigned long numdups = 0;
     264             : 
     265             : static struct tlist *
     266           0 : tlist_new(const char *name)
     267             : {
     268           0 :     struct tlist *tl = calloc(1, sizeof(*tl));
     269           0 :     tl->name = strdup(name);
     270           0 :     ASN1_TAILQ_INIT(&tl->template);
     271           0 :     return tl;
     272             : }
     273             : 
     274             : static void
     275           0 : tlist_header(struct tlist *t, const char *fmt, ...)
     276             : {
     277             :     va_list ap;
     278           0 :     va_start(ap, fmt);
     279           0 :     if (vasprintf(&t->header, fmt, ap) < 0 || t->header == NULL)
     280           0 :         errx(1, "malloc");
     281           0 :     va_end(ap);
     282           0 : }
     283             : 
     284             : static unsigned long
     285           0 : tlist_count(struct tlist *tl)
     286             : {
     287           0 :     unsigned int count = 0;
     288             :     struct template *q;
     289             : 
     290           0 :     ASN1_TAILQ_FOREACH(q, &tl->template, members) {
     291           0 :         count++;
     292             :     }
     293           0 :     return count;
     294             : }
     295             : 
     296             : static void
     297           0 : tlist_add(struct tlist *tl)
     298             : {
     299           0 :     ASN1_TAILQ_INSERT_TAIL(&tlistmaster, tl, tmembers);
     300           0 : }
     301             : 
     302             : static void
     303           0 : tlist_print(struct tlist *tl)
     304             : {
     305             :     struct template *q;
     306           0 :     unsigned int i = 1;
     307           0 :     FILE *f = get_code_file();
     308             : 
     309           0 :     fprintf(f, "static const struct asn1_template asn1_%s[] = {\n", tl->name);
     310           0 :     fprintf(f, "/* 0 */ %s,\n", tl->header);
     311           0 :     ASN1_TAILQ_FOREACH(q, &tl->template, members) {
     312           0 :         int last = (ASN1_TAILQ_LAST(&tl->template, templatehead) == q);
     313           0 :         fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");
     314             :     }
     315           0 :     fprintf(f, "};\n");
     316           0 : }
     317             : 
     318             : static struct tlist *
     319           0 : tlist_find_by_name(const char *name)
     320             : {
     321             :     struct tlist *ql;
     322           0 :     ASN1_TAILQ_FOREACH(ql, &tlistmaster, tmembers) {
     323           0 :         if (strcmp(ql->name, name) == 0)
     324           0 :             return ql;
     325             :     }
     326           0 :     return NULL;
     327             : }
     328             : 
     329             : static int
     330           0 : tlist_cmp_name(const char *tname, const char *qname)
     331             : {
     332           0 :     struct tlist *tl = tlist_find_by_name(tname);
     333           0 :     struct tlist *ql = tlist_find_by_name(qname);
     334           0 :     return tlist_cmp(tl, ql);
     335             : }
     336             : 
     337             : static int
     338           0 : tlist_cmp(const struct tlist *tl, const struct tlist *ql)
     339             : {
     340             :     int ret;
     341             :     struct template *t, *q;
     342             : 
     343           0 :     ret = strcmp(tl->header, ql->header);
     344           0 :     if (ret) return ret;
     345             : 
     346           0 :     q = ASN1_TAILQ_FIRST(&ql->template);
     347           0 :     ASN1_TAILQ_FOREACH(t, &tl->template, members) {
     348           0 :         if (q == NULL) return 1;
     349             : 
     350           0 :         if (t->ptr == NULL || q->ptr == NULL) {
     351           0 :             ret = strcmp(t->line, q->line);
     352           0 :             if (ret) return ret;
     353             :         } else {
     354           0 :             ret = strcmp(t->tt, q->tt);
     355           0 :             if (ret) return ret;
     356             : 
     357           0 :             ret = strcmp(t->offset, q->offset);
     358           0 :             if (ret) return ret;
     359             : 
     360           0 :             if ((ret = strcmp(t->ptr, q->ptr)) != 0 ||
     361           0 :                 (ret = tlist_cmp_name(t->ptr, q->ptr)) != 0)
     362           0 :                 return ret;
     363             :         }
     364           0 :         q = ASN1_TAILQ_NEXT(q, members);
     365             :     }
     366           0 :     if (q != NULL) return -1;
     367           0 :     return 0;
     368             : }
     369             : 
     370             : 
     371             : static const char *
     372           0 : tlist_find_dup(const struct tlist *tl)
     373             : {
     374             :     struct tlist *ql;
     375             : 
     376           0 :     ASN1_TAILQ_FOREACH(ql, &tlistmaster, tmembers) {
     377           0 :         if (tlist_cmp(ql, tl) == 0) {
     378           0 :             numdups++;
     379           0 :             return ql->name;
     380             :         }
     381             :     }
     382           0 :     return NULL;
     383             : }
     384             : 
     385             : 
     386             : /*
     387             :  *
     388             :  */
     389             : 
     390             : static struct template *
     391           0 : add_line(struct templatehead *t, const char *fmt, ...)
     392             : {
     393           0 :     struct template *q = calloc(1, sizeof(*q));
     394             :     va_list ap;
     395           0 :     va_start(ap, fmt);
     396           0 :     if (vasprintf(&q->line, fmt, ap) < 0 || q->line == NULL)
     397           0 :         errx(1, "malloc");
     398           0 :     va_end(ap);
     399           0 :     ASN1_TAILQ_INSERT_TAIL(t, q, members);
     400           0 :     return q;
     401             : }
     402             : 
     403             : static void
     404           0 : add_line_pointer(struct templatehead *t,
     405             :                  const char *ptr,
     406             :                  const char *offset,
     407             :                  const char *ttfmt,
     408             :                  ...)
     409             : {
     410             :     struct template *q;
     411             :     va_list ap;
     412           0 :     char *tt = NULL;
     413             : 
     414           0 :     va_start(ap, ttfmt);
     415           0 :     if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL)
     416           0 :         errx(1, "malloc");
     417           0 :     va_end(ap);
     418             : 
     419           0 :     q = add_line(t, "{ %s, %s, asn1_%s }", tt, offset, ptr);
     420           0 :     q->tt = tt;
     421           0 :     q->offset = strdup(offset);
     422           0 :     q->ptr = strdup(ptr);
     423           0 : }
     424             : 
     425             : static int
     426           0 : use_extern(const Symbol *s)
     427             : {
     428           0 :     if (s->type == NULL)
     429           0 :         return 1;
     430           0 :     return 0;
     431             : }
     432             : 
     433             : static int
     434           0 : is_struct(Type *t, int isstruct)
     435             : {
     436             :     size_t i;
     437             : 
     438           0 :     if (t->type == TType)
     439           0 :         return 0;
     440           0 :     if (t->type == TSequence || t->type == TSet || t->type == TChoice)
     441           0 :         return 1;
     442           0 :     if (t->type == TTag)
     443           0 :         return is_struct(t->subtype, isstruct);
     444             : 
     445           0 :     for (i = 0; i < sizeof(types)/sizeof(types[0]); i++) {
     446           0 :         if (t->type == types[i].type) {
     447           0 :             if (types[i].is_struct == 0)
     448           0 :                 return 0;
     449             :             else
     450           0 :                 break;
     451             :         }
     452             :     }
     453             : 
     454           0 :     return isstruct;
     455             : }
     456             : 
     457             : static const Type *
     458           0 : compact_tag(const Type *t)
     459             : {
     460           0 :     while (t->type == TTag)
     461           0 :         t = t->subtype;
     462           0 :     return t;
     463             : }
     464             : 
     465             : static void
     466           0 : template_members(struct templatehead *temp, const char *basetype, const char *name, const Type *t, int optional, int isstruct, int need_offset)
     467             : {
     468           0 :     char *poffset = NULL;
     469             : 
     470           0 :     if (optional && t->type != TTag && t->type != TType)
     471           0 :         errx(1, "%s...%s is optional and not a (TTag or TType)", basetype, name);
     472             : 
     473           0 :     poffset = partial_offset(basetype, name, need_offset);
     474             : 
     475           0 :     switch (t->type) {
     476           0 :     case TType:
     477           0 :         if (use_extern(t->symbol)) {
     478           0 :             add_line(temp, "{ A1_OP_TYPE_EXTERN %s, %s, &asn1_extern_%s}",
     479             :                      optional ? "|A1_FLAG_OPTIONAL" : "",
     480           0 :                      poffset, t->symbol->gen_name);
     481             :         } else {
     482           0 :             add_line_pointer(temp, t->symbol->gen_name, poffset,
     483             :                              "A1_OP_TYPE %s", optional ? "|A1_FLAG_OPTIONAL" : "");
     484             :         }
     485           0 :         break;
     486           0 :     case TInteger: {
     487           0 :         char *itype = NULL;
     488             : 
     489           0 :         if (t->members)
     490           0 :             itype = "IMEMBER";
     491           0 :         else if (t->range == NULL)
     492           0 :             itype = "HEIM_INTEGER";
     493           0 :         else if (t->range->min == INT_MIN && t->range->max == INT_MAX)
     494           0 :             itype = "INTEGER";
     495           0 :         else if (t->range->min == 0 && t->range->max == UINT_MAX)
     496           0 :             itype = "UNSIGNED";
     497           0 :         else if (t->range->min == 0 && t->range->max == INT_MAX)
     498           0 :             itype = "UNSIGNED";
     499             :         else
     500           0 :             errx(1, "%s: unsupported range %d -> %d",
     501           0 :                  name, t->range->min, t->range->max);
     502             : 
     503           0 :         add_line(temp, "{ A1_PARSE_T(A1T_%s), %s, NULL }", itype, poffset);
     504           0 :         break;
     505             :     }
     506           0 :     case TGeneralString:
     507           0 :         add_line(temp, "{ A1_PARSE_T(A1T_GENERAL_STRING), %s, NULL }", poffset);
     508           0 :         break;
     509           0 :     case TTeletexString:
     510           0 :         add_line(temp, "{ A1_PARSE_T(A1T_TELETEX_STRING), %s, NULL }", poffset);
     511           0 :         break;
     512           0 :     case TPrintableString:
     513           0 :         add_line(temp, "{ A1_PARSE_T(A1T_PRINTABLE_STRING), %s, NULL }", poffset);
     514           0 :         break;
     515           0 :     case TOctetString:
     516           0 :         add_line(temp, "{ A1_PARSE_T(A1T_OCTET_STRING), %s, NULL }", poffset);
     517           0 :         break;
     518           0 :     case TIA5String:
     519           0 :         add_line(temp, "{ A1_PARSE_T(A1T_IA5_STRING), %s, NULL }", poffset);
     520           0 :         break;
     521           0 :     case TBMPString:
     522           0 :         add_line(temp, "{ A1_PARSE_T(A1T_BMP_STRING), %s, NULL }", poffset);
     523           0 :         break;
     524           0 :     case TUniversalString:
     525           0 :         add_line(temp, "{ A1_PARSE_T(A1T_UNIVERSAL_STRING), %s, NULL }", poffset);
     526           0 :         break;
     527           0 :     case TVisibleString:
     528           0 :         add_line(temp, "{ A1_PARSE_T(A1T_VISIBLE_STRING), %s, NULL }", poffset);
     529           0 :         break;
     530           0 :     case TUTF8String:
     531           0 :         add_line(temp, "{ A1_PARSE_T(A1T_UTF8_STRING), %s, NULL }", poffset);
     532           0 :         break;
     533           0 :     case TGeneralizedTime:
     534           0 :         add_line(temp, "{ A1_PARSE_T(A1T_GENERALIZED_TIME), %s, NULL }", poffset);
     535           0 :         break;
     536           0 :     case TUTCTime:
     537           0 :         add_line(temp, "{ A1_PARSE_T(A1T_UTC_TIME), %s, NULL }", poffset);
     538           0 :         break;
     539           0 :     case TBoolean:
     540           0 :         add_line(temp, "{ A1_PARSE_T(A1T_BOOLEAN), %s, NULL }", poffset);
     541           0 :         break;
     542           0 :     case TOID:
     543           0 :         add_line(temp, "{ A1_PARSE_T(A1T_OID), %s, NULL }", poffset);
     544           0 :         break;
     545           0 :     case TNull:
     546           0 :         break;
     547           0 :     case TBitString: {
     548             :         struct templatehead template;
     549             :         struct template *q;
     550             :         Member *m;
     551           0 :         size_t count = 0, i;
     552           0 :         char *bname = NULL;
     553           0 :         FILE *f = get_code_file();
     554             : 
     555           0 :         ASN1_TAILQ_INIT(&template);
     556             : 
     557           0 :         if (ASN1_TAILQ_EMPTY(t->members)) {
     558           0 :             add_line(temp, "{ A1_PARSE_T(A1T_HEIM_BIT_STRING), %s, NULL }", poffset);
     559           0 :             break;
     560             :         }
     561             : 
     562           0 :         if (asprintf(&bname, "bmember_%s_%p", name ? name : "", t) < 0 || bname == NULL)
     563           0 :             errx(1, "malloc");
     564           0 :         output_name(bname);
     565             : 
     566           0 :         ASN1_TAILQ_FOREACH(m, t->members, members) {
     567           0 :             add_line(&template, "{ 0, %d, 0 } /* %s */", m->val, m->gen_name);
     568             :         }
     569             : 
     570           0 :         ASN1_TAILQ_FOREACH(q, &template, members) {
     571           0 :             count++;
     572             :         }
     573             : 
     574           0 :         fprintf(f, "static const struct asn1_template asn1_%s_%s[] = {\n", basetype, bname);
     575           0 :         fprintf(f, "/* 0 */ { 0%s, sizeof(%s), ((void *)%lu) },\n",
     576           0 :                 rfc1510_bitstring ? "|A1_HBF_RFC1510" : "",
     577             :                 basetype, (unsigned long)count);
     578           0 :         i = 1;
     579           0 :         ASN1_TAILQ_FOREACH(q, &template, members) {
     580           0 :             int last = (ASN1_TAILQ_LAST(&template, templatehead) == q);
     581           0 :             fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");
     582             :         }
     583           0 :         fprintf(f, "};\n");
     584             : 
     585           0 :         add_line(temp, "{ A1_OP_BMEMBER, %s, asn1_%s_%s }", poffset, basetype, bname);
     586             : 
     587           0 :         free(bname);
     588             : 
     589           0 :         break;
     590             :     }
     591           0 :     case TSequence: {
     592             :         Member *m;
     593             : 
     594           0 :         ASN1_TAILQ_FOREACH(m, t->members, members) {
     595           0 :             char *newbasename = NULL;
     596             : 
     597           0 :             if (m->ellipsis)
     598           0 :                 continue;
     599             : 
     600           0 :             if (name) {
     601           0 :                 if (asprintf(&newbasename, "%s_%s", basetype, name) < 0)
     602           0 :                     errx(1, "malloc");
     603             :             } else
     604           0 :                 newbasename = strdup(basetype);
     605           0 :             if (newbasename == NULL)
     606           0 :                 errx(1, "malloc");
     607             : 
     608           0 :             template_members(temp, newbasename, m->gen_name, m->type, m->optional, isstruct, 1);
     609             : 
     610           0 :             free(newbasename);
     611             :         }
     612             : 
     613           0 :         break;
     614             :     }
     615           0 :     case TTag: {
     616           0 :         char *tname = NULL, *elname = NULL;
     617             :         const char *sename, *dupname;
     618           0 :         int subtype_is_struct = is_struct(t->subtype, isstruct);
     619             : 
     620           0 :         if (subtype_is_struct)
     621           0 :             sename = basetype;
     622             :         else
     623           0 :             sename = symbol_name(basetype, t->subtype);
     624             : 
     625           0 :         if (asprintf(&tname, "tag_%s_%p", name ? name : "", t) < 0 || tname == NULL)
     626           0 :             errx(1, "malloc");
     627           0 :         output_name(tname);
     628             : 
     629           0 :         if (asprintf(&elname, "%s_%s", basetype, tname) < 0 || elname == NULL)
     630           0 :             errx(1, "malloc");
     631             : 
     632           0 :         generate_template_type(elname, &dupname, NULL, sename, name,
     633           0 :                                t->subtype, 0, subtype_is_struct, 0);
     634             : 
     635           0 :         add_line_pointer(temp, dupname, poffset,
     636             :                          "A1_TAG_T(%s,%s,%s)%s",
     637           0 :                          classname(t->tag.tagclass),
     638           0 :                          is_primitive_type(t->subtype->type)  ? "PRIM" : "CONS",
     639           0 :                          valuename(t->tag.tagclass, t->tag.tagvalue),
     640             :                          optional ? "|A1_FLAG_OPTIONAL" : "");
     641             : 
     642           0 :         free(tname);
     643           0 :         free(elname);
     644             : 
     645           0 :         break;
     646             :     }
     647           0 :     case TSetOf:
     648             :     case TSequenceOf: {
     649           0 :         const char *type = NULL, *tname, *dupname;
     650           0 :         char *sename = NULL, *elname = NULL;
     651           0 :         int subtype_is_struct = is_struct(t->subtype, 0);
     652             : 
     653           0 :         if (name && subtype_is_struct) {
     654           0 :             tname = "seofTstruct";
     655           0 :             if (asprintf(&sename, "%s_%s_val", basetype, name) < 0)
     656           0 :                 errx(1, "malloc");
     657           0 :         } else if (subtype_is_struct) {
     658           0 :             tname = "seofTstruct";
     659           0 :             if (asprintf(&sename, "%s_val", symbol_name(basetype, t->subtype)) < 0)
     660           0 :                 errx(1, "malloc");
     661             :         } else {
     662           0 :             if (name)
     663           0 :                 tname = name;
     664             :             else
     665           0 :                 tname = "seofTstruct";
     666           0 :             sename = strdup(symbol_name(basetype, t->subtype));
     667             :         }
     668           0 :         if (sename == NULL)
     669           0 :             errx(1, "malloc");
     670             : 
     671           0 :         if (t->type == TSetOf) type = "A1_OP_SETOF";
     672           0 :         else if (t->type == TSequenceOf) type = "A1_OP_SEQOF";
     673           0 :         else abort();
     674             : 
     675           0 :         if (asprintf(&elname, "%s_%s_%p", basetype, tname, t) < 0 || elname == NULL)
     676           0 :             errx(1, "malloc");
     677             : 
     678           0 :         generate_template_type(elname, &dupname, NULL, sename, NULL, t->subtype,
     679             :                                0, subtype_is_struct, need_offset);
     680             : 
     681           0 :         add_line(temp, "{ %s, %s, asn1_%s }", type, poffset, dupname);
     682           0 :         free(sename);
     683           0 :         break;
     684             :     }
     685           0 :     case TChoice: {
     686             :         struct templatehead template;
     687             :         struct template *q;
     688           0 :         size_t count = 0, i;
     689           0 :         char *tname = NULL;
     690           0 :         FILE *f = get_code_file();
     691             :         Member *m;
     692           0 :         int ellipsis = 0;
     693             :         char *e;
     694             : 
     695           0 :         ASN1_TAILQ_INIT(&template);
     696             : 
     697           0 :         if (asprintf(&tname, "asn1_choice_%s_%s%x",
     698           0 :                      basetype, name ? name : "", (unsigned int)(uintptr_t)t) < 0 || tname == NULL)
     699           0 :             errx(1, "malloc");
     700             : 
     701           0 :         ASN1_TAILQ_FOREACH(m, t->members, members) {
     702             :             const char *dupname;
     703           0 :             char *elname = NULL;
     704           0 :             char *newbasename = NULL;
     705             :             int subtype_is_struct;
     706             : 
     707           0 :             if (m->ellipsis) {
     708           0 :                 ellipsis = 1;
     709           0 :                 continue;
     710             :             }
     711             : 
     712           0 :             subtype_is_struct = is_struct(m->type, 0);
     713             : 
     714           0 :             if (asprintf(&elname, "%s_choice_%s", basetype, m->gen_name) < 0 || elname == NULL)
     715           0 :                 errx(1, "malloc");
     716             : 
     717           0 :             if (subtype_is_struct) {
     718           0 :                 if (asprintf(&newbasename, "%s_%s", basetype, m->gen_name) < 0)
     719           0 :                     errx(1, "malloc");
     720             :             } else
     721           0 :                 newbasename = strdup(basetype);
     722             : 
     723           0 :             if (newbasename == NULL)
     724           0 :                 errx(1, "malloc");
     725             : 
     726             : 
     727           0 :             generate_template_type(elname, &dupname, NULL,
     728           0 :                                    symbol_name(newbasename, m->type),
     729           0 :                                    NULL, m->type, 0, subtype_is_struct, 1);
     730             : 
     731           0 :             add_line(&template, "{ %s, offsetof(%s%s, u.%s), asn1_%s }",
     732             :                      m->label, isstruct ? "struct " : "",
     733             :                      basetype, m->gen_name,
     734             :                      dupname);
     735             : 
     736           0 :             free(elname);
     737           0 :             free(newbasename);
     738             :         }
     739             : 
     740           0 :         e = NULL;
     741           0 :         if (ellipsis) {
     742           0 :             if (asprintf(&e, "offsetof(%s%s, u.asn1_ellipsis)", isstruct ? "struct " : "", basetype) < 0 || e == NULL)
     743           0 :                 errx(1, "malloc");
     744             :         }
     745             : 
     746           0 :         ASN1_TAILQ_FOREACH(q, &template, members) {
     747           0 :             count++;
     748             :         }
     749             : 
     750           0 :         fprintf(f, "static const struct asn1_template %s[] = {\n", tname);
     751           0 :         fprintf(f, "/* 0 */ { %s, offsetof(%s%s, element), ((void *)%lu) },\n",
     752           0 :                 e ? e : "0", isstruct ? "struct " : "", basetype, (unsigned long)count);
     753           0 :         i = 1;
     754           0 :         ASN1_TAILQ_FOREACH(q, &template, members) {
     755           0 :             int last = (ASN1_TAILQ_LAST(&template, templatehead) == q);
     756           0 :             fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");
     757             :         }
     758           0 :         fprintf(f, "};\n");
     759             : 
     760           0 :         add_line(temp, "{ A1_OP_CHOICE, %s, %s }", poffset, tname);
     761             : 
     762           0 :         free(e);
     763           0 :         free(tname);
     764           0 :         break;
     765             :     }
     766           0 :     default:
     767           0 :         abort ();
     768             :     }
     769           0 :     if (poffset)
     770           0 :         free(poffset);
     771           0 : }
     772             : 
     773             : static void
     774           0 : gen_extern_stubs(FILE *f, const char *name)
     775             : {
     776           0 :     fprintf(f,
     777             :             "static const struct asn1_type_func asn1_extern_%s = {\n"
     778             :             "\t(asn1_type_encode)encode_%s,\n"
     779             :             "\t(asn1_type_decode)decode_%s,\n"
     780             :             "\t(asn1_type_length)length_%s,\n"
     781             :             "\t(asn1_type_copy)copy_%s,\n"
     782             :             "\t(asn1_type_release)free_%s,\n"
     783             :             "\tsizeof(%s)\n"
     784             :             "};\n",
     785             :             name, name, name, name,
     786             :             name, name, name);
     787           0 : }
     788             : 
     789             : void
     790         855 : gen_template_import(const Symbol *s)
     791             : {
     792         855 :     FILE *f = get_code_file();
     793             : 
     794         855 :     if (template_flag == 0)
     795         810 :         return;
     796             : 
     797           0 :     gen_extern_stubs(f, s->gen_name);
     798             : }
     799             : 
     800             : static void
     801           0 : generate_template_type(const char *varname,
     802             :                        const char **dupname,
     803             :                        const char *symname,
     804             :                        const char *basetype,
     805             :                        const char *name,
     806             :                        Type *type,
     807             :                        int optional, int isstruct, int need_offset)
     808             : {
     809             :     struct tlist *tl;
     810             :     const char *dup;
     811           0 :     int have_ellipsis = 0;
     812             : 
     813           0 :     tl = tlist_new(varname);
     814             : 
     815           0 :     template_members(&tl->template, basetype, name, type, optional, isstruct, need_offset);
     816             : 
     817             :     /* if its a sequence or set type, check if there is a ellipsis */
     818           0 :     if (type->type == TSequence || type->type == TSet) {
     819             :         Member *m;
     820           0 :         ASN1_TAILQ_FOREACH(m, type->members, members) {
     821           0 :             if (m->ellipsis)
     822           0 :                 have_ellipsis = 1;
     823             :         }
     824             :     }
     825             : 
     826           0 :     if (ASN1_TAILQ_EMPTY(&tl->template) && compact_tag(type)->type != TNull)
     827           0 :         errx(1, "Tag %s...%s with no content ?", basetype, name ? name : "");
     828             : 
     829           0 :     tlist_header(tl, "{ 0%s%s, sizeof(%s%s), ((void *)%lu) }",
     830           0 :                  (symname && preserve_type(symname)) ? "|A1_HF_PRESERVE" : "",
     831             :                  have_ellipsis ? "|A1_HF_ELLIPSIS" : "",
     832             :                  isstruct ? "struct " : "", basetype, tlist_count(tl));
     833             : 
     834           0 :     dup = tlist_find_dup(tl);
     835           0 :     if (dup) {
     836           0 :         if (strcmp(dup, tl->name) == 0)
     837           0 :             errx(1, "found dup of ourself");
     838           0 :         *dupname = dup;
     839             :     } else {
     840           0 :         *dupname = tl->name;
     841           0 :         tlist_print(tl);
     842           0 :         tlist_add(tl);
     843             :     }
     844           0 : }
     845             : 
     846             : 
     847             : void
     848           0 : generate_template(const Symbol *s)
     849             : {
     850           0 :     FILE *f = get_code_file();
     851             :     const char *dupname;
     852             : 
     853           0 :     if (use_extern(s)) {
     854           0 :         gen_extern_stubs(f, s->gen_name);
     855           0 :         return;
     856             :     }
     857             : 
     858           0 :     generate_template_type(s->gen_name, &dupname, s->name, s->gen_name, NULL, s->type, 0, 0, 1);
     859             : 
     860           0 :     fprintf(f,
     861             :             "\n"
     862             :             "int\n"
     863             :             "decode_%s(const unsigned char *p, size_t len, %s *data, size_t *size)\n"
     864             :             "{\n"
     865             :             "    return _asn1_decode_top(asn1_%s, 0|%s, p, len, data, size);\n"
     866             :             "}\n"
     867             :             "\n",
     868             :             s->gen_name,
     869             :             s->gen_name,
     870             :             dupname,
     871           0 :             support_ber ? "A1_PF_ALLOW_BER" : "0");
     872             : 
     873           0 :     fprintf(f,
     874             :             "\n"
     875             :             "int\n"
     876             :             "encode_%s(unsigned char *p, size_t len, const %s *data, size_t *size)\n"
     877             :             "{\n"
     878             :             "    return _asn1_encode(asn1_%s, p, len, data, size);\n"
     879             :             "}\n"
     880             :             "\n",
     881             :             s->gen_name,
     882             :             s->gen_name,
     883             :             dupname);
     884             : 
     885           0 :     fprintf(f,
     886             :             "\n"
     887             :             "size_t\n"
     888             :             "length_%s(const %s *data)\n"
     889             :             "{\n"
     890             :             "    return _asn1_length(asn1_%s, data);\n"
     891             :             "}\n"
     892             :             "\n",
     893             :             s->gen_name,
     894             :             s->gen_name,
     895             :             dupname);
     896             : 
     897             : 
     898           0 :     fprintf(f,
     899             :             "\n"
     900             :             "void\n"
     901             :             "free_%s(%s *data)\n"
     902             :             "{\n"
     903             :             "    _asn1_free(asn1_%s, data);\n"
     904             :             "}\n"
     905             :             "\n",
     906             :             s->gen_name,
     907             :             s->gen_name,
     908             :             dupname);
     909             : 
     910           0 :     fprintf(f,
     911             :             "\n"
     912             :             "int\n"
     913             :             "copy_%s(const %s *from, %s *to)\n"
     914             :             "{\n"
     915             :             "    return _asn1_copy_top(asn1_%s, from, to);\n"
     916             :             "}\n"
     917             :             "\n",
     918             :             s->gen_name,
     919             :             s->gen_name,
     920             :             s->gen_name,
     921             :             dupname);
     922             : }

Generated by: LCOV version 1.13