LTP GCOV extension - code coverage report
Current view: directory - lib/asn1 - gen_template.c
Test: samba_4_0_test.lcov.info
Date: 2010-08-06 Instrumented lines: 353
Code covered: 2.0 % Executed lines: 7

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

Generated by: LTP GCOV extension version 1.6