blob: 02df593a8a2cb7e98088faf0dd8e193f5f36667f [file] [log] [blame]
vlmfa67ddc2004-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 */
vlma57277e2004-09-15 11:47:23 +000015static int asn1f_fix_module__phase_1(arg_t *arg);
16static int asn1f_fix_module__phase_2(arg_t *arg);
vlmfa67ddc2004-06-03 03:38:44 +000017static int asn1f_fix_simple(arg_t *arg); /* For INTEGER/ENUMERATED */
18static int asn1f_fix_constructed(arg_t *arg); /* For SEQUENCE/SET/CHOICE */
vlmb6fd3b22004-08-25 00:42:25 +000019static int asn1f_resolve_constraints(arg_t *arg); /* For subtype constraints */
20static int asn1f_check_constraints(arg_t *arg); /* For subtype constraints */
vlmfa67ddc2004-06-03 03:38:44 +000021
vlmb5be8c32004-08-18 05:42:05 +000022arg_t a1f_replace_me_with_proper_interface_arg;
vlmfa67ddc2004-06-03 03:38:44 +000023
24/*
25 * Scan every module defined here in search for inconsistences.
26 */
27int
28asn1f_process(asn1p_t *asn, enum asn1f_flags flags,
29 error_logger_f error_logger) {
30 arg_t arg;
31 int fatals = 0;
32 int warnings = 0;
33
34 /*
35 * Check validity of arguments.
36 */
37 if(asn == NULL) {
38 errno = EINVAL;
39 return -1;
40 }
41
42 /*
43 * If errors handler is not specified, default to internal one.
44 */
45 if(error_logger == 0) {
46 error_logger = _default_error_logger;
47 }
48
49 memset(&arg, 0, sizeof(arg));
50 arg.asn = asn;
51 arg.eh = error_logger;
52
53 if(flags & A1F_DEBUG) {
54 arg.debug = arg.eh;
55 arg.debug(-1, "Called %s() with flags %d", __func__, flags);
56 flags &= ~A1F_DEBUG;
57 }
58
vlmd8d90352004-08-20 13:25:56 +000059 /* Allow SIZE() constraint for INTEGER and other types */
60 if(flags & A1F_EXTENDED_SizeConstraint) {
61 arg.flags |= A1F_EXTENDED_SizeConstraint;
62 flags &= ~A1F_EXTENDED_SizeConstraint;
63 if(arg.debug) {
64 arg.debug(-1,
65 "Extended SizeConstraint support enabled");
66 }
67 }
68
vlmb5be8c32004-08-18 05:42:05 +000069 a1f_replace_me_with_proper_interface_arg = arg;
70
vlmfa67ddc2004-06-03 03:38:44 +000071 /*
72 * Check that we haven't missed an unknown flag.
73 */
74 if(flags) {
75 errno = EINVAL;
76 return -1;
77 }
78
79 /*
80 * Process each module in the list.
81 */
82 TQ_FOR(arg.mod, &(asn->modules), mod_next) {
vlma57277e2004-09-15 11:47:23 +000083 int ret = asn1f_fix_module__phase_1(&arg);
vlmfa67ddc2004-06-03 03:38:44 +000084 /*
85 * These lines are used for illustration purposes.
86 * RET2RVAL() is used everywhere else.
87 */
88 if(ret == -1) fatals++;
89 if(ret == 1) warnings++;
90 }
vlma57277e2004-09-15 11:47:23 +000091 TQ_FOR(arg.mod, &(asn->modules), mod_next) {
92 int ret = asn1f_fix_module__phase_2(&arg);
93 if(ret == -1) fatals++;
94 if(ret == 1) warnings++;
95 }
96
97 memset(&a1f_replace_me_with_proper_interface_arg, 0, sizeof(arg_t));
vlmfa67ddc2004-06-03 03:38:44 +000098
vlmb5be8c32004-08-18 05:42:05 +000099 memset(&a1f_replace_me_with_proper_interface_arg, 0, sizeof(arg_t));
100
vlmfa67ddc2004-06-03 03:38:44 +0000101 /*
102 * Compute a return value.
103 */
104 return fatals?-1:warnings?1:0;
105}
106
107/*
108 * Check the internals of a single module.
109 */
110static int
vlma57277e2004-09-15 11:47:23 +0000111asn1f_fix_module__phase_1(arg_t *arg) {
vlmfa67ddc2004-06-03 03:38:44 +0000112 asn1p_expr_t *expr;
113 int rvalue = 0;
vlmb6fd3b22004-08-25 00:42:25 +0000114 int ret;
vlmfa67ddc2004-06-03 03:38:44 +0000115
vlmb5be8c32004-08-18 05:42:05 +0000116 switch((arg->mod->module_flags & MSF_MASK_TAGS)) {
vlmfa67ddc2004-06-03 03:38:44 +0000117 case MSF_NOFLAGS:
118 case MSF_EXPLICIT_TAGS:
119 case MSF_IMPLICIT_TAGS:
120 case MSF_AUTOMATIC_TAGS:
121 break;
122 default:
123 FATAL("Module %s defined with ambiguous global tagging mode",
124 arg->mod->Identifier);
125 RET2RVAL(-1, rvalue);
126 }
127
vlmb5be8c32004-08-18 05:42:05 +0000128 switch((arg->mod->module_flags & MSF_MASK_INSTRUCTIONS)) {
129 case MSF_NOFLAGS:
vlmf645aff2004-08-22 03:09:24 +0000130 /*
131 * arg->mod->module_flags |= MSF_TAG_INSTRUCTIONS;
132 */
vlmb5be8c32004-08-18 05:42:05 +0000133 break;
134 case MSF_unk_INSTRUCTIONS:
135 WARNING("Module %s defined with unrecognized "
136 "encoding reference", arg->mod->Identifier);
137 RET2RVAL(1, rvalue);
138 /* Fall through */
139 case MSF_TAG_INSTRUCTIONS:
140 case MSF_XER_INSTRUCTIONS:
141 break;
142 default:
143 FATAL("Module %s defined with ambiguous encoding reference",
144 arg->mod->Identifier);
145 RET2RVAL(-1, rvalue);
146 }
147
vlmfa67ddc2004-06-03 03:38:44 +0000148 /*
149 * Do various non-recursive transformations.
150 * Order is not important.
151 */
152 TQ_FOR(expr, &(arg->mod->members), next) {
vlmfa67ddc2004-06-03 03:38:44 +0000153 arg->expr = expr;
154
155 if(expr->meta_type == AMT_PARAMTYPE)
156 /* Do not process the parametrized type just yet */
157 continue;
158
159 DEBUG("=== Now processing \"%s\" at line %d ===",
160 expr->Identifier, expr->_lineno);
161 assert(expr->meta_type != AMT_INVALID);
162
163 /*
164 * 2.1 Pre-process simple types (ENUMERATED, INTEGER, etc).
165 */
166 ret = asn1f_recurse_expr(arg, asn1f_fix_simple);
167 RET2RVAL(ret, rvalue);
168
169 /*
vlmfa67ddc2004-06-03 03:38:44 +0000170 * 2.5.4
171 */
172 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_types);
173 RET2RVAL(ret, rvalue);
174
175 /*
vlm76142452004-09-05 10:36:22 +0000176 * Fix tagging of top-level types.
177 */
178 ret = asn1f_fix_constr_tag(arg, 1);
179 RET2RVAL(ret, rvalue);
180
181 /*
182 * 2.[234] Process SEQUENCE/SET/CHOICE types.
183 */
184 ret = asn1f_recurse_expr(arg, asn1f_fix_constructed);
185 RET2RVAL(ret, rvalue);
186
187 /*
vlmfa67ddc2004-06-03 03:38:44 +0000188 * 2.5.5
189 */
190 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_values);
191 RET2RVAL(ret, rvalue);
192
193 /*
194 * Resolve references in constraints.
195 */
vlmb6fd3b22004-08-25 00:42:25 +0000196 ret = asn1f_recurse_expr(arg, asn1f_resolve_constraints);
vlmfa67ddc2004-06-03 03:38:44 +0000197 RET2RVAL(ret, rvalue);
198
199 /*
200 * 6. INTEGER value processed at 2.5.4.
201 */
202
203 /*
204 * Make sure everybody's behaving well.
205 */
206 assert(arg->expr == expr);
207 }
208
209 /*
210 * 5. Automatic tagging
211 */
212 TQ_FOR(expr, &(arg->mod->members), next) {
vlmfa67ddc2004-06-03 03:38:44 +0000213
214 arg->expr = expr;
215
216 ret = asn1f_recurse_expr(arg, asn1f_fix_constr_autotag);
217 RET2RVAL(ret, rvalue);
218
219 assert(arg->expr == expr);
220 }
221
222 /*
223 * 8. fix BIT STRING
224 * 9. fix spaces in cstrings
225 */
226 TQ_FOR(expr, &(arg->mod->members), next) {
vlmfa67ddc2004-06-03 03:38:44 +0000227 arg->expr = expr;
228
229 ret = asn1f_recurse_expr(arg, asn1f_fix_bit_string);
230 RET2RVAL(ret, rvalue);
231
232 ret = asn1f_recurse_expr(arg, asn1f_fix_cstring);
233 RET2RVAL(ret, rvalue);
234
235 assert(arg->expr == expr);
236 }
237
238 /*
239 * ... Check for tags distinctness.
240 */
241 TQ_FOR(expr, &(arg->mod->members), next) {
vlmfa67ddc2004-06-03 03:38:44 +0000242 arg->expr = expr;
243
244 ret = asn1f_recurse_expr(arg, asn1f_check_constr_tags_distinct);
245 RET2RVAL(ret, rvalue);
246
247 assert(arg->expr == expr);
248 }
249
vlma57277e2004-09-15 11:47:23 +0000250 return rvalue;
251}
252
253static int
254asn1f_fix_module__phase_2(arg_t *arg) {
255 asn1p_expr_t *expr;
256 int rvalue = 0;
257 int ret;
258
vlmb6fd3b22004-08-25 00:42:25 +0000259 /*
260 * Check semantic validity of constraints.
261 */
262 TQ_FOR(expr, &(arg->mod->members), next) {
263 arg->expr = expr;
264
vlm76142452004-09-05 10:36:22 +0000265 if(arg->expr->meta_type == AMT_PARAMTYPE)
266 /* Do not process the parametrized types here */
267 continue;
268
vlmb6fd3b22004-08-25 00:42:25 +0000269 ret = asn1f_recurse_expr(arg, asn1f_check_constraints);
270 RET2RVAL(ret, rvalue);
271
272 assert(arg->expr == expr);
273 }
274
vlmfa67ddc2004-06-03 03:38:44 +0000275 return rvalue;
276}
277
vlmfa67ddc2004-06-03 03:38:44 +0000278static int
279asn1f_fix_simple(arg_t *arg) {
280 int rvalue = 0;
281 int ret;
282
283 ret = asn1f_fix_enum(arg);
284 RET2RVAL(ret, rvalue);
285
286 ret = asn1f_fix_integer(arg);
287 RET2RVAL(ret, rvalue);
288
289 return rvalue;
290}
291
292static int
293asn1f_fix_constructed(arg_t *arg) {
294 int rvalue = 0;
295 int ret;
296
297 switch(arg->expr->expr_type) {
298 case ASN_CONSTR_SEQUENCE:
299 case ASN_CONSTR_SET:
300 case ASN_CONSTR_CHOICE:
301 break;
302 default:
303 return 0;
304 }
305
306 /* Check identifier distinctness */
307 ret = asn1f_check_unique_expr(arg, NULL);
308 RET2RVAL(ret, rvalue);
309
310 /* Fix extensibility */
311 ret = asn1f_fix_constr_ext(arg);
312 RET2RVAL(ret, rvalue);
313
314 /* Fix tagging */
vlm76142452004-09-05 10:36:22 +0000315 ret = asn1f_fix_constr_tag(arg, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000316 RET2RVAL(ret, rvalue);
317
vlmf645aff2004-08-22 03:09:24 +0000318 /* Import COMPONENTS OF stuff */
319 ret = asn1f_pull_components_of(arg);
320 RET2RVAL(ret, rvalue);
321
vlmfa67ddc2004-06-03 03:38:44 +0000322 return rvalue;
323}
324
325static int
vlmb6fd3b22004-08-25 00:42:25 +0000326asn1f_resolve_constraints(arg_t *arg) {
vlmb5be8c32004-08-18 05:42:05 +0000327 asn1p_expr_t *top_parent;
vlmd8d90352004-08-20 13:25:56 +0000328 asn1p_expr_type_e etype;
vlmfa67ddc2004-06-03 03:38:44 +0000329 int rvalue = 0;
330 int ret;
331
vlmf645aff2004-08-22 03:09:24 +0000332 top_parent = asn1f_find_terminal_type(arg, arg->expr);
vlmd8d90352004-08-20 13:25:56 +0000333 if(top_parent)
334 etype = top_parent->expr_type;
335 else etype = A1TC_INVALID;
336
vlm76142452004-09-05 10:36:22 +0000337 DEBUG("asn1f_resolve_constraints(%s)", arg->expr->Identifier);
338
vlmf645aff2004-08-22 03:09:24 +0000339 ret = asn1constraint_resolve(arg, arg->expr->module,
340 arg->expr->constraints, etype, 0);
vlmb5be8c32004-08-18 05:42:05 +0000341 RET2RVAL(ret, rvalue);
vlmfa67ddc2004-06-03 03:38:44 +0000342
vlmb6fd3b22004-08-25 00:42:25 +0000343 return rvalue;
344}
345
346static int
347asn1f_check_constraints(arg_t *arg) {
348 static enum asn1p_constraint_type_e test_types[] = {
349 ACT_EL_RANGE, ACT_CT_SIZE, ACT_CT_FROM };
350 asn1p_expr_t *top_parent;
351 asn1cnst_range_t *range;
352 asn1p_expr_type_e etype;
353 unsigned int i;
354 int rvalue = 0;
355 int ret;
356
vlm76142452004-09-05 10:36:22 +0000357 DEBUG("asn1f_check_constraints(%s{%d/%d})",
358 arg->expr->Identifier,
359 arg->expr->meta_type, arg->expr->expr_type);
360
vlmb6fd3b22004-08-25 00:42:25 +0000361 top_parent = asn1f_find_terminal_type(arg, arg->expr);
362 if(!top_parent)
363 return 0;
364 etype = top_parent->expr_type;
365
vlmb5be8c32004-08-18 05:42:05 +0000366 ret = asn1constraint_pullup(arg);
367 RET2RVAL(ret, rvalue);
368
vlmb6fd3b22004-08-25 00:42:25 +0000369 for(i = 0; i < sizeof(test_types)/sizeof(test_types[0]); i++) {
370 range = asn1constraint_compute_PER_range(
vlm1b406f52004-08-25 02:04:39 +0000371 etype,
vlmb6fd3b22004-08-25 00:42:25 +0000372 arg->expr->combined_constraints,
vlm1b406f52004-08-25 02:04:39 +0000373 test_types[i], 0, 0, 0);
vlm76142452004-09-05 10:36:22 +0000374 if(!range && errno == EPERM) {
375 FATAL("This error happened for %s (%d) at line %d",
376 arg->expr->Identifier,
377 arg->expr->meta_type,
378 arg->expr->_lineno);
vlmb6fd3b22004-08-25 00:42:25 +0000379 return -1;
vlm76142452004-09-05 10:36:22 +0000380 }
vlmb6fd3b22004-08-25 00:42:25 +0000381 asn1constraint_range_free(range);
vlmb5be8c32004-08-18 05:42:05 +0000382 }
vlmb6fd3b22004-08-25 00:42:25 +0000383
vlmfa67ddc2004-06-03 03:38:44 +0000384 return rvalue;
385}
386
387/*
388 * Print everything to stderr
389 */
390static void
391_default_error_logger(int _severity, const char *fmt, ...) {
392 va_list ap;
393 char *pfx = "";
394
395 switch(_severity) {
396 case -1: pfx = "DEBUG: "; break;
397 case 0: pfx = "WARNING: "; break;
398 case 1: pfx = "FATAL: "; break;
399 }
400
401 fprintf(stderr, "%s", pfx);
402 va_start(ap, fmt);
403 vfprintf(stderr, fmt, ap);
404 va_end(ap);
405 fprintf(stderr, "\n");
406}