blob: 79fd0d865aa62722e4dcd1422d79e98cef9148ed [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
Lev Walkin8945e0e2004-09-10 06:07:04 +00003#define AFT_MAGIC_ANY 1 /* _fetch_tag() flag */
Lev Walkind541c252004-09-05 10:36:22 +00004
Lev Walkinf15320b2004-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);
Lev Walkind541c252004-09-05 10:36:22 +00007static int _asn1f_fix_type_tag(arg_t *arg, asn1p_expr_t *expr);
Lev Walkinf15320b2004-06-03 03:38:44 +00008
Lev Walkin4ec3b4c2004-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 */
Lev Walkin1004aa92004-09-08 00:28:11 +000071 while((memb = TQ_REMOVE(&(coft->members), next))) {
Lev Walkin4ec3b4c2004-08-22 03:09:24 +000072 TQ_ADD(&list, memb, next);
Lev Walkin1004aa92004-09-08 00:28:11 +000073 memb->parent_expr = expr;
74 }
Lev Walkin4ec3b4c2004-08-22 03:09:24 +000075
76 asn1p_expr_free(coft); /* Remove wrapper */
77 }
78
79 /* Move the stuff back */
Lev Walkin1ef05162004-08-25 00:42:25 +000080 TQ_MOVE(&(expr->members), &list);
Lev Walkin4ec3b4c2004-08-22 03:09:24 +000081
82 return r_value;
83}
Lev Walkinf15320b2004-06-03 03:38:44 +000084
Lev Walkind541c252004-09-05 10:36:22 +000085/*
86 * Fix extensibility parts inside constructed types (SEQUENCE, SET, CHOICE).
87 */
Lev Walkinf15320b2004-06-03 03:38:44 +000088int
89asn1f_fix_constr_ext(arg_t *arg) {
90 asn1p_expr_t *expr = arg->expr;
91 asn1p_expr_t *v;
92 TQ_HEAD(asn1p_expr_t) root_list;
93 TQ_HEAD(asn1p_expr_t) ext_list;
94 TQ_HEAD(asn1p_expr_t) *cur_list;
95 int r_value = 0;
96 int ext_count = 0;
97
98 switch(expr->expr_type) {
99 case ASN_CONSTR_SEQUENCE:
100 case ASN_CONSTR_SET:
101 case ASN_CONSTR_CHOICE:
102 break;
103 default:
104 return 0;
105 }
106
107 DEBUG("%s(%s) for line %d", __func__,
108 expr->Identifier, expr->_lineno);
109
110 TQ_INIT(&root_list);
111 TQ_INIT(&ext_list);
112 cur_list = (void *)&root_list;
113
Lev Walkind541c252004-09-05 10:36:22 +0000114 /*
115 * Split the set of fields into two lists, the root list
116 * and the extensions list.
117 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000118 while((v = TQ_REMOVE(&(expr->members), next))) {
119 if(v->expr_type == A1TC_EXTENSIBLE) {
120 ext_count++;
121 switch(ext_count) {
122 case 1: cur_list = (void *)&ext_list; break;
123 case 2:
124 cur_list = (void *)&root_list;
125 if(v->value) {
126 FATAL("Optional extension marker "
127 "must not contain "
128 "an exception mark "
129 "at line %d", v->_lineno);
130 r_value = -1;
131 }
132 asn1p_expr_free(v);
133 continue;
134 case 3:
135 FATAL("Third extension marker "
136 "is not allowed at line %d", v->_lineno);
137 default:
138 r_value = -1;
139 }
140 }
141
142 TQ_ADD(cur_list, v, next);
143 }
144
145 /*
146 * Copy the root list and extension list back into the main list.
147 */
Lev Walkin1ef05162004-08-25 00:42:25 +0000148 TQ_MOVE(&(expr->members), &root_list);
Lev Walkinf15320b2004-06-03 03:38:44 +0000149 while((v = TQ_REMOVE(&ext_list, next)))
150 TQ_ADD(&(expr->members), v, next);
151
152 if(arg->mod->module_flags & MSF_EXTENSIBILITY_IMPLIED
Lev Walkin1ef05162004-08-25 00:42:25 +0000153 && ext_count == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000154 v = asn1p_expr_new(0);
155 if(v) {
156 v->Identifier = strdup("...");
157 v->expr_type = A1TC_EXTENSIBLE;
158 v->meta_type = AMT_TYPE;
Lev Walkin7ccf2a42004-07-01 00:51:31 +0000159 v->_lineno = expr->_lineno; /* The best we can do */
Lev Walkinf15320b2004-06-03 03:38:44 +0000160 if(v->Identifier == NULL) {
161 asn1p_expr_free(v);
162 r_value = -1;
163 } else {
Lev Walkin1004aa92004-09-08 00:28:11 +0000164 asn1p_expr_add(expr, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000165 }
166 } else {
167 r_value = -1;
168 }
169 }
170
171 return r_value;
172}
173
174
175int
Lev Walkind541c252004-09-05 10:36:22 +0000176asn1f_fix_constr_tag(arg_t *arg, int fix_top_level) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000177 asn1p_expr_t *expr = arg->expr;
178 asn1p_expr_t *v;
Lev Walkinf15320b2004-06-03 03:38:44 +0000179 int root_tagged = 0; /* The root component is manually tagged */
180 int ext_tagged = 0; /* The extensions are manually tagged */
181 int component_number = 0;
182 int r_value = 0;
183
Lev Walkind541c252004-09-05 10:36:22 +0000184 DEBUG("%s(%s) for line %d", __func__,
185 expr->Identifier, expr->_lineno);
186
187 /*
188 * Fix the top-level type itself first.
189 */
190 if(fix_top_level) {
191 if(expr->tag.tag_class == TC_NOCLASS)
192 return r_value;
193
194 if(_asn1f_fix_type_tag(arg, expr))
195 r_value = -1;
196
197 return r_value;
198 }
199
Lev Walkinf15320b2004-06-03 03:38:44 +0000200 switch(expr->expr_type) {
201 case ASN_CONSTR_SEQUENCE:
202 case ASN_CONSTR_SET:
203 case ASN_CONSTR_CHOICE:
204 break;
205 default:
206 return 0;
207 }
208
Lev Walkinf15320b2004-06-03 03:38:44 +0000209 TQ_FOR(v, &(expr->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000210
211 if(v->expr_type == A1TC_EXTENSIBLE) {
212 component_number++;
213 continue;
214 }
215
216 if(v->tag.tag_class == TC_NOCLASS) {
217 continue;
Lev Walkinf15320b2004-06-03 03:38:44 +0000218 }
219
Lev Walkind541c252004-09-05 10:36:22 +0000220 switch(component_number) {
221 case 0: case 2:
222 root_tagged = 1; break;
223 default:
224 ext_tagged = 1; break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000225 }
226
Lev Walkind541c252004-09-05 10:36:22 +0000227 if(_asn1f_fix_type_tag(arg, v))
228 r_value = -1;
229
Lev Walkinf15320b2004-06-03 03:38:44 +0000230 }
231
Lev Walkind43915b2004-09-15 11:48:34 +0000232 if((arg->mod->module_flags & MSF_AUTOMATIC_TAGS)
233 && !root_tagged) {
234 if(ext_tagged) {
235 /* X.690: 28.4 */
236 FATAL("In %s at line %d: "
237 "extensions are tagged "
238 "but root components are not",
239 expr->Identifier, expr->_lineno);
240 r_value = -1;
241 } else {
242 /* Make a decision on automatic tagging */
243 expr->auto_tags_OK = 1;
244 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000245 }
246
247 return r_value;
248}
249
Lev Walkind541c252004-09-05 10:36:22 +0000250static int
251_asn1f_fix_type_tag(arg_t *arg, asn1p_expr_t *expr) {
252 int must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, expr);
Lev Walkin07f388c2004-10-11 11:43:08 +0000253 int module_impl_tags = (arg->mod->module_flags & MSF_IMPLICIT_TAGS);
Lev Walkind541c252004-09-05 10:36:22 +0000254 int r_value = 0;
255
Lev Walkin07f388c2004-10-11 11:43:08 +0000256 if(expr->tag.tag_mode == TM_DEFAULT) {
257 if(must_explicit || module_impl_tags == 0)
Lev Walkind541c252004-09-05 10:36:22 +0000258 expr->tag.tag_mode = TM_EXPLICIT;
Lev Walkin07f388c2004-10-11 11:43:08 +0000259 else
260 expr->tag.tag_mode = TM_IMPLICIT;
Lev Walkind541c252004-09-05 10:36:22 +0000261 }
262
263 /*
264 * Perform a final sanity check.
265 */
266 if(must_explicit) {
267 if(expr->tag.tag_mode == TM_IMPLICIT) {
268 FATAL("%s tagged in IMPLICIT mode "
269 "but must be EXPLICIT at line %d",
270 expr->Identifier, expr->_lineno);
271 r_value = -1;
272 } else {
273 expr->tag.tag_mode = TM_EXPLICIT;
274 }
275 }
276
277 return r_value;
278}
279
Lev Walkinf15320b2004-06-03 03:38:44 +0000280int
281asn1f_fix_constr_autotag(arg_t *arg) {
282 asn1p_expr_t *expr = arg->expr;
283 asn1p_expr_t *v;
Lev Walkinb8108ec2004-09-29 13:17:17 +0000284 asn1c_integer_t tag_value = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000285 int r_value = 0;
286
287 switch(expr->expr_type) {
288 case ASN_CONSTR_SEQUENCE:
289 case ASN_CONSTR_SET:
290 case ASN_CONSTR_CHOICE:
291 if(expr->auto_tags_OK)
292 break;
293 /* Automatic tagging is not applicable */
294 /* Fall through */
295 default:
296 return 0;
297 }
298
299 DEBUG("%s(%s) for line %d", __func__,
300 expr->Identifier, expr->_lineno);
301
302 TQ_FOR(v, &(expr->members), next) {
303 int must_explicit;
304
Lev Walkin144db9b2004-10-12 23:26:53 +0000305 if(v->expr_type == A1TC_EXTENSIBLE) {
306 /* 28.5, d) */
307 continue;
308 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000309
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000310 if(0) {
311 /* This may be not true in case COMPONENTS OF */
312 assert(v->tag.tag_class == TC_NOCLASS);
313 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000314
315 must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, v);
316
317 v->tag.tag_class = TC_CONTEXT_SPECIFIC;
318 v->tag.tag_mode = must_explicit ? TM_EXPLICIT : TM_IMPLICIT;
319 v->tag.tag_value = tag_value++;
320 }
321
322 return r_value;
323}
324
325/*
326 * Check that tags are distinct.
327 */
328int
329asn1f_check_constr_tags_distinct(arg_t *arg) {
330 asn1p_expr_t *expr = arg->expr;
331 asn1p_expr_t *v;
332 int r_value = 0;
333
334 switch(expr->expr_type) {
335 case ASN_CONSTR_SEQUENCE:
336 case ASN_CONSTR_SET:
337 case ASN_CONSTR_CHOICE:
338 break;
339 default:
340 return 0;
341 }
342
343 TQ_FOR(v, &(expr->members), next) {
344 /*
345 * In every series of non-mandatory components,
346 * the tags must be distinct from each other AND the
347 * tag of the following mandatory component.
348 * For SET and CHOICE treat everything as a big set of
349 * non-mandatory components.
350 */
Lev Walkind43915b2004-09-15 11:48:34 +0000351 if(expr->expr_type != ASN_CONSTR_SEQUENCE || v->marker.flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000352 asn1p_expr_t *nv;
353 for(nv = v; (nv = TQ_NEXT(nv, next));) {
354 if(_asn1f_compare_tags(arg, v, nv))
355 r_value = -1;
356 if(expr->expr_type == ASN_CONSTR_SEQUENCE
Lev Walkind43915b2004-09-15 11:48:34 +0000357 && !nv->marker.flags) break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000358 }
359 }
360 }
361
362 return r_value;
363}
364
365static int
366_asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v) {
Lev Walkind541c252004-09-05 10:36:22 +0000367 struct asn1p_type_tag_s tag;
368 struct asn1p_type_tag_s save_tag;
Lev Walkinf15320b2004-06-03 03:38:44 +0000369 asn1p_expr_t *reft;
Lev Walkind541c252004-09-05 10:36:22 +0000370 int ret;
371
372 /*
373 * Fetch the _next_ tag for this type.
374 */
375 save_tag = v->tag; /* Save existing tag */
376 memset(&v->tag, 0, sizeof(v->tag)); /* Remove it temporarily */
Lev Walkin8945e0e2004-09-10 06:07:04 +0000377 ret = asn1f_fetch_outmost_tag(arg->asn, arg->mod, v, &tag, 0);
Lev Walkind541c252004-09-05 10:36:22 +0000378 v->tag = save_tag; /* Restore the tag back */
379
380 if(ret == 0) return 0; /* If found tag, it's okay */
Lev Walkinf15320b2004-06-03 03:38:44 +0000381
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000382 reft = asn1f_find_terminal_type(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000383 if(reft) {
384 switch(reft->expr_type) {
Lev Walkind541c252004-09-05 10:36:22 +0000385 case ASN_TYPE_ANY:
Lev Walkinf15320b2004-06-03 03:38:44 +0000386 case ASN_CONSTR_CHOICE:
387 return 1;
388 default:
389 return 0;
390 }
391 }
392
393 return 0;
394}
395
396/*
397 * Check that the tags are distinct.
398 */
399static int
400_asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b) {
401 struct asn1p_type_tag_s ta, tb;
402 int ra, rb;
403 int ret;
404
Lev Walkin8945e0e2004-09-10 06:07:04 +0000405 ra = asn1f_fetch_outmost_tag(arg->asn, arg->mod, a, &ta, AFT_MAGIC_ANY);
406 rb = asn1f_fetch_outmost_tag(arg->asn, arg->mod, b, &tb, AFT_MAGIC_ANY);
Lev Walkinf15320b2004-06-03 03:38:44 +0000407
408 /*
409 * If both tags are explicitly or implicitly given, use them.
410 */
411 if(ra == 0 && rb == 0) {
412 /*
413 * Simple case: fetched both tags.
414 */
Lev Walkind541c252004-09-05 10:36:22 +0000415
416 if((ta.tag_value == tb.tag_value
417 && ta.tag_class == tb.tag_class)
418 || ta.tag_value == -1 /* Spread IMAGINARY ANY tag... */
419 || tb.tag_value == -1 /* ...it is an evil virus, fear it! */
420 ) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000421 char *p = (a->expr_type == A1TC_EXTENSIBLE)
422 ?"potentially ":"";
Lev Walkind43915b2004-09-15 11:48:34 +0000423 FATAL("Processing %s at line %d: component \"%s\" at line %d %shas the same tag "
Lev Walkinf15320b2004-06-03 03:38:44 +0000424 "with component \"%s\" at line %d",
Lev Walkind43915b2004-09-15 11:48:34 +0000425 arg->expr->Identifier,
426 arg->expr->_lineno,
Lev Walkinf15320b2004-06-03 03:38:44 +0000427 a->Identifier,
428 a->_lineno,
429 p,
430 b->Identifier,
431 b->_lineno
432 );
Lev Walkin7ccf2a42004-07-01 00:51:31 +0000433 if((arg->mod->module_flags & MSF_EXTENSIBILITY_IMPLIED)
434 && (a->expr_type == A1TC_EXTENSIBLE)
435 && (b->expr_type == A1TC_EXTENSIBLE)) {
436 FATAL("The previous error is due to "
437 "improper use of "
438 "EXTENSIBILITY IMPLIED flag "
439 "of module %s",
440 arg->mod->Identifier);
441 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000442 return -1;
443 } else {
444 /* Tags are distinct */
445 return 0;
446 }
447 }
448
449 /**********************************************************
450 * Now we must perform some very funny recursion to check
451 * multiple components of CHOICE type, etc.
452 */
453
454 DEBUG("Comparing tags %s:%x <-> %s:%x",
455 a->Identifier, a->expr_type,
456 b->Identifier, b->expr_type);
457
Lev Walkind43915b2004-09-15 11:48:34 +0000458 if(ra && a->meta_type == AMT_TYPEREF) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000459
460 DEBUG(" %s is a type reference", a->Identifier);
461
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000462 a = asn1f_lookup_symbol(arg, a->module, a->reference);
Lev Walkinf15320b2004-06-03 03:38:44 +0000463 if(!a) return 0; /* Already FATAL()'ed somewhere else */
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000464 WITH_MODULE(a->module, ret = _asn1f_compare_tags(arg, a, b));
Lev Walkinf15320b2004-06-03 03:38:44 +0000465 return ret;
466 }
467
Lev Walkind43915b2004-09-15 11:48:34 +0000468 if(ra && a->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000469 asn1p_expr_t *v;
470
471 DEBUG(" %s is a choice type (%d)", a->Identifier, a->_mark);
472
473 /*
474 * Iterate over members of CHOICE.
475 */
476 //if(a->_mark & TM_RECURSION) return 0;
477 TQ_FOR(v, &(a->members), next) {
478 //a->_mark |= TM_RECURSION;
479 ret = _asn1f_compare_tags(arg, v, b);
480 //a->_mark &= ~TM_RECURSION;
481 if(ret) return ret;
482 }
483 return 0;
484 }
485
Lev Walkind43915b2004-09-15 11:48:34 +0000486 if(rb && b->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000487 return _asn1f_compare_tags(arg, b, a);
488 }
489
490 if(a->_mark & TM_RECURSION) return 0;
491 if(b->_mark & TM_RECURSION) return 0;
492 a->_mark |= TM_RECURSION;
493 b->_mark |= TM_RECURSION;
494 ret = _asn1f_compare_tags(arg, b, a);
495 a->_mark &= ~TM_RECURSION;
496 b->_mark &= ~TM_RECURSION;
497
498 return ret;
499}
500