blob: db4d4ed18b7c593ec70c04844dbd007ef5ba8efa [file] [log] [blame]
vlmfa67ddc2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
vlm8fbd5622004-09-10 06:07:04 +00003#define ADD_TAG(skip, newtag) do { \
4 void *__p; \
vlm72425de2004-09-13 08:31:01 +00005 if(skip && !(flags & AFT_FULL_COLLECT)) { \
vlm1308d2b2004-09-10 15:49:15 +00006 if(newtag.tag_mode != TM_IMPLICIT) \
7 skip--; \
8 break; \
9 } else { \
10 if(newtag.tag_mode == TM_IMPLICIT) \
11 skip++; \
12 } \
vlm8fbd5622004-09-10 06:07:04 +000013 __p = realloc((*tags), \
14 sizeof(struct asn1p_type_tag_s) * (count + 1)); \
15 if(!__p) return -1; \
16 *tags = __p; \
17 (*tags)[count++] = newtag; \
18 if((flags & AFT_FETCH_OUTMOST)) return count; \
vlm8fbd5622004-09-10 06:07:04 +000019} while(0)
vlmfa67ddc2004-06-03 03:38:44 +000020
vlm337167e2005-11-26 11:25:14 +000021/* X.691, #22.2 */
22static int asn1f_fetch_minimal_choice_root_tag(arg_t *arg, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e flags);
23
vlm8fbd5622004-09-10 06:07:04 +000024static int
25asn1f_fetch_tags_impl(arg_t *arg, struct asn1p_type_tag_s **tags, int count, int skip, enum asn1f_aft_flags_e flags) {
26 asn1p_expr_t *expr = arg->expr;
vlmfa67ddc2004-06-03 03:38:44 +000027
vlmdc7cf042006-03-09 08:49:26 +000028 DEBUG("Fetching tag from %s: meta %d, type %s", expr->Identifier,
29 expr->meta_type, expr->expr_type);
30
vlm8fbd5622004-09-10 06:07:04 +000031 /* If this type is tagged, add this tag first */
32 if(expr->tag.tag_class != TC_NOCLASS)
33 ADD_TAG(skip, expr->tag);
34
35 /* REMOVE ME */
vlmfa67ddc2004-06-03 03:38:44 +000036 if(expr->expr_type == A1TC_EXTENSIBLE) {
vlm8fbd5622004-09-10 06:07:04 +000037 struct asn1p_type_tag_s tt;
38 memset(&tt, 0, sizeof(tt));
39 tt.tag_class = -1;
40 ADD_TAG(skip, tt);
41 return count;
vlmfa67ddc2004-06-03 03:38:44 +000042 }
43
44 if(expr->meta_type == AMT_TYPE) {
vlm8fbd5622004-09-10 06:07:04 +000045 struct asn1p_type_tag_s tt;
46 memset(&tt, 0, sizeof(tt));
47 tt.tag_class = TC_UNIVERSAL;
48 tt.tag_value = expr_type2uclass_value[expr->expr_type];
49 if(tt.tag_value == 0) {
50 if(expr->expr_type == ASN_TYPE_ANY
51 && (flags & AFT_IMAGINARY_ANY))
52 tt.tag_value = -1;
vlm337167e2005-11-26 11:25:14 +000053 else if(expr->expr_type != ASN_CONSTR_CHOICE)
54 return -1;
55 else if(count) return count;
56 else if((flags & AFT_CANON_CHOICE) == 0)
57 return -1;
58 else if(asn1f_fetch_minimal_choice_root_tag(arg,
59 &tt, flags))
vlm8fbd5622004-09-10 06:07:04 +000060 return -1;
vlm76142452004-09-05 10:36:22 +000061 }
vlm8fbd5622004-09-10 06:07:04 +000062 ADD_TAG(skip, tt);
63 return count;
vlmfa67ddc2004-06-03 03:38:44 +000064 }
65
66 if(expr->meta_type == AMT_TYPEREF) {
vlm1308d2b2004-09-10 15:49:15 +000067 asn1p_expr_t *nexpr;
vlm337167e2005-11-26 11:25:14 +000068 DEBUG("Following the reference %s", expr->Identifier);
vlm0c6d3812006-03-21 03:40:38 +000069 nexpr = asn1f_lookup_symbol(arg, expr->module, expr->rhs_pspecs, expr->reference);
vlm1308d2b2004-09-10 15:49:15 +000070 if(nexpr == NULL) {
71 if(errno != EEXIST) /* -fknown-extern-type */
72 return -1;
73 if(!count)
74 return 0; /* OK */
75 if((*tags)[count-1].tag_mode == TM_IMPLICIT) {
76 WARNING("Tagging mode for %s "
77 "is IMPLICIT, assuming %s "
78 "has exactly one tag",
79 expr->Identifier,
80 asn1f_printable_reference(expr->reference)
81 );
82 return count;
83 }
84 FATAL("Tagging mode %s -> %s "
85 "dangerously incompatible",
86 expr->Identifier,
87 asn1f_printable_reference(expr->reference)
88 );
89 return -1;
90 } else {
91 arg->expr = nexpr;
92 }
vlmfa67ddc2004-06-03 03:38:44 +000093 if(expr->_mark & TM_RECURSION)
94 return -1;
vlmfa67ddc2004-06-03 03:38:44 +000095 expr->_mark |= TM_RECURSION;
vlm8fbd5622004-09-10 06:07:04 +000096 count = asn1f_fetch_tags_impl(arg, tags, count, skip, flags);
vlmfa67ddc2004-06-03 03:38:44 +000097 expr->_mark &= ~TM_RECURSION;
vlm8fbd5622004-09-10 06:07:04 +000098 return count;
vlmfa67ddc2004-06-03 03:38:44 +000099 }
100
vlm337167e2005-11-26 11:25:14 +0000101 DEBUG("No tags discovered for type %d", expr->expr_type);
102
vlmfa67ddc2004-06-03 03:38:44 +0000103 return -1;
104}
105
vlm337167e2005-11-26 11:25:14 +0000106static int
107asn1f_fetch_minimal_choice_root_tag(arg_t *arg, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e flags) {
108 struct asn1p_type_tag_s min_tag;
109 asn1p_expr_t *v;
110
111 memset(&min_tag, 0, sizeof(min_tag));
112 min_tag.tag_class = TC_PRIVATE + 1;
113
114 TQ_FOR(v, &(arg->expr->members), next) {
115 arg_t tmparg = *arg;
116 struct asn1p_type_tag_s *tags = 0;
117 int count;
118
119 if(v->expr_type == A1TC_EXTENSIBLE)
120 break; /* Search only within extension root */
121
122 tmparg.expr = v;
123 count = asn1f_fetch_tags_impl(&tmparg, &tags, 0, 0, flags);
124 if(count <= 0) continue;
125
126 if(tags[0].tag_class < min_tag.tag_class)
127 min_tag = tags[0];
128 else if(tags[0].tag_class == min_tag.tag_class
129 && tags[0].tag_value < min_tag.tag_value)
130 min_tag = tags[0];
131 free(tags);
132 }
133
134 if(min_tag.tag_class == TC_PRIVATE + 1)
135 return -1;
136 else
137 *tag = min_tag;
138 return 0;
139}
vlm8fbd5622004-09-10 06:07:04 +0000140
141int
vlm337167e2005-11-26 11:25:14 +0000142asn1f_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) {
vlm8fbd5622004-09-10 06:07:04 +0000143 struct asn1p_type_tag_s *tags;
vlm8fbd5622004-09-10 06:07:04 +0000144 int count;
145
vlm337167e2005-11-26 11:25:14 +0000146 flags |= AFT_FETCH_OUTMOST;
vlm8fbd5622004-09-10 06:07:04 +0000147
148 count = asn1f_fetch_tags(asn, mod, expr, &tags, flags);
149 if(count <= 0) return count;
150
151 *tag = tags[0];
152 free(tags);
153
154 return 0;
155}
156
157int
158asn1f_fetch_tags(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s **tags_r, enum asn1f_aft_flags_e flags) {
159 arg_t arg;
160 struct asn1p_type_tag_s *tags = 0;
161 int count;
162
163 memset(&arg, 0, sizeof(arg));
164 arg.asn = asn;
165 arg.mod = mod;
166 arg.expr = expr;
167
168 count = asn1f_fetch_tags_impl(&arg, &tags, 0, 0, flags);
169 if(count <= 0 && tags) {
170 free(tags);
171 tags = 0;
172 }
173 *tags_r = tags;
174 return count;
175}