root/source4/heimdal/lib/asn1/gen_decode.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. decode_primitive
  2. is_primitive_type
  3. find_tag
  4. range_check
  5. decode_type
  6. generate_type_decode

   1 /*
   2  * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
   3  * (Royal Institute of Technology, Stockholm, Sweden).
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  *
  13  * 2. Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in the
  15  *    documentation and/or other materials provided with the distribution.
  16  *
  17  * 3. Neither the name of the Institute nor the names of its contributors
  18  *    may be used to endorse or promote products derived from this software
  19  *    without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31  * SUCH DAMAGE.
  32  */
  33 
  34 #include "gen_locl.h"
  35 #include "lex.h"
  36 
  37 RCSID("$Id$");
  38 
  39 static void
  40 decode_primitive (const char *typename, const char *name, const char *forwstr)
     /* [<][>][^][v][top][bottom][index][help] */
  41 {
  42 #if 0
  43     fprintf (codefile,
  44              "e = decode_%s(p, len, %s, &l);\n"
  45              "%s;\n",
  46              typename,
  47              name,
  48              forwstr);
  49 #else
  50     fprintf (codefile,
  51              "e = der_get_%s(p, len, %s, &l);\n"
  52              "if(e) %s;\np += l; len -= l; ret += l;\n",
  53              typename,
  54              name,
  55              forwstr);
  56 #endif
  57 }
  58 
  59 static int
  60 is_primitive_type(int type)
     /* [<][>][^][v][top][bottom][index][help] */
  61 {
  62     switch(type) {
  63     case TInteger:
  64     case TBoolean:
  65     case TOctetString:
  66     case TBitString:
  67     case TEnumerated:
  68     case TGeneralizedTime:
  69     case TGeneralString:
  70     case TOID:
  71     case TUTCTime:
  72     case TUTF8String:
  73     case TPrintableString:
  74     case TIA5String:
  75     case TBMPString:
  76     case TUniversalString:
  77     case TVisibleString:
  78     case TNull:
  79         return 1;
  80     default:
  81         return 0;
  82     }
  83 }
  84 
  85 static void
  86 find_tag (const Type *t,
     /* [<][>][^][v][top][bottom][index][help] */
  87           Der_class *cl, Der_type *ty, unsigned *tag)
  88 {
  89     switch (t->type) {
  90     case TBitString:
  91         *cl  = ASN1_C_UNIV;
  92         *ty  = PRIM;
  93         *tag = UT_BitString;
  94         break;
  95     case TBoolean:
  96         *cl  = ASN1_C_UNIV;
  97         *ty  = PRIM;
  98         *tag = UT_Boolean;
  99         break;
 100     case TChoice:
 101         errx(1, "Cannot have recursive CHOICE");
 102     case TEnumerated:
 103         *cl  = ASN1_C_UNIV;
 104         *ty  = PRIM;
 105         *tag = UT_Enumerated;
 106         break;
 107     case TGeneralString:
 108         *cl  = ASN1_C_UNIV;
 109         *ty  = PRIM;
 110         *tag = UT_GeneralString;
 111         break;
 112     case TGeneralizedTime:
 113         *cl  = ASN1_C_UNIV;
 114         *ty  = PRIM;
 115         *tag = UT_GeneralizedTime;
 116         break;
 117     case TIA5String:
 118         *cl  = ASN1_C_UNIV;
 119         *ty  = PRIM;
 120         *tag = UT_IA5String;
 121         break;
 122     case TInteger:
 123         *cl  = ASN1_C_UNIV;
 124         *ty  = PRIM;
 125         *tag = UT_Integer;
 126         break;
 127     case TNull:
 128         *cl  = ASN1_C_UNIV;
 129         *ty  = PRIM;
 130         *tag = UT_Null;
 131         break;
 132     case TOID:
 133         *cl  = ASN1_C_UNIV;
 134         *ty  = PRIM;
 135         *tag = UT_OID;
 136         break;
 137     case TOctetString:
 138         *cl  = ASN1_C_UNIV;
 139         *ty  = PRIM;
 140         *tag = UT_OctetString;
 141         break;
 142     case TPrintableString:
 143         *cl  = ASN1_C_UNIV;
 144         *ty  = PRIM;
 145         *tag = UT_PrintableString;
 146         break;
 147     case TSequence:
 148     case TSequenceOf:
 149         *cl  = ASN1_C_UNIV;
 150         *ty  = CONS;
 151         *tag = UT_Sequence;
 152         break;
 153     case TSet:
 154     case TSetOf:
 155         *cl  = ASN1_C_UNIV;
 156         *ty  = CONS;
 157         *tag = UT_Set;
 158         break;
 159     case TTag:
 160         *cl  = t->tag.tagclass;
 161         *ty  = is_primitive_type(t->subtype->type) ? PRIM : CONS;
 162         *tag = t->tag.tagvalue;
 163         break;
 164     case TType:
 165         if ((t->symbol->stype == Stype && t->symbol->type == NULL)
 166             || t->symbol->stype == SUndefined) {
 167             error_message("%s is imported or still undefined, "
 168                           " can't generate tag checking data in CHOICE "
 169                           "without this information",
 170                           t->symbol->name);
 171             exit(1);
 172         }
 173         find_tag(t->symbol->type, cl, ty, tag);
 174         return;
 175     case TUTCTime:
 176         *cl  = ASN1_C_UNIV;
 177         *ty  = PRIM;
 178         *tag = UT_UTCTime;
 179         break;
 180     case TUTF8String:
 181         *cl  = ASN1_C_UNIV;
 182         *ty  = PRIM;
 183         *tag = UT_UTF8String;
 184         break;
 185     case TBMPString:
 186         *cl  = ASN1_C_UNIV;
 187         *ty  = PRIM;
 188         *tag = UT_BMPString;
 189         break;
 190     case TUniversalString:
 191         *cl  = ASN1_C_UNIV;
 192         *ty  = PRIM;
 193         *tag = UT_UniversalString;
 194         break;
 195     case TVisibleString:
 196         *cl  = ASN1_C_UNIV;
 197         *ty  = PRIM;
 198         *tag = UT_VisibleString;
 199         break;
 200     default:
 201         abort();
 202     }
 203 }
 204 
 205 static void
 206 range_check(const char *name,
     /* [<][>][^][v][top][bottom][index][help] */
 207             const char *length,
 208             const char *forwstr,
 209             struct range *r)
 210 {
 211     if (r->min == r->max + 2 || r->min < r->max)
 212         fprintf (codefile,
 213                  "if ((%s)->%s > %d) {\n"
 214                  "e = ASN1_MAX_CONSTRAINT; %s;\n"
 215                  "}\n",
 216                  name, length, r->max, forwstr);
 217     if (r->min - 1 == r->max || r->min < r->max)
 218         fprintf (codefile,
 219                  "if ((%s)->%s < %d) {\n"
 220                  "e = ASN1_MIN_CONSTRAINT; %s;\n"
 221                  "}\n",
 222                  name, length, r->min, forwstr);
 223     if (r->max == r->min)
 224         fprintf (codefile,
 225                  "if ((%s)->%s != %d) {\n"
 226                  "e = ASN1_EXACT_CONSTRAINT; %s;\n"
 227                  "}\n",
 228                  name, length, r->min, forwstr);
 229 }
 230 
 231 static int
 232 decode_type (const char *name, const Type *t, int optional,
     /* [<][>][^][v][top][bottom][index][help] */
 233              const char *forwstr, const char *tmpstr)
 234 {
 235     switch (t->type) {
 236     case TType: {
 237         if (optional)
 238             fprintf(codefile,
 239                     "%s = calloc(1, sizeof(*%s));\n"
 240                     "if (%s == NULL) %s;\n",
 241                     name, name, name, forwstr);
 242         fprintf (codefile,
 243                  "e = decode_%s(p, len, %s, &l);\n",
 244                  t->symbol->gen_name, name);
 245         if (optional) {
 246             fprintf (codefile,
 247                      "if(e) {\n"
 248                      "free(%s);\n"
 249                      "%s = NULL;\n"
 250                      "} else {\n"
 251                      "p += l; len -= l; ret += l;\n"
 252                      "}\n",
 253                      name, name);
 254         } else {
 255             fprintf (codefile,
 256                      "if(e) %s;\n",
 257                      forwstr);
 258             fprintf (codefile,
 259                      "p += l; len -= l; ret += l;\n");
 260         }
 261         break;
 262     }
 263     case TInteger:
 264         if(t->members) {
 265             fprintf(codefile,
 266                     "{\n"
 267                     "int enumint;\n");
 268             decode_primitive ("integer", "&enumint", forwstr);
 269             fprintf(codefile,
 270                     "*%s = enumint;\n"
 271                     "}\n",
 272                     name);
 273         } else if (t->range == NULL) {
 274             decode_primitive ("heim_integer", name, forwstr);
 275         } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
 276             decode_primitive ("integer", name, forwstr);
 277         } else if (t->range->min == 0 && t->range->max == UINT_MAX) {
 278             decode_primitive ("unsigned", name, forwstr);
 279         } else if (t->range->min == 0 && t->range->max == INT_MAX) {
 280             decode_primitive ("unsigned", name, forwstr);
 281         } else
 282             errx(1, "%s: unsupported range %d -> %d",
 283                  name, t->range->min, t->range->max);
 284         break;
 285     case TBoolean:
 286       decode_primitive ("boolean", name, forwstr);
 287       break;
 288     case TEnumerated:
 289         decode_primitive ("enumerated", name, forwstr);
 290         break;
 291     case TOctetString:
 292         decode_primitive ("octet_string", name, forwstr);
 293         if (t->range)
 294             range_check(name, "length", forwstr, t->range);
 295         break;
 296     case TBitString: {
 297         Member *m;
 298         int pos = 0;
 299 
 300         if (ASN1_TAILQ_EMPTY(t->members)) {
 301             decode_primitive ("bit_string", name, forwstr);
 302             break;
 303         }
 304         fprintf(codefile,
 305                 "if (len < 1) return ASN1_OVERRUN;\n"
 306                 "p++; len--; ret++;\n");
 307         fprintf(codefile,
 308                 "do {\n"
 309                 "if (len < 1) break;\n");
 310         ASN1_TAILQ_FOREACH(m, t->members, members) {
 311             while (m->val / 8 > pos / 8) {
 312                 fprintf (codefile,
 313                          "p++; len--; ret++;\n"
 314                          "if (len < 1) break;\n");
 315                 pos += 8;
 316             }
 317             fprintf (codefile,
 318                      "(%s)->%s = (*p >> %d) & 1;\n",
 319                      name, m->gen_name, 7 - m->val % 8);
 320         }
 321         fprintf(codefile,
 322                 "} while(0);\n");
 323         fprintf (codefile,
 324                  "p += len; ret += len;\n");
 325         break;
 326     }
 327     case TSequence: {
 328         Member *m;
 329 
 330         if (t->members == NULL)
 331             break;
 332 
 333         ASN1_TAILQ_FOREACH(m, t->members, members) {
 334             char *s;
 335 
 336             if (m->ellipsis)
 337                 continue;
 338 
 339             asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&",
 340                       name, m->gen_name);
 341             if (s == NULL)
 342                 errx(1, "malloc");
 343             decode_type (s, m->type, m->optional, forwstr, m->gen_name);
 344             free (s);
 345         }
 346         
 347         break;
 348     }
 349     case TSet: {
 350         Member *m;
 351         unsigned int memno;
 352 
 353         if(t->members == NULL)
 354             break;
 355 
 356         fprintf(codefile, "{\n");
 357         fprintf(codefile, "unsigned int members = 0;\n");
 358         fprintf(codefile, "while(len > 0) {\n");
 359         fprintf(codefile,
 360                 "Der_class class;\n"
 361                 "Der_type type;\n"
 362                 "int tag;\n"
 363                 "e = der_get_tag (p, len, &class, &type, &tag, NULL);\n"
 364                 "if(e) %s;\n", forwstr);
 365         fprintf(codefile, "switch (MAKE_TAG(class, type, tag)) {\n");
 366         memno = 0;
 367         ASN1_TAILQ_FOREACH(m, t->members, members) {
 368             char *s;
 369 
 370             assert(m->type->type == TTag);
 371 
 372             fprintf(codefile, "case MAKE_TAG(%s, %s, %s):\n",
 373                     classname(m->type->tag.tagclass),
 374                     is_primitive_type(m->type->subtype->type) ? "PRIM" : "CONS",
 375                     valuename(m->type->tag.tagclass, m->type->tag.tagvalue));
 376 
 377             asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name);
 378             if (s == NULL)
 379                 errx(1, "malloc");
 380             if(m->optional)
 381                 fprintf(codefile,
 382                         "%s = calloc(1, sizeof(*%s));\n"
 383                         "if (%s == NULL) { e = ENOMEM; %s; }\n",
 384                         s, s, s, forwstr);
 385             decode_type (s, m->type, 0, forwstr, m->gen_name);
 386             free (s);
 387 
 388             fprintf(codefile, "members |= (1 << %d);\n", memno);
 389             memno++;
 390             fprintf(codefile, "break;\n");
 391         }
 392         fprintf(codefile,
 393                 "default:\n"
 394                 "return ASN1_MISPLACED_FIELD;\n"
 395                 "break;\n");
 396         fprintf(codefile, "}\n");
 397         fprintf(codefile, "}\n");
 398         memno = 0;
 399         ASN1_TAILQ_FOREACH(m, t->members, members) {
 400             char *s;
 401 
 402             asprintf (&s, "%s->%s", name, m->gen_name);
 403             if (s == NULL)
 404                 errx(1, "malloc");
 405             fprintf(codefile, "if((members & (1 << %d)) == 0)\n", memno);
 406             if(m->optional)
 407                 fprintf(codefile, "%s = NULL;\n", s);
 408             else if(m->defval)
 409                 gen_assign_defval(s, m->defval);
 410             else
 411                 fprintf(codefile, "return ASN1_MISSING_FIELD;\n");
 412             free(s);
 413             memno++;
 414         }
 415         fprintf(codefile, "}\n");
 416         break;
 417     }
 418     case TSetOf:
 419     case TSequenceOf: {
 420         char *n;
 421         char *sname;
 422 
 423         fprintf (codefile,
 424                  "{\n"
 425                  "size_t %s_origlen = len;\n"
 426                  "size_t %s_oldret = ret;\n"
 427                  "size_t %s_olen = 0;\n"
 428                  "void *%s_tmp;\n"
 429                  "ret = 0;\n"
 430                  "(%s)->len = 0;\n"
 431                  "(%s)->val = NULL;\n",
 432                  tmpstr,
 433                  tmpstr,
 434                  tmpstr,
 435                  tmpstr,
 436                  name,
 437                  name);
 438 
 439         fprintf (codefile,
 440                  "while(ret < %s_origlen) {\n"
 441                  "size_t %s_nlen = %s_olen + sizeof(*((%s)->val));\n"
 442                  "if (%s_olen > %s_nlen) { e = ASN1_OVERFLOW; %s; }\n"
 443                  "%s_olen = %s_nlen;\n"
 444                  "%s_tmp = realloc((%s)->val, %s_olen);\n"
 445                  "if (%s_tmp == NULL) { e = ENOMEM; %s; }\n"
 446                  "(%s)->val = %s_tmp;\n",
 447                  tmpstr,
 448                  tmpstr, tmpstr, name,
 449                  tmpstr, tmpstr, forwstr,
 450                  tmpstr, tmpstr,
 451                  tmpstr, name, tmpstr,
 452                  tmpstr, forwstr,
 453                  name, tmpstr);
 454 
 455         asprintf (&n, "&(%s)->val[(%s)->len]", name, name);
 456         if (n == NULL)
 457             errx(1, "malloc");
 458         asprintf (&sname, "%s_s_of", tmpstr);
 459         if (sname == NULL)
 460             errx(1, "malloc");
 461         decode_type (n, t->subtype, 0, forwstr, sname);
 462         fprintf (codefile,
 463                  "(%s)->len++;\n"
 464                  "len = %s_origlen - ret;\n"
 465                  "}\n"
 466                  "ret += %s_oldret;\n"
 467                  "}\n",
 468                  name,
 469                  tmpstr, tmpstr);
 470         if (t->range)
 471             range_check(name, "len", forwstr, t->range);
 472         free (n);
 473         free (sname);
 474         break;
 475     }
 476     case TGeneralizedTime:
 477         decode_primitive ("generalized_time", name, forwstr);
 478         break;
 479     case TGeneralString:
 480         decode_primitive ("general_string", name, forwstr);
 481         break;
 482     case TTag:{
 483         char *tname;
 484 
 485         fprintf(codefile,
 486                 "{\n"
 487                 "size_t %s_datalen, %s_oldlen;\n",
 488                 tmpstr, tmpstr);
 489         if(dce_fix)
 490             fprintf(codefile,
 491                     "int dce_fix;\n");
 492         fprintf(codefile, "e = der_match_tag_and_length(p, len, %s, %s, %s, "
 493                 "&%s_datalen, &l);\n",
 494                 classname(t->tag.tagclass),
 495                 is_primitive_type(t->subtype->type) ? "PRIM" : "CONS",
 496                 valuename(t->tag.tagclass, t->tag.tagvalue),
 497                 tmpstr);
 498         if(optional) {
 499             fprintf(codefile,
 500                     "if(e) {\n"
 501                     "%s = NULL;\n"
 502                     "} else {\n"
 503                      "%s = calloc(1, sizeof(*%s));\n"
 504                      "if (%s == NULL) { e = ENOMEM; %s; }\n",
 505                      name, name, name, name, forwstr);
 506         } else {
 507             fprintf(codefile, "if(e) %s;\n", forwstr);
 508         }
 509         fprintf (codefile,
 510                  "p += l; len -= l; ret += l;\n"
 511                  "%s_oldlen = len;\n",
 512                  tmpstr);
 513         if(dce_fix)
 514             fprintf (codefile,
 515                      "if((dce_fix = _heim_fix_dce(%s_datalen, &len)) < 0)\n"
 516                      "{ e = ASN1_BAD_FORMAT; %s; }\n",
 517                      tmpstr, forwstr);
 518         else
 519             fprintf(codefile,
 520                     "if (%s_datalen > len) { e = ASN1_OVERRUN; %s; }\n"
 521                     "len = %s_datalen;\n", tmpstr, forwstr, tmpstr);
 522         asprintf (&tname, "%s_Tag", tmpstr);
 523         if (tname == NULL)
 524             errx(1, "malloc");
 525         decode_type (name, t->subtype, 0, forwstr, tname);
 526         if(dce_fix)
 527             fprintf(codefile,
 528                     "if(dce_fix){\n"
 529                     "e = der_match_tag_and_length (p, len, "
 530                     "(Der_class)0,(Der_type)0, UT_EndOfContent, "
 531                     "&%s_datalen, &l);\n"
 532                     "if(e) %s;\np += l; len -= l; ret += l;\n"
 533                     "} else \n", tmpstr, forwstr);
 534         fprintf(codefile,
 535                 "len = %s_oldlen - %s_datalen;\n",
 536                 tmpstr, tmpstr);
 537         if(optional)
 538             fprintf(codefile,
 539                     "}\n");
 540         fprintf(codefile,
 541                 "}\n");
 542         free(tname);
 543         break;
 544     }
 545     case TChoice: {
 546         Member *m, *have_ellipsis = NULL;
 547         const char *els = "";
 548 
 549         if (t->members == NULL)
 550             break;
 551 
 552         ASN1_TAILQ_FOREACH(m, t->members, members) {
 553             const Type *tt = m->type;
 554             char *s;
 555             Der_class cl;
 556             Der_type  ty;
 557             unsigned  tag;
 558         
 559             if (m->ellipsis) {
 560                 have_ellipsis = m;
 561                 continue;
 562             }
 563 
 564             find_tag(tt, &cl, &ty, &tag);
 565 
 566             fprintf(codefile,
 567                     "%sif (der_match_tag(p, len, %s, %s, %s, NULL) == 0) {\n",
 568                     els,
 569                     classname(cl),
 570                     ty ? "CONS" : "PRIM",
 571                     valuename(cl, tag));
 572             asprintf (&s, "%s(%s)->u.%s", m->optional ? "" : "&",
 573                       name, m->gen_name);
 574             if (s == NULL)
 575                 errx(1, "malloc");
 576             decode_type (s, m->type, m->optional, forwstr, m->gen_name);
 577             fprintf(codefile,
 578                     "(%s)->element = %s;\n",
 579                     name, m->label);
 580             free(s);
 581             fprintf(codefile,
 582                     "}\n");
 583             els = "else ";
 584         }
 585         if (have_ellipsis) {
 586             fprintf(codefile,
 587                     "else {\n"
 588                     "(%s)->u.%s.data = calloc(1, len);\n"
 589                     "if ((%s)->u.%s.data == NULL) {\n"
 590                     "e = ENOMEM; %s;\n"
 591                     "}\n"
 592                     "(%s)->u.%s.length = len;\n"
 593                     "memcpy((%s)->u.%s.data, p, len);\n"
 594                     "(%s)->element = %s;\n"
 595                     "p += len;\n"
 596                     "ret += len;\n"
 597                     "len -= len;\n"
 598                     "}\n",
 599                     name, have_ellipsis->gen_name,
 600                     name, have_ellipsis->gen_name,
 601                     forwstr,
 602                     name, have_ellipsis->gen_name,
 603                     name, have_ellipsis->gen_name,
 604                     name, have_ellipsis->label);
 605         } else {
 606             fprintf(codefile,
 607                     "else {\n"
 608                     "e = ASN1_PARSE_ERROR;\n"
 609                     "%s;\n"
 610                     "}\n",
 611                     forwstr);
 612         }
 613         break;
 614     }
 615     case TUTCTime:
 616         decode_primitive ("utctime", name, forwstr);
 617         break;
 618     case TUTF8String:
 619         decode_primitive ("utf8string", name, forwstr);
 620         break;
 621     case TPrintableString:
 622         decode_primitive ("printable_string", name, forwstr);
 623         break;
 624     case TIA5String:
 625         decode_primitive ("ia5_string", name, forwstr);
 626         break;
 627     case TBMPString:
 628         decode_primitive ("bmp_string", name, forwstr);
 629         break;
 630     case TUniversalString:
 631         decode_primitive ("universal_string", name, forwstr);
 632         break;
 633     case TVisibleString:
 634         decode_primitive ("visible_string", name, forwstr);
 635         break;
 636     case TNull:
 637         fprintf (codefile, "/* NULL */\n");
 638         break;
 639     case TOID:
 640         decode_primitive ("oid", name, forwstr);
 641         break;
 642     default :
 643         abort ();
 644     }
 645     return 0;
 646 }
 647 
 648 void
 649 generate_type_decode (const Symbol *s)
     /* [<][>][^][v][top][bottom][index][help] */
 650 {
 651     int preserve = preserve_type(s->name) ? TRUE : FALSE;
 652 
 653     fprintf (headerfile,
 654              "int    "
 655              "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
 656              s->gen_name, s->gen_name);
 657 
 658     fprintf (codefile, "int\n"
 659              "decode_%s(const unsigned char *p,"
 660              " size_t len, %s *data, size_t *size)\n"
 661              "{\n",
 662              s->gen_name, s->gen_name);
 663 
 664     switch (s->type->type) {
 665     case TInteger:
 666     case TBoolean:
 667     case TOctetString:
 668     case TOID:
 669     case TGeneralizedTime:
 670     case TGeneralString:
 671     case TUTF8String:
 672     case TPrintableString:
 673     case TIA5String:
 674     case TBMPString:
 675     case TUniversalString:
 676     case TVisibleString:
 677     case TUTCTime:
 678     case TNull:
 679     case TEnumerated:
 680     case TBitString:
 681     case TSequence:
 682     case TSequenceOf:
 683     case TSet:
 684     case TSetOf:
 685     case TTag:
 686     case TType:
 687     case TChoice:
 688         fprintf (codefile,
 689                  "size_t ret = 0;\n"
 690                  "size_t l;\n"
 691                  "int e;\n");
 692         if (preserve)
 693             fprintf (codefile, "const unsigned char *begin = p;\n");
 694 
 695         fprintf (codefile, "\n");
 696         fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); /* hack to avoid `unused variable' */
 697 
 698         decode_type ("data", s->type, 0, "goto fail", "Top");
 699         if (preserve)
 700             fprintf (codefile,
 701                      "data->_save.data = calloc(1, ret);\n"
 702                      "if (data->_save.data == NULL) { \n"
 703                      "e = ENOMEM; goto fail; \n"
 704                      "}\n"
 705                      "data->_save.length = ret;\n"
 706                      "memcpy(data->_save.data, begin, ret);\n");
 707         fprintf (codefile,
 708                  "if(size) *size = ret;\n"
 709                  "return 0;\n");
 710         fprintf (codefile,
 711                  "fail:\n"
 712                  "free_%s(data);\n"
 713                  "return e;\n",
 714                  s->gen_name);
 715         break;
 716     default:
 717         abort ();
 718     }
 719     fprintf (codefile, "}\n\n");
 720 }

/* [<][>][^][v][top][bottom][index][help] */