Line data Source code
1 : /*
2 : * Copyright (c) 1997 - 2005 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 :
36 : RCSID("$Id$");
37 :
38 : static int used_fail;
39 :
40 : static void
41 646 : copy_primitive (const char *typename, const char *from, const char *to)
42 : {
43 680 : fprintf (codefile, "if(der_copy_%s(%s, %s)) goto fail;\n",
44 : typename, from, to);
45 646 : used_fail++;
46 646 : }
47 :
48 : static void
49 7285 : copy_type (const char *from, const char *to, const Type *t, int preserve)
50 : {
51 7486 : switch (t->type) {
52 1539 : case TType:
53 : #if 0
54 : copy_type (from, to, t->symbol->type, preserve);
55 : #endif
56 1620 : fprintf (codefile, "if(copy_%s(%s, %s)) goto fail;\n",
57 1539 : t->symbol->gen_name, from, to);
58 1539 : used_fail++;
59 1539 : break;
60 418 : case TInteger:
61 418 : if (t->range == NULL && t->members == NULL) {
62 76 : copy_primitive ("heim_integer", from, to);
63 72 : break;
64 : }
65 20 : HEIM_FALLTHROUGH;
66 : case TBoolean:
67 : case TEnumerated :
68 380 : fprintf(codefile, "*(%s) = *(%s);\n", to, from);
69 360 : break;
70 252 : case TOctetString:
71 266 : copy_primitive ("octet_string", from, to);
72 252 : break;
73 190 : case TBitString:
74 190 : if (HEIM_TAILQ_EMPTY(t->members))
75 133 : copy_primitive ("bit_string", from, to);
76 : else
77 57 : fprintf(codefile, "*(%s) = *(%s);\n", to, from);
78 180 : break;
79 722 : case TSet:
80 : case TSequence:
81 : case TChoice: {
82 722 : Member *m, *have_ellipsis = NULL;
83 :
84 722 : if(t->members == NULL)
85 0 : break;
86 :
87 722 : if ((t->type == TSequence || t->type == TChoice) && preserve) {
88 0 : fprintf(codefile,
89 : "{ int ret;\n"
90 : "ret = der_copy_octet_string(&(%s)->_save, &(%s)->_save);\n"
91 : "if (ret) goto fail;\n"
92 : "}\n",
93 : from, to);
94 0 : used_fail++;
95 : }
96 :
97 722 : if(t->type == TChoice) {
98 171 : fprintf(codefile, "(%s)->element = (%s)->element;\n", to, from);
99 171 : fprintf(codefile, "switch((%s)->element) {\n", from);
100 : }
101 :
102 3287 : HEIM_TAILQ_FOREACH(m, t->members, members) {
103 135 : char *fs;
104 135 : char *ts;
105 :
106 2565 : if (m->ellipsis) {
107 114 : have_ellipsis = m;
108 114 : continue;
109 : }
110 :
111 2451 : if(t->type == TChoice)
112 627 : fprintf(codefile, "case %s:\n", m->label);
113 :
114 4773 : if (asprintf (&fs, "%s(%s)->%s%s",
115 2451 : m->optional ? "" : "&", from,
116 2451 : t->type == TChoice ? "u." : "", m->gen_name) < 0)
117 0 : errx(1, "malloc");
118 2451 : if (fs == NULL)
119 0 : errx(1, "malloc");
120 4773 : if (asprintf (&ts, "%s(%s)->%s%s",
121 2451 : m->optional ? "" : "&", to,
122 2451 : t->type == TChoice ? "u." : "", m->gen_name) < 0)
123 0 : errx(1, "malloc");
124 2451 : if (ts == NULL)
125 0 : errx(1, "malloc");
126 2451 : if(m->optional){
127 950 : fprintf(codefile, "if(%s) {\n", fs);
128 950 : fprintf(codefile, "%s = calloc(1, sizeof(*%s));\n", ts, ts);
129 950 : fprintf(codefile, "if(%s == NULL) goto fail;\n", ts);
130 950 : used_fail++;
131 : }
132 2451 : copy_type (fs, ts, m->type, FALSE);
133 2451 : if(m->optional){
134 950 : fprintf(codefile, "}else\n");
135 950 : fprintf(codefile, "%s = NULL;\n", ts);
136 : }
137 2451 : free (fs);
138 2451 : free (ts);
139 2451 : if(t->type == TChoice)
140 723 : fprintf(codefile, "break;\n");
141 : }
142 722 : if(t->type == TChoice) {
143 171 : if (have_ellipsis) {
144 19 : fprintf(codefile, "case %s: {\n"
145 : "int ret;\n"
146 : "ret=der_copy_octet_string(&(%s)->u.%s, &(%s)->u.%s);\n"
147 : "if (ret) goto fail;\n"
148 : "break;\n"
149 : "}\n",
150 : have_ellipsis->label,
151 : from, have_ellipsis->gen_name,
152 : to, have_ellipsis->gen_name);
153 19 : used_fail++;
154 : }
155 171 : fprintf(codefile, "}\n");
156 : }
157 684 : break;
158 : }
159 304 : case TSetOf:
160 : case TSequenceOf: {
161 304 : char *f = NULL, *T = NULL;
162 :
163 304 : fprintf (codefile, "if(((%s)->val = "
164 : "calloc(1, (%s)->len * sizeof(*(%s)->val))) == NULL && (%s)->len != 0)\n",
165 : to, from, to, from);
166 304 : fprintf (codefile, "goto fail;\n");
167 304 : used_fail++;
168 304 : fprintf(codefile,
169 : "for((%s)->len = 0; (%s)->len < (%s)->len; (%s)->len++){\n",
170 : to, to, from, to);
171 304 : if (asprintf(&f, "&(%s)->val[(%s)->len]", from, to) < 0)
172 0 : errx(1, "malloc");
173 304 : if (f == NULL)
174 0 : errx(1, "malloc");
175 304 : if (asprintf(&T, "&(%s)->val[(%s)->len]", to, to) < 0)
176 0 : errx(1, "malloc");
177 304 : if (T == NULL)
178 0 : errx(1, "malloc");
179 304 : copy_type(f, T, t->subtype, FALSE);
180 304 : fprintf(codefile, "}\n");
181 304 : free(f);
182 304 : free(T);
183 304 : break;
184 : }
185 0 : case TGeneralizedTime:
186 0 : fprintf(codefile, "*(%s) = *(%s);\n", to, from);
187 0 : break;
188 18 : case TGeneralString:
189 19 : copy_primitive ("general_string", from, to);
190 18 : break;
191 0 : case TTeletexString:
192 0 : copy_primitive ("general_string", from, to);
193 0 : break;
194 0 : case TUTCTime:
195 0 : fprintf(codefile, "*(%s) = *(%s);\n", to, from);
196 0 : break;
197 72 : case TUTF8String:
198 76 : copy_primitive ("utf8string", from, to);
199 72 : break;
200 0 : case TPrintableString:
201 0 : copy_primitive ("printable_string", from, to);
202 0 : break;
203 0 : case TIA5String:
204 0 : copy_primitive ("ia5_string", from, to);
205 0 : break;
206 0 : case TBMPString:
207 0 : copy_primitive ("bmp_string", from, to);
208 0 : break;
209 0 : case TUniversalString:
210 0 : copy_primitive ("universal_string", from, to);
211 0 : break;
212 0 : case TVisibleString:
213 0 : copy_primitive ("visible_string", from, to);
214 0 : break;
215 3819 : case TTag:
216 3819 : copy_type (from, to, t->subtype, preserve);
217 3819 : break;
218 72 : case TOID:
219 76 : copy_primitive ("oid", from, to);
220 72 : break;
221 18 : case TNull:
222 18 : break;
223 0 : default :
224 0 : abort ();
225 : }
226 7285 : }
227 :
228 : void
229 912 : generate_type_copy (const Symbol *s)
230 : {
231 48 : struct decoration deco;
232 912 : ssize_t more_deco = -1;
233 912 : int preserve = preserve_type(s->name) ? TRUE : FALSE;
234 912 : int save_used_fail = used_fail;
235 :
236 912 : used_fail = 0;
237 :
238 960 : fprintf (codefile, "int ASN1CALL\n"
239 : "copy_%s(const %s *from, %s *to)\n"
240 : "{\n"
241 : "memset(to, 0, sizeof(*to));\n",
242 912 : s->gen_name, s->gen_name, s->gen_name);
243 912 : copy_type ("from", "to", s->type, preserve);
244 950 : while (decorate_type(s->gen_name, &deco, &more_deco)) {
245 38 : if (deco.ext && deco.copy_function_name == NULL) {
246 : /* Decorated with field of external type but no copy function */
247 38 : if (deco.ptr)
248 0 : fprintf(codefile, "(to)->%s = 0;\n", deco.field_name);
249 : else
250 38 : fprintf(codefile, "memset(&(to)->%s, 0, sizeof((to)->%s));\n",
251 : deco.field_name, deco.field_name);
252 0 : } else if (deco.ext) {
253 : /* Decorated with field of external type w/ copy function */
254 0 : if (deco.ptr) {
255 0 : fprintf(codefile, "if (from->%s) {\n", deco.field_name);
256 0 : fprintf(codefile, "(to)->%s = calloc(1, sizeof(*(to)->%s));\n",
257 : deco.field_name, deco.field_name);
258 0 : fprintf(codefile, "if (%s((from)->%s, (to)->%s)) goto fail;\n",
259 : deco.copy_function_name, deco.field_name, deco.field_name);
260 0 : fprintf(codefile, "}\n");
261 : } else {
262 0 : fprintf(codefile, "if (%s(&(from)->%s, &(to)->%s)) goto fail;\n",
263 : deco.copy_function_name, deco.field_name, deco.field_name);
264 : }
265 0 : } else if (deco.opt) {
266 : /* Decorated with optional field of ASN.1 type */
267 0 : fprintf(codefile, "if (from->%s) {\n", deco.field_name);
268 0 : fprintf(codefile, "(to)->%s = calloc(1, sizeof(*(to)->%s));\n", deco.field_name, deco.field_name);
269 0 : fprintf(codefile, "if (copy_%s((from)->%s, (to)->%s)) goto fail;\n", deco.field_type, deco.field_name, deco.field_name);
270 0 : fprintf(codefile, "}\n");
271 : } else {
272 : /* Decorated with required field of ASN.1 type */
273 0 : fprintf(codefile, "if (copy_%s(&(from)->%s, &(to)->%s)) goto fail;\n", deco.field_type, deco.field_name, deco.field_name);
274 : }
275 38 : used_fail++;
276 38 : free(deco.field_type);
277 : }
278 912 : fprintf (codefile, "return 0;\n");
279 :
280 912 : if (used_fail)
281 865 : fprintf (codefile, "fail:\n"
282 : "free_%s(to);\n"
283 : "return ENOMEM;\n",
284 817 : s->gen_name);
285 :
286 912 : fprintf(codefile,
287 : "}\n\n");
288 912 : used_fail = save_used_fail;
289 912 : }
290 :
|