upgrade: PER related changes
diff --git a/libasn1fix/asn1fix_constr.c b/libasn1fix/asn1fix_constr.c
index 7adbcac..ea2fcf1 100644
--- a/libasn1fix/asn1fix_constr.c
+++ b/libasn1fix/asn1fix_constr.c
@@ -1,7 +1,5 @@
#include "asn1fix_internal.h"
-#define AFT_MAGIC_ANY 1 /* _fetch_tag() flag */
-
static int _asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v);
static int _asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b);
static int _asn1f_fix_type_tag(arg_t *arg, asn1p_expr_t *expr);
@@ -337,6 +335,7 @@
case ASN_CONSTR_SEQUENCE:
case ASN_CONSTR_SET:
case ASN_CONSTR_CHOICE:
+ DEBUG("Checking tags of members of constructed types");
break;
default:
return 0;
@@ -353,6 +352,8 @@
if(expr->expr_type != ASN_CONSTR_SEQUENCE || v->marker.flags) {
asn1p_expr_t *nv;
for(nv = v; (nv = TQ_NEXT(nv, next));) {
+ DEBUG("S/C comparing tags %s s. %s",
+ v->Identifier, nv->Identifier);
if(_asn1f_compare_tags(arg, v, nv))
r_value = -1;
if(expr->expr_type == ASN_CONSTR_SEQUENCE
@@ -404,12 +405,15 @@
int ra, rb;
int ret;
- ra = asn1f_fetch_outmost_tag(arg->asn, arg->mod, a, &ta, AFT_MAGIC_ANY);
- rb = asn1f_fetch_outmost_tag(arg->asn, arg->mod, b, &tb, AFT_MAGIC_ANY);
+ ra = asn1f_fetch_outmost_tag(arg->asn, arg->mod, a,
+ &ta, AFT_IMAGINARY_ANY);
+ rb = asn1f_fetch_outmost_tag(arg->asn, arg->mod, b,
+ &tb, AFT_IMAGINARY_ANY);
/*
* If both tags are explicitly or implicitly given, use them.
*/
+ DEBUG("Fetching outmost tags: %d, %d", ra, rb);
if(ra == 0 && rb == 0) {
/*
* Simple case: fetched both tags.
diff --git a/libasn1fix/asn1fix_retrieve.c b/libasn1fix/asn1fix_retrieve.c
index 730c861..4236858 100644
--- a/libasn1fix/asn1fix_retrieve.c
+++ b/libasn1fix/asn1fix_retrieve.c
@@ -370,6 +370,7 @@
return NULL;
}
+ tc->_type_referenced = 1;
tc->_mark |= TM_RECURSION;
WITH_MODULE(tc->module,
expr = asn1f_find_terminal_thing(arg, tc, what));
diff --git a/libasn1fix/asn1fix_tags.c b/libasn1fix/asn1fix_tags.c
index ff662cc..dfda441 100644
--- a/libasn1fix/asn1fix_tags.c
+++ b/libasn1fix/asn1fix_tags.c
@@ -18,6 +18,9 @@
if((flags & AFT_FETCH_OUTMOST)) return count; \
} while(0)
+/* X.691, #22.2 */
+static int asn1f_fetch_minimal_choice_root_tag(arg_t *arg, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e flags);
+
static int
asn1f_fetch_tags_impl(arg_t *arg, struct asn1p_type_tag_s **tags, int count, int skip, enum asn1f_aft_flags_e flags) {
asn1p_expr_t *expr = arg->expr;
@@ -44,9 +47,13 @@
if(expr->expr_type == ASN_TYPE_ANY
&& (flags & AFT_IMAGINARY_ANY))
tt.tag_value = -1;
- else if(expr->expr_type == ASN_CONSTR_CHOICE)
- return count ? count : -1;
- else
+ else if(expr->expr_type != ASN_CONSTR_CHOICE)
+ return -1;
+ else if(count) return count;
+ else if((flags & AFT_CANON_CHOICE) == 0)
+ return -1;
+ else if(asn1f_fetch_minimal_choice_root_tag(arg,
+ &tt, flags))
return -1;
}
ADD_TAG(skip, tt);
@@ -55,6 +62,7 @@
if(expr->meta_type == AMT_TYPEREF) {
asn1p_expr_t *nexpr;
+ DEBUG("Following the reference %s", expr->Identifier);
nexpr = asn1f_lookup_symbol(arg, expr->module, expr->reference);
if(nexpr == NULL) {
if(errno != EEXIST) /* -fknown-extern-type */
@@ -87,18 +95,52 @@
return count;
}
+ DEBUG("No tags discovered for type %d", expr->expr_type);
+
return -1;
}
+static int
+asn1f_fetch_minimal_choice_root_tag(arg_t *arg, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e flags) {
+ struct asn1p_type_tag_s min_tag;
+ asn1p_expr_t *v;
+
+ memset(&min_tag, 0, sizeof(min_tag));
+ min_tag.tag_class = TC_PRIVATE + 1;
+
+ TQ_FOR(v, &(arg->expr->members), next) {
+ arg_t tmparg = *arg;
+ struct asn1p_type_tag_s *tags = 0;
+ int count;
+
+ if(v->expr_type == A1TC_EXTENSIBLE)
+ break; /* Search only within extension root */
+
+ tmparg.expr = v;
+ count = asn1f_fetch_tags_impl(&tmparg, &tags, 0, 0, flags);
+ if(count <= 0) continue;
+
+ if(tags[0].tag_class < min_tag.tag_class)
+ min_tag = tags[0];
+ else if(tags[0].tag_class == min_tag.tag_class
+ && tags[0].tag_value < min_tag.tag_value)
+ min_tag = tags[0];
+ free(tags);
+ }
+
+ if(min_tag.tag_class == TC_PRIVATE + 1)
+ return -1;
+ else
+ *tag = min_tag;
+ return 0;
+}
int
-asn1f_fetch_outmost_tag(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, int _aft_imaginary_any) {
+asn1f_fetch_outmost_tag(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e flags) {
struct asn1p_type_tag_s *tags;
- enum asn1f_aft_flags_e flags;
int count;
- flags = AFT_FETCH_OUTMOST;
- flags |= AFT_IMAGINARY_ANY * _aft_imaginary_any;
+ flags |= AFT_FETCH_OUTMOST;
count = asn1f_fetch_tags(asn, mod, expr, &tags, flags);
if(count <= 0) return count;
diff --git a/libasn1fix/asn1fix_tags.h b/libasn1fix/asn1fix_tags.h
index a4c31ad..0fbbefe 100644
--- a/libasn1fix/asn1fix_tags.h
+++ b/libasn1fix/asn1fix_tags.h
@@ -5,6 +5,7 @@
AFT_IMAGINARY_ANY = 0x01, /* Treat ANY tag as [IMAGINARY ANY] */
AFT_FETCH_OUTMOST = 0x02, /* Fetch only outmost tag */
AFT_FULL_COLLECT = 0x04, /* Collect all tags */
+ AFT_CANON_CHOICE = 0x08, /* Fetch the minimal CHOICE root tag */
};
/*
@@ -24,6 +25,6 @@
* Type3 ::= SEQUENCE { ... }
* Will yield [2] for Type1.
*/
-int asn1f_fetch_outmost_tag(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, int _aft_imaginary_any);
+int asn1f_fetch_outmost_tag(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e);
#endif /* _ASN1FIX_TAGS_H_ */