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