blob: 4a279325c7c21fa71b6ca626332f5ed4b1461979 [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 */
Lev Walkin1ef05162004-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 */
Lev Walkinf15320b2004-06-03 03:38:44 +000020
Lev Walkinb45e0672004-08-18 05:42:05 +000021arg_t a1f_replace_me_with_proper_interface_arg;
Lev Walkinf15320b2004-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
Lev Walkin5253da42004-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
Lev Walkinb45e0672004-08-18 05:42:05 +000068 a1f_replace_me_with_proper_interface_arg = arg;
69
Lev Walkinf15320b2004-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
Lev Walkinb45e0672004-08-18 05:42:05 +000091 memset(&a1f_replace_me_with_proper_interface_arg, 0, sizeof(arg_t));
92
Lev Walkinf15320b2004-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;
Lev Walkin1ef05162004-08-25 00:42:25 +0000106 int ret;
Lev Walkinf15320b2004-06-03 03:38:44 +0000107
Lev Walkinb45e0672004-08-18 05:42:05 +0000108 switch((arg->mod->module_flags & MSF_MASK_TAGS)) {
Lev Walkinf15320b2004-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
Lev Walkinb45e0672004-08-18 05:42:05 +0000120 switch((arg->mod->module_flags & MSF_MASK_INSTRUCTIONS)) {
121 case MSF_NOFLAGS:
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000122 /*
123 * arg->mod->module_flags |= MSF_TAG_INSTRUCTIONS;
124 */
Lev Walkinb45e0672004-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
Lev Walkinf15320b2004-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) {
Lev Walkinf15320b2004-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 /*
Lev Walkinf15320b2004-06-03 03:38:44 +0000162 * 2.5.4
163 */
164 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_types);
165 RET2RVAL(ret, rvalue);
166
167 /*
Lev Walkind541c252004-09-05 10:36:22 +0000168 * Fix tagging of top-level types.
169 */
170 ret = asn1f_fix_constr_tag(arg, 1);
171 RET2RVAL(ret, rvalue);
172
173 /*
174 * 2.[234] Process SEQUENCE/SET/CHOICE types.
175 */
176 ret = asn1f_recurse_expr(arg, asn1f_fix_constructed);
177 RET2RVAL(ret, rvalue);
178
179 /*
Lev Walkinf15320b2004-06-03 03:38:44 +0000180 * 2.5.5
181 */
182 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_values);
183 RET2RVAL(ret, rvalue);
184
185 /*
186 * Resolve references in constraints.
187 */
Lev Walkin1ef05162004-08-25 00:42:25 +0000188 ret = asn1f_recurse_expr(arg, asn1f_resolve_constraints);
Lev Walkinf15320b2004-06-03 03:38:44 +0000189 RET2RVAL(ret, rvalue);
190
191 /*
192 * 6. INTEGER value processed at 2.5.4.
193 */
194
195 /*
196 * Make sure everybody's behaving well.
197 */
198 assert(arg->expr == expr);
199 }
200
201 /*
202 * 5. Automatic tagging
203 */
204 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000205
206 arg->expr = expr;
207
208 ret = asn1f_recurse_expr(arg, asn1f_fix_constr_autotag);
209 RET2RVAL(ret, rvalue);
210
211 assert(arg->expr == expr);
212 }
213
214 /*
215 * 8. fix BIT STRING
216 * 9. fix spaces in cstrings
217 */
218 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000219 arg->expr = expr;
220
221 ret = asn1f_recurse_expr(arg, asn1f_fix_bit_string);
222 RET2RVAL(ret, rvalue);
223
224 ret = asn1f_recurse_expr(arg, asn1f_fix_cstring);
225 RET2RVAL(ret, rvalue);
226
227 assert(arg->expr == expr);
228 }
229
230 /*
231 * ... Check for tags distinctness.
232 */
233 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000234 arg->expr = expr;
235
236 ret = asn1f_recurse_expr(arg, asn1f_check_constr_tags_distinct);
237 RET2RVAL(ret, rvalue);
238
239 assert(arg->expr == expr);
240 }
241
Lev Walkin1ef05162004-08-25 00:42:25 +0000242 /*
243 * Check semantic validity of constraints.
244 */
245 TQ_FOR(expr, &(arg->mod->members), next) {
246 arg->expr = expr;
247
Lev Walkind541c252004-09-05 10:36:22 +0000248 if(arg->expr->meta_type == AMT_PARAMTYPE)
249 /* Do not process the parametrized types here */
250 continue;
251
Lev Walkin1ef05162004-08-25 00:42:25 +0000252 ret = asn1f_recurse_expr(arg, asn1f_check_constraints);
253 RET2RVAL(ret, rvalue);
254
255 assert(arg->expr == expr);
256 }
257
Lev Walkinf15320b2004-06-03 03:38:44 +0000258 return rvalue;
259}
260
261
262static int
263asn1f_fix_simple(arg_t *arg) {
264 int rvalue = 0;
265 int ret;
266
267 ret = asn1f_fix_enum(arg);
268 RET2RVAL(ret, rvalue);
269
270 ret = asn1f_fix_integer(arg);
271 RET2RVAL(ret, rvalue);
272
273 return rvalue;
274}
275
276static int
277asn1f_fix_constructed(arg_t *arg) {
278 int rvalue = 0;
279 int ret;
280
281 switch(arg->expr->expr_type) {
282 case ASN_CONSTR_SEQUENCE:
283 case ASN_CONSTR_SET:
284 case ASN_CONSTR_CHOICE:
285 break;
286 default:
287 return 0;
288 }
289
290 /* Check identifier distinctness */
291 ret = asn1f_check_unique_expr(arg, NULL);
292 RET2RVAL(ret, rvalue);
293
294 /* Fix extensibility */
295 ret = asn1f_fix_constr_ext(arg);
296 RET2RVAL(ret, rvalue);
297
298 /* Fix tagging */
Lev Walkind541c252004-09-05 10:36:22 +0000299 ret = asn1f_fix_constr_tag(arg, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000300 RET2RVAL(ret, rvalue);
301
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000302 /* Import COMPONENTS OF stuff */
303 ret = asn1f_pull_components_of(arg);
304 RET2RVAL(ret, rvalue);
305
Lev Walkinf15320b2004-06-03 03:38:44 +0000306 return rvalue;
307}
308
309static int
Lev Walkin1ef05162004-08-25 00:42:25 +0000310asn1f_resolve_constraints(arg_t *arg) {
Lev Walkinb45e0672004-08-18 05:42:05 +0000311 asn1p_expr_t *top_parent;
Lev Walkin5253da42004-08-20 13:25:56 +0000312 asn1p_expr_type_e etype;
Lev Walkinf15320b2004-06-03 03:38:44 +0000313 int rvalue = 0;
314 int ret;
315
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000316 top_parent = asn1f_find_terminal_type(arg, arg->expr);
Lev Walkin5253da42004-08-20 13:25:56 +0000317 if(top_parent)
318 etype = top_parent->expr_type;
319 else etype = A1TC_INVALID;
320
Lev Walkind541c252004-09-05 10:36:22 +0000321 DEBUG("asn1f_resolve_constraints(%s)", arg->expr->Identifier);
322
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000323 ret = asn1constraint_resolve(arg, arg->expr->module,
324 arg->expr->constraints, etype, 0);
Lev Walkinb45e0672004-08-18 05:42:05 +0000325 RET2RVAL(ret, rvalue);
Lev Walkinf15320b2004-06-03 03:38:44 +0000326
Lev Walkin1ef05162004-08-25 00:42:25 +0000327 return rvalue;
328}
329
330static int
331asn1f_check_constraints(arg_t *arg) {
332 static enum asn1p_constraint_type_e test_types[] = {
333 ACT_EL_RANGE, ACT_CT_SIZE, ACT_CT_FROM };
334 asn1p_expr_t *top_parent;
335 asn1cnst_range_t *range;
336 asn1p_expr_type_e etype;
337 unsigned int i;
338 int rvalue = 0;
339 int ret;
340
Lev Walkind541c252004-09-05 10:36:22 +0000341 DEBUG("asn1f_check_constraints(%s{%d/%d})",
342 arg->expr->Identifier,
343 arg->expr->meta_type, arg->expr->expr_type);
344
Lev Walkin1ef05162004-08-25 00:42:25 +0000345 top_parent = asn1f_find_terminal_type(arg, arg->expr);
346 if(!top_parent)
347 return 0;
348 etype = top_parent->expr_type;
349
Lev Walkinb45e0672004-08-18 05:42:05 +0000350 ret = asn1constraint_pullup(arg);
351 RET2RVAL(ret, rvalue);
352
Lev Walkin1ef05162004-08-25 00:42:25 +0000353 for(i = 0; i < sizeof(test_types)/sizeof(test_types[0]); i++) {
354 range = asn1constraint_compute_PER_range(
Lev Walkinb9fa7802004-08-25 02:04:39 +0000355 etype,
Lev Walkin1ef05162004-08-25 00:42:25 +0000356 arg->expr->combined_constraints,
Lev Walkinb9fa7802004-08-25 02:04:39 +0000357 test_types[i], 0, 0, 0);
Lev Walkind541c252004-09-05 10:36:22 +0000358 if(!range && errno == EPERM) {
359 FATAL("This error happened for %s (%d) at line %d",
360 arg->expr->Identifier,
361 arg->expr->meta_type,
362 arg->expr->_lineno);
Lev Walkin1ef05162004-08-25 00:42:25 +0000363 return -1;
Lev Walkind541c252004-09-05 10:36:22 +0000364 }
Lev Walkin1ef05162004-08-25 00:42:25 +0000365 asn1constraint_range_free(range);
Lev Walkinb45e0672004-08-18 05:42:05 +0000366 }
Lev Walkin1ef05162004-08-25 00:42:25 +0000367
Lev Walkinf15320b2004-06-03 03:38:44 +0000368 return rvalue;
369}
370
371/*
372 * Print everything to stderr
373 */
374static void
375_default_error_logger(int _severity, const char *fmt, ...) {
376 va_list ap;
377 char *pfx = "";
378
379 switch(_severity) {
380 case -1: pfx = "DEBUG: "; break;
381 case 0: pfx = "WARNING: "; break;
382 case 1: pfx = "FATAL: "; break;
383 }
384
385 fprintf(stderr, "%s", pfx);
386 va_start(ap, fmt);
387 vfprintf(stderr, fmt, ap);
388 va_end(ap);
389 fprintf(stderr, "\n");
390}