blob: 2a78aa13145ed813ae0a6df84f91da18f4771656 [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 */
18static int asn1f_fix_constraints(arg_t *arg); /* For subtype constraints */
19
vlmb5be8c32004-08-18 05:42:05 +000020arg_t a1f_replace_me_with_proper_interface_arg;
vlmfa67ddc2004-06-03 03:38:44 +000021
22/*
23 * Scan every module defined here in search for inconsistences.
24 */
25int
26asn1f_process(asn1p_t *asn, enum asn1f_flags flags,
27 error_logger_f error_logger) {
28 arg_t arg;
29 int fatals = 0;
30 int warnings = 0;
31
32 /*
33 * Check validity of arguments.
34 */
35 if(asn == NULL) {
36 errno = EINVAL;
37 return -1;
38 }
39
40 /*
41 * If errors handler is not specified, default to internal one.
42 */
43 if(error_logger == 0) {
44 error_logger = _default_error_logger;
45 }
46
47 memset(&arg, 0, sizeof(arg));
48 arg.asn = asn;
49 arg.eh = error_logger;
50
51 if(flags & A1F_DEBUG) {
52 arg.debug = arg.eh;
53 arg.debug(-1, "Called %s() with flags %d", __func__, flags);
54 flags &= ~A1F_DEBUG;
55 }
56
vlmd8d90352004-08-20 13:25:56 +000057 /* Allow SIZE() constraint for INTEGER and other types */
58 if(flags & A1F_EXTENDED_SizeConstraint) {
59 arg.flags |= A1F_EXTENDED_SizeConstraint;
60 flags &= ~A1F_EXTENDED_SizeConstraint;
61 if(arg.debug) {
62 arg.debug(-1,
63 "Extended SizeConstraint support enabled");
64 }
65 }
66
vlmb5be8c32004-08-18 05:42:05 +000067 a1f_replace_me_with_proper_interface_arg = arg;
68
vlmfa67ddc2004-06-03 03:38:44 +000069 /*
70 * Check that we haven't missed an unknown flag.
71 */
72 if(flags) {
73 errno = EINVAL;
74 return -1;
75 }
76
77 /*
78 * Process each module in the list.
79 */
80 TQ_FOR(arg.mod, &(asn->modules), mod_next) {
81 int ret = asn1f_fix_module(&arg);
82 /*
83 * These lines are used for illustration purposes.
84 * RET2RVAL() is used everywhere else.
85 */
86 if(ret == -1) fatals++;
87 if(ret == 1) warnings++;
88 }
89
vlmb5be8c32004-08-18 05:42:05 +000090 memset(&a1f_replace_me_with_proper_interface_arg, 0, sizeof(arg_t));
91
vlmfa67ddc2004-06-03 03:38:44 +000092 /*
93 * Compute a return value.
94 */
95 return fatals?-1:warnings?1:0;
96}
97
98/*
99 * Check the internals of a single module.
100 */
101static int
102asn1f_fix_module(arg_t *arg) {
103 asn1p_expr_t *expr;
104 int rvalue = 0;
105
vlmb5be8c32004-08-18 05:42:05 +0000106 switch((arg->mod->module_flags & MSF_MASK_TAGS)) {
vlmfa67ddc2004-06-03 03:38:44 +0000107 case MSF_NOFLAGS:
108 case MSF_EXPLICIT_TAGS:
109 case MSF_IMPLICIT_TAGS:
110 case MSF_AUTOMATIC_TAGS:
111 break;
112 default:
113 FATAL("Module %s defined with ambiguous global tagging mode",
114 arg->mod->Identifier);
115 RET2RVAL(-1, rvalue);
116 }
117
vlmb5be8c32004-08-18 05:42:05 +0000118 switch((arg->mod->module_flags & MSF_MASK_INSTRUCTIONS)) {
119 case MSF_NOFLAGS:
120 //arg->mod->module_flags |= MSF_TAG_INSTRUCTIONS;
121 break;
122 case MSF_unk_INSTRUCTIONS:
123 WARNING("Module %s defined with unrecognized "
124 "encoding reference", arg->mod->Identifier);
125 RET2RVAL(1, rvalue);
126 /* Fall through */
127 case MSF_TAG_INSTRUCTIONS:
128 case MSF_XER_INSTRUCTIONS:
129 break;
130 default:
131 FATAL("Module %s defined with ambiguous encoding reference",
132 arg->mod->Identifier);
133 RET2RVAL(-1, rvalue);
134 }
135
vlmfa67ddc2004-06-03 03:38:44 +0000136 /*
137 * Do various non-recursive transformations.
138 * Order is not important.
139 */
140 TQ_FOR(expr, &(arg->mod->members), next) {
141 int ret;
142 arg->expr = expr;
143
144 if(expr->meta_type == AMT_PARAMTYPE)
145 /* Do not process the parametrized type just yet */
146 continue;
147
148 DEBUG("=== Now processing \"%s\" at line %d ===",
149 expr->Identifier, expr->_lineno);
150 assert(expr->meta_type != AMT_INVALID);
151
152 /*
153 * 2.1 Pre-process simple types (ENUMERATED, INTEGER, etc).
154 */
155 ret = asn1f_recurse_expr(arg, asn1f_fix_simple);
156 RET2RVAL(ret, rvalue);
157
158 /*
159 * 2.[234] Process SEQUENCE/SET/CHOICE types.
160 */
161 ret = asn1f_recurse_expr(arg, asn1f_fix_constructed);
162 RET2RVAL(ret, rvalue);
163
164 /*
165 * 2.5.4
166 */
167 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_types);
168 RET2RVAL(ret, rvalue);
169
170 /*
171 * 2.5.5
172 */
173 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_values);
174 RET2RVAL(ret, rvalue);
175
176 /*
177 * Resolve references in constraints.
178 */
179 ret = asn1f_recurse_expr(arg, asn1f_fix_constraints);
180 RET2RVAL(ret, rvalue);
181
182 /*
183 * 6. INTEGER value processed at 2.5.4.
184 */
185
186 /*
187 * Make sure everybody's behaving well.
188 */
189 assert(arg->expr == expr);
190 }
191
192 /*
193 * 5. Automatic tagging
194 */
195 TQ_FOR(expr, &(arg->mod->members), next) {
196 int ret;
197
198 arg->expr = expr;
199
200 ret = asn1f_recurse_expr(arg, asn1f_fix_constr_autotag);
201 RET2RVAL(ret, rvalue);
202
203 assert(arg->expr == expr);
204 }
205
206 /*
207 * 8. fix BIT STRING
208 * 9. fix spaces in cstrings
209 */
210 TQ_FOR(expr, &(arg->mod->members), next) {
211 int ret;
212 arg->expr = expr;
213
214 ret = asn1f_recurse_expr(arg, asn1f_fix_bit_string);
215 RET2RVAL(ret, rvalue);
216
217 ret = asn1f_recurse_expr(arg, asn1f_fix_cstring);
218 RET2RVAL(ret, rvalue);
219
220 assert(arg->expr == expr);
221 }
222
223 /*
224 * ... Check for tags distinctness.
225 */
226 TQ_FOR(expr, &(arg->mod->members), next) {
227 int ret;
228 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
236 return rvalue;
237}
238
239
240static int
241asn1f_fix_simple(arg_t *arg) {
242 int rvalue = 0;
243 int ret;
244
245 ret = asn1f_fix_enum(arg);
246 RET2RVAL(ret, rvalue);
247
248 ret = asn1f_fix_integer(arg);
249 RET2RVAL(ret, rvalue);
250
251 return rvalue;
252}
253
254static int
255asn1f_fix_constructed(arg_t *arg) {
256 int rvalue = 0;
257 int ret;
258
259 switch(arg->expr->expr_type) {
260 case ASN_CONSTR_SEQUENCE:
261 case ASN_CONSTR_SET:
262 case ASN_CONSTR_CHOICE:
263 break;
264 default:
265 return 0;
266 }
267
268 /* Check identifier distinctness */
269 ret = asn1f_check_unique_expr(arg, NULL);
270 RET2RVAL(ret, rvalue);
271
272 /* Fix extensibility */
273 ret = asn1f_fix_constr_ext(arg);
274 RET2RVAL(ret, rvalue);
275
276 /* Fix tagging */
277 ret = asn1f_fix_constr_tag(arg);
278 RET2RVAL(ret, rvalue);
279
280 return rvalue;
281}
282
283static int
vlmfa67ddc2004-06-03 03:38:44 +0000284asn1f_fix_constraints(arg_t *arg) {
vlmb5be8c32004-08-18 05:42:05 +0000285 asn1p_expr_t *top_parent;
vlmd8d90352004-08-20 13:25:56 +0000286 asn1p_expr_type_e etype;
vlmfa67ddc2004-06-03 03:38:44 +0000287 int rvalue = 0;
288 int ret;
289
vlmd8d90352004-08-20 13:25:56 +0000290 top_parent = asn1f_find_terminal_type(arg, arg->expr, NULL);
291 if(top_parent)
292 etype = top_parent->expr_type;
293 else etype = A1TC_INVALID;
294
295 ret = asn1constraint_resolve(arg, arg->expr->constraints, etype, 0);
vlmb5be8c32004-08-18 05:42:05 +0000296 RET2RVAL(ret, rvalue);
vlmfa67ddc2004-06-03 03:38:44 +0000297
vlmb5be8c32004-08-18 05:42:05 +0000298 ret = asn1constraint_pullup(arg);
299 RET2RVAL(ret, rvalue);
300
vlmb5be8c32004-08-18 05:42:05 +0000301 if(top_parent) {
302 static enum asn1p_constraint_type_e test_types[] = {
303 ACT_EL_RANGE, ACT_CT_SIZE, ACT_CT_FROM };
304 unsigned int i;
305 for(i = 0; i < sizeof(test_types)/sizeof(test_types[0]); i++) {
306 asn1cnst_range_t *range;
307 range = asn1constraint_compute_PER_range(
308 top_parent->expr_type,
309 arg->expr->combined_constraints,
310 test_types[i], 0, 0);
311 if(!range && errno == EPERM)
312 return -1;
313 asn1constraint_range_free(range);
314 }
315 }
316
vlmfa67ddc2004-06-03 03:38:44 +0000317 return rvalue;
318}
319
320/*
321 * Print everything to stderr
322 */
323static void
324_default_error_logger(int _severity, const char *fmt, ...) {
325 va_list ap;
326 char *pfx = "";
327
328 switch(_severity) {
329 case -1: pfx = "DEBUG: "; break;
330 case 0: pfx = "WARNING: "; break;
331 case 1: pfx = "FATAL: "; break;
332 }
333
334 fprintf(stderr, "%s", pfx);
335 va_start(ap, fmt);
336 vfprintf(stderr, fmt, ap);
337 va_end(ap);
338 fprintf(stderr, "\n");
339}