blob: fab78d37731f7f89cb4635c802b6a57bbe683177 [file] [log] [blame]
vlmfa67ddc2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
3static int _asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v);
4static int _asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b);
5
vlmf645aff2004-08-22 03:09:24 +00006int
7asn1f_pull_components_of(arg_t *arg) {
8 TQ_HEAD(asn1p_expr_t) list;
9 asn1p_expr_t *expr = arg->expr;
10 asn1p_expr_t *memb;
11 int r_value = 0;
12
13 switch(expr->expr_type) {
14 case ASN_CONSTR_SEQUENCE:
15 case ASN_CONSTR_SET:
16 break;
17 default:
18 return 0;
19 }
20
21 TQ_INIT(&list);
22
23 /*
24 * Look into
25 */
26 while((memb = TQ_REMOVE(&(expr->members), next))) {
27 asn1p_expr_t *coft; /* COMPONENTS OF thing itself */
28 asn1p_expr_t *terminal; /* Terminal of the referenced type */
29
30 if(memb->expr_type != A1TC_COMPONENTS_OF) {
31 TQ_ADD(&list, memb, next);
32 continue;
33 }
34
35 coft = TQ_FIRST(&memb->members);
36 assert(coft);
37 assert(!TQ_NEXT(coft, next));
38
39 /*
40 * Find the referenced type.
41 */
42 terminal = asn1f_find_terminal_type(arg, coft);
43 if(!terminal || (terminal->expr_type != expr->expr_type)) {
44 FATAL("COMPONENTS OF at line %d "
45 "must reference a %s type",
46 coft->_lineno,
47 expr->expr_type==ASN_CONSTR_SET
48 ? "SET" : "SEQUENCE"
49 );
50 TQ_ADD(&list, memb, next);
51 r_value = -1;
52 continue;
53 }
54
55 /*
56 * Clone the final structure.
57 */
58
59 coft = asn1p_expr_clone(terminal, 1 /* Skip extensions */);
60 if(!coft) return -1; /* ENOMEM */
61
62 asn1p_expr_free(memb); /* Don't need it anymore*/
63
64 /*
65 * Move all components of the cloned structure
66 * into the current one.
67 */
68 while((memb = TQ_REMOVE(&(coft->members), next)))
69 TQ_ADD(&list, memb, next);
70
71 asn1p_expr_free(coft); /* Remove wrapper */
72 }
73
74 /* Move the stuff back */
vlmb6fd3b22004-08-25 00:42:25 +000075 TQ_MOVE(&(expr->members), &list);
vlmf645aff2004-08-22 03:09:24 +000076
77 return r_value;
78}
vlmfa67ddc2004-06-03 03:38:44 +000079
80int
81asn1f_fix_constr_ext(arg_t *arg) {
82 asn1p_expr_t *expr = arg->expr;
83 asn1p_expr_t *v;
84 TQ_HEAD(asn1p_expr_t) root_list;
85 TQ_HEAD(asn1p_expr_t) ext_list;
86 TQ_HEAD(asn1p_expr_t) *cur_list;
87 int r_value = 0;
88 int ext_count = 0;
89
90 switch(expr->expr_type) {
91 case ASN_CONSTR_SEQUENCE:
92 case ASN_CONSTR_SET:
93 case ASN_CONSTR_CHOICE:
94 break;
95 default:
96 return 0;
97 }
98
99 DEBUG("%s(%s) for line %d", __func__,
100 expr->Identifier, expr->_lineno);
101
102 TQ_INIT(&root_list);
103 TQ_INIT(&ext_list);
104 cur_list = (void *)&root_list;
105
106 while((v = TQ_REMOVE(&(expr->members), next))) {
107 if(v->expr_type == A1TC_EXTENSIBLE) {
108 ext_count++;
109 switch(ext_count) {
110 case 1: cur_list = (void *)&ext_list; break;
111 case 2:
112 cur_list = (void *)&root_list;
113 if(v->value) {
114 FATAL("Optional extension marker "
115 "must not contain "
116 "an exception mark "
117 "at line %d", v->_lineno);
118 r_value = -1;
119 }
120 asn1p_expr_free(v);
121 continue;
122 case 3:
123 FATAL("Third extension marker "
124 "is not allowed at line %d", v->_lineno);
125 default:
126 r_value = -1;
127 }
128 }
129
130 TQ_ADD(cur_list, v, next);
131 }
132
133 /*
134 * Copy the root list and extension list back into the main list.
135 */
vlmb6fd3b22004-08-25 00:42:25 +0000136 TQ_MOVE(&(expr->members), &root_list);
vlmfa67ddc2004-06-03 03:38:44 +0000137 while((v = TQ_REMOVE(&ext_list, next)))
138 TQ_ADD(&(expr->members), v, next);
139
140 if(arg->mod->module_flags & MSF_EXTENSIBILITY_IMPLIED
vlmb6fd3b22004-08-25 00:42:25 +0000141 && ext_count == 0) {
vlmfa67ddc2004-06-03 03:38:44 +0000142 v = asn1p_expr_new(0);
143 if(v) {
144 v->Identifier = strdup("...");
145 v->expr_type = A1TC_EXTENSIBLE;
146 v->meta_type = AMT_TYPE;
vlm4f4f56d2004-07-01 00:51:31 +0000147 v->_lineno = expr->_lineno; /* The best we can do */
vlmfa67ddc2004-06-03 03:38:44 +0000148 if(v->Identifier == NULL) {
149 asn1p_expr_free(v);
150 r_value = -1;
151 } else {
152 TQ_ADD(&(expr->members), v, next);
153 }
154 } else {
155 r_value = -1;
156 }
157 }
158
159 return r_value;
160}
161
162
163int
164asn1f_fix_constr_tag(arg_t *arg) {
165 asn1p_expr_t *expr = arg->expr;
166 asn1p_expr_t *v;
167 int fl_impl_tags = 0;
168 int fl_auto_tags = 0;
169 int root_tagged = 0; /* The root component is manually tagged */
170 int ext_tagged = 0; /* The extensions are manually tagged */
171 int component_number = 0;
172 int r_value = 0;
173
174 switch(expr->expr_type) {
175 case ASN_CONSTR_SEQUENCE:
176 case ASN_CONSTR_SET:
177 case ASN_CONSTR_CHOICE:
178 break;
179 default:
180 return 0;
181 }
182
183 fl_impl_tags = (arg->mod->module_flags & MSF_IMPLICIT_TAGS);
184 fl_auto_tags = (arg->mod->module_flags & MSF_AUTOMATIC_TAGS);
185
186 DEBUG("%s(%s) {%d, %d} for line %d", __func__,
187 expr->Identifier, fl_impl_tags, fl_auto_tags, expr->_lineno);
188
189 TQ_FOR(v, &(expr->members), next) {
190 int must_explicit = 0;
191
192 if(v->expr_type == A1TC_EXTENSIBLE) {
193 component_number++;
194 continue;
195 }
196
197 if(v->tag.tag_class == TC_NOCLASS) {
198 continue;
199 } else {
200 switch(component_number) {
201 case 0: case 2:
202 root_tagged = 1; break;
203 default:
204 ext_tagged = 1; break;
205 }
206 }
207
208 must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, v);
209
210 if(fl_impl_tags) {
211 if(v->tag.tag_mode != TM_EXPLICIT) {
212 if(must_explicit)
213 v->tag.tag_mode = TM_EXPLICIT;
214 else
215 v->tag.tag_mode = TM_IMPLICIT;
216 }
217 } else {
218 if(v->tag.tag_mode == TM_DEFAULT) {
219 v->tag.tag_mode = TM_EXPLICIT;
220 }
221 }
222
223 /*
224 * Perform a final sanity check.
225 */
226 if(must_explicit) {
227 if(v->tag.tag_mode == TM_IMPLICIT) {
228 FATAL("%s tagged in IMPLICIT mode "
229 "but must be EXPLICIT at line %d",
230 v->Identifier, v->_lineno);
231 r_value = -1;
232 } else {
233 v->tag.tag_mode = TM_EXPLICIT;
234 }
235 }
236 }
237
238 if(ext_tagged && !root_tagged) {
239 FATAL("In %s at line %d: "
240 "extensions are tagged "
241 "but root components are not",
242 expr->Identifier, expr->_lineno);
243 r_value = -1;
244 } else if(!root_tagged && !ext_tagged && fl_auto_tags) {
245 expr->auto_tags_OK = 1;
246 }
247
248 return r_value;
249}
250
251int
252asn1f_fix_constr_autotag(arg_t *arg) {
253 asn1p_expr_t *expr = arg->expr;
254 asn1p_expr_t *v;
255 asn1_integer_t tag_value = 0;
256 int r_value = 0;
257
258 switch(expr->expr_type) {
259 case ASN_CONSTR_SEQUENCE:
260 case ASN_CONSTR_SET:
261 case ASN_CONSTR_CHOICE:
262 if(expr->auto_tags_OK)
263 break;
264 /* Automatic tagging is not applicable */
265 /* Fall through */
266 default:
267 return 0;
268 }
269
270 DEBUG("%s(%s) for line %d", __func__,
271 expr->Identifier, expr->_lineno);
272
273 TQ_FOR(v, &(expr->members), next) {
274 int must_explicit;
275
276 if(v->expr_type == A1TC_EXTENSIBLE)
277 break;
278
vlmf645aff2004-08-22 03:09:24 +0000279 if(0) {
280 /* This may be not true in case COMPONENTS OF */
281 assert(v->tag.tag_class == TC_NOCLASS);
282 }
vlmfa67ddc2004-06-03 03:38:44 +0000283
284 must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, v);
285
286 v->tag.tag_class = TC_CONTEXT_SPECIFIC;
287 v->tag.tag_mode = must_explicit ? TM_EXPLICIT : TM_IMPLICIT;
288 v->tag.tag_value = tag_value++;
289 }
290
291 return r_value;
292}
293
294/*
295 * Check that tags are distinct.
296 */
297int
298asn1f_check_constr_tags_distinct(arg_t *arg) {
299 asn1p_expr_t *expr = arg->expr;
300 asn1p_expr_t *v;
301 int r_value = 0;
302
303 switch(expr->expr_type) {
304 case ASN_CONSTR_SEQUENCE:
305 case ASN_CONSTR_SET:
306 case ASN_CONSTR_CHOICE:
307 break;
308 default:
309 return 0;
310 }
311
312 TQ_FOR(v, &(expr->members), next) {
313 /*
314 * In every series of non-mandatory components,
315 * the tags must be distinct from each other AND the
316 * tag of the following mandatory component.
317 * For SET and CHOICE treat everything as a big set of
318 * non-mandatory components.
319 */
320 if(expr->expr_type != ASN_CONSTR_SEQUENCE || v->marker) {
321 asn1p_expr_t *nv;
322 for(nv = v; (nv = TQ_NEXT(nv, next));) {
323 if(_asn1f_compare_tags(arg, v, nv))
324 r_value = -1;
325 if(expr->expr_type == ASN_CONSTR_SEQUENCE
326 && !nv->marker) break;
327 }
328 }
329 }
330
331 return r_value;
332}
333
334static int
335_asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v) {
336 asn1p_expr_t *reft;
337
vlmf645aff2004-08-22 03:09:24 +0000338 reft = asn1f_find_terminal_type(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000339 if(reft) {
340 switch(reft->expr_type) {
341 case ASN_CONSTR_CHOICE:
342 return 1;
343 default:
344 return 0;
345 }
346 }
347
348 return 0;
349}
350
351/*
352 * Check that the tags are distinct.
353 */
354static int
355_asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b) {
356 struct asn1p_type_tag_s ta, tb;
357 int ra, rb;
358 int ret;
359
360 ra = asn1f_fetch_tag(arg->asn, arg->mod, a, &ta);
361 rb = asn1f_fetch_tag(arg->asn, arg->mod, b, &tb);
362
363 /*
364 * If both tags are explicitly or implicitly given, use them.
365 */
366 if(ra == 0 && rb == 0) {
367 /*
368 * Simple case: fetched both tags.
369 */
370 if(ta.tag_value == tb.tag_value
371 && ta.tag_class == tb.tag_class) {
372 char *p = (a->expr_type == A1TC_EXTENSIBLE)
373 ?"potentially ":"";
374 FATAL("Component \"%s\" at line %d %shas the same tag "
375 "with component \"%s\" at line %d",
376 a->Identifier,
377 a->_lineno,
378 p,
379 b->Identifier,
380 b->_lineno
381 );
vlm4f4f56d2004-07-01 00:51:31 +0000382 if((arg->mod->module_flags & MSF_EXTENSIBILITY_IMPLIED)
383 && (a->expr_type == A1TC_EXTENSIBLE)
384 && (b->expr_type == A1TC_EXTENSIBLE)) {
385 FATAL("The previous error is due to "
386 "improper use of "
387 "EXTENSIBILITY IMPLIED flag "
388 "of module %s",
389 arg->mod->Identifier);
390 }
vlmfa67ddc2004-06-03 03:38:44 +0000391 return -1;
392 } else {
393 /* Tags are distinct */
394 return 0;
395 }
396 }
397
398 /**********************************************************
399 * Now we must perform some very funny recursion to check
400 * multiple components of CHOICE type, etc.
401 */
402
403 DEBUG("Comparing tags %s:%x <-> %s:%x",
404 a->Identifier, a->expr_type,
405 b->Identifier, b->expr_type);
406
407 if(a->meta_type == AMT_TYPEREF) {
vlmfa67ddc2004-06-03 03:38:44 +0000408
409 DEBUG(" %s is a type reference", a->Identifier);
410
vlmf645aff2004-08-22 03:09:24 +0000411 a = asn1f_lookup_symbol(arg, a->module, a->reference);
vlmfa67ddc2004-06-03 03:38:44 +0000412 if(!a) return 0; /* Already FATAL()'ed somewhere else */
vlmf645aff2004-08-22 03:09:24 +0000413 WITH_MODULE(a->module, ret = _asn1f_compare_tags(arg, a, b));
vlmfa67ddc2004-06-03 03:38:44 +0000414 return ret;
415 }
416
417 if(a->expr_type == ASN_CONSTR_CHOICE) {
418 asn1p_expr_t *v;
419
420 DEBUG(" %s is a choice type (%d)", a->Identifier, a->_mark);
421
422 /*
423 * Iterate over members of CHOICE.
424 */
425 //if(a->_mark & TM_RECURSION) return 0;
426 TQ_FOR(v, &(a->members), next) {
427 //a->_mark |= TM_RECURSION;
428 ret = _asn1f_compare_tags(arg, v, b);
429 //a->_mark &= ~TM_RECURSION;
430 if(ret) return ret;
431 }
432 return 0;
433 }
434
435 if(b->expr_type == ASN_CONSTR_CHOICE) {
436 return _asn1f_compare_tags(arg, b, a);
437 }
438
439 if(a->_mark & TM_RECURSION) return 0;
440 if(b->_mark & TM_RECURSION) return 0;
441 a->_mark |= TM_RECURSION;
442 b->_mark |= TM_RECURSION;
443 ret = _asn1f_compare_tags(arg, b, a);
444 a->_mark &= ~TM_RECURSION;
445 b->_mark &= ~TM_RECURSION;
446
447 return ret;
448}
449