1 #include "asn1fix_internal.h"
2 #include <asn1_namespace.h>
4 #define ADD_TAG(skip, newtag) do { \
6 if(skip && !(flags & AFT_FULL_COLLECT)) { \
7 if(newtag.tag_mode != TM_IMPLICIT) \
11 if(newtag.tag_mode == TM_IMPLICIT) \
14 __p = realloc((*tags), \
15 sizeof(struct asn1p_type_tag_s) * (count + 1)); \
18 (*tags)[count++] = newtag; \
19 if((flags & AFT_FETCH_OUTMOST)) return count; \
23 static int asn1f_fetch_minimal_choice_root_tag(arg_t *arg, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e flags);
26 asn1f_fetch_tags_impl(arg_t *arg, struct asn1p_type_tag_s **tags, int count, int skip, enum asn1f_aft_flags_e flags) {
27 asn1p_expr_t *expr = arg->expr;
29 DEBUG("Fetching tag from %s: meta %d, type %s", expr->Identifier,
30 expr->meta_type, expr->expr_type);
32 /* If this type is tagged, add this tag first */
33 if(expr->tag.tag_class != TC_NOCLASS)
34 ADD_TAG(skip, expr->tag);
37 if(expr->expr_type == A1TC_EXTENSIBLE) {
38 struct asn1p_type_tag_s tt;
39 memset(&tt, 0, sizeof(tt));
45 if(expr->meta_type == AMT_TYPE) {
46 struct asn1p_type_tag_s tt;
47 memset(&tt, 0, sizeof(tt));
48 tt.tag_class = TC_UNIVERSAL;
49 tt.tag_value = expr_type2uclass_value[expr->expr_type];
50 if(tt.tag_value == 0) {
51 if(expr->expr_type == ASN_TYPE_ANY
52 && (flags & AFT_IMAGINARY_ANY))
54 else if(expr->expr_type != ASN_CONSTR_CHOICE)
56 else if(count) return count;
57 else if((flags & AFT_CANON_CHOICE) == 0)
59 else if(asn1f_fetch_minimal_choice_root_tag(arg,
67 if(expr->meta_type == AMT_TYPEREF) {
69 DEBUG("Following the reference %s", expr->Identifier);
70 nexpr = asn1f_lookup_symbol(arg, expr->rhs_pspecs, expr->reference);
72 if(errno != EEXIST) /* -fknown-extern-type */
76 if((*tags)[count-1].tag_mode == TM_IMPLICIT) {
77 WARNING("Tagging mode for %s "
78 "is IMPLICIT, assuming %s "
79 "has exactly one tag",
81 asn1f_printable_reference(expr->reference)
85 FATAL("Tagging mode %s -> %s "
86 "dangerously incompatible",
88 asn1f_printable_reference(expr->reference)
94 if(expr->_mark & TM_RECURSION)
96 expr->_mark |= TM_RECURSION;
97 count = asn1f_fetch_tags_impl(arg, tags, count, skip, flags);
98 expr->_mark &= ~TM_RECURSION;
102 DEBUG("No tags discovered for type %d", expr->expr_type);
108 asn1f_fetch_minimal_choice_root_tag(arg_t *arg, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e flags) {
109 struct asn1p_type_tag_s min_tag;
112 memset(&min_tag, 0, sizeof(min_tag));
113 min_tag.tag_class = TC_PRIVATE + 1;
115 TQ_FOR(v, &(arg->expr->members), next) {
117 struct asn1p_type_tag_s *tags = 0;
120 if(v->expr_type == A1TC_EXTENSIBLE)
121 break; /* Search only within extension root */
124 count = asn1f_fetch_tags_impl(&tmparg, &tags, 0, 0, flags);
125 if(count <= 0) continue;
127 if(tags[0].tag_class < min_tag.tag_class)
129 else if(tags[0].tag_class == min_tag.tag_class
130 && tags[0].tag_value < min_tag.tag_value)
135 if(min_tag.tag_class == TC_PRIVATE + 1)
143 asn1f_fetch_outmost_tag(asn1p_t *asn, asn1_namespace_t *ns, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e flags) {
144 struct asn1p_type_tag_s *tags;
147 flags |= AFT_FETCH_OUTMOST;
149 count = asn1f_fetch_tags(asn, ns, mod, expr, &tags, flags);
150 if(count <= 0) return count;
159 asn1f_fetch_tags(asn1p_t *asn, asn1_namespace_t *ns, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s **tags_r, enum asn1f_aft_flags_e flags) {
161 struct asn1p_type_tag_s *tags = 0;
164 memset(&arg, 0, sizeof(arg));
170 count = asn1f_fetch_tags_impl(&arg, &tags, 0, 0, flags);