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