blob: 2aa798271b66aed9dd2d3f604611ac2db65c5d8d [file] [log] [blame]
vlmfa67ddc2004-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;
74 if(v->Identifier == NULL) {
75 asn1p_expr_free(v);
76 r_value = -1;
77 } else {
78 TQ_ADD(&(expr->members), v, next);
79 }
80 } else {
81 r_value = -1;
82 }
83 }
84
85 return r_value;
86}
87
88
89int
90asn1f_fix_constr_tag(arg_t *arg) {
91 asn1p_expr_t *expr = arg->expr;
92 asn1p_expr_t *v;
93 int fl_impl_tags = 0;
94 int fl_auto_tags = 0;
95 int root_tagged = 0; /* The root component is manually tagged */
96 int ext_tagged = 0; /* The extensions are manually tagged */
97 int component_number = 0;
98 int r_value = 0;
99
100 switch(expr->expr_type) {
101 case ASN_CONSTR_SEQUENCE:
102 case ASN_CONSTR_SET:
103 case ASN_CONSTR_CHOICE:
104 break;
105 default:
106 return 0;
107 }
108
109 fl_impl_tags = (arg->mod->module_flags & MSF_IMPLICIT_TAGS);
110 fl_auto_tags = (arg->mod->module_flags & MSF_AUTOMATIC_TAGS);
111
112 DEBUG("%s(%s) {%d, %d} for line %d", __func__,
113 expr->Identifier, fl_impl_tags, fl_auto_tags, expr->_lineno);
114
115 TQ_FOR(v, &(expr->members), next) {
116 int must_explicit = 0;
117
118 if(v->expr_type == A1TC_EXTENSIBLE) {
119 component_number++;
120 continue;
121 }
122
123 if(v->tag.tag_class == TC_NOCLASS) {
124 continue;
125 } else {
126 switch(component_number) {
127 case 0: case 2:
128 root_tagged = 1; break;
129 default:
130 ext_tagged = 1; break;
131 }
132 }
133
134 must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, v);
135
136 if(fl_impl_tags) {
137 if(v->tag.tag_mode != TM_EXPLICIT) {
138 if(must_explicit)
139 v->tag.tag_mode = TM_EXPLICIT;
140 else
141 v->tag.tag_mode = TM_IMPLICIT;
142 }
143 } else {
144 if(v->tag.tag_mode == TM_DEFAULT) {
145 v->tag.tag_mode = TM_EXPLICIT;
146 }
147 }
148
149 /*
150 * Perform a final sanity check.
151 */
152 if(must_explicit) {
153 if(v->tag.tag_mode == TM_IMPLICIT) {
154 FATAL("%s tagged in IMPLICIT mode "
155 "but must be EXPLICIT at line %d",
156 v->Identifier, v->_lineno);
157 r_value = -1;
158 } else {
159 v->tag.tag_mode = TM_EXPLICIT;
160 }
161 }
162 }
163
164 if(ext_tagged && !root_tagged) {
165 FATAL("In %s at line %d: "
166 "extensions are tagged "
167 "but root components are not",
168 expr->Identifier, expr->_lineno);
169 r_value = -1;
170 } else if(!root_tagged && !ext_tagged && fl_auto_tags) {
171 expr->auto_tags_OK = 1;
172 }
173
174 return r_value;
175}
176
177int
178asn1f_fix_constr_autotag(arg_t *arg) {
179 asn1p_expr_t *expr = arg->expr;
180 asn1p_expr_t *v;
181 asn1_integer_t tag_value = 0;
182 int r_value = 0;
183
184 switch(expr->expr_type) {
185 case ASN_CONSTR_SEQUENCE:
186 case ASN_CONSTR_SET:
187 case ASN_CONSTR_CHOICE:
188 if(expr->auto_tags_OK)
189 break;
190 /* Automatic tagging is not applicable */
191 /* Fall through */
192 default:
193 return 0;
194 }
195
196 DEBUG("%s(%s) for line %d", __func__,
197 expr->Identifier, expr->_lineno);
198
199 TQ_FOR(v, &(expr->members), next) {
200 int must_explicit;
201
202 if(v->expr_type == A1TC_EXTENSIBLE)
203 break;
204
205 assert(v->tag.tag_class == TC_NOCLASS);
206
207 must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, v);
208
209 v->tag.tag_class = TC_CONTEXT_SPECIFIC;
210 v->tag.tag_mode = must_explicit ? TM_EXPLICIT : TM_IMPLICIT;
211 v->tag.tag_value = tag_value++;
212 }
213
214 return r_value;
215}
216
217/*
218 * Check that tags are distinct.
219 */
220int
221asn1f_check_constr_tags_distinct(arg_t *arg) {
222 asn1p_expr_t *expr = arg->expr;
223 asn1p_expr_t *v;
224 int r_value = 0;
225
226 switch(expr->expr_type) {
227 case ASN_CONSTR_SEQUENCE:
228 case ASN_CONSTR_SET:
229 case ASN_CONSTR_CHOICE:
230 break;
231 default:
232 return 0;
233 }
234
235 TQ_FOR(v, &(expr->members), next) {
236 /*
237 * In every series of non-mandatory components,
238 * the tags must be distinct from each other AND the
239 * tag of the following mandatory component.
240 * For SET and CHOICE treat everything as a big set of
241 * non-mandatory components.
242 */
243 if(expr->expr_type != ASN_CONSTR_SEQUENCE || v->marker) {
244 asn1p_expr_t *nv;
245 for(nv = v; (nv = TQ_NEXT(nv, next));) {
246 if(_asn1f_compare_tags(arg, v, nv))
247 r_value = -1;
248 if(expr->expr_type == ASN_CONSTR_SEQUENCE
249 && !nv->marker) break;
250 }
251 }
252 }
253
254 return r_value;
255}
256
257static int
258_asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v) {
259 asn1p_expr_t *reft;
260
261 reft = asn1f_find_terminal_type(arg, v, 0);
262 if(reft) {
263 switch(reft->expr_type) {
264 case ASN_CONSTR_CHOICE:
265 return 1;
266 default:
267 return 0;
268 }
269 }
270
271 return 0;
272}
273
274/*
275 * Check that the tags are distinct.
276 */
277static int
278_asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b) {
279 struct asn1p_type_tag_s ta, tb;
280 int ra, rb;
281 int ret;
282
283 ra = asn1f_fetch_tag(arg->asn, arg->mod, a, &ta);
284 rb = asn1f_fetch_tag(arg->asn, arg->mod, b, &tb);
285
286 /*
287 * If both tags are explicitly or implicitly given, use them.
288 */
289 if(ra == 0 && rb == 0) {
290 /*
291 * Simple case: fetched both tags.
292 */
293 if(ta.tag_value == tb.tag_value
294 && ta.tag_class == tb.tag_class) {
295 char *p = (a->expr_type == A1TC_EXTENSIBLE)
296 ?"potentially ":"";
297 FATAL("Component \"%s\" at line %d %shas the same tag "
298 "with component \"%s\" at line %d",
299 a->Identifier,
300 a->_lineno,
301 p,
302 b->Identifier,
303 b->_lineno
304 );
305 return -1;
306 } else {
307 /* Tags are distinct */
308 return 0;
309 }
310 }
311
312 /**********************************************************
313 * Now we must perform some very funny recursion to check
314 * multiple components of CHOICE type, etc.
315 */
316
317 DEBUG("Comparing tags %s:%x <-> %s:%x",
318 a->Identifier, a->expr_type,
319 b->Identifier, b->expr_type);
320
321 if(a->meta_type == AMT_TYPEREF) {
322 asn1p_module_t *mod;
323
324 DEBUG(" %s is a type reference", a->Identifier);
325
326 a = asn1f_lookup_symbol(arg, a->reference, &mod);
327 if(!a) return 0; /* Already FATAL()'ed somewhere else */
328 WITH_MODULE(mod, ret = _asn1f_compare_tags(arg, a, b));
329 return ret;
330 }
331
332 if(a->expr_type == ASN_CONSTR_CHOICE) {
333 asn1p_expr_t *v;
334
335 DEBUG(" %s is a choice type (%d)", a->Identifier, a->_mark);
336
337 /*
338 * Iterate over members of CHOICE.
339 */
340 //if(a->_mark & TM_RECURSION) return 0;
341 TQ_FOR(v, &(a->members), next) {
342 //a->_mark |= TM_RECURSION;
343 ret = _asn1f_compare_tags(arg, v, b);
344 //a->_mark &= ~TM_RECURSION;
345 if(ret) return ret;
346 }
347 return 0;
348 }
349
350 if(b->expr_type == ASN_CONSTR_CHOICE) {
351 return _asn1f_compare_tags(arg, b, a);
352 }
353
354 if(a->_mark & TM_RECURSION) return 0;
355 if(b->_mark & TM_RECURSION) return 0;
356 a->_mark |= TM_RECURSION;
357 b->_mark |= TM_RECURSION;
358 ret = _asn1f_compare_tags(arg, b, a);
359 a->_mark &= ~TM_RECURSION;
360 b->_mark &= ~TM_RECURSION;
361
362 return ret;
363}
364