blob: 46a32727b25bb71ac9d5f37a1add291db894e000 [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 */
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 */
vlmb6fd3b22004-08-25 00:42:25 +000018static int asn1f_resolve_constraints(arg_t *arg); /* For subtype constraints */
19static int asn1f_check_constraints(arg_t *arg); /* For subtype constraints */
vlmfa67ddc2004-06-03 03:38:44 +000020
vlmb5be8c32004-08-18 05:42:05 +000021arg_t a1f_replace_me_with_proper_interface_arg;
vlmfa67ddc2004-06-03 03:38:44 +000022
23/*
24 * Scan every module defined here in search for inconsistences.
25 */
26int
27asn1f_process(asn1p_t *asn, enum asn1f_flags flags,
28 error_logger_f error_logger) {
29 arg_t arg;
30 int fatals = 0;
31 int warnings = 0;
32
33 /*
34 * Check validity of arguments.
35 */
36 if(asn == NULL) {
37 errno = EINVAL;
38 return -1;
39 }
40
41 /*
42 * If errors handler is not specified, default to internal one.
43 */
44 if(error_logger == 0) {
45 error_logger = _default_error_logger;
46 }
47
48 memset(&arg, 0, sizeof(arg));
49 arg.asn = asn;
50 arg.eh = error_logger;
51
52 if(flags & A1F_DEBUG) {
53 arg.debug = arg.eh;
54 arg.debug(-1, "Called %s() with flags %d", __func__, flags);
55 flags &= ~A1F_DEBUG;
56 }
57
vlmd8d90352004-08-20 13:25:56 +000058 /* Allow SIZE() constraint for INTEGER and other types */
59 if(flags & A1F_EXTENDED_SizeConstraint) {
60 arg.flags |= A1F_EXTENDED_SizeConstraint;
61 flags &= ~A1F_EXTENDED_SizeConstraint;
62 if(arg.debug) {
63 arg.debug(-1,
64 "Extended SizeConstraint support enabled");
65 }
66 }
67
vlmb5be8c32004-08-18 05:42:05 +000068 a1f_replace_me_with_proper_interface_arg = arg;
69
vlmfa67ddc2004-06-03 03:38:44 +000070 /*
71 * Check that we haven't missed an unknown flag.
72 */
73 if(flags) {
74 errno = EINVAL;
75 return -1;
76 }
77
78 /*
79 * Process each module in the list.
80 */
81 TQ_FOR(arg.mod, &(asn->modules), mod_next) {
82 int ret = asn1f_fix_module(&arg);
83 /*
84 * These lines are used for illustration purposes.
85 * RET2RVAL() is used everywhere else.
86 */
87 if(ret == -1) fatals++;
88 if(ret == 1) warnings++;
89 }
90
vlmb5be8c32004-08-18 05:42:05 +000091 memset(&a1f_replace_me_with_proper_interface_arg, 0, sizeof(arg_t));
92
vlmfa67ddc2004-06-03 03:38:44 +000093 /*
94 * Compute a return value.
95 */
96 return fatals?-1:warnings?1:0;
97}
98
99/*
100 * Check the internals of a single module.
101 */
102static int
103asn1f_fix_module(arg_t *arg) {
104 asn1p_expr_t *expr;
105 int rvalue = 0;
vlmb6fd3b22004-08-25 00:42:25 +0000106 int ret;
vlmfa67ddc2004-06-03 03:38:44 +0000107
vlmb5be8c32004-08-18 05:42:05 +0000108 switch((arg->mod->module_flags & MSF_MASK_TAGS)) {
vlmfa67ddc2004-06-03 03:38:44 +0000109 case MSF_NOFLAGS:
110 case MSF_EXPLICIT_TAGS:
111 case MSF_IMPLICIT_TAGS:
112 case MSF_AUTOMATIC_TAGS:
113 break;
114 default:
115 FATAL("Module %s defined with ambiguous global tagging mode",
116 arg->mod->Identifier);
117 RET2RVAL(-1, rvalue);
118 }
119
vlmb5be8c32004-08-18 05:42:05 +0000120 switch((arg->mod->module_flags & MSF_MASK_INSTRUCTIONS)) {
121 case MSF_NOFLAGS:
vlmf645aff2004-08-22 03:09:24 +0000122 /*
123 * arg->mod->module_flags |= MSF_TAG_INSTRUCTIONS;
124 */
vlmb5be8c32004-08-18 05:42:05 +0000125 break;
126 case MSF_unk_INSTRUCTIONS:
127 WARNING("Module %s defined with unrecognized "
128 "encoding reference", arg->mod->Identifier);
129 RET2RVAL(1, rvalue);
130 /* Fall through */
131 case MSF_TAG_INSTRUCTIONS:
132 case MSF_XER_INSTRUCTIONS:
133 break;
134 default:
135 FATAL("Module %s defined with ambiguous encoding reference",
136 arg->mod->Identifier);
137 RET2RVAL(-1, rvalue);
138 }
139
vlmfa67ddc2004-06-03 03:38:44 +0000140 /*
141 * Do various non-recursive transformations.
142 * Order is not important.
143 */
144 TQ_FOR(expr, &(arg->mod->members), next) {
vlmfa67ddc2004-06-03 03:38:44 +0000145 arg->expr = expr;
146
147 if(expr->meta_type == AMT_PARAMTYPE)
148 /* Do not process the parametrized type just yet */
149 continue;
150
151 DEBUG("=== Now processing \"%s\" at line %d ===",
152 expr->Identifier, expr->_lineno);
153 assert(expr->meta_type != AMT_INVALID);
154
155 /*
156 * 2.1 Pre-process simple types (ENUMERATED, INTEGER, etc).
157 */
158 ret = asn1f_recurse_expr(arg, asn1f_fix_simple);
159 RET2RVAL(ret, rvalue);
160
161 /*
162 * 2.[234] Process SEQUENCE/SET/CHOICE types.
163 */
164 ret = asn1f_recurse_expr(arg, asn1f_fix_constructed);
165 RET2RVAL(ret, rvalue);
166
167 /*
168 * 2.5.4
169 */
170 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_types);
171 RET2RVAL(ret, rvalue);
172
173 /*
174 * 2.5.5
175 */
176 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_values);
177 RET2RVAL(ret, rvalue);
178
179 /*
180 * Resolve references in constraints.
181 */
vlmb6fd3b22004-08-25 00:42:25 +0000182 ret = asn1f_recurse_expr(arg, asn1f_resolve_constraints);
vlmfa67ddc2004-06-03 03:38:44 +0000183 RET2RVAL(ret, rvalue);
184
185 /*
186 * 6. INTEGER value processed at 2.5.4.
187 */
188
189 /*
190 * Make sure everybody's behaving well.
191 */
192 assert(arg->expr == expr);
193 }
194
195 /*
196 * 5. Automatic tagging
197 */
198 TQ_FOR(expr, &(arg->mod->members), next) {
vlmfa67ddc2004-06-03 03:38:44 +0000199
200 arg->expr = expr;
201
202 ret = asn1f_recurse_expr(arg, asn1f_fix_constr_autotag);
203 RET2RVAL(ret, rvalue);
204
205 assert(arg->expr == expr);
206 }
207
208 /*
209 * 8. fix BIT STRING
210 * 9. fix spaces in cstrings
211 */
212 TQ_FOR(expr, &(arg->mod->members), next) {
vlmfa67ddc2004-06-03 03:38:44 +0000213 arg->expr = expr;
214
215 ret = asn1f_recurse_expr(arg, asn1f_fix_bit_string);
216 RET2RVAL(ret, rvalue);
217
218 ret = asn1f_recurse_expr(arg, asn1f_fix_cstring);
219 RET2RVAL(ret, rvalue);
220
221 assert(arg->expr == expr);
222 }
223
224 /*
225 * ... Check for tags distinctness.
226 */
227 TQ_FOR(expr, &(arg->mod->members), next) {
vlmfa67ddc2004-06-03 03:38:44 +0000228 arg->expr = expr;
229
230 ret = asn1f_recurse_expr(arg, asn1f_check_constr_tags_distinct);
231 RET2RVAL(ret, rvalue);
232
233 assert(arg->expr == expr);
234 }
235
vlmb6fd3b22004-08-25 00:42:25 +0000236 /*
237 * Check semantic validity of constraints.
238 */
239 TQ_FOR(expr, &(arg->mod->members), next) {
240 arg->expr = expr;
241
242 ret = asn1f_recurse_expr(arg, asn1f_check_constraints);
243 RET2RVAL(ret, rvalue);
244
245 assert(arg->expr == expr);
246 }
247
vlmfa67ddc2004-06-03 03:38:44 +0000248 return rvalue;
249}
250
251
252static int
253asn1f_fix_simple(arg_t *arg) {
254 int rvalue = 0;
255 int ret;
256
257 ret = asn1f_fix_enum(arg);
258 RET2RVAL(ret, rvalue);
259
260 ret = asn1f_fix_integer(arg);
261 RET2RVAL(ret, rvalue);
262
263 return rvalue;
264}
265
266static int
267asn1f_fix_constructed(arg_t *arg) {
268 int rvalue = 0;
269 int ret;
270
271 switch(arg->expr->expr_type) {
272 case ASN_CONSTR_SEQUENCE:
273 case ASN_CONSTR_SET:
274 case ASN_CONSTR_CHOICE:
275 break;
276 default:
277 return 0;
278 }
279
280 /* Check identifier distinctness */
281 ret = asn1f_check_unique_expr(arg, NULL);
282 RET2RVAL(ret, rvalue);
283
284 /* Fix extensibility */
285 ret = asn1f_fix_constr_ext(arg);
286 RET2RVAL(ret, rvalue);
287
288 /* Fix tagging */
289 ret = asn1f_fix_constr_tag(arg);
290 RET2RVAL(ret, rvalue);
291
vlmf645aff2004-08-22 03:09:24 +0000292 /* Import COMPONENTS OF stuff */
293 ret = asn1f_pull_components_of(arg);
294 RET2RVAL(ret, rvalue);
295
vlmfa67ddc2004-06-03 03:38:44 +0000296 return rvalue;
297}
298
299static int
vlmb6fd3b22004-08-25 00:42:25 +0000300asn1f_resolve_constraints(arg_t *arg) {
vlmb5be8c32004-08-18 05:42:05 +0000301 asn1p_expr_t *top_parent;
vlmd8d90352004-08-20 13:25:56 +0000302 asn1p_expr_type_e etype;
vlmfa67ddc2004-06-03 03:38:44 +0000303 int rvalue = 0;
304 int ret;
305
vlmf645aff2004-08-22 03:09:24 +0000306 top_parent = asn1f_find_terminal_type(arg, arg->expr);
vlmd8d90352004-08-20 13:25:56 +0000307 if(top_parent)
308 etype = top_parent->expr_type;
309 else etype = A1TC_INVALID;
310
vlmf645aff2004-08-22 03:09:24 +0000311 ret = asn1constraint_resolve(arg, arg->expr->module,
312 arg->expr->constraints, etype, 0);
vlmb5be8c32004-08-18 05:42:05 +0000313 RET2RVAL(ret, rvalue);
vlmfa67ddc2004-06-03 03:38:44 +0000314
vlmb6fd3b22004-08-25 00:42:25 +0000315 return rvalue;
316}
317
318static int
319asn1f_check_constraints(arg_t *arg) {
320 static enum asn1p_constraint_type_e test_types[] = {
321 ACT_EL_RANGE, ACT_CT_SIZE, ACT_CT_FROM };
322 asn1p_expr_t *top_parent;
323 asn1cnst_range_t *range;
324 asn1p_expr_type_e etype;
325 unsigned int i;
326 int rvalue = 0;
327 int ret;
328
329 top_parent = asn1f_find_terminal_type(arg, arg->expr);
330 if(!top_parent)
331 return 0;
332 etype = top_parent->expr_type;
333
vlmb5be8c32004-08-18 05:42:05 +0000334 ret = asn1constraint_pullup(arg);
335 RET2RVAL(ret, rvalue);
336
vlmb6fd3b22004-08-25 00:42:25 +0000337 for(i = 0; i < sizeof(test_types)/sizeof(test_types[0]); i++) {
338 range = asn1constraint_compute_PER_range(
vlm1b406f52004-08-25 02:04:39 +0000339 etype,
vlmb6fd3b22004-08-25 00:42:25 +0000340 arg->expr->combined_constraints,
vlm1b406f52004-08-25 02:04:39 +0000341 test_types[i], 0, 0, 0);
vlmb6fd3b22004-08-25 00:42:25 +0000342 if(!range && errno == EPERM)
343 return -1;
344 asn1constraint_range_free(range);
vlmb5be8c32004-08-18 05:42:05 +0000345 }
vlmb6fd3b22004-08-25 00:42:25 +0000346
vlmfa67ddc2004-06-03 03:38:44 +0000347 return rvalue;
348}
349
350/*
351 * Print everything to stderr
352 */
353static void
354_default_error_logger(int _severity, const char *fmt, ...) {
355 va_list ap;
356 char *pfx = "";
357
358 switch(_severity) {
359 case -1: pfx = "DEBUG: "; break;
360 case 0: pfx = "WARNING: "; break;
361 case 1: pfx = "FATAL: "; break;
362 }
363
364 fprintf(stderr, "%s", pfx);
365 va_start(ap, fmt);
366 vfprintf(stderr, fmt, ap);
367 va_end(ap);
368 fprintf(stderr, "\n");
369}