blob: dfda441002fe1cf841e4b64847bea848ba8f8c0a [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 ADD_TAG(skip, newtag) do { \
4 void *__p; \
Lev Walkin188ed2c2004-09-13 08:31:01 +00005 if(skip && !(flags & AFT_FULL_COLLECT)) { \
Lev Walkin906654e2004-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 } \
Lev Walkin8945e0e2004-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; \
Lev Walkin8945e0e2004-09-10 06:07:04 +000019} while(0)
Lev Walkinf15320b2004-06-03 03:38:44 +000020
Lev Walkin59b176e2005-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
Lev Walkin8945e0e2004-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;
Lev Walkinf15320b2004-06-03 03:38:44 +000027
Lev Walkin8945e0e2004-09-10 06:07:04 +000028 /* If this type is tagged, add this tag first */
29 if(expr->tag.tag_class != TC_NOCLASS)
30 ADD_TAG(skip, expr->tag);
31
32 /* REMOVE ME */
Lev Walkinf15320b2004-06-03 03:38:44 +000033 if(expr->expr_type == A1TC_EXTENSIBLE) {
Lev Walkin8945e0e2004-09-10 06:07:04 +000034 struct asn1p_type_tag_s tt;
35 memset(&tt, 0, sizeof(tt));
36 tt.tag_class = -1;
37 ADD_TAG(skip, tt);
38 return count;
Lev Walkinf15320b2004-06-03 03:38:44 +000039 }
40
41 if(expr->meta_type == AMT_TYPE) {
Lev Walkin8945e0e2004-09-10 06:07:04 +000042 struct asn1p_type_tag_s tt;
43 memset(&tt, 0, sizeof(tt));
44 tt.tag_class = TC_UNIVERSAL;
45 tt.tag_value = expr_type2uclass_value[expr->expr_type];
46 if(tt.tag_value == 0) {
47 if(expr->expr_type == ASN_TYPE_ANY
48 && (flags & AFT_IMAGINARY_ANY))
49 tt.tag_value = -1;
Lev Walkin59b176e2005-11-26 11:25:14 +000050 else if(expr->expr_type != ASN_CONSTR_CHOICE)
51 return -1;
52 else if(count) return count;
53 else if((flags & AFT_CANON_CHOICE) == 0)
54 return -1;
55 else if(asn1f_fetch_minimal_choice_root_tag(arg,
56 &tt, flags))
Lev Walkin8945e0e2004-09-10 06:07:04 +000057 return -1;
Lev Walkind541c252004-09-05 10:36:22 +000058 }
Lev Walkin8945e0e2004-09-10 06:07:04 +000059 ADD_TAG(skip, tt);
60 return count;
Lev Walkinf15320b2004-06-03 03:38:44 +000061 }
62
63 if(expr->meta_type == AMT_TYPEREF) {
Lev Walkin906654e2004-09-10 15:49:15 +000064 asn1p_expr_t *nexpr;
Lev Walkin59b176e2005-11-26 11:25:14 +000065 DEBUG("Following the reference %s", expr->Identifier);
Lev Walkin906654e2004-09-10 15:49:15 +000066 nexpr = asn1f_lookup_symbol(arg, expr->module, expr->reference);
67 if(nexpr == NULL) {
68 if(errno != EEXIST) /* -fknown-extern-type */
69 return -1;
70 if(!count)
71 return 0; /* OK */
72 if((*tags)[count-1].tag_mode == TM_IMPLICIT) {
73 WARNING("Tagging mode for %s "
74 "is IMPLICIT, assuming %s "
75 "has exactly one tag",
76 expr->Identifier,
77 asn1f_printable_reference(expr->reference)
78 );
79 return count;
80 }
81 FATAL("Tagging mode %s -> %s "
82 "dangerously incompatible",
83 expr->Identifier,
84 asn1f_printable_reference(expr->reference)
85 );
86 return -1;
87 } else {
88 arg->expr = nexpr;
89 }
Lev Walkinf15320b2004-06-03 03:38:44 +000090 if(expr->_mark & TM_RECURSION)
91 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +000092 expr->_mark |= TM_RECURSION;
Lev Walkin8945e0e2004-09-10 06:07:04 +000093 count = asn1f_fetch_tags_impl(arg, tags, count, skip, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +000094 expr->_mark &= ~TM_RECURSION;
Lev Walkin8945e0e2004-09-10 06:07:04 +000095 return count;
Lev Walkinf15320b2004-06-03 03:38:44 +000096 }
97
Lev Walkin59b176e2005-11-26 11:25:14 +000098 DEBUG("No tags discovered for type %d", expr->expr_type);
99
Lev Walkinf15320b2004-06-03 03:38:44 +0000100 return -1;
101}
102
Lev Walkin59b176e2005-11-26 11:25:14 +0000103static int
104asn1f_fetch_minimal_choice_root_tag(arg_t *arg, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e flags) {
105 struct asn1p_type_tag_s min_tag;
106 asn1p_expr_t *v;
107
108 memset(&min_tag, 0, sizeof(min_tag));
109 min_tag.tag_class = TC_PRIVATE + 1;
110
111 TQ_FOR(v, &(arg->expr->members), next) {
112 arg_t tmparg = *arg;
113 struct asn1p_type_tag_s *tags = 0;
114 int count;
115
116 if(v->expr_type == A1TC_EXTENSIBLE)
117 break; /* Search only within extension root */
118
119 tmparg.expr = v;
120 count = asn1f_fetch_tags_impl(&tmparg, &tags, 0, 0, flags);
121 if(count <= 0) continue;
122
123 if(tags[0].tag_class < min_tag.tag_class)
124 min_tag = tags[0];
125 else if(tags[0].tag_class == min_tag.tag_class
126 && tags[0].tag_value < min_tag.tag_value)
127 min_tag = tags[0];
128 free(tags);
129 }
130
131 if(min_tag.tag_class == TC_PRIVATE + 1)
132 return -1;
133 else
134 *tag = min_tag;
135 return 0;
136}
Lev Walkin8945e0e2004-09-10 06:07:04 +0000137
138int
Lev Walkin59b176e2005-11-26 11:25:14 +0000139asn1f_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) {
Lev Walkin8945e0e2004-09-10 06:07:04 +0000140 struct asn1p_type_tag_s *tags;
Lev Walkin8945e0e2004-09-10 06:07:04 +0000141 int count;
142
Lev Walkin59b176e2005-11-26 11:25:14 +0000143 flags |= AFT_FETCH_OUTMOST;
Lev Walkin8945e0e2004-09-10 06:07:04 +0000144
145 count = asn1f_fetch_tags(asn, mod, expr, &tags, flags);
146 if(count <= 0) return count;
147
148 *tag = tags[0];
149 free(tags);
150
151 return 0;
152}
153
154int
155asn1f_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) {
156 arg_t arg;
157 struct asn1p_type_tag_s *tags = 0;
158 int count;
159
160 memset(&arg, 0, sizeof(arg));
161 arg.asn = asn;
162 arg.mod = mod;
163 arg.expr = expr;
164
165 count = asn1f_fetch_tags_impl(&arg, &tags, 0, 0, flags);
166 if(count <= 0 && tags) {
167 free(tags);
168 tags = 0;
169 }
170 *tags_r = tags;
171 return count;
172}