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