blob: c89da6cc237686f19a40f95bbd756f2db56206df [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
Lev Walkin33f63f82005-03-20 11:27:19 +00003enum ftt_what {
4 FTT_TYPE, /* Find the type of the given expression */
5 FTT_VALUE, /* Find the value of the given expression */
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08006 FTT_CONSTR_TYPE /* Find the type of the given expression having constraint */
Lev Walkin33f63f82005-03-20 11:27:19 +00007};
8
9static asn1p_expr_t *asn1f_find_terminal_thing(arg_t *arg, asn1p_expr_t *expr, enum ftt_what);
Lev Walkinf15320b2004-06-03 03:38:44 +000010static int asn1f_compatible_with_exports(arg_t *arg, asn1p_module_t *mod, const char *name);
11
12
13/*
14 * Lookup a child by its name.
15 */
16asn1p_expr_t *
17asn1f_lookup_child(asn1p_expr_t *tc, const char *name) {
18 asn1p_expr_t *child_tc;
19
20 TQ_FOR(child_tc, &(tc->members), next) {
21 if(child_tc->Identifier
22 && strcmp(child_tc->Identifier, name) == 0) {
23 return child_tc;
24 }
25 }
26
27 errno = ESRCH;
28 return NULL;
29}
30
31asn1p_module_t *
Lev Walkin163db362004-09-15 11:46:47 +000032asn1f_lookup_in_imports(arg_t *arg, asn1p_module_t *mod, const char *name) {
Lev Walkinf15320b2004-06-03 03:38:44 +000033 asn1p_xports_t *xp;
34 asn1p_expr_t *tc;
35
36 /*
37 * Search in which exactly module this name is defined.
38 */
Lev Walkin163db362004-09-15 11:46:47 +000039 TQ_FOR(xp, &(mod->imports), xp_next) {
Lev Walkinf15320b2004-06-03 03:38:44 +000040 TQ_FOR(tc, &(xp->members), next) {
41 if(strcmp(name, tc->Identifier) == 0)
42 break;
43 }
44 if(tc) break;
45 }
46 if(xp == NULL) {
47 errno = ESRCH;
48 return NULL;
49 }
50
51 /*
52 * Okay, right now we have a module name and, hopefully, an OID.
53 * Search the arg->asn for the specified module.
54 */
Lev Walkinb36317c2005-08-12 10:09:10 +000055 mod = asn1f_lookup_module(arg, xp->fromModuleName, xp->identifier.oid);
Lev Walkinf15320b2004-06-03 03:38:44 +000056 if(mod == NULL) {
Lev Walkind8095522005-03-18 05:20:39 +000057 /* Conditional debug */
58 if(!(arg->expr->_mark & TM_BROKEN)) {
59 arg->expr->_mark |= TM_BROKEN;
Lev Walkin9e366ba2005-04-12 17:46:30 +000060 FATAL("Cannot find external module \"%s\" "
61 "mentioned for "
Lev Walkin41635d32006-03-18 05:06:57 +000062 "\"%s\" at line %d. "
63 "Obtain this module and instruct compiler to process it too.",
Lev Walkinb36317c2005-08-12 10:09:10 +000064 xp->fromModuleName, name, arg->expr->_lineno);
Lev Walkind8095522005-03-18 05:20:39 +000065 }
Lev Walkinf15320b2004-06-03 03:38:44 +000066 /* ENOENT/ETOOMANYREFS */
67 return NULL;
68 }
69
70 /*
71 * Check that the EXPORTS section of this module contains
72 * the symbol we care about, or it is EXPORTS ALL.
73 */
74 if(asn1f_compatible_with_exports(arg, mod, name)) {
75 errno = EPERM;
76 return NULL;
77 }
78
79 return mod;
80}
81
82asn1p_module_t *
Lev Walkinea6635b2017-08-06 23:23:04 -070083asn1f_lookup_module(arg_t *arg, const char *module_name, const asn1p_oid_t *oid) {
Lev Walkinf15320b2004-06-03 03:38:44 +000084 asn1p_module_t *mod;
85
86 assert(module_name);
87
88 /*
89 * If OID is given, the module_name is unused.
90 * If OID is not given, the module_name may mean
91 * either the real module's name, or the symbol which is the
92 * result of renaming. Check this first.
93 */
94 if(oid == 0) {
95 asn1p_xports_t *xp;
96 /*
97 * Check inside the IMPORTS section for possible renaming.
98 * Renaming practically means that a module_name is mentioned
99 * somewhere in the IMPORTS section AND OID is given.
100 */
101 TQ_FOR(xp, &(arg->mod->imports), xp_next) {
Lev Walkinb36317c2005-08-12 10:09:10 +0000102 if(strcmp(module_name, xp->fromModuleName))
Lev Walkinf15320b2004-06-03 03:38:44 +0000103 continue;
104 if(oid) {
105 FATAL("Ambiguous reference: "
106 "%s "
107 "matches several modules",
108 module_name);
109 errno = ETOOMANYREFS;
110 return NULL;
111 }
112 /*
113 * Yes, there is a renaming.
114 * Make lookup use OID instead.
115 */
Lev Walkinb36317c2005-08-12 10:09:10 +0000116 oid = xp->identifier.oid;
Lev Walkinf15320b2004-06-03 03:38:44 +0000117 }
118 }
119
120 /*
121 * Perform lookup using OID or module_name.
122 */
123 TQ_FOR(mod, &(arg->asn->modules), mod_next) {
124 if(oid) {
125 if(mod->module_oid) {
126 if(asn1p_oid_compare(oid,
127 mod->module_oid)) {
128 continue;
129 } else {
130 /* Match! Even if name doesn't. */
131 return mod;
132 }
133 } else {
134 /* Not match, even if name is the same. */
135 continue;
136 }
137 }
138
Lev Walkinb36317c2005-08-12 10:09:10 +0000139 if(strcmp(module_name, mod->ModuleName) == 0)
Lev Walkinf15320b2004-06-03 03:38:44 +0000140 return mod;
141 }
142
143 DEBUG("\tModule \"%s\" not found", module_name);
144
145 errno = ENOENT;
146 return NULL;
147}
148
Lev Walkin41635d32006-03-18 05:06:57 +0000149static asn1p_expr_t *
Lev Walkinc0e03b92017-08-22 01:48:23 -0700150asn1f_lookup_symbol_impl(arg_t *arg, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t *ref, int recursion_depth) {
151 asn1_namespace_t *initial_namespace = arg->ns;
152 asn1p_ref_t tmp_ref;
Lev Walkin163db362004-09-15 11:46:47 +0000153 asn1p_module_t *imports_from;
Lev Walkinf15320b2004-06-03 03:38:44 +0000154 char *modulename;
155 char *identifier;
156
Lev Walkinc0e03b92017-08-22 01:48:23 -0700157 if(ref->module && arg->mod != ref->module) {
158 return WITH_MODULE(
159 ref->module,
160 asn1f_lookup_symbol_impl(arg, rhs_pspecs, ref, recursion_depth));
161 }
162
Lev Walkinf15320b2004-06-03 03:38:44 +0000163 /*
164 * First of all, a reference to a symbol may be specified
165 * using several possible forms:
166 * a) simple identifier
167 * v INTEGER ::= value
168 * b) external reference
169 * v INTEGER ::= Module1.value
170 * c) class-related stuff (the most complex stuff)
171 * v ::= <[A-Z][A-Z0-9a-z-]*>.&<[A-Z0-9a-z-]+>.
172 * All other forms are not implemented at this moment.
173 */
174
Lev Walkinc0e03b92017-08-22 01:48:23 -0700175 DEBUG("Lookup (%s) in %s for line %d",
Lev Walkinf15320b2004-06-03 03:38:44 +0000176 asn1f_printable_reference(ref),
Lev Walkinc0e03b92017-08-22 01:48:23 -0700177 asn1_namespace_string(initial_namespace),
Lev Walkinf15320b2004-06-03 03:38:44 +0000178 ref->_lineno);
179
Lev Walkin41635d32006-03-18 05:06:57 +0000180 if(recursion_depth++ > 30 /* Arbitrary constant */) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700181 FATAL(
182 "Excessive circular referencing detected in namespace %s for %s at "
183 "line %d",
184 asn1_namespace_string(initial_namespace),
185 asn1f_printable_reference(ref), ref->_lineno);
186 errno = ETOOMANYREFS;
Lev Walkin41635d32006-03-18 05:06:57 +0000187 return NULL;
188 }
189
Lev Walkinf15320b2004-06-03 03:38:44 +0000190 if(ref->comp_count == 1) {
191 modulename = NULL;
192 identifier = ref->components[0].name;
193 } else if(ref->comp_count == 2
194 && ref->components[1].name[0] != '&') {
195 modulename = ref->components[0].name;
196 identifier = ref->components[1].name;
197 } else if(ref->comp_count > 1
198 && isupper(ref->components[0].name[0])
199 && ref->components[1].name[0] == '&') {
200 asn1p_expr_t *extract;
201 /*
202 * This is a reference to a CLASS-related stuff.
203 * Employ a separate function for that.
204 */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700205 extract = asn1f_class_access(arg, rhs_pspecs, ref);
Lev Walkinf15320b2004-06-03 03:38:44 +0000206
207 return extract;
208 } else {
209 DEBUG("\tToo many components: %d", ref->comp_count);
210 errno = EINVAL;
211 return NULL;
212 }
213
Lev Walkinc0e03b92017-08-22 01:48:23 -0700214 if(modulename) {
215 /*
216 * The modulename is specified inside this reference.
217 * To avoid recursion, reformat the reference
218 * as it were local to that module.
219 */
220 tmp_ref = *ref;
221 tmp_ref.components++; /* Hide the first element */
222 tmp_ref.comp_count--;
223 assert(tmp_ref.comp_count > 0);
224 ref = &tmp_ref;
225 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000226
Lev Walkinc0e03b92017-08-22 01:48:23 -0700227 asn1_namespace_t *my_namespace = initial_namespace;
Lev Walkinf15320b2004-06-03 03:38:44 +0000228
Lev Walkinc0e03b92017-08-22 01:48:23 -0700229#define DISPOSE_OF_MY_NAMESPACE() \
230 do { \
231 int tmp_errno = errno; \
232 if(my_namespace != initial_namespace) { \
233 asn1_namespace_free(my_namespace); \
234 my_namespace = NULL; \
235 } \
236 errno = tmp_errno; \
237 } while(0)
Lev Walkind8095522005-03-18 05:20:39 +0000238
Lev Walkinc0e03b92017-08-22 01:48:23 -0700239 /*
240 * If module name is specified explicitly
241 * OR the current module's IMPORTS clause contains the identifier,
242 * switch namespace to that module.
243 */
244 if(modulename) {
245 imports_from = asn1f_lookup_module(arg, modulename, 0);
246 if(imports_from == NULL) {
247 FATAL(
248 "Module \"%s\" "
249 "mentioned at line %d is not found",
250 modulename, ref->_lineno);
251 return NULL;
252 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000253
Lev Walkinc0e03b92017-08-22 01:48:23 -0700254 /*
255 * Check that the EXPORTS section of this module contains
256 * the symbol we care about, or it is EXPORTS ALL.
257 */
258 if(asn1f_compatible_with_exports(arg, imports_from, identifier)) {
259 errno = EPERM;
260 return NULL;
261 }
Lev Walkin6b3ff542006-03-06 14:51:00 +0000262
Lev Walkinc0e03b92017-08-22 01:48:23 -0700263 my_namespace = asn1_namespace_new_from_module(imports_from, 1);
264 DEBUG("Lookup (%s) in %s for line %d", asn1f_printable_reference(ref),
265 asn1_namespace_string(my_namespace), ref->_lineno);
266 }
Lev Walkina00d6b32006-03-21 03:40:38 +0000267
Lev Walkinc0e03b92017-08-22 01:48:23 -0700268 size_t namespace_switches = 0;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800269
Lev Walkinc0e03b92017-08-22 01:48:23 -0700270 /*
271 * Search through all layers of the namespace.
272 */
273 for(ssize_t ns_item = my_namespace->elements_count - 1; ns_item >= 0;
274 ns_item--) {
275 struct asn1_namespace_element_s *ns_el =
276 &my_namespace->elements[ns_item];
277 asn1p_expr_t *ref_tc; /* Referenced tc */
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800278
Lev Walkinc0e03b92017-08-22 01:48:23 -0700279 switch(ns_el->selector) {
280 case NAM_SYMBOL:
281 if(modulename) {
282 /*
283 * Trying to match a fully specified "Module.Symbol"
284 * against the "Symbol" parameter. Doesn't match.
285 */
286 continue;
287 }
288 if(strcmp(ns_el->u.symbol.identifier, identifier) != 0) {
289 continue;
290 } else {
291 DEBUG("Lookup (%s) in %s for line %d => found as parameter",
292 asn1f_printable_reference(ref),
293 asn1_namespace_string(my_namespace), ref->_lineno);
294 DISPOSE_OF_MY_NAMESPACE();
295 return ns_el->u.symbol.resolution;
296 }
297 case NAM_SPACE:
298 /*
299 * Do a direct symbol search in the given module.
300 */
301 TQ_FOR(ref_tc, &(ns_el->u.space.module->members), next) {
302 if(ref_tc->Identifier)
303 if(strcmp(ref_tc->Identifier, identifier) == 0) break;
304 }
305 if(ref_tc) {
306 /* It is acceptable that we don't use input parameters */
307 if(rhs_pspecs && !ref_tc->lhs_params) {
308 WARNING(
309 "Parameterized type %s expected "
310 "for %s at line %d",
311 ref_tc->Identifier, asn1f_printable_reference(ref),
312 ref->_lineno);
313 }
314 if(!rhs_pspecs && ref_tc->lhs_params) {
315 FATAL(
316 "Type %s expects specialization "
317 "from %s at line %d",
318 ref_tc->Identifier, asn1f_printable_reference(ref),
319 ref->_lineno);
320 errno = EPERM;
321 return NULL;
322 }
323 if(rhs_pspecs && ref_tc->lhs_params) {
324 /* Specialize the target */
325 ref_tc =
326 asn1f_parameterization_fork(arg, ref_tc, rhs_pspecs);
327 }
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800328
Lev Walkinc0e03b92017-08-22 01:48:23 -0700329 DISPOSE_OF_MY_NAMESPACE();
330 return ref_tc;
331 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000332
Lev Walkinc0e03b92017-08-22 01:48:23 -0700333 /*
334 if(!expr && !(arg->expr->_mark & TM_BROKEN)
335 && !(imports_from->_tags & MT_STANDARD_MODULE)) {
336 arg->expr->_mark |= TM_BROKEN;
337 if(modulename) {
338 } else {
339 FATAL(
340 "Module %s referred in IMPORTS section "
341 "for %s of module %s does not contain "
342 "the requested symbol",
343 imports_from->ModuleName,
344 asn1f_printable_reference(ref), mod->ModuleName);
345 }
346 }
347 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000348
Lev Walkinc0e03b92017-08-22 01:48:23 -0700349 /* Search inside the IMPORTS section of the given module */
350 imports_from =
351 asn1f_lookup_in_imports(arg, ns_el->u.space.module, identifier);
352 if(imports_from) {
353
354 if(namespace_switches++ > 10 /* Arbitrary constant */) {
355 FATAL(
356 "Excessive circular referencing detected in namespace "
357 "%s for %s at "
358 "line %d",
359 asn1_namespace_string(arg->ns),
360 asn1f_printable_reference(ref), ref->_lineno);
361 errno = ETOOMANYREFS;
362 return NULL;
363 }
364
365 /* Switch namespace */
366 DISPOSE_OF_MY_NAMESPACE();
367 my_namespace = asn1_namespace_new_from_module(imports_from, 1);
368 DEBUG("Lookup (%s) in %s for line %d",
369 asn1f_printable_reference(ref),
370 asn1_namespace_string(my_namespace), ref->_lineno);
371 ns_item = my_namespace->elements_count;
372
373 continue;
374 } else if(errno != ESRCH) {
375 /*
376 * Return only if the name was not found.
377 * If module was not found or more serious error
378 * encountered, just return preserving the errno.
379 */
380 DISPOSE_OF_MY_NAMESPACE();
381 return NULL;
382 }
383
384 if(modulename) {
385 FATAL(
386 "Module %s referred by %s in module %s "
387 "does not contain the requested symbol",
388 ns_el->u.space.module->ModuleName,
389 asn1f_printable_reference(ref), modulename);
390 break;
391 }
392
393 /* Search failed in the given namespace */
394 continue;
395 }
396 }
397
398 DEBUG(
399 "Namespace %s does not contain \"%s\" "
400 "mentioned at line %d: %s",
401 asn1_namespace_string(my_namespace), identifier, ref->_lineno,
402 strerror(errno));
403
404 DISPOSE_OF_MY_NAMESPACE();
405
406 if(asn1f_check_known_external_type(identifier) == 0) {
Lev Walkin6b3ff542006-03-06 14:51:00 +0000407 errno = EEXIST; /* Exists somewhere */
408 } else {
409 errno = ESRCH;
410 }
411 return NULL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000412}
413
414
415asn1p_expr_t *
Lev Walkinc0e03b92017-08-22 01:48:23 -0700416asn1f_lookup_symbol(arg_t *arg, asn1p_expr_t *rhs_pspecs,
417 const asn1p_ref_t *ref) {
418 return asn1f_lookup_symbol_impl(arg, rhs_pspecs, ref, 0);
Lev Walkin41635d32006-03-18 05:06:57 +0000419}
420
421asn1p_expr_t *
Lev Walkin6fec44d2004-08-22 03:10:23 +0000422asn1f_find_terminal_type(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin33f63f82005-03-20 11:27:19 +0000423 return asn1f_find_terminal_thing(arg, expr, FTT_TYPE);
Lev Walkinf15320b2004-06-03 03:38:44 +0000424}
425
426asn1p_expr_t *
Lev Walkin6fec44d2004-08-22 03:10:23 +0000427asn1f_find_terminal_value(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin33f63f82005-03-20 11:27:19 +0000428 return asn1f_find_terminal_thing(arg, expr, FTT_VALUE);
Lev Walkinf15320b2004-06-03 03:38:44 +0000429}
430
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800431asn1p_expr_t *
432asn1f_find_ancestor_type_with_PER_constraint(arg_t *arg, asn1p_expr_t *expr) {
433 return asn1f_find_terminal_thing(arg, expr, FTT_CONSTR_TYPE);
434}
435
Lev Walkinf15320b2004-06-03 03:38:44 +0000436static asn1p_expr_t *
Lev Walkin33f63f82005-03-20 11:27:19 +0000437asn1f_find_terminal_thing(arg_t *arg, asn1p_expr_t *expr, enum ftt_what what) {
Lev Walkin039a09e2005-03-20 13:17:48 +0000438 asn1p_ref_t *ref = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000439 asn1p_expr_t *tc;
440
Lev Walkinc0e03b92017-08-22 01:48:23 -0700441 if(arg->mod != expr->module) {
442 return WITH_MODULE(expr->module,
443 asn1f_find_terminal_thing(arg, expr, what));
444 }
445
446 switch(what) {
447 case FTT_TYPE:
448 case FTT_CONSTR_TYPE:
449 /* Expression may be a terminal type itself */
450 if(expr->expr_type != A1TC_REFERENCE) {
451 return expr;
452 }
453 ref = expr->reference;
454 break;
455 case FTT_VALUE:
456 assert(expr->meta_type == AMT_VALUE);
457 assert(expr->value);
458 /* Expression may be a terminal type itself */
459 if(expr->value->type != ATV_REFERENCED) {
460 return expr;
461 }
462 ref = expr->value->value.reference;
463 break;
464 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000465
Lev Walkin03850182005-03-10 10:02:50 +0000466 DEBUG("%s(%s->%s) for line %d",
Lev Walkin33f63f82005-03-20 11:27:19 +0000467 (what == FTT_VALUE)?"VALUE":"TYPE",
Lev Walkinf15320b2004-06-03 03:38:44 +0000468 expr->Identifier, asn1f_printable_reference(ref),
469 expr->_lineno);
470
471 assert(ref);
472
473 /*
474 * Lookup inside the type itself (ENUMERATED, INTEGER, etc).
475 */
Lev Walkin33f63f82005-03-20 11:27:19 +0000476 if(what == FTT_VALUE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000477 asn1p_expr_t *val_type_tc;
Lev Walkin6fec44d2004-08-22 03:10:23 +0000478 val_type_tc = asn1f_find_terminal_type(arg, expr);
Lev Walkinc0e03b92017-08-22 01:48:23 -0700479 if(val_type_tc
480 && WITH_MODULE(val_type_tc->module,
481 asn1f_look_value_in_type(arg, val_type_tc, expr))) {
482 return expr;
483 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000484 if(expr->value->type != ATV_REFERENCED) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700485 return expr;
Lev Walkinf15320b2004-06-03 03:38:44 +0000486 }
487 assert(ref == expr->value->value.reference);
488 ref = expr->value->value.reference;
489 }
490
491 /*
Lev Walkind8095522005-03-18 05:20:39 +0000492 * Lookup inside the default module and its IMPORTS section.
Lev Walkinf15320b2004-06-03 03:38:44 +0000493 */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700494 tc = asn1f_lookup_symbol(arg, expr->rhs_pspecs, ref);
495 if(tc == NULL) {
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800496 /*
497 * Lookup inside the ref's module and its IMPORTS section.
498 */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700499 tc = WITH_MODULE(ref->module,
500 asn1f_lookup_symbol(arg, expr->rhs_pspecs, ref));
501 if(tc == NULL) {
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800502 DEBUG("\tSymbol \"%s\" not found: %s",
503 asn1f_printable_reference(ref),
504 strerror(errno));
Lev Walkinc0e03b92017-08-22 01:48:23 -0700505 return NULL;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800506 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000507 }
508
509 /*
510 * Recursive loops detection.
511 */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700512 if(tc->_mark & TM_RECURSION) {
513 DEBUG("Recursion loop detected for %s at line %d",
514 asn1f_printable_reference(ref), ref->_lineno);
515 errno = EPERM;
516 return NULL;
517 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000518
Lev Walkinc0e03b92017-08-22 01:48:23 -0700519 tc->_type_referenced = 1;
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800520
Lev Walkinc0e03b92017-08-22 01:48:23 -0700521 if((what == FTT_CONSTR_TYPE) && (tc->constraints)) {
522 return tc;
523 }
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800524
Lev Walkinc0e03b92017-08-22 01:48:23 -0700525 tc->_mark |= TM_RECURSION;
526 expr = WITH_MODULE(tc->module, asn1f_find_terminal_thing(arg, tc, what));
527 tc->_mark &= ~TM_RECURSION;
Lev Walkinf15320b2004-06-03 03:38:44 +0000528
Lev Walkinc0e03b92017-08-22 01:48:23 -0700529 return expr;
Lev Walkinf15320b2004-06-03 03:38:44 +0000530}
531
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800532
Lev Walkinf15320b2004-06-03 03:38:44 +0000533/*
534 * Make sure that the specified name is present or otherwise does
535 * not contradict with the EXPORTS clause of the specified module.
536 */
537static int
538asn1f_compatible_with_exports(arg_t *arg, asn1p_module_t *mod, const char *name) {
539 asn1p_xports_t *exports;
540 asn1p_expr_t *item;
541
542 assert(mod);
543 assert(name);
544
545 exports = TQ_FIRST(&(mod->exports));
546 if(exports == NULL) {
547 /* No EXPORTS section or EXPORTS ALL; */
548 return 0;
549 }
550
551 TQ_FOR(item, &(exports->members), next) {
552 if(strcmp(item->Identifier, name) == 0)
553 return 0;
554 }
555
Lev Walkind8095522005-03-18 05:20:39 +0000556 /* Conditional debug */
557 if(!(arg->expr->_mark & TM_BROKEN)) {
558 arg->expr->_mark |= TM_BROKEN;
559 FATAL("EXPORTS section of module %s in %s "
560 "does not mention %s at line %d",
Lev Walkinb36317c2005-08-12 10:09:10 +0000561 mod->ModuleName, mod->source_file_name, name,
Lev Walkind8095522005-03-18 05:20:39 +0000562 arg->expr->_lineno);
563 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000564
565 errno = ESRCH;
566 return -1;
567}