blob: 8c9dd3833398f959db7f4766d8cc1501b8ade6c1 [file] [log] [blame]
vlmfa67ddc2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
vlm76142452004-09-05 10:36:22 +00003#define AFT_IMAGINARY_ANY 1 /* _fetch_tag() flag */
4
vlmfa67ddc2004-06-03 03:38:44 +00005static int _asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v);
6static int _asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b);
vlm76142452004-09-05 10:36:22 +00007static int _asn1f_fix_type_tag(arg_t *arg, asn1p_expr_t *expr);
vlmfa67ddc2004-06-03 03:38:44 +00008
vlmf645aff2004-08-22 03:09:24 +00009int
10asn1f_pull_components_of(arg_t *arg) {
11 TQ_HEAD(asn1p_expr_t) list;
12 asn1p_expr_t *expr = arg->expr;
13 asn1p_expr_t *memb;
14 int r_value = 0;
15
16 switch(expr->expr_type) {
17 case ASN_CONSTR_SEQUENCE:
18 case ASN_CONSTR_SET:
19 break;
20 default:
21 return 0;
22 }
23
24 TQ_INIT(&list);
25
26 /*
27 * Look into
28 */
29 while((memb = TQ_REMOVE(&(expr->members), next))) {
30 asn1p_expr_t *coft; /* COMPONENTS OF thing itself */
31 asn1p_expr_t *terminal; /* Terminal of the referenced type */
32
33 if(memb->expr_type != A1TC_COMPONENTS_OF) {
34 TQ_ADD(&list, memb, next);
35 continue;
36 }
37
38 coft = TQ_FIRST(&memb->members);
39 assert(coft);
40 assert(!TQ_NEXT(coft, next));
41
42 /*
43 * Find the referenced type.
44 */
45 terminal = asn1f_find_terminal_type(arg, coft);
46 if(!terminal || (terminal->expr_type != expr->expr_type)) {
47 FATAL("COMPONENTS OF at line %d "
48 "must reference a %s type",
49 coft->_lineno,
50 expr->expr_type==ASN_CONSTR_SET
51 ? "SET" : "SEQUENCE"
52 );
53 TQ_ADD(&list, memb, next);
54 r_value = -1;
55 continue;
56 }
57
58 /*
59 * Clone the final structure.
60 */
61
62 coft = asn1p_expr_clone(terminal, 1 /* Skip extensions */);
63 if(!coft) return -1; /* ENOMEM */
64
65 asn1p_expr_free(memb); /* Don't need it anymore*/
66
67 /*
68 * Move all components of the cloned structure
69 * into the current one.
70 */
71 while((memb = TQ_REMOVE(&(coft->members), next)))
72 TQ_ADD(&list, memb, next);
73
74 asn1p_expr_free(coft); /* Remove wrapper */
75 }
76
77 /* Move the stuff back */
vlmb6fd3b22004-08-25 00:42:25 +000078 TQ_MOVE(&(expr->members), &list);
vlmf645aff2004-08-22 03:09:24 +000079
80 return r_value;
81}
vlmfa67ddc2004-06-03 03:38:44 +000082
vlm76142452004-09-05 10:36:22 +000083/*
84 * Fix extensibility parts inside constructed types (SEQUENCE, SET, CHOICE).
85 */
vlmfa67ddc2004-06-03 03:38:44 +000086int
87asn1f_fix_constr_ext(arg_t *arg) {
88 asn1p_expr_t *expr = arg->expr;
89 asn1p_expr_t *v;
90 TQ_HEAD(asn1p_expr_t) root_list;
91 TQ_HEAD(asn1p_expr_t) ext_list;
92 TQ_HEAD(asn1p_expr_t) *cur_list;
93 int r_value = 0;
94 int ext_count = 0;
95
96 switch(expr->expr_type) {
97 case ASN_CONSTR_SEQUENCE:
98 case ASN_CONSTR_SET:
99 case ASN_CONSTR_CHOICE:
100 break;
101 default:
102 return 0;
103 }
104
105 DEBUG("%s(%s) for line %d", __func__,
106 expr->Identifier, expr->_lineno);
107
108 TQ_INIT(&root_list);
109 TQ_INIT(&ext_list);
110 cur_list = (void *)&root_list;
111
vlm76142452004-09-05 10:36:22 +0000112 /*
113 * Split the set of fields into two lists, the root list
114 * and the extensions list.
115 */
vlmfa67ddc2004-06-03 03:38:44 +0000116 while((v = TQ_REMOVE(&(expr->members), next))) {
117 if(v->expr_type == A1TC_EXTENSIBLE) {
118 ext_count++;
119 switch(ext_count) {
120 case 1: cur_list = (void *)&ext_list; break;
121 case 2:
122 cur_list = (void *)&root_list;
123 if(v->value) {
124 FATAL("Optional extension marker "
125 "must not contain "
126 "an exception mark "
127 "at line %d", v->_lineno);
128 r_value = -1;
129 }
130 asn1p_expr_free(v);
131 continue;
132 case 3:
133 FATAL("Third extension marker "
134 "is not allowed at line %d", v->_lineno);
135 default:
136 r_value = -1;
137 }
138 }
139
140 TQ_ADD(cur_list, v, next);
141 }
142
143 /*
144 * Copy the root list and extension list back into the main list.
145 */
vlmb6fd3b22004-08-25 00:42:25 +0000146 TQ_MOVE(&(expr->members), &root_list);
vlmfa67ddc2004-06-03 03:38:44 +0000147 while((v = TQ_REMOVE(&ext_list, next)))
148 TQ_ADD(&(expr->members), v, next);
149
150 if(arg->mod->module_flags & MSF_EXTENSIBILITY_IMPLIED
vlmb6fd3b22004-08-25 00:42:25 +0000151 && ext_count == 0) {
vlmfa67ddc2004-06-03 03:38:44 +0000152 v = asn1p_expr_new(0);
153 if(v) {
154 v->Identifier = strdup("...");
155 v->expr_type = A1TC_EXTENSIBLE;
156 v->meta_type = AMT_TYPE;
vlm4f4f56d2004-07-01 00:51:31 +0000157 v->_lineno = expr->_lineno; /* The best we can do */
vlmfa67ddc2004-06-03 03:38:44 +0000158 if(v->Identifier == NULL) {
159 asn1p_expr_free(v);
160 r_value = -1;
161 } else {
162 TQ_ADD(&(expr->members), v, next);
163 }
164 } else {
165 r_value = -1;
166 }
167 }
168
169 return r_value;
170}
171
172
173int
vlm76142452004-09-05 10:36:22 +0000174asn1f_fix_constr_tag(arg_t *arg, int fix_top_level) {
vlmfa67ddc2004-06-03 03:38:44 +0000175 asn1p_expr_t *expr = arg->expr;
176 asn1p_expr_t *v;
vlmfa67ddc2004-06-03 03:38:44 +0000177 int root_tagged = 0; /* The root component is manually tagged */
178 int ext_tagged = 0; /* The extensions are manually tagged */
179 int component_number = 0;
180 int r_value = 0;
181
vlm76142452004-09-05 10:36:22 +0000182 DEBUG("%s(%s) for line %d", __func__,
183 expr->Identifier, expr->_lineno);
184
185 /*
186 * Fix the top-level type itself first.
187 */
188 if(fix_top_level) {
189 if(expr->tag.tag_class == TC_NOCLASS)
190 return r_value;
191
192 if(_asn1f_fix_type_tag(arg, expr))
193 r_value = -1;
194
195 return r_value;
196 }
197
vlmfa67ddc2004-06-03 03:38:44 +0000198 switch(expr->expr_type) {
199 case ASN_CONSTR_SEQUENCE:
200 case ASN_CONSTR_SET:
201 case ASN_CONSTR_CHOICE:
202 break;
203 default:
204 return 0;
205 }
206
vlmfa67ddc2004-06-03 03:38:44 +0000207 TQ_FOR(v, &(expr->members), next) {
vlmfa67ddc2004-06-03 03:38:44 +0000208
209 if(v->expr_type == A1TC_EXTENSIBLE) {
210 component_number++;
211 continue;
212 }
213
214 if(v->tag.tag_class == TC_NOCLASS) {
215 continue;
vlmfa67ddc2004-06-03 03:38:44 +0000216 }
217
vlm76142452004-09-05 10:36:22 +0000218 switch(component_number) {
219 case 0: case 2:
220 root_tagged = 1; break;
221 default:
222 ext_tagged = 1; break;
vlmfa67ddc2004-06-03 03:38:44 +0000223 }
224
vlm76142452004-09-05 10:36:22 +0000225 if(_asn1f_fix_type_tag(arg, v))
226 r_value = -1;
227
vlmfa67ddc2004-06-03 03:38:44 +0000228 }
229
230 if(ext_tagged && !root_tagged) {
231 FATAL("In %s at line %d: "
232 "extensions are tagged "
233 "but root components are not",
234 expr->Identifier, expr->_lineno);
235 r_value = -1;
vlm76142452004-09-05 10:36:22 +0000236 } else if(!root_tagged && !ext_tagged
237 && (arg->mod->module_flags & MSF_AUTOMATIC_TAGS)) {
238 /* Make a decision on automatic tagging */
vlmfa67ddc2004-06-03 03:38:44 +0000239 expr->auto_tags_OK = 1;
240 }
241
242 return r_value;
243}
244
vlm76142452004-09-05 10:36:22 +0000245static int
246_asn1f_fix_type_tag(arg_t *arg, asn1p_expr_t *expr) {
247 int must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, expr);
248 int fl_impl_tags = (arg->mod->module_flags & MSF_IMPLICIT_TAGS);
249 int r_value = 0;
250
251 if(fl_impl_tags) {
252 if(expr->tag.tag_mode != TM_EXPLICIT) {
253 if(must_explicit)
254 expr->tag.tag_mode = TM_EXPLICIT;
255 else
256 expr->tag.tag_mode = TM_IMPLICIT;
257 }
258 } else {
259 if(expr->tag.tag_mode == TM_DEFAULT) {
260 expr->tag.tag_mode = TM_EXPLICIT;
261 }
262 }
263
264 /*
265 * Perform a final sanity check.
266 */
267 if(must_explicit) {
268 if(expr->tag.tag_mode == TM_IMPLICIT) {
269 FATAL("%s tagged in IMPLICIT mode "
270 "but must be EXPLICIT at line %d",
271 expr->Identifier, expr->_lineno);
272 r_value = -1;
273 } else {
274 expr->tag.tag_mode = TM_EXPLICIT;
275 }
276 }
277
278 return r_value;
279}
280
vlmfa67ddc2004-06-03 03:38:44 +0000281int
282asn1f_fix_constr_autotag(arg_t *arg) {
283 asn1p_expr_t *expr = arg->expr;
284 asn1p_expr_t *v;
285 asn1_integer_t tag_value = 0;
286 int r_value = 0;
287
288 switch(expr->expr_type) {
289 case ASN_CONSTR_SEQUENCE:
290 case ASN_CONSTR_SET:
291 case ASN_CONSTR_CHOICE:
292 if(expr->auto_tags_OK)
293 break;
294 /* Automatic tagging is not applicable */
295 /* Fall through */
296 default:
297 return 0;
298 }
299
300 DEBUG("%s(%s) for line %d", __func__,
301 expr->Identifier, expr->_lineno);
302
303 TQ_FOR(v, &(expr->members), next) {
304 int must_explicit;
305
306 if(v->expr_type == A1TC_EXTENSIBLE)
307 break;
308
vlmf645aff2004-08-22 03:09:24 +0000309 if(0) {
310 /* This may be not true in case COMPONENTS OF */
311 assert(v->tag.tag_class == TC_NOCLASS);
312 }
vlmfa67ddc2004-06-03 03:38:44 +0000313
314 must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, v);
315
316 v->tag.tag_class = TC_CONTEXT_SPECIFIC;
317 v->tag.tag_mode = must_explicit ? TM_EXPLICIT : TM_IMPLICIT;
318 v->tag.tag_value = tag_value++;
319 }
320
321 return r_value;
322}
323
324/*
325 * Check that tags are distinct.
326 */
327int
328asn1f_check_constr_tags_distinct(arg_t *arg) {
329 asn1p_expr_t *expr = arg->expr;
330 asn1p_expr_t *v;
331 int r_value = 0;
332
333 switch(expr->expr_type) {
334 case ASN_CONSTR_SEQUENCE:
335 case ASN_CONSTR_SET:
336 case ASN_CONSTR_CHOICE:
337 break;
338 default:
339 return 0;
340 }
341
342 TQ_FOR(v, &(expr->members), next) {
343 /*
344 * In every series of non-mandatory components,
345 * the tags must be distinct from each other AND the
346 * tag of the following mandatory component.
347 * For SET and CHOICE treat everything as a big set of
348 * non-mandatory components.
349 */
350 if(expr->expr_type != ASN_CONSTR_SEQUENCE || v->marker) {
351 asn1p_expr_t *nv;
352 for(nv = v; (nv = TQ_NEXT(nv, next));) {
353 if(_asn1f_compare_tags(arg, v, nv))
354 r_value = -1;
355 if(expr->expr_type == ASN_CONSTR_SEQUENCE
356 && !nv->marker) break;
357 }
358 }
359 }
360
361 return r_value;
362}
363
364static int
365_asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v) {
vlm76142452004-09-05 10:36:22 +0000366 struct asn1p_type_tag_s tag;
367 struct asn1p_type_tag_s save_tag;
vlmfa67ddc2004-06-03 03:38:44 +0000368 asn1p_expr_t *reft;
vlm76142452004-09-05 10:36:22 +0000369 int ret;
370
371 /*
372 * Fetch the _next_ tag for this type.
373 */
374 save_tag = v->tag; /* Save existing tag */
375 memset(&v->tag, 0, sizeof(v->tag)); /* Remove it temporarily */
376 ret = asn1f_fetch_tag(arg->asn, arg->mod, v, &tag, 0);
377 v->tag = save_tag; /* Restore the tag back */
378
379 if(ret == 0) return 0; /* If found tag, it's okay */
vlmfa67ddc2004-06-03 03:38:44 +0000380
vlmf645aff2004-08-22 03:09:24 +0000381 reft = asn1f_find_terminal_type(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000382 if(reft) {
383 switch(reft->expr_type) {
vlm76142452004-09-05 10:36:22 +0000384 case ASN_TYPE_ANY:
vlmfa67ddc2004-06-03 03:38:44 +0000385 case ASN_CONSTR_CHOICE:
386 return 1;
387 default:
388 return 0;
389 }
390 }
391
392 return 0;
393}
394
395/*
396 * Check that the tags are distinct.
397 */
398static int
399_asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b) {
400 struct asn1p_type_tag_s ta, tb;
401 int ra, rb;
402 int ret;
403
vlm76142452004-09-05 10:36:22 +0000404 ra = asn1f_fetch_tag(arg->asn, arg->mod, a, &ta, AFT_IMAGINARY_ANY);
405 rb = asn1f_fetch_tag(arg->asn, arg->mod, b, &tb, AFT_IMAGINARY_ANY);
vlmfa67ddc2004-06-03 03:38:44 +0000406
407 /*
408 * If both tags are explicitly or implicitly given, use them.
409 */
410 if(ra == 0 && rb == 0) {
411 /*
412 * Simple case: fetched both tags.
413 */
vlm76142452004-09-05 10:36:22 +0000414
415 if((ta.tag_value == tb.tag_value
416 && ta.tag_class == tb.tag_class)
417 || ta.tag_value == -1 /* Spread IMAGINARY ANY tag... */
418 || tb.tag_value == -1 /* ...it is an evil virus, fear it! */
419 ) {
vlmfa67ddc2004-06-03 03:38:44 +0000420 char *p = (a->expr_type == A1TC_EXTENSIBLE)
421 ?"potentially ":"";
422 FATAL("Component \"%s\" at line %d %shas the same tag "
423 "with component \"%s\" at line %d",
424 a->Identifier,
425 a->_lineno,
426 p,
427 b->Identifier,
428 b->_lineno
429 );
vlm4f4f56d2004-07-01 00:51:31 +0000430 if((arg->mod->module_flags & MSF_EXTENSIBILITY_IMPLIED)
431 && (a->expr_type == A1TC_EXTENSIBLE)
432 && (b->expr_type == A1TC_EXTENSIBLE)) {
433 FATAL("The previous error is due to "
434 "improper use of "
435 "EXTENSIBILITY IMPLIED flag "
436 "of module %s",
437 arg->mod->Identifier);
438 }
vlmfa67ddc2004-06-03 03:38:44 +0000439 return -1;
440 } else {
441 /* Tags are distinct */
442 return 0;
443 }
444 }
445
446 /**********************************************************
447 * Now we must perform some very funny recursion to check
448 * multiple components of CHOICE type, etc.
449 */
450
451 DEBUG("Comparing tags %s:%x <-> %s:%x",
452 a->Identifier, a->expr_type,
453 b->Identifier, b->expr_type);
454
455 if(a->meta_type == AMT_TYPEREF) {
vlmfa67ddc2004-06-03 03:38:44 +0000456
457 DEBUG(" %s is a type reference", a->Identifier);
458
vlmf645aff2004-08-22 03:09:24 +0000459 a = asn1f_lookup_symbol(arg, a->module, a->reference);
vlmfa67ddc2004-06-03 03:38:44 +0000460 if(!a) return 0; /* Already FATAL()'ed somewhere else */
vlmf645aff2004-08-22 03:09:24 +0000461 WITH_MODULE(a->module, ret = _asn1f_compare_tags(arg, a, b));
vlmfa67ddc2004-06-03 03:38:44 +0000462 return ret;
463 }
464
465 if(a->expr_type == ASN_CONSTR_CHOICE) {
466 asn1p_expr_t *v;
467
468 DEBUG(" %s is a choice type (%d)", a->Identifier, a->_mark);
469
470 /*
471 * Iterate over members of CHOICE.
472 */
473 //if(a->_mark & TM_RECURSION) return 0;
474 TQ_FOR(v, &(a->members), next) {
475 //a->_mark |= TM_RECURSION;
476 ret = _asn1f_compare_tags(arg, v, b);
477 //a->_mark &= ~TM_RECURSION;
478 if(ret) return ret;
479 }
480 return 0;
481 }
482
483 if(b->expr_type == ASN_CONSTR_CHOICE) {
484 return _asn1f_compare_tags(arg, b, a);
485 }
486
487 if(a->_mark & TM_RECURSION) return 0;
488 if(b->_mark & TM_RECURSION) return 0;
489 a->_mark |= TM_RECURSION;
490 b->_mark |= TM_RECURSION;
491 ret = _asn1f_compare_tags(arg, b, a);
492 a->_mark &= ~TM_RECURSION;
493 b->_mark &= ~TM_RECURSION;
494
495 return ret;
496}
497