LCOV - code coverage report
Current view: top level - lib/asn1 - gen_template.c (source / functions) Hit Total Coverage
Test: samba_4_0_test.lcov.info Lines: 8 398 2.0 %
Date: 2014-04-02 Functions: 2 40 5.0 %
Branches: 2 294 0.7 %

           Branch data     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                 :         45 : get_code_file(void)
     186                 :            : {
     187         [ -  + ]:         45 :     if (!one_code_file)
     188                 :          0 :         return templatefile;
     189                 :         45 :     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                 :            :     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                 :            :     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                 :            :     case TGeneralString:
     507                 :          0 :         add_line(temp, "{ A1_PARSE_T(A1T_GENERAL_STRING), %s, NULL }", poffset);
     508                 :          0 :         break;
     509                 :            :     case TTeletexString:
     510                 :          0 :         add_line(temp, "{ A1_PARSE_T(A1T_TELETEX_STRING), %s, NULL }", poffset);
     511                 :          0 :         break;
     512                 :            :     case TPrintableString:
     513                 :          0 :         add_line(temp, "{ A1_PARSE_T(A1T_PRINTABLE_STRING), %s, NULL }", poffset);
     514                 :          0 :         break;
     515                 :            :     case TOctetString:
     516                 :          0 :         add_line(temp, "{ A1_PARSE_T(A1T_OCTET_STRING), %s, NULL }", poffset);
     517                 :          0 :         break;
     518                 :            :     case TIA5String:
     519                 :          0 :         add_line(temp, "{ A1_PARSE_T(A1T_IA5_STRING), %s, NULL }", poffset);
     520                 :          0 :         break;
     521                 :            :     case TBMPString:
     522                 :          0 :         add_line(temp, "{ A1_PARSE_T(A1T_BMP_STRING), %s, NULL }", poffset);
     523                 :          0 :         break;
     524                 :            :     case TUniversalString:
     525                 :          0 :         add_line(temp, "{ A1_PARSE_T(A1T_UNIVERSAL_STRING), %s, NULL }", poffset);
     526                 :          0 :         break;
     527                 :            :     case TVisibleString:
     528                 :          0 :         add_line(temp, "{ A1_PARSE_T(A1T_VISIBLE_STRING), %s, NULL }", poffset);
     529                 :          0 :         break;
     530                 :            :     case TUTF8String:
     531                 :          0 :         add_line(temp, "{ A1_PARSE_T(A1T_UTF8_STRING), %s, NULL }", poffset);
     532                 :          0 :         break;
     533                 :            :     case TGeneralizedTime:
     534                 :          0 :         add_line(temp, "{ A1_PARSE_T(A1T_GENERALIZED_TIME), %s, NULL }", poffset);
     535                 :          0 :         break;
     536                 :            :     case TUTCTime:
     537                 :          0 :         add_line(temp, "{ A1_PARSE_T(A1T_UTC_TIME), %s, NULL }", poffset);
     538                 :          0 :         break;
     539                 :            :     case TBoolean:
     540                 :          0 :         add_line(temp, "{ A1_PARSE_T(A1T_BOOLEAN), %s, NULL }", poffset);
     541                 :          0 :         break;
     542                 :            :     case TOID:
     543                 :          0 :         add_line(temp, "{ A1_PARSE_T(A1T_OID), %s, NULL }", poffset);
     544                 :          0 :         break;
     545                 :            :     case TNull:
     546                 :          0 :         break;
     547                 :            :     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                 :            :     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                 :            :     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                 :            :     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                 :            :     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                 :            :     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                 :         45 : gen_template_import(const Symbol *s)
     791                 :            : {
     792                 :         45 :     FILE *f = get_code_file();
     793                 :            : 
     794         [ +  - ]:         45 :     if (template_flag == 0)
     795                 :         45 :         return;
     796                 :            : 
     797                 :         45 :     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.9