blob: af1109993d420a6db160325ac6c4c4f7e33a9b02 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include <stdlib.h>
2#include <string.h>
3#include <errno.h>
4#include <stdarg.h>
5
6#include "asn1fix.h"
7#include "asn1fix_internal.h"
8
9/* Print everything to stderr */
10static void _default_error_logger(int _severity, const char *fmt, ...);
11
12/*
13 * Internal check functions.
14 */
15static int asn1f_fix_module(arg_t *arg);
16static int asn1f_fix_simple(arg_t *arg); /* For INTEGER/ENUMERATED */
17static int asn1f_fix_constructed(arg_t *arg); /* For SEQUENCE/SET/CHOICE */
18static int asn1f_fix_constraints(arg_t *arg); /* For subtype constraints */
19
20
21/*
22 * Scan every module defined here in search for inconsistences.
23 */
24int
25asn1f_process(asn1p_t *asn, enum asn1f_flags flags,
26 error_logger_f error_logger) {
27 arg_t arg;
28 int fatals = 0;
29 int warnings = 0;
30
31 /*
32 * Check validity of arguments.
33 */
34 if(asn == NULL) {
35 errno = EINVAL;
36 return -1;
37 }
38
39 /*
40 * If errors handler is not specified, default to internal one.
41 */
42 if(error_logger == 0) {
43 error_logger = _default_error_logger;
44 }
45
46 memset(&arg, 0, sizeof(arg));
47 arg.asn = asn;
48 arg.eh = error_logger;
49
50 if(flags & A1F_DEBUG) {
51 arg.debug = arg.eh;
52 arg.debug(-1, "Called %s() with flags %d", __func__, flags);
53 flags &= ~A1F_DEBUG;
54 }
55
56 /*
57 * Check that we haven't missed an unknown flag.
58 */
59 if(flags) {
60 errno = EINVAL;
61 return -1;
62 }
63
64 /*
65 * Process each module in the list.
66 */
67 TQ_FOR(arg.mod, &(asn->modules), mod_next) {
68 int ret = asn1f_fix_module(&arg);
69 /*
70 * These lines are used for illustration purposes.
71 * RET2RVAL() is used everywhere else.
72 */
73 if(ret == -1) fatals++;
74 if(ret == 1) warnings++;
75 }
76
77 /*
78 * Compute a return value.
79 */
80 return fatals?-1:warnings?1:0;
81}
82
83/*
84 * Check the internals of a single module.
85 */
86static int
87asn1f_fix_module(arg_t *arg) {
88 asn1p_expr_t *expr;
89 int rvalue = 0;
90
91 switch((arg->mod->module_flags
92 & (MSF_EXPLICIT_TAGS | MSF_IMPLICIT_TAGS | MSF_AUTOMATIC_TAGS))) {
93 case MSF_NOFLAGS:
94 case MSF_EXPLICIT_TAGS:
95 case MSF_IMPLICIT_TAGS:
96 case MSF_AUTOMATIC_TAGS:
97 break;
98 default:
99 FATAL("Module %s defined with ambiguous global tagging mode",
100 arg->mod->Identifier);
101 RET2RVAL(-1, rvalue);
102 }
103
104 /*
105 * Do various non-recursive transformations.
106 * Order is not important.
107 */
108 TQ_FOR(expr, &(arg->mod->members), next) {
109 int ret;
110 arg->expr = expr;
111
112 if(expr->meta_type == AMT_PARAMTYPE)
113 /* Do not process the parametrized type just yet */
114 continue;
115
116 DEBUG("=== Now processing \"%s\" at line %d ===",
117 expr->Identifier, expr->_lineno);
118 assert(expr->meta_type != AMT_INVALID);
119
120 /*
121 * 2.1 Pre-process simple types (ENUMERATED, INTEGER, etc).
122 */
123 ret = asn1f_recurse_expr(arg, asn1f_fix_simple);
124 RET2RVAL(ret, rvalue);
125
126 /*
127 * 2.[234] Process SEQUENCE/SET/CHOICE types.
128 */
129 ret = asn1f_recurse_expr(arg, asn1f_fix_constructed);
130 RET2RVAL(ret, rvalue);
131
132 /*
133 * 2.5.4
134 */
135 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_types);
136 RET2RVAL(ret, rvalue);
137
138 /*
139 * 2.5.5
140 */
141 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_values);
142 RET2RVAL(ret, rvalue);
143
144 /*
145 * Resolve references in constraints.
146 */
147 ret = asn1f_recurse_expr(arg, asn1f_fix_constraints);
148 RET2RVAL(ret, rvalue);
149
150 /*
151 * 6. INTEGER value processed at 2.5.4.
152 */
153
154 /*
155 * Make sure everybody's behaving well.
156 */
157 assert(arg->expr == expr);
158 }
159
160 /*
161 * 5. Automatic tagging
162 */
163 TQ_FOR(expr, &(arg->mod->members), next) {
164 int ret;
165
166 arg->expr = expr;
167
168 ret = asn1f_recurse_expr(arg, asn1f_fix_constr_autotag);
169 RET2RVAL(ret, rvalue);
170
171 assert(arg->expr == expr);
172 }
173
174 /*
175 * 8. fix BIT STRING
176 * 9. fix spaces in cstrings
177 */
178 TQ_FOR(expr, &(arg->mod->members), next) {
179 int ret;
180 arg->expr = expr;
181
182 ret = asn1f_recurse_expr(arg, asn1f_fix_bit_string);
183 RET2RVAL(ret, rvalue);
184
185 ret = asn1f_recurse_expr(arg, asn1f_fix_cstring);
186 RET2RVAL(ret, rvalue);
187
188 assert(arg->expr == expr);
189 }
190
191 /*
192 * ... Check for tags distinctness.
193 */
194 TQ_FOR(expr, &(arg->mod->members), next) {
195 int ret;
196 arg->expr = expr;
197
198 ret = asn1f_recurse_expr(arg, asn1f_check_constr_tags_distinct);
199 RET2RVAL(ret, rvalue);
200
201 assert(arg->expr == expr);
202 }
203
204 return rvalue;
205}
206
207
208static int
209asn1f_fix_simple(arg_t *arg) {
210 int rvalue = 0;
211 int ret;
212
213 ret = asn1f_fix_enum(arg);
214 RET2RVAL(ret, rvalue);
215
216 ret = asn1f_fix_integer(arg);
217 RET2RVAL(ret, rvalue);
218
219 return rvalue;
220}
221
222static int
223asn1f_fix_constructed(arg_t *arg) {
224 int rvalue = 0;
225 int ret;
226
227 switch(arg->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 /* Check identifier distinctness */
237 ret = asn1f_check_unique_expr(arg, NULL);
238 RET2RVAL(ret, rvalue);
239
240 /* Fix extensibility */
241 ret = asn1f_fix_constr_ext(arg);
242 RET2RVAL(ret, rvalue);
243
244 /* Fix tagging */
245 ret = asn1f_fix_constr_tag(arg);
246 RET2RVAL(ret, rvalue);
247
248 return rvalue;
249}
250
251static int
252_constraint_value_resolve(arg_t *arg, asn1p_value_t **value) {
253 asn1p_expr_t expr;
254 asn1p_expr_t *tmp_expr;
255 asn1p_module_t *tmp_mod;
256 asn1p_module_t *mod_r = NULL;
257 int rvalue = 0;
258 int ret;
259
260 tmp_expr = asn1f_lookup_symbol(arg, (*value)->value.reference, &mod_r);
261 if(tmp_expr == NULL) {
262 FATAL("Cannot find symbol %s "
263 "used in %s subtype constraint at line %d",
264 asn1f_printable_reference((*value)->value.reference),
265 arg->expr->Identifier, arg->expr->_lineno);
266 assert((*value)->type == ATV_REFERENCED);
267 return -1;
268 }
269
270 memset(&expr, 0, sizeof(expr));
271 expr.meta_type = tmp_expr->meta_type;
272 expr.expr_type = tmp_expr->expr_type;
273 expr.Identifier = tmp_expr->Identifier;
274 expr.value = *value;
275 tmp_expr = arg->expr;
276 tmp_mod = arg->mod;
277 arg->expr = &expr;
278 arg->mod = mod_r;
279 ret = asn1f_fix_dereference_values(arg);
280 RET2RVAL(ret, rvalue);
281 arg->expr = tmp_expr;
282 arg->mod = tmp_mod;
283 assert(expr.value);
284 *value = expr.value;
285
286 return rvalue;
287}
288
289static int
290_resolve_constraints(arg_t *arg, asn1p_constraint_t *ct) {
291 int rvalue = 0;
292 int ret;
293 int el;
294
295 /* Don't touch information object classes */
296 if(ct->type == ACT_CT_WCOMP
297 || ct->type == ACT_CT_WCOMPS
298 || ct->type == ACT_CA_CRC)
299 return 0;
300
301 if(ct->value && ct->value->type == ATV_REFERENCED) {
302 ret = _constraint_value_resolve(arg, &ct->value);
303 RET2RVAL(ret, rvalue);
304 }
305 if(ct->range_start && ct->range_start->type == ATV_REFERENCED) {
306 ret = _constraint_value_resolve(arg, &ct->range_start);
307 RET2RVAL(ret, rvalue);
308 }
309 if(ct->range_stop && ct->range_stop->type == ATV_REFERENCED) {
310 ret = _constraint_value_resolve(arg, &ct->range_stop);
311 RET2RVAL(ret, rvalue);
312 }
313
314 for(el = 0; el < ct->el_count; el++) {
315 ret = _resolve_constraints(arg, ct->elements[el]);
316 RET2RVAL(ret, rvalue);
317 }
318
319 return rvalue;
320}
321
322static int
323asn1f_fix_constraints(arg_t *arg) {
324 int rvalue = 0;
325 int ret;
326
327 if(arg->expr->constraints) {
328 ret = _resolve_constraints(arg, arg->expr->constraints);
329 RET2RVAL(ret, rvalue);
330 }
331
332 return rvalue;
333}
334
335/*
336 * Print everything to stderr
337 */
338static void
339_default_error_logger(int _severity, const char *fmt, ...) {
340 va_list ap;
341 char *pfx = "";
342
343 switch(_severity) {
344 case -1: pfx = "DEBUG: "; break;
345 case 0: pfx = "WARNING: "; break;
346 case 1: pfx = "FATAL: "; break;
347 }
348
349 fprintf(stderr, "%s", pfx);
350 va_start(ap, fmt);
351 vfprintf(stderr, fmt, ap);
352 va_end(ap);
353 fprintf(stderr, "\n");
354}