blob: 4db233f6eda8bce6ca2a0556796f6bc470ec0637 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
3static int _asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v);
4static int _asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b);
5
6
7int
8asn1f_fix_constr_ext(arg_t *arg) {
9 asn1p_expr_t *expr = arg->expr;
10 asn1p_expr_t *v;
11 TQ_HEAD(asn1p_expr_t) root_list;
12 TQ_HEAD(asn1p_expr_t) ext_list;
13 TQ_HEAD(asn1p_expr_t) *cur_list;
14 int r_value = 0;
15 int ext_count = 0;
16
17 switch(expr->expr_type) {
18 case ASN_CONSTR_SEQUENCE:
19 case ASN_CONSTR_SET:
20 case ASN_CONSTR_CHOICE:
21 break;
22 default:
23 return 0;
24 }
25
26 DEBUG("%s(%s) for line %d", __func__,
27 expr->Identifier, expr->_lineno);
28
29 TQ_INIT(&root_list);
30 TQ_INIT(&ext_list);
31 cur_list = (void *)&root_list;
32
33 while((v = TQ_REMOVE(&(expr->members), next))) {
34 if(v->expr_type == A1TC_EXTENSIBLE) {
35 ext_count++;
36 switch(ext_count) {
37 case 1: cur_list = (void *)&ext_list; break;
38 case 2:
39 cur_list = (void *)&root_list;
40 if(v->value) {
41 FATAL("Optional extension marker "
42 "must not contain "
43 "an exception mark "
44 "at line %d", v->_lineno);
45 r_value = -1;
46 }
47 asn1p_expr_free(v);
48 continue;
49 case 3:
50 FATAL("Third extension marker "
51 "is not allowed at line %d", v->_lineno);
52 default:
53 r_value = -1;
54 }
55 }
56
57 TQ_ADD(cur_list, v, next);
58 }
59
60 /*
61 * Copy the root list and extension list back into the main list.
62 */
63 TQ_HEAD_COPY(&(expr->members), &root_list);
64 while((v = TQ_REMOVE(&ext_list, next)))
65 TQ_ADD(&(expr->members), v, next);
66
67 if(arg->mod->module_flags & MSF_EXTENSIBILITY_IMPLIED
68 && ext_count < 1) {
69 v = asn1p_expr_new(0);
70 if(v) {
71 v->Identifier = strdup("...");
72 v->expr_type = A1TC_EXTENSIBLE;
73 v->meta_type = AMT_TYPE;
Lev Walkin7ccf2a42004-07-01 00:51:31 +000074 v->_lineno = expr->_lineno; /* The best we can do */
Lev Walkinf15320b2004-06-03 03:38:44 +000075 if(v->Identifier == NULL) {
76 asn1p_expr_free(v);
77 r_value = -1;
78 } else {
79 TQ_ADD(&(expr->members), v, next);
80 }
81 } else {
82 r_value = -1;
83 }
84 }
85
86 return r_value;
87}
88
89
90int
91asn1f_fix_constr_tag(arg_t *arg) {
92 asn1p_expr_t *expr = arg->expr;
93 asn1p_expr_t *v;
94 int fl_impl_tags = 0;
95 int fl_auto_tags = 0;
96 int root_tagged = 0; /* The root component is manually tagged */
97 int ext_tagged = 0; /* The extensions are manually tagged */
98 int component_number = 0;
99 int r_value = 0;
100
101 switch(expr->expr_type) {
102 case ASN_CONSTR_SEQUENCE:
103 case ASN_CONSTR_SET:
104 case ASN_CONSTR_CHOICE:
105 break;
106 default:
107 return 0;
108 }
109
110 fl_impl_tags = (arg->mod->module_flags & MSF_IMPLICIT_TAGS);
111 fl_auto_tags = (arg->mod->module_flags & MSF_AUTOMATIC_TAGS);
112
113 DEBUG("%s(%s) {%d, %d} for line %d", __func__,
114 expr->Identifier, fl_impl_tags, fl_auto_tags, expr->_lineno);
115
116 TQ_FOR(v, &(expr->members), next) {
117 int must_explicit = 0;
118
119 if(v->expr_type == A1TC_EXTENSIBLE) {
120 component_number++;
121 continue;
122 }
123
124 if(v->tag.tag_class == TC_NOCLASS) {
125 continue;
126 } else {
127 switch(component_number) {
128 case 0: case 2:
129 root_tagged = 1; break;
130 default:
131 ext_tagged = 1; break;
132 }
133 }
134
135 must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, v);
136
137 if(fl_impl_tags) {
138 if(v->tag.tag_mode != TM_EXPLICIT) {
139 if(must_explicit)
140 v->tag.tag_mode = TM_EXPLICIT;
141 else
142 v->tag.tag_mode = TM_IMPLICIT;
143 }
144 } else {
145 if(v->tag.tag_mode == TM_DEFAULT) {
146 v->tag.tag_mode = TM_EXPLICIT;
147 }
148 }
149
150 /*
151 * Perform a final sanity check.
152 */
153 if(must_explicit) {
154 if(v->tag.tag_mode == TM_IMPLICIT) {
155 FATAL("%s tagged in IMPLICIT mode "
156 "but must be EXPLICIT at line %d",
157 v->Identifier, v->_lineno);
158 r_value = -1;
159 } else {
160 v->tag.tag_mode = TM_EXPLICIT;
161 }
162 }
163 }
164
165 if(ext_tagged && !root_tagged) {
166 FATAL("In %s at line %d: "
167 "extensions are tagged "
168 "but root components are not",
169 expr->Identifier, expr->_lineno);
170 r_value = -1;
171 } else if(!root_tagged && !ext_tagged && fl_auto_tags) {
172 expr->auto_tags_OK = 1;
173 }
174
175 return r_value;
176}
177
178int
179asn1f_fix_constr_autotag(arg_t *arg) {
180 asn1p_expr_t *expr = arg->expr;
181 asn1p_expr_t *v;
182 asn1_integer_t tag_value = 0;
183 int r_value = 0;
184
185 switch(expr->expr_type) {
186 case ASN_CONSTR_SEQUENCE:
187 case ASN_CONSTR_SET:
188 case ASN_CONSTR_CHOICE:
189 if(expr->auto_tags_OK)
190 break;
191 /* Automatic tagging is not applicable */
192 /* Fall through */
193 default:
194 return 0;
195 }
196
197 DEBUG("%s(%s) for line %d", __func__,
198 expr->Identifier, expr->_lineno);
199
200 TQ_FOR(v, &(expr->members), next) {
201 int must_explicit;
202
203 if(v->expr_type == A1TC_EXTENSIBLE)
204 break;
205
206 assert(v->tag.tag_class == TC_NOCLASS);
207
208 must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, v);
209
210 v->tag.tag_class = TC_CONTEXT_SPECIFIC;
211 v->tag.tag_mode = must_explicit ? TM_EXPLICIT : TM_IMPLICIT;
212 v->tag.tag_value = tag_value++;
213 }
214
215 return r_value;
216}
217
218/*
219 * Check that tags are distinct.
220 */
221int
222asn1f_check_constr_tags_distinct(arg_t *arg) {
223 asn1p_expr_t *expr = arg->expr;
224 asn1p_expr_t *v;
225 int r_value = 0;
226
227 switch(expr->expr_type) {
228 case ASN_CONSTR_SEQUENCE:
229 case ASN_CONSTR_SET:
230 case ASN_CONSTR_CHOICE:
231 break;
232 default:
233 return 0;
234 }
235
236 TQ_FOR(v, &(expr->members), next) {
237 /*
238 * In every series of non-mandatory components,
239 * the tags must be distinct from each other AND the
240 * tag of the following mandatory component.
241 * For SET and CHOICE treat everything as a big set of
242 * non-mandatory components.
243 */
244 if(expr->expr_type != ASN_CONSTR_SEQUENCE || v->marker) {
245 asn1p_expr_t *nv;
246 for(nv = v; (nv = TQ_NEXT(nv, next));) {
247 if(_asn1f_compare_tags(arg, v, nv))
248 r_value = -1;
249 if(expr->expr_type == ASN_CONSTR_SEQUENCE
250 && !nv->marker) break;
251 }
252 }
253 }
254
255 return r_value;
256}
257
258static int
259_asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v) {
260 asn1p_expr_t *reft;
261
262 reft = asn1f_find_terminal_type(arg, v, 0);
263 if(reft) {
264 switch(reft->expr_type) {
265 case ASN_CONSTR_CHOICE:
266 return 1;
267 default:
268 return 0;
269 }
270 }
271
272 return 0;
273}
274
275/*
276 * Check that the tags are distinct.
277 */
278static int
279_asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b) {
280 struct asn1p_type_tag_s ta, tb;
281 int ra, rb;
282 int ret;
283
284 ra = asn1f_fetch_tag(arg->asn, arg->mod, a, &ta);
285 rb = asn1f_fetch_tag(arg->asn, arg->mod, b, &tb);
286
287 /*
288 * If both tags are explicitly or implicitly given, use them.
289 */
290 if(ra == 0 && rb == 0) {
291 /*
292 * Simple case: fetched both tags.
293 */
294 if(ta.tag_value == tb.tag_value
295 && ta.tag_class == tb.tag_class) {
296 char *p = (a->expr_type == A1TC_EXTENSIBLE)
297 ?"potentially ":"";
298 FATAL("Component \"%s\" at line %d %shas the same tag "
299 "with component \"%s\" at line %d",
300 a->Identifier,
301 a->_lineno,
302 p,
303 b->Identifier,
304 b->_lineno
305 );
Lev Walkin7ccf2a42004-07-01 00:51:31 +0000306 if((arg->mod->module_flags & MSF_EXTENSIBILITY_IMPLIED)
307 && (a->expr_type == A1TC_EXTENSIBLE)
308 && (b->expr_type == A1TC_EXTENSIBLE)) {
309 FATAL("The previous error is due to "
310 "improper use of "
311 "EXTENSIBILITY IMPLIED flag "
312 "of module %s",
313 arg->mod->Identifier);
314 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000315 return -1;
316 } else {
317 /* Tags are distinct */
318 return 0;
319 }
320 }
321
322 /**********************************************************
323 * Now we must perform some very funny recursion to check
324 * multiple components of CHOICE type, etc.
325 */
326
327 DEBUG("Comparing tags %s:%x <-> %s:%x",
328 a->Identifier, a->expr_type,
329 b->Identifier, b->expr_type);
330
331 if(a->meta_type == AMT_TYPEREF) {
332 asn1p_module_t *mod;
333
334 DEBUG(" %s is a type reference", a->Identifier);
335
336 a = asn1f_lookup_symbol(arg, a->reference, &mod);
337 if(!a) return 0; /* Already FATAL()'ed somewhere else */
338 WITH_MODULE(mod, ret = _asn1f_compare_tags(arg, a, b));
339 return ret;
340 }
341
342 if(a->expr_type == ASN_CONSTR_CHOICE) {
343 asn1p_expr_t *v;
344
345 DEBUG(" %s is a choice type (%d)", a->Identifier, a->_mark);
346
347 /*
348 * Iterate over members of CHOICE.
349 */
350 //if(a->_mark & TM_RECURSION) return 0;
351 TQ_FOR(v, &(a->members), next) {
352 //a->_mark |= TM_RECURSION;
353 ret = _asn1f_compare_tags(arg, v, b);
354 //a->_mark &= ~TM_RECURSION;
355 if(ret) return ret;
356 }
357 return 0;
358 }
359
360 if(b->expr_type == ASN_CONSTR_CHOICE) {
361 return _asn1f_compare_tags(arg, b, a);
362 }
363
364 if(a->_mark & TM_RECURSION) return 0;
365 if(b->_mark & TM_RECURSION) return 0;
366 a->_mark |= TM_RECURSION;
367 b->_mark |= TM_RECURSION;
368 ret = _asn1f_compare_tags(arg, b, a);
369 a->_mark &= ~TM_RECURSION;
370 b->_mark &= ~TM_RECURSION;
371
372 return ret;
373}
374