blob: 4810079187f69d2fdbd06e871ad10adce1c9c4b8 [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 */
18static int asn1f_fix_constraints(arg_t *arg); /* For subtype constraints */
19
Lev Walkinb45e0672004-08-18 05:42:05 +000020arg_t a1f_replace_me_with_proper_interface_arg;
Lev Walkinf15320b2004-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
Lev Walkin5253da42004-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
Lev Walkinb45e0672004-08-18 05:42:05 +000067 a1f_replace_me_with_proper_interface_arg = arg;
68
Lev Walkinf15320b2004-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
Lev Walkinb45e0672004-08-18 05:42:05 +000090 memset(&a1f_replace_me_with_proper_interface_arg, 0, sizeof(arg_t));
91
Lev Walkinf15320b2004-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
Lev Walkinb45e0672004-08-18 05:42:05 +0000106 switch((arg->mod->module_flags & MSF_MASK_TAGS)) {
Lev Walkinf15320b2004-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
Lev Walkinb45e0672004-08-18 05:42:05 +0000118 switch((arg->mod->module_flags & MSF_MASK_INSTRUCTIONS)) {
119 case MSF_NOFLAGS:
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000120 /*
121 * arg->mod->module_flags |= MSF_TAG_INSTRUCTIONS;
122 */
Lev Walkinb45e0672004-08-18 05:42:05 +0000123 break;
124 case MSF_unk_INSTRUCTIONS:
125 WARNING("Module %s defined with unrecognized "
126 "encoding reference", arg->mod->Identifier);
127 RET2RVAL(1, rvalue);
128 /* Fall through */
129 case MSF_TAG_INSTRUCTIONS:
130 case MSF_XER_INSTRUCTIONS:
131 break;
132 default:
133 FATAL("Module %s defined with ambiguous encoding reference",
134 arg->mod->Identifier);
135 RET2RVAL(-1, rvalue);
136 }
137
Lev Walkinf15320b2004-06-03 03:38:44 +0000138 /*
139 * Do various non-recursive transformations.
140 * Order is not important.
141 */
142 TQ_FOR(expr, &(arg->mod->members), next) {
143 int ret;
144 arg->expr = expr;
145
146 if(expr->meta_type == AMT_PARAMTYPE)
147 /* Do not process the parametrized type just yet */
148 continue;
149
150 DEBUG("=== Now processing \"%s\" at line %d ===",
151 expr->Identifier, expr->_lineno);
152 assert(expr->meta_type != AMT_INVALID);
153
154 /*
155 * 2.1 Pre-process simple types (ENUMERATED, INTEGER, etc).
156 */
157 ret = asn1f_recurse_expr(arg, asn1f_fix_simple);
158 RET2RVAL(ret, rvalue);
159
160 /*
161 * 2.[234] Process SEQUENCE/SET/CHOICE types.
162 */
163 ret = asn1f_recurse_expr(arg, asn1f_fix_constructed);
164 RET2RVAL(ret, rvalue);
165
166 /*
167 * 2.5.4
168 */
169 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_types);
170 RET2RVAL(ret, rvalue);
171
172 /*
173 * 2.5.5
174 */
175 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_values);
176 RET2RVAL(ret, rvalue);
177
178 /*
179 * Resolve references in constraints.
180 */
181 ret = asn1f_recurse_expr(arg, asn1f_fix_constraints);
182 RET2RVAL(ret, rvalue);
183
184 /*
185 * 6. INTEGER value processed at 2.5.4.
186 */
187
188 /*
189 * Make sure everybody's behaving well.
190 */
191 assert(arg->expr == expr);
192 }
193
194 /*
195 * 5. Automatic tagging
196 */
197 TQ_FOR(expr, &(arg->mod->members), next) {
198 int ret;
199
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) {
213 int ret;
214 arg->expr = expr;
215
216 ret = asn1f_recurse_expr(arg, asn1f_fix_bit_string);
217 RET2RVAL(ret, rvalue);
218
219 ret = asn1f_recurse_expr(arg, asn1f_fix_cstring);
220 RET2RVAL(ret, rvalue);
221
222 assert(arg->expr == expr);
223 }
224
225 /*
226 * ... Check for tags distinctness.
227 */
228 TQ_FOR(expr, &(arg->mod->members), next) {
229 int ret;
230 arg->expr = expr;
231
232 ret = asn1f_recurse_expr(arg, asn1f_check_constr_tags_distinct);
233 RET2RVAL(ret, rvalue);
234
235 assert(arg->expr == expr);
236 }
237
238 return rvalue;
239}
240
241
242static int
243asn1f_fix_simple(arg_t *arg) {
244 int rvalue = 0;
245 int ret;
246
247 ret = asn1f_fix_enum(arg);
248 RET2RVAL(ret, rvalue);
249
250 ret = asn1f_fix_integer(arg);
251 RET2RVAL(ret, rvalue);
252
253 return rvalue;
254}
255
256static int
257asn1f_fix_constructed(arg_t *arg) {
258 int rvalue = 0;
259 int ret;
260
261 switch(arg->expr->expr_type) {
262 case ASN_CONSTR_SEQUENCE:
263 case ASN_CONSTR_SET:
264 case ASN_CONSTR_CHOICE:
265 break;
266 default:
267 return 0;
268 }
269
270 /* Check identifier distinctness */
271 ret = asn1f_check_unique_expr(arg, NULL);
272 RET2RVAL(ret, rvalue);
273
274 /* Fix extensibility */
275 ret = asn1f_fix_constr_ext(arg);
276 RET2RVAL(ret, rvalue);
277
278 /* Fix tagging */
279 ret = asn1f_fix_constr_tag(arg);
280 RET2RVAL(ret, rvalue);
281
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000282 /* Import COMPONENTS OF stuff */
283 ret = asn1f_pull_components_of(arg);
284 RET2RVAL(ret, rvalue);
285
Lev Walkinf15320b2004-06-03 03:38:44 +0000286 return rvalue;
287}
288
289static int
Lev Walkinf15320b2004-06-03 03:38:44 +0000290asn1f_fix_constraints(arg_t *arg) {
Lev Walkinb45e0672004-08-18 05:42:05 +0000291 asn1p_expr_t *top_parent;
Lev Walkin5253da42004-08-20 13:25:56 +0000292 asn1p_expr_type_e etype;
Lev Walkinf15320b2004-06-03 03:38:44 +0000293 int rvalue = 0;
294 int ret;
295
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000296 top_parent = asn1f_find_terminal_type(arg, arg->expr);
Lev Walkin5253da42004-08-20 13:25:56 +0000297 if(top_parent)
298 etype = top_parent->expr_type;
299 else etype = A1TC_INVALID;
300
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000301 ret = asn1constraint_resolve(arg, arg->expr->module,
302 arg->expr->constraints, etype, 0);
Lev Walkinb45e0672004-08-18 05:42:05 +0000303 RET2RVAL(ret, rvalue);
Lev Walkinf15320b2004-06-03 03:38:44 +0000304
Lev Walkinb45e0672004-08-18 05:42:05 +0000305 ret = asn1constraint_pullup(arg);
306 RET2RVAL(ret, rvalue);
307
Lev Walkinb45e0672004-08-18 05:42:05 +0000308 if(top_parent) {
309 static enum asn1p_constraint_type_e test_types[] = {
310 ACT_EL_RANGE, ACT_CT_SIZE, ACT_CT_FROM };
311 unsigned int i;
312 for(i = 0; i < sizeof(test_types)/sizeof(test_types[0]); i++) {
313 asn1cnst_range_t *range;
314 range = asn1constraint_compute_PER_range(
315 top_parent->expr_type,
316 arg->expr->combined_constraints,
317 test_types[i], 0, 0);
318 if(!range && errno == EPERM)
319 return -1;
320 asn1constraint_range_free(range);
321 }
322 }
323
Lev Walkinf15320b2004-06-03 03:38:44 +0000324 return rvalue;
325}
326
327/*
328 * Print everything to stderr
329 */
330static void
331_default_error_logger(int _severity, const char *fmt, ...) {
332 va_list ap;
333 char *pfx = "";
334
335 switch(_severity) {
336 case -1: pfx = "DEBUG: "; break;
337 case 0: pfx = "WARNING: "; break;
338 case 1: pfx = "FATAL: "; break;
339 }
340
341 fprintf(stderr, "%s", pfx);
342 va_start(ap, fmt);
343 vfprintf(stderr, fmt, ap);
344 va_end(ap);
345 fprintf(stderr, "\n");
346}