blob: 33123fc24dc759cfabe4315a27b0df3d6cda36d6 [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 */
Lev Walkind24c62d2004-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);
Lev Walkinf15320b2004-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 */
Lev Walkin1ef05162004-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 */
Lev Walkinf15320b2004-06-03 03:38:44 +000021
Lev Walkinb45e0672004-08-18 05:42:05 +000022arg_t a1f_replace_me_with_proper_interface_arg;
Lev Walkinf15320b2004-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
Lev Walkin5253da42004-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
Lev Walkinb45e0672004-08-18 05:42:05 +000069 a1f_replace_me_with_proper_interface_arg = arg;
70
Lev Walkinf15320b2004-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) {
Lev Walkind24c62d2004-09-15 11:47:23 +000083 int ret = asn1f_fix_module__phase_1(&arg);
Lev Walkinf15320b2004-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 }
Lev Walkind24c62d2004-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));
Lev Walkinf15320b2004-06-03 03:38:44 +000098
99 /*
100 * Compute a return value.
101 */
102 return fatals?-1:warnings?1:0;
103}
104
105/*
106 * Check the internals of a single module.
107 */
108static int
Lev Walkind24c62d2004-09-15 11:47:23 +0000109asn1f_fix_module__phase_1(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000110 asn1p_expr_t *expr;
111 int rvalue = 0;
Lev Walkin1ef05162004-08-25 00:42:25 +0000112 int ret;
Lev Walkinf15320b2004-06-03 03:38:44 +0000113
Lev Walkinb45e0672004-08-18 05:42:05 +0000114 switch((arg->mod->module_flags & MSF_MASK_TAGS)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000115 case MSF_NOFLAGS:
116 case MSF_EXPLICIT_TAGS:
117 case MSF_IMPLICIT_TAGS:
118 case MSF_AUTOMATIC_TAGS:
119 break;
120 default:
121 FATAL("Module %s defined with ambiguous global tagging mode",
122 arg->mod->Identifier);
123 RET2RVAL(-1, rvalue);
124 }
125
Lev Walkinb45e0672004-08-18 05:42:05 +0000126 switch((arg->mod->module_flags & MSF_MASK_INSTRUCTIONS)) {
127 case MSF_NOFLAGS:
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000128 /*
129 * arg->mod->module_flags |= MSF_TAG_INSTRUCTIONS;
130 */
Lev Walkinb45e0672004-08-18 05:42:05 +0000131 break;
132 case MSF_unk_INSTRUCTIONS:
133 WARNING("Module %s defined with unrecognized "
134 "encoding reference", arg->mod->Identifier);
135 RET2RVAL(1, rvalue);
136 /* Fall through */
137 case MSF_TAG_INSTRUCTIONS:
138 case MSF_XER_INSTRUCTIONS:
139 break;
140 default:
141 FATAL("Module %s defined with ambiguous encoding reference",
142 arg->mod->Identifier);
143 RET2RVAL(-1, rvalue);
144 }
145
Lev Walkinf15320b2004-06-03 03:38:44 +0000146 /*
147 * Do various non-recursive transformations.
148 * Order is not important.
149 */
150 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000151 arg->expr = expr;
152
153 if(expr->meta_type == AMT_PARAMTYPE)
154 /* Do not process the parametrized type just yet */
155 continue;
156
157 DEBUG("=== Now processing \"%s\" at line %d ===",
158 expr->Identifier, expr->_lineno);
159 assert(expr->meta_type != AMT_INVALID);
160
161 /*
162 * 2.1 Pre-process simple types (ENUMERATED, INTEGER, etc).
163 */
164 ret = asn1f_recurse_expr(arg, asn1f_fix_simple);
165 RET2RVAL(ret, rvalue);
166
167 /*
Lev Walkinf15320b2004-06-03 03:38:44 +0000168 * 2.5.4
169 */
170 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_types);
171 RET2RVAL(ret, rvalue);
172
173 /*
Lev Walkind541c252004-09-05 10:36:22 +0000174 * Fix tagging of top-level types.
175 */
176 ret = asn1f_fix_constr_tag(arg, 1);
177 RET2RVAL(ret, rvalue);
178
179 /*
180 * 2.[234] Process SEQUENCE/SET/CHOICE types.
181 */
182 ret = asn1f_recurse_expr(arg, asn1f_fix_constructed);
183 RET2RVAL(ret, rvalue);
184
185 /*
Lev Walkinf15320b2004-06-03 03:38:44 +0000186 * 2.5.5
187 */
188 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_values);
189 RET2RVAL(ret, rvalue);
190
191 /*
192 * Resolve references in constraints.
193 */
Lev Walkin1ef05162004-08-25 00:42:25 +0000194 ret = asn1f_recurse_expr(arg, asn1f_resolve_constraints);
Lev Walkinf15320b2004-06-03 03:38:44 +0000195 RET2RVAL(ret, rvalue);
196
197 /*
198 * 6. INTEGER value processed at 2.5.4.
199 */
200
201 /*
202 * Make sure everybody's behaving well.
203 */
204 assert(arg->expr == expr);
205 }
206
207 /*
208 * 5. Automatic tagging
209 */
210 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000211
212 arg->expr = expr;
213
214 ret = asn1f_recurse_expr(arg, asn1f_fix_constr_autotag);
215 RET2RVAL(ret, rvalue);
216
217 assert(arg->expr == expr);
218 }
219
220 /*
221 * 8. fix BIT STRING
222 * 9. fix spaces in cstrings
223 */
224 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000225 arg->expr = expr;
226
227 ret = asn1f_recurse_expr(arg, asn1f_fix_bit_string);
228 RET2RVAL(ret, rvalue);
229
230 ret = asn1f_recurse_expr(arg, asn1f_fix_cstring);
231 RET2RVAL(ret, rvalue);
232
233 assert(arg->expr == expr);
234 }
235
236 /*
237 * ... Check for tags distinctness.
238 */
239 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000240 arg->expr = expr;
241
242 ret = asn1f_recurse_expr(arg, asn1f_check_constr_tags_distinct);
243 RET2RVAL(ret, rvalue);
244
245 assert(arg->expr == expr);
246 }
247
Lev Walkind24c62d2004-09-15 11:47:23 +0000248 return rvalue;
249}
250
251static int
252asn1f_fix_module__phase_2(arg_t *arg) {
253 asn1p_expr_t *expr;
254 int rvalue = 0;
255 int ret;
256
Lev Walkin1ef05162004-08-25 00:42:25 +0000257 TQ_FOR(expr, &(arg->mod->members), next) {
258 arg->expr = expr;
259
Lev Walkind541c252004-09-05 10:36:22 +0000260 if(arg->expr->meta_type == AMT_PARAMTYPE)
261 /* Do not process the parametrized types here */
262 continue;
263
Lev Walkinb25fa062004-09-29 13:17:06 +0000264 /*
265 * Check semantic validity of constraints.
266 */
Lev Walkin1ef05162004-08-25 00:42:25 +0000267 ret = asn1f_recurse_expr(arg, asn1f_check_constraints);
268 RET2RVAL(ret, rvalue);
269
270 assert(arg->expr == expr);
271 }
272
Lev Walkinf15320b2004-06-03 03:38:44 +0000273 return rvalue;
274}
275
Lev Walkinf15320b2004-06-03 03:38:44 +0000276static int
277asn1f_fix_simple(arg_t *arg) {
278 int rvalue = 0;
279 int ret;
280
281 ret = asn1f_fix_enum(arg);
282 RET2RVAL(ret, rvalue);
283
284 ret = asn1f_fix_integer(arg);
285 RET2RVAL(ret, rvalue);
286
287 return rvalue;
288}
289
290static int
291asn1f_fix_constructed(arg_t *arg) {
292 int rvalue = 0;
293 int ret;
294
295 switch(arg->expr->expr_type) {
296 case ASN_CONSTR_SEQUENCE:
297 case ASN_CONSTR_SET:
298 case ASN_CONSTR_CHOICE:
299 break;
300 default:
301 return 0;
302 }
303
304 /* Check identifier distinctness */
305 ret = asn1f_check_unique_expr(arg, NULL);
306 RET2RVAL(ret, rvalue);
307
308 /* Fix extensibility */
309 ret = asn1f_fix_constr_ext(arg);
310 RET2RVAL(ret, rvalue);
311
312 /* Fix tagging */
Lev Walkind541c252004-09-05 10:36:22 +0000313 ret = asn1f_fix_constr_tag(arg, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000314 RET2RVAL(ret, rvalue);
315
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000316 /* Import COMPONENTS OF stuff */
317 ret = asn1f_pull_components_of(arg);
318 RET2RVAL(ret, rvalue);
319
Lev Walkinf15320b2004-06-03 03:38:44 +0000320 return rvalue;
321}
322
323static int
Lev Walkin1ef05162004-08-25 00:42:25 +0000324asn1f_resolve_constraints(arg_t *arg) {
Lev Walkinb45e0672004-08-18 05:42:05 +0000325 asn1p_expr_t *top_parent;
Lev Walkin5253da42004-08-20 13:25:56 +0000326 asn1p_expr_type_e etype;
Lev Walkinf15320b2004-06-03 03:38:44 +0000327 int rvalue = 0;
328 int ret;
329
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000330 top_parent = asn1f_find_terminal_type(arg, arg->expr);
Lev Walkin5253da42004-08-20 13:25:56 +0000331 if(top_parent)
332 etype = top_parent->expr_type;
333 else etype = A1TC_INVALID;
334
Lev Walkind541c252004-09-05 10:36:22 +0000335 DEBUG("asn1f_resolve_constraints(%s)", arg->expr->Identifier);
336
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000337 ret = asn1constraint_resolve(arg, arg->expr->module,
338 arg->expr->constraints, etype, 0);
Lev Walkinb45e0672004-08-18 05:42:05 +0000339 RET2RVAL(ret, rvalue);
Lev Walkinf15320b2004-06-03 03:38:44 +0000340
Lev Walkin1ef05162004-08-25 00:42:25 +0000341 return rvalue;
342}
343
344static int
345asn1f_check_constraints(arg_t *arg) {
346 static enum asn1p_constraint_type_e test_types[] = {
347 ACT_EL_RANGE, ACT_CT_SIZE, ACT_CT_FROM };
348 asn1p_expr_t *top_parent;
349 asn1cnst_range_t *range;
350 asn1p_expr_type_e etype;
351 unsigned int i;
352 int rvalue = 0;
353 int ret;
354
Lev Walkind541c252004-09-05 10:36:22 +0000355 DEBUG("asn1f_check_constraints(%s{%d/%d})",
356 arg->expr->Identifier,
357 arg->expr->meta_type, arg->expr->expr_type);
358
Lev Walkin1ef05162004-08-25 00:42:25 +0000359 top_parent = asn1f_find_terminal_type(arg, arg->expr);
360 if(!top_parent)
361 return 0;
362 etype = top_parent->expr_type;
363
Lev Walkinb45e0672004-08-18 05:42:05 +0000364 ret = asn1constraint_pullup(arg);
365 RET2RVAL(ret, rvalue);
366
Lev Walkin1ef05162004-08-25 00:42:25 +0000367 for(i = 0; i < sizeof(test_types)/sizeof(test_types[0]); i++) {
368 range = asn1constraint_compute_PER_range(
Lev Walkinb9fa7802004-08-25 02:04:39 +0000369 etype,
Lev Walkin1ef05162004-08-25 00:42:25 +0000370 arg->expr->combined_constraints,
Lev Walkinb9fa7802004-08-25 02:04:39 +0000371 test_types[i], 0, 0, 0);
Lev Walkind541c252004-09-05 10:36:22 +0000372 if(!range && errno == EPERM) {
373 FATAL("This error happened for %s (%d) at line %d",
374 arg->expr->Identifier,
375 arg->expr->meta_type,
376 arg->expr->_lineno);
Lev Walkin1ef05162004-08-25 00:42:25 +0000377 return -1;
Lev Walkind541c252004-09-05 10:36:22 +0000378 }
Lev Walkin1ef05162004-08-25 00:42:25 +0000379 asn1constraint_range_free(range);
Lev Walkinb45e0672004-08-18 05:42:05 +0000380 }
Lev Walkin1ef05162004-08-25 00:42:25 +0000381
Lev Walkinf15320b2004-06-03 03:38:44 +0000382 return rvalue;
383}
384
385/*
386 * Print everything to stderr
387 */
388static void
389_default_error_logger(int _severity, const char *fmt, ...) {
390 va_list ap;
391 char *pfx = "";
392
393 switch(_severity) {
394 case -1: pfx = "DEBUG: "; break;
395 case 0: pfx = "WARNING: "; break;
396 case 1: pfx = "FATAL: "; break;
397 }
398
399 fprintf(stderr, "%s", pfx);
400 va_start(ap, fmt);
401 vfprintf(stderr, fmt, ap);
402 va_end(ap);
403 fprintf(stderr, "\n");
404}