1 #include "asn1fix_internal.h"
3 static int _asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v);
4 static int _asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b);
5 static int _asn1f_fix_type_tag(arg_t *arg, asn1p_expr_t *expr);
8 asn1f_pull_components_of(arg_t *arg) {
9 TQ_HEAD(asn1p_expr_t) list;
10 asn1p_expr_t *expr = arg->expr;
14 switch(expr->expr_type) {
15 case ASN_CONSTR_SEQUENCE:
27 while((memb = TQ_REMOVE(&(expr->members), next))) {
28 asn1p_expr_t *coft; /* COMPONENTS OF thing itself */
29 asn1p_expr_t *terminal; /* Terminal of the referenced type */
31 if(memb->expr_type != A1TC_COMPONENTS_OF) {
32 TQ_ADD(&list, memb, next);
36 coft = TQ_FIRST(&memb->members);
38 assert(!TQ_NEXT(coft, next));
41 * Find the referenced type.
43 terminal = asn1f_find_terminal_type(arg, coft);
44 if(!terminal || (terminal->expr_type != expr->expr_type)) {
45 FATAL("COMPONENTS OF at line %d "
46 "must reference a %s type",
48 expr->expr_type==ASN_CONSTR_SET
51 TQ_ADD(&list, memb, next);
57 * Clone the final structure.
60 coft = asn1p_expr_clone(terminal, 1 /* Skip extensions */);
61 if(!coft) return -1; /* ENOMEM */
64 asn1p_expr_free(memb); /* Don't need it anymore*/
66 /* Actual removal clashes with constraints... skip. */
70 * Move all components of the cloned structure
71 * into the current one.
73 while((memb = TQ_REMOVE(&(coft->members), next))) {
74 TQ_ADD(&list, memb, next);
75 memb->parent_expr = expr;
78 asn1p_expr_free(coft); /* Remove wrapper */
81 /* Move the stuff back */
82 TQ_MOVE(&(expr->members), &list);
88 * Fix extensibility parts inside constructed types (SEQUENCE, SET, CHOICE).
91 asn1f_fix_constr_ext(arg_t *arg) {
92 asn1p_expr_t *expr = arg->expr;
94 TQ_HEAD(asn1p_expr_t) root_list;
95 TQ_HEAD(asn1p_expr_t) ext_list;
96 TQ_HEAD(asn1p_expr_t) *cur_list;
100 switch(expr->expr_type) {
101 case ASN_CONSTR_SEQUENCE:
103 case ASN_CONSTR_CHOICE:
109 DEBUG("(%s) for line %d", expr->Identifier, expr->_lineno);
113 cur_list = (void *)&root_list;
116 * Split the set of fields into two lists, the root list
117 * and the extensions list.
119 while((v = TQ_REMOVE(&(expr->members), next))) {
120 if(v->expr_type == A1TC_EXTENSIBLE) {
123 case 1: cur_list = (void *)&ext_list; break;
125 cur_list = (void *)&root_list;
127 FATAL("Optional extension marker "
130 "at line %d", v->_lineno);
136 FATAL("Third extension marker "
137 "is not allowed at line %d", v->_lineno);
144 TQ_ADD(cur_list, v, next);
148 * Copy the root list and extension list back into the main list.
150 TQ_MOVE(&(expr->members), &root_list);
151 while((v = TQ_REMOVE(&ext_list, next)))
152 TQ_ADD(&(expr->members), v, next);
154 if(arg->mod->module_flags & MSF_EXTENSIBILITY_IMPLIED
156 v = asn1p_expr_new(0, arg->mod);
158 v->Identifier = strdup("...");
159 v->expr_type = A1TC_EXTENSIBLE;
160 v->meta_type = AMT_TYPE;
161 v->_lineno = expr->_lineno; /* The best we can do */
162 if(v->Identifier == NULL) {
166 asn1p_expr_add(expr, v);
178 asn1f_fix_constr_tag(arg_t *arg, int fix_top_level) {
179 asn1p_expr_t *expr = arg->expr;
181 int root_tagged = 0; /* The root component is manually tagged */
182 int ext_tagged = 0; /* The extensions are manually tagged */
183 int component_number = 0;
186 DEBUG("(%s) for line %d", expr->Identifier, expr->_lineno);
189 * Fix the top-level type itself first.
192 if(expr->tag.tag_class == TC_NOCLASS)
195 if(_asn1f_fix_type_tag(arg, expr))
201 switch(expr->expr_type) {
202 case ASN_CONSTR_SEQUENCE:
204 case ASN_CONSTR_CHOICE:
210 TQ_FOR(v, &(expr->members), next) {
212 if(v->expr_type == A1TC_EXTENSIBLE) {
217 if(v->tag.tag_class == TC_NOCLASS) {
221 switch(component_number) {
223 root_tagged = 1; break;
225 ext_tagged = 1; break;
228 if(_asn1f_fix_type_tag(arg, v))
233 if((arg->mod->module_flags & MSF_AUTOMATIC_TAGS)
237 FATAL("In %s at line %d: "
238 "extensions are tagged "
239 "but root components are not",
240 expr->Identifier, expr->_lineno);
243 /* Make a decision on automatic tagging */
244 expr->auto_tags_OK = 1;
252 _asn1f_fix_type_tag(arg_t *arg, asn1p_expr_t *expr) {
253 int must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, expr);
254 int module_impl_tags = (arg->mod->module_flags
255 & (MSF_IMPLICIT_TAGS | MSF_AUTOMATIC_TAGS));
258 if(expr->tag.tag_mode == TM_DEFAULT) {
259 if(must_explicit || module_impl_tags == 0)
260 expr->tag.tag_mode = TM_EXPLICIT;
262 expr->tag.tag_mode = TM_IMPLICIT;
266 * Perform a final sanity check.
269 if(expr->tag.tag_mode == TM_IMPLICIT) {
270 FATAL("%s tagged in IMPLICIT mode "
271 "but must be EXPLICIT at line %d",
272 expr->Identifier, expr->_lineno);
275 expr->tag.tag_mode = TM_EXPLICIT;
283 asn1f_fix_constr_autotag(arg_t *arg) {
284 asn1p_expr_t *expr = arg->expr;
286 asn1c_integer_t tag_value = 0;
289 switch(expr->expr_type) {
290 case ASN_CONSTR_SEQUENCE:
292 case ASN_CONSTR_CHOICE:
293 if(expr->auto_tags_OK)
295 /* Automatic tagging is not applicable */
301 DEBUG("(%s) for line %d", expr->Identifier, expr->_lineno);
303 TQ_FOR(v, &(expr->members), next) {
306 if(v->expr_type == A1TC_EXTENSIBLE) {
312 /* This may be not true in case COMPONENTS OF */
313 assert(v->tag.tag_class == TC_NOCLASS);
316 must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, v);
318 v->tag.tag_class = TC_CONTEXT_SPECIFIC;
319 v->tag.tag_mode = must_explicit ? TM_EXPLICIT : TM_IMPLICIT;
320 v->tag.tag_value = tag_value++;
327 * Check that tags are distinct.
330 asn1f_check_constr_tags_distinct(arg_t *arg) {
331 asn1p_expr_t *expr = arg->expr;
335 switch(expr->expr_type) {
336 case ASN_CONSTR_SEQUENCE:
338 case ASN_CONSTR_CHOICE:
344 TQ_FOR(v, &(expr->members), next) {
346 * In every series of non-mandatory components,
347 * the tags must be distinct from each other AND the
348 * tag of the following mandatory component.
349 * For SET and CHOICE treat everything as a big set of
350 * non-mandatory components.
352 if(expr->expr_type != ASN_CONSTR_SEQUENCE || v->marker.flags) {
354 for(nv = v; (nv = TQ_NEXT(nv, next));) {
355 DEBUG("S/C comparing tags %s s. %s",
356 v->Identifier, nv->Identifier);
357 if(_asn1f_compare_tags(arg, v, nv))
359 if(expr->expr_type == ASN_CONSTR_SEQUENCE
360 && !nv->marker.flags) break;
369 _asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v) {
370 struct asn1p_type_tag_s tag;
371 struct asn1p_type_tag_s save_tag;
376 * Fetch the _next_ tag for this type.
378 save_tag = v->tag; /* Save existing tag */
379 memset(&v->tag, 0, sizeof(v->tag)); /* Remove it temporarily */
380 ret = asn1f_fetch_outmost_tag(arg->asn, arg->ns, arg->mod, v, &tag, 0);
381 v->tag = save_tag; /* Restore the tag back */
383 if(ret == 0) return 0; /* If found tag, it's okay */
385 reft = asn1f_find_terminal_type(arg, v);
387 switch(reft->expr_type) {
389 case ASN_CONSTR_CHOICE:
400 * Check that the tags are distinct.
403 _asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b) {
404 struct asn1p_type_tag_s ta, tb;
408 ra = asn1f_fetch_outmost_tag(arg->asn, arg->ns, arg->mod, a,
409 &ta, AFT_IMAGINARY_ANY);
410 rb = asn1f_fetch_outmost_tag(arg->asn, arg->ns, arg->mod, b,
411 &tb, AFT_IMAGINARY_ANY);
414 * If both tags are explicitly or implicitly given, use them.
416 DEBUG("Fetching outmost tags: %d, %d", ra, rb);
417 if(ra == 0 && rb == 0) {
419 * Simple case: fetched both tags.
422 if((ta.tag_value == tb.tag_value
423 && ta.tag_class == tb.tag_class)
424 || ta.tag_value == -1 /* Spread IMAGINARY ANY tag... */
425 || tb.tag_value == -1 /* ...it is an evil virus, fear it! */
427 char tagbuf[2][TAG2STRING_BUFFER_SIZE];
428 char *p = (a->expr_type == A1TC_EXTENSIBLE)
430 FATAL("Processing %s at line %d: component \"%s\" at line %d %shas the same tag "
431 "as component \"%s\" at line %d",
432 arg->expr->Identifier,
440 FATAL("Consider adding AUTOMATIC TAGS "
441 "after module %s DEFINITIONS, "
442 "or manually tag components",
443 arg->expr->module->ModuleName);
444 DEBUG("Tags: %s %s vs. %s %s",
445 asn1p_tag2string(&ta, tagbuf[0]),
447 asn1p_tag2string(&tb, tagbuf[1]),
450 if((arg->mod->module_flags & MSF_EXTENSIBILITY_IMPLIED)
451 && (a->expr_type == A1TC_EXTENSIBLE)
452 && (b->expr_type == A1TC_EXTENSIBLE)) {
453 FATAL("The previous error is due to "
455 "EXTENSIBILITY IMPLIED flag "
457 arg->mod->ModuleName);
461 /* Tags are distinct */
466 /**********************************************************
467 * Now we must perform some very funny recursion to check
468 * multiple components of CHOICE type, etc.
471 DEBUG("Comparing tags %s:%x <-> %s:%x",
472 a->Identifier, a->expr_type,
473 b->Identifier, b->expr_type);
475 if(ra && a->meta_type == AMT_TYPEREF) {
477 DEBUG(" %s is a type reference", a->Identifier);
479 a = asn1f_lookup_symbol(arg, a->rhs_pspecs, a->reference);
480 if(!a) return 0; /* Already FATAL()'ed somewhere else */
481 return WITH_MODULE(a->module, _asn1f_compare_tags(arg, a, b));
484 if(ra && a->expr_type == ASN_CONSTR_CHOICE) {
487 DEBUG(" %s is a choice type (%d)", a->Identifier, a->_mark);
490 * Iterate over members of CHOICE.
492 //if(a->_mark & TM_RECURSION) return 0;
493 TQ_FOR(v, &(a->members), next) {
494 //a->_mark |= TM_RECURSION;
495 ret = _asn1f_compare_tags(arg, v, b);
496 //a->_mark &= ~TM_RECURSION;
502 if(rb && b->expr_type == ASN_CONSTR_CHOICE) {
503 return _asn1f_compare_tags(arg, b, a);
506 if(a->_mark & TM_RECURSION) return 0;
507 if(b->_mark & TM_RECURSION) return 0;
508 a->_mark |= TM_RECURSION;
509 b->_mark |= TM_RECURSION;
510 ret = _asn1f_compare_tags(arg, b, a);
511 a->_mark &= ~TM_RECURSION;
512 b->_mark &= ~TM_RECURSION;