blob: d8cc863cdc4e2cb53a16b200dc8ca545f8fe25ad [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
Lev Walkin4efbfb72005-02-25 14:20:30 +00002#include "asn1fix.h"
Lev Walkinf15320b2004-06-03 03:38:44 +00003
4/* Print everything to stderr */
5static void _default_error_logger(int _severity, const char *fmt, ...);
6
7/*
8 * Internal check functions.
9 */
Lev Walkind24c62d2004-09-15 11:47:23 +000010static int asn1f_fix_module__phase_1(arg_t *arg);
11static int asn1f_fix_module__phase_2(arg_t *arg);
Lev Walkinf15320b2004-06-03 03:38:44 +000012static int asn1f_fix_simple(arg_t *arg); /* For INTEGER/ENUMERATED */
13static int asn1f_fix_constructed(arg_t *arg); /* For SEQUENCE/SET/CHOICE */
Lev Walkin1ef05162004-08-25 00:42:25 +000014static int asn1f_resolve_constraints(arg_t *arg); /* For subtype constraints */
15static int asn1f_check_constraints(arg_t *arg); /* For subtype constraints */
Lev Walkinf593f102005-02-22 07:59:59 +000016static int asn1f_check_duplicate(arg_t *arg);
Lev Walkin1dec5802005-03-04 09:02:27 +000017static int asn1f_apply_unique_index(arg_t *arg);
Lev Walkinf15320b2004-06-03 03:38:44 +000018
Lev Walkinb45e0672004-08-18 05:42:05 +000019arg_t a1f_replace_me_with_proper_interface_arg;
Lev Walkinf15320b2004-06-03 03:38:44 +000020
21/*
22 * Scan every module defined here in search for inconsistences.
23 */
24int
25asn1f_process(asn1p_t *asn, enum asn1f_flags flags,
26 error_logger_f error_logger) {
27 arg_t arg;
28 int fatals = 0;
29 int warnings = 0;
Lev Walkin4533a5f2005-03-18 04:22:41 +000030 int ret;
Lev Walkinf15320b2004-06-03 03:38:44 +000031
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.
Lev Walkinf593f102005-02-22 07:59:59 +000079 * PHASE I.
Lev Walkinf15320b2004-06-03 03:38:44 +000080 */
81 TQ_FOR(arg.mod, &(asn->modules), mod_next) {
Lev Walkin4533a5f2005-03-18 04:22:41 +000082 ret = asn1f_fix_module__phase_1(&arg);
Lev Walkinf15320b2004-06-03 03:38:44 +000083 /*
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 }
Lev Walkinf593f102005-02-22 07:59:59 +000090 /* PHASE II. */
Lev Walkind24c62d2004-09-15 11:47:23 +000091 TQ_FOR(arg.mod, &(asn->modules), mod_next) {
Lev Walkin4533a5f2005-03-18 04:22:41 +000092 ret = asn1f_fix_module__phase_2(&arg);
Lev Walkind24c62d2004-09-15 11:47:23 +000093 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 Walkin4533a5f2005-03-18 04:22:41 +0000113 asn1p_module_t *omod;
114
115 /*
116 * Check that we don't have a similarly named module.
117 */
118 TQ_FOR(omod, &arg->asn->modules, mod_next) {
119 int sameNames;
120 if(omod == arg->mod) break;
Lev Walkinb36317c2005-08-12 10:09:10 +0000121 sameNames = strcmp(omod->ModuleName, arg->mod->ModuleName)?0:1;
Lev Walkin4533a5f2005-03-18 04:22:41 +0000122 if(omod->module_oid && arg->mod->module_oid) {
123 /* Compare only the OID. */
124 if(asn1p_oid_compare(omod->module_oid,
125 arg->mod->module_oid) == 0) {
Lev Walkin1a447952005-03-18 04:26:12 +0000126 FATAL("ASN.1 module %s in %s "
Lev Walkin4533a5f2005-03-18 04:22:41 +0000127 "has the same OBJECT IDENTIFIER"
Lev Walkin1a447952005-03-18 04:26:12 +0000128 " as module %s",
Lev Walkinb36317c2005-08-12 10:09:10 +0000129 omod->ModuleName,
Lev Walkin1a447952005-03-18 04:26:12 +0000130 omod->source_file_name,
Lev Walkinb36317c2005-08-12 10:09:10 +0000131 arg->mod->ModuleName
Lev Walkin4533a5f2005-03-18 04:22:41 +0000132 );
133 RET2RVAL(-1, rvalue);
134 } else if(sameNames) {
Lev Walkinb36317c2005-08-12 10:09:10 +0000135 WARNING("ASN.1 module %s is defined more than once, with different OIDs", omod->ModuleName);
Lev Walkin4533a5f2005-03-18 04:22:41 +0000136 RET2RVAL(1, rvalue);
137 }
138 } else if(sameNames) {
139 FATAL("ASN.1 module %s is defined more than once",
Lev Walkinb36317c2005-08-12 10:09:10 +0000140 omod->ModuleName);
Lev Walkin4533a5f2005-03-18 04:22:41 +0000141 RET2RVAL(-1, rvalue);
142 }
143 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000144
Lev Walkinb45e0672004-08-18 05:42:05 +0000145 switch((arg->mod->module_flags & MSF_MASK_TAGS)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000146 case MSF_NOFLAGS:
147 case MSF_EXPLICIT_TAGS:
148 case MSF_IMPLICIT_TAGS:
149 case MSF_AUTOMATIC_TAGS:
150 break;
151 default:
152 FATAL("Module %s defined with ambiguous global tagging mode",
Lev Walkinb36317c2005-08-12 10:09:10 +0000153 arg->mod->ModuleName);
Lev Walkinf15320b2004-06-03 03:38:44 +0000154 RET2RVAL(-1, rvalue);
155 }
156
Lev Walkinb45e0672004-08-18 05:42:05 +0000157 switch((arg->mod->module_flags & MSF_MASK_INSTRUCTIONS)) {
158 case MSF_NOFLAGS:
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000159 /*
160 * arg->mod->module_flags |= MSF_TAG_INSTRUCTIONS;
161 */
Lev Walkinb45e0672004-08-18 05:42:05 +0000162 break;
163 case MSF_unk_INSTRUCTIONS:
164 WARNING("Module %s defined with unrecognized "
Lev Walkinb36317c2005-08-12 10:09:10 +0000165 "encoding reference", arg->mod->ModuleName);
Lev Walkinb45e0672004-08-18 05:42:05 +0000166 RET2RVAL(1, rvalue);
167 /* Fall through */
168 case MSF_TAG_INSTRUCTIONS:
169 case MSF_XER_INSTRUCTIONS:
170 break;
171 default:
172 FATAL("Module %s defined with ambiguous encoding reference",
Lev Walkinb36317c2005-08-12 10:09:10 +0000173 arg->mod->ModuleName);
Lev Walkinb45e0672004-08-18 05:42:05 +0000174 RET2RVAL(-1, rvalue);
175 }
176
Lev Walkinf15320b2004-06-03 03:38:44 +0000177 /*
178 * Do various non-recursive transformations.
Lev Walkinf15320b2004-06-03 03:38:44 +0000179 */
180 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000181 arg->expr = expr;
182
Lev Walkinf593f102005-02-22 07:59:59 +0000183 /* Check whether this type is a duplicate */
184 ret = asn1f_check_duplicate(arg);
185 RET2RVAL(ret, rvalue);
186
Lev Walkinf15320b2004-06-03 03:38:44 +0000187 if(expr->meta_type == AMT_PARAMTYPE)
188 /* Do not process the parametrized type just yet */
189 continue;
190
Lev Walkind370e9f2006-03-16 10:03:35 +0000191 DEBUG("=== Now processing \"%s\" (%d/0x%x) at line %d ===",
192 expr->Identifier, expr->meta_type, expr->expr_type,
193 expr->_lineno);
Lev Walkinf15320b2004-06-03 03:38:44 +0000194 assert(expr->meta_type != AMT_INVALID);
195
196 /*
197 * 2.1 Pre-process simple types (ENUMERATED, INTEGER, etc).
198 */
199 ret = asn1f_recurse_expr(arg, asn1f_fix_simple);
200 RET2RVAL(ret, rvalue);
201
202 /*
Lev Walkinf15320b2004-06-03 03:38:44 +0000203 * 2.5.4
204 */
205 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_types);
206 RET2RVAL(ret, rvalue);
207
208 /*
Lev Walkind541c252004-09-05 10:36:22 +0000209 * Fix tagging of top-level types.
210 */
211 ret = asn1f_fix_constr_tag(arg, 1);
212 RET2RVAL(ret, rvalue);
213
214 /*
215 * 2.[234] Process SEQUENCE/SET/CHOICE types.
216 */
217 ret = asn1f_recurse_expr(arg, asn1f_fix_constructed);
218 RET2RVAL(ret, rvalue);
219
220 /*
Lev Walkinf15320b2004-06-03 03:38:44 +0000221 * 2.5.5
222 */
223 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_values);
224 RET2RVAL(ret, rvalue);
225
226 /*
Lev Walkind370e9f2006-03-16 10:03:35 +0000227 * Parse class objects and fill up the object class with data.
Lev Walkinaa7f5302006-03-14 15:53:59 +0000228 */
Lev Walkind370e9f2006-03-16 10:03:35 +0000229 ret = asn1f_parse_class_object(arg);
230 RET2RVAL(ret, rvalue);
Lev Walkinaa7f5302006-03-14 15:53:59 +0000231
232 /*
Lev Walkinf15320b2004-06-03 03:38:44 +0000233 * Resolve references in constraints.
234 */
Lev Walkin1ef05162004-08-25 00:42:25 +0000235 ret = asn1f_recurse_expr(arg, asn1f_resolve_constraints);
Lev Walkinf15320b2004-06-03 03:38:44 +0000236 RET2RVAL(ret, rvalue);
237
238 /*
239 * 6. INTEGER value processed at 2.5.4.
240 */
241
242 /*
243 * Make sure everybody's behaving well.
244 */
245 assert(arg->expr == expr);
246 }
247
248 /*
249 * 5. Automatic tagging
250 */
251 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000252
253 arg->expr = expr;
254
255 ret = asn1f_recurse_expr(arg, asn1f_fix_constr_autotag);
256 RET2RVAL(ret, rvalue);
257
258 assert(arg->expr == expr);
259 }
260
261 /*
262 * 8. fix BIT STRING
263 * 9. fix spaces in cstrings
264 */
265 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000266 arg->expr = expr;
267
268 ret = asn1f_recurse_expr(arg, asn1f_fix_bit_string);
269 RET2RVAL(ret, rvalue);
270
271 ret = asn1f_recurse_expr(arg, asn1f_fix_cstring);
272 RET2RVAL(ret, rvalue);
273
274 assert(arg->expr == expr);
275 }
276
277 /*
278 * ... Check for tags distinctness.
279 */
280 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000281 arg->expr = expr;
282
283 ret = asn1f_recurse_expr(arg, asn1f_check_constr_tags_distinct);
284 RET2RVAL(ret, rvalue);
285
286 assert(arg->expr == expr);
287 }
288
Lev Walkind24c62d2004-09-15 11:47:23 +0000289 return rvalue;
290}
291
292static int
293asn1f_fix_module__phase_2(arg_t *arg) {
294 asn1p_expr_t *expr;
295 int rvalue = 0;
296 int ret;
297
Lev Walkin1ef05162004-08-25 00:42:25 +0000298 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkind370e9f2006-03-16 10:03:35 +0000299 }
300
301 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkin1ef05162004-08-25 00:42:25 +0000302 arg->expr = expr;
303
Lev Walkinf593f102005-02-22 07:59:59 +0000304 if(expr->meta_type == AMT_PARAMTYPE)
Lev Walkind541c252004-09-05 10:36:22 +0000305 /* Do not process the parametrized types here */
306 continue;
307
Lev Walkinb25fa062004-09-29 13:17:06 +0000308 /*
Lev Walkin3645c1c2004-10-31 00:11:50 +0000309 * Dereference DEFAULT values.
310 */
311 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_defaults);
312 RET2RVAL(ret, rvalue);
313
314 /*
Lev Walkinb25fa062004-09-29 13:17:06 +0000315 * Check semantic validity of constraints.
316 */
Lev Walkin1ef05162004-08-25 00:42:25 +0000317 ret = asn1f_recurse_expr(arg, asn1f_check_constraints);
318 RET2RVAL(ret, rvalue);
319
Lev Walkin1dec5802005-03-04 09:02:27 +0000320 /*
321 * Uniquely tag each inner type.
322 */
323 asn1f_apply_unique_index(0);
324 ret = asn1f_recurse_expr(arg, asn1f_apply_unique_index);
325 RET2RVAL(ret, rvalue);
326
Lev Walkin1ef05162004-08-25 00:42:25 +0000327 assert(arg->expr == expr);
328 }
329
Lev Walkinf15320b2004-06-03 03:38:44 +0000330 return rvalue;
331}
332
Lev Walkinf15320b2004-06-03 03:38:44 +0000333static int
334asn1f_fix_simple(arg_t *arg) {
335 int rvalue = 0;
336 int ret;
337
338 ret = asn1f_fix_enum(arg);
339 RET2RVAL(ret, rvalue);
340
341 ret = asn1f_fix_integer(arg);
342 RET2RVAL(ret, rvalue);
343
344 return rvalue;
345}
346
347static int
348asn1f_fix_constructed(arg_t *arg) {
349 int rvalue = 0;
350 int ret;
351
352 switch(arg->expr->expr_type) {
353 case ASN_CONSTR_SEQUENCE:
354 case ASN_CONSTR_SET:
355 case ASN_CONSTR_CHOICE:
356 break;
357 default:
358 return 0;
359 }
360
361 /* Check identifier distinctness */
362 ret = asn1f_check_unique_expr(arg, NULL);
363 RET2RVAL(ret, rvalue);
364
365 /* Fix extensibility */
366 ret = asn1f_fix_constr_ext(arg);
367 RET2RVAL(ret, rvalue);
368
369 /* Fix tagging */
Lev Walkind541c252004-09-05 10:36:22 +0000370 ret = asn1f_fix_constr_tag(arg, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000371 RET2RVAL(ret, rvalue);
372
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000373 /* Import COMPONENTS OF stuff */
374 ret = asn1f_pull_components_of(arg);
375 RET2RVAL(ret, rvalue);
376
Lev Walkinf15320b2004-06-03 03:38:44 +0000377 return rvalue;
378}
379
380static int
Lev Walkin1ef05162004-08-25 00:42:25 +0000381asn1f_resolve_constraints(arg_t *arg) {
Lev Walkinb45e0672004-08-18 05:42:05 +0000382 asn1p_expr_t *top_parent;
Lev Walkin5253da42004-08-20 13:25:56 +0000383 asn1p_expr_type_e etype;
Lev Walkinf15320b2004-06-03 03:38:44 +0000384 int rvalue = 0;
385 int ret;
386
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000387 top_parent = asn1f_find_terminal_type(arg, arg->expr);
Lev Walkin5253da42004-08-20 13:25:56 +0000388 if(top_parent)
389 etype = top_parent->expr_type;
390 else etype = A1TC_INVALID;
391
Lev Walkin03850182005-03-10 10:02:50 +0000392 DEBUG("(%s)", arg->expr->Identifier);
Lev Walkind541c252004-09-05 10:36:22 +0000393
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000394 ret = asn1constraint_resolve(arg, arg->expr->constraints, etype, 0);
Lev Walkinb45e0672004-08-18 05:42:05 +0000395 RET2RVAL(ret, rvalue);
Lev Walkinf15320b2004-06-03 03:38:44 +0000396
Lev Walkin1ef05162004-08-25 00:42:25 +0000397 return rvalue;
398}
399
400static int
401asn1f_check_constraints(arg_t *arg) {
402 static enum asn1p_constraint_type_e test_types[] = {
403 ACT_EL_RANGE, ACT_CT_SIZE, ACT_CT_FROM };
404 asn1p_expr_t *top_parent;
405 asn1cnst_range_t *range;
406 asn1p_expr_type_e etype;
407 unsigned int i;
408 int rvalue = 0;
409 int ret;
410
Lev Walkin03850182005-03-10 10:02:50 +0000411 DEBUG("(%s{%d/%d})",
Lev Walkind541c252004-09-05 10:36:22 +0000412 arg->expr->Identifier,
413 arg->expr->meta_type, arg->expr->expr_type);
414
Lev Walkin1ef05162004-08-25 00:42:25 +0000415 top_parent = asn1f_find_terminal_type(arg, arg->expr);
416 if(!top_parent)
417 return 0;
418 etype = top_parent->expr_type;
419
Lev Walkinb45e0672004-08-18 05:42:05 +0000420 ret = asn1constraint_pullup(arg);
421 RET2RVAL(ret, rvalue);
422
Lev Walkin1ef05162004-08-25 00:42:25 +0000423 for(i = 0; i < sizeof(test_types)/sizeof(test_types[0]); i++) {
424 range = asn1constraint_compute_PER_range(
Lev Walkinb9fa7802004-08-25 02:04:39 +0000425 etype,
Lev Walkin1ef05162004-08-25 00:42:25 +0000426 arg->expr->combined_constraints,
Lev Walkin4b553412005-08-14 14:45:44 +0000427 test_types[i], 0, 0,
428 CPR_noflags /* ignore -fbless-SIZE */);
Lev Walkind541c252004-09-05 10:36:22 +0000429 if(!range && errno == EPERM) {
Lev Walkin9288d1c2005-03-10 11:27:13 +0000430 FATAL("This error happened for \"%s\" (meta %d) "
431 "at line %d",
Lev Walkind541c252004-09-05 10:36:22 +0000432 arg->expr->Identifier,
433 arg->expr->meta_type,
434 arg->expr->_lineno);
Lev Walkin1ef05162004-08-25 00:42:25 +0000435 return -1;
Lev Walkind541c252004-09-05 10:36:22 +0000436 }
Lev Walkin1ef05162004-08-25 00:42:25 +0000437 asn1constraint_range_free(range);
Lev Walkinb45e0672004-08-18 05:42:05 +0000438 }
Lev Walkin1ef05162004-08-25 00:42:25 +0000439
Lev Walkinf15320b2004-06-03 03:38:44 +0000440 return rvalue;
441}
442
Lev Walkinf593f102005-02-22 07:59:59 +0000443static int
444asn1f_check_duplicate(arg_t *arg) {
445 arg_t tmparg = *arg;
Lev Walkin9c2285a2006-03-09 08:49:26 +0000446 int rvalue = 0;
Lev Walkinf593f102005-02-22 07:59:59 +0000447
448 /*
449 * This is a linear scan in search of a similar type.
450 * The linear scan is just fine for the task, no need to over-optimize.
451 */
452 TQ_FOR(tmparg.mod, &arg->asn->modules, mod_next) {
Lev Walkin1a7cbd72006-03-07 10:39:42 +0000453 int critical = 1; /* FATAL */
454
455 if((arg->mod->_tags & MT_STANDARD_MODULE)
456 != (tmparg.mod->_tags & MT_STANDARD_MODULE)) {
457 /* Ignore clashes with standard module */
458 critical = 0; /* WARNING */
459 }
460
Lev Walkinf593f102005-02-22 07:59:59 +0000461 TQ_FOR(tmparg.expr, &(tmparg.mod->members), next) {
Lev Walkin1a7cbd72006-03-07 10:39:42 +0000462 int diff_files; /* different files */
463
Lev Walkinf593f102005-02-22 07:59:59 +0000464 assert(tmparg.expr->Identifier);
465 assert(arg->expr->Identifier);
Lev Walkin1a7cbd72006-03-07 10:39:42 +0000466
Lev Walkinf593f102005-02-22 07:59:59 +0000467 if(tmparg.expr == arg->expr) break;
468
469 if(strcmp(tmparg.expr->Identifier,
Lev Walkin1a7cbd72006-03-07 10:39:42 +0000470 arg->expr->Identifier))
471 continue;
472
473 diff_files = strcmp(arg->mod->source_file_name,
474 tmparg.mod->source_file_name) ? 1 : 0;
475
476 LOG(critical,
477 "ASN.1 expression \"%s\" at line %d of module %s\n"
478 "clashes with expression \"%s\" at line %d of module %s"
479 "%s%s%s.\n"
Lev Walkin41635d32006-03-18 05:06:57 +0000480 "Rename or remove either instance "
481 "to resolve the conflict",
Lev Walkin1a7cbd72006-03-07 10:39:42 +0000482 arg->expr->Identifier,
483 arg->expr->_lineno,
484 arg->mod->ModuleName,
485 tmparg.expr->Identifier,
486 tmparg.expr->_lineno,
487 tmparg.mod->ModuleName,
488 diff_files ? " (" : "",
489 diff_files ? tmparg.mod->source_file_name : "",
490 diff_files ? ")" : "");
491 if(critical)
Lev Walkinf593f102005-02-22 07:59:59 +0000492 return -1;
Lev Walkin9c2285a2006-03-09 08:49:26 +0000493 RET2RVAL(1, rvalue);
Lev Walkinf593f102005-02-22 07:59:59 +0000494 }
495 if(tmparg.mod == arg->mod) break;
496 }
497
Lev Walkin9c2285a2006-03-09 08:49:26 +0000498 return rvalue;
Lev Walkinf593f102005-02-22 07:59:59 +0000499}
500
Lev Walkin1dec5802005-03-04 09:02:27 +0000501static int
502asn1f_apply_unique_index(arg_t *arg) {
503 static int unique_index;
504 if(!arg) { unique_index = 0; return 0; }
505
Lev Walkin1dec5802005-03-04 09:02:27 +0000506 arg->expr->_type_unique_index = ++unique_index;
507
508 return 0;
509}
510
Lev Walkinf15320b2004-06-03 03:38:44 +0000511/*
512 * Print everything to stderr
513 */
514static void
515_default_error_logger(int _severity, const char *fmt, ...) {
516 va_list ap;
517 char *pfx = "";
518
519 switch(_severity) {
520 case -1: pfx = "DEBUG: "; break;
521 case 0: pfx = "WARNING: "; break;
522 case 1: pfx = "FATAL: "; break;
523 }
524
525 fprintf(stderr, "%s", pfx);
526 va_start(ap, fmt);
527 vfprintf(stderr, fmt, ap);
528 va_end(ap);
529 fprintf(stderr, "\n");
530}