blob: 536f502080a15dce21b0dd7e436cfd9975976b9e [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;
Bi-Ruei, Chiuaeff7172017-09-11 13:54:45 +080034 asn1p_module_t *fromModule;
35 asn1p_expr_t *tc = (asn1p_expr_t *)0;
36 asn1p_expr_t *memb = (asn1p_expr_t *)0;
37 asn1p_expr_t *v = (asn1p_expr_t *)0;
Lev Walkinf15320b2004-06-03 03:38:44 +000038
39 /*
40 * Search in which exactly module this name is defined.
41 */
Lev Walkin163db362004-09-15 11:46:47 +000042 TQ_FOR(xp, &(mod->imports), xp_next) {
Bi-Ruei, Chiuaeff7172017-09-11 13:54:45 +080043 fromModule = asn1f_lookup_module(arg, xp->fromModuleName, NULL);
Lev Walkinf15320b2004-06-03 03:38:44 +000044 TQ_FOR(tc, &(xp->members), next) {
45 if(strcmp(name, tc->Identifier) == 0)
46 break;
Bi-Ruei, Chiuaeff7172017-09-11 13:54:45 +080047
48 if(!fromModule)
49 continue;
50
51 TQ_FOR(memb, &(fromModule->members), next) {
52 if((memb->expr_type != ASN_BASIC_ENUMERATED) ||
53 (strcmp(memb->Identifier, tc->Identifier) != 0))
54 continue;
55
56 v = asn1f_lookup_child(memb, name);
57 if (v) break;
58 }
59 if(v) break;
Lev Walkinf15320b2004-06-03 03:38:44 +000060 }
61 if(tc) break;
62 }
63 if(xp == NULL) {
64 errno = ESRCH;
65 return NULL;
66 }
67
68 /*
69 * Okay, right now we have a module name and, hopefully, an OID.
70 * Search the arg->asn for the specified module.
71 */
Lev Walkinb36317c2005-08-12 10:09:10 +000072 mod = asn1f_lookup_module(arg, xp->fromModuleName, xp->identifier.oid);
Lev Walkinf15320b2004-06-03 03:38:44 +000073 if(mod == NULL) {
Lev Walkind8095522005-03-18 05:20:39 +000074 /* Conditional debug */
75 if(!(arg->expr->_mark & TM_BROKEN)) {
76 arg->expr->_mark |= TM_BROKEN;
Lev Walkin9e366ba2005-04-12 17:46:30 +000077 FATAL("Cannot find external module \"%s\" "
78 "mentioned for "
Lev Walkin41635d32006-03-18 05:06:57 +000079 "\"%s\" at line %d. "
80 "Obtain this module and instruct compiler to process it too.",
Lev Walkinb36317c2005-08-12 10:09:10 +000081 xp->fromModuleName, name, arg->expr->_lineno);
Lev Walkind8095522005-03-18 05:20:39 +000082 }
Lev Walkinf15320b2004-06-03 03:38:44 +000083 /* ENOENT/ETOOMANYREFS */
84 return NULL;
85 }
86
87 /*
88 * Check that the EXPORTS section of this module contains
89 * the symbol we care about, or it is EXPORTS ALL.
90 */
91 if(asn1f_compatible_with_exports(arg, mod, name)) {
92 errno = EPERM;
93 return NULL;
94 }
95
96 return mod;
97}
98
99asn1p_module_t *
Lev Walkinea6635b2017-08-06 23:23:04 -0700100asn1f_lookup_module(arg_t *arg, const char *module_name, const asn1p_oid_t *oid) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000101 asn1p_module_t *mod;
102
103 assert(module_name);
104
105 /*
106 * If OID is given, the module_name is unused.
107 * If OID is not given, the module_name may mean
108 * either the real module's name, or the symbol which is the
109 * result of renaming. Check this first.
110 */
111 if(oid == 0) {
112 asn1p_xports_t *xp;
113 /*
114 * Check inside the IMPORTS section for possible renaming.
115 * Renaming practically means that a module_name is mentioned
116 * somewhere in the IMPORTS section AND OID is given.
117 */
118 TQ_FOR(xp, &(arg->mod->imports), xp_next) {
Lev Walkinb36317c2005-08-12 10:09:10 +0000119 if(strcmp(module_name, xp->fromModuleName))
Lev Walkinf15320b2004-06-03 03:38:44 +0000120 continue;
121 if(oid) {
122 FATAL("Ambiguous reference: "
123 "%s "
124 "matches several modules",
125 module_name);
126 errno = ETOOMANYREFS;
127 return NULL;
128 }
129 /*
130 * Yes, there is a renaming.
131 * Make lookup use OID instead.
132 */
Lev Walkinb36317c2005-08-12 10:09:10 +0000133 oid = xp->identifier.oid;
Lev Walkinf15320b2004-06-03 03:38:44 +0000134 }
135 }
136
137 /*
138 * Perform lookup using OID or module_name.
139 */
140 TQ_FOR(mod, &(arg->asn->modules), mod_next) {
141 if(oid) {
142 if(mod->module_oid) {
143 if(asn1p_oid_compare(oid,
144 mod->module_oid)) {
145 continue;
146 } else {
147 /* Match! Even if name doesn't. */
148 return mod;
149 }
150 } else {
151 /* Not match, even if name is the same. */
152 continue;
153 }
154 }
155
Lev Walkinb36317c2005-08-12 10:09:10 +0000156 if(strcmp(module_name, mod->ModuleName) == 0)
Lev Walkinf15320b2004-06-03 03:38:44 +0000157 return mod;
158 }
159
160 DEBUG("\tModule \"%s\" not found", module_name);
161
162 errno = ENOENT;
163 return NULL;
164}
165
Lev Walkin41635d32006-03-18 05:06:57 +0000166static asn1p_expr_t *
Lev Walkinc0e03b92017-08-22 01:48:23 -0700167asn1f_lookup_symbol_impl(arg_t *arg, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t *ref, int recursion_depth) {
168 asn1_namespace_t *initial_namespace = arg->ns;
169 asn1p_ref_t tmp_ref;
Lev Walkin163db362004-09-15 11:46:47 +0000170 asn1p_module_t *imports_from;
Lev Walkinf15320b2004-06-03 03:38:44 +0000171 char *modulename;
172 char *identifier;
173
Lev Walkinc0e03b92017-08-22 01:48:23 -0700174 if(ref->module && arg->mod != ref->module) {
175 return WITH_MODULE(
176 ref->module,
177 asn1f_lookup_symbol_impl(arg, rhs_pspecs, ref, recursion_depth));
178 }
179
Lev Walkinf15320b2004-06-03 03:38:44 +0000180 /*
181 * First of all, a reference to a symbol may be specified
182 * using several possible forms:
183 * a) simple identifier
184 * v INTEGER ::= value
185 * b) external reference
186 * v INTEGER ::= Module1.value
187 * c) class-related stuff (the most complex stuff)
188 * v ::= <[A-Z][A-Z0-9a-z-]*>.&<[A-Z0-9a-z-]+>.
189 * All other forms are not implemented at this moment.
190 */
191
Lev Walkinc0e03b92017-08-22 01:48:23 -0700192 DEBUG("Lookup (%s) in %s for line %d",
Lev Walkinf15320b2004-06-03 03:38:44 +0000193 asn1f_printable_reference(ref),
Lev Walkinc0e03b92017-08-22 01:48:23 -0700194 asn1_namespace_string(initial_namespace),
Lev Walkinf15320b2004-06-03 03:38:44 +0000195 ref->_lineno);
196
Lev Walkin41635d32006-03-18 05:06:57 +0000197 if(recursion_depth++ > 30 /* Arbitrary constant */) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700198 FATAL(
199 "Excessive circular referencing detected in namespace %s for %s at "
200 "line %d",
201 asn1_namespace_string(initial_namespace),
202 asn1f_printable_reference(ref), ref->_lineno);
203 errno = ETOOMANYREFS;
Lev Walkin41635d32006-03-18 05:06:57 +0000204 return NULL;
205 }
206
Lev Walkinf15320b2004-06-03 03:38:44 +0000207 if(ref->comp_count == 1) {
208 modulename = NULL;
209 identifier = ref->components[0].name;
210 } else if(ref->comp_count == 2
211 && ref->components[1].name[0] != '&') {
212 modulename = ref->components[0].name;
213 identifier = ref->components[1].name;
214 } else if(ref->comp_count > 1
215 && isupper(ref->components[0].name[0])
216 && ref->components[1].name[0] == '&') {
217 asn1p_expr_t *extract;
218 /*
219 * This is a reference to a CLASS-related stuff.
220 * Employ a separate function for that.
221 */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700222 extract = asn1f_class_access(arg, rhs_pspecs, ref);
Lev Walkinf15320b2004-06-03 03:38:44 +0000223
224 return extract;
225 } else {
226 DEBUG("\tToo many components: %d", ref->comp_count);
227 errno = EINVAL;
228 return NULL;
229 }
230
Lev Walkinc0e03b92017-08-22 01:48:23 -0700231 if(modulename) {
232 /*
233 * The modulename is specified inside this reference.
234 * To avoid recursion, reformat the reference
235 * as it were local to that module.
236 */
237 tmp_ref = *ref;
238 tmp_ref.components++; /* Hide the first element */
239 tmp_ref.comp_count--;
240 assert(tmp_ref.comp_count > 0);
241 ref = &tmp_ref;
242 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000243
Lev Walkinc0e03b92017-08-22 01:48:23 -0700244 asn1_namespace_t *my_namespace = initial_namespace;
Lev Walkinf15320b2004-06-03 03:38:44 +0000245
Lev Walkinc0e03b92017-08-22 01:48:23 -0700246#define DISPOSE_OF_MY_NAMESPACE() \
247 do { \
248 int tmp_errno = errno; \
249 if(my_namespace != initial_namespace) { \
250 asn1_namespace_free(my_namespace); \
251 my_namespace = NULL; \
252 } \
253 errno = tmp_errno; \
254 } while(0)
Lev Walkind8095522005-03-18 05:20:39 +0000255
Lev Walkinc0e03b92017-08-22 01:48:23 -0700256 /*
257 * If module name is specified explicitly
258 * OR the current module's IMPORTS clause contains the identifier,
259 * switch namespace to that module.
260 */
261 if(modulename) {
262 imports_from = asn1f_lookup_module(arg, modulename, 0);
263 if(imports_from == NULL) {
264 FATAL(
265 "Module \"%s\" "
266 "mentioned at line %d is not found",
267 modulename, ref->_lineno);
268 return NULL;
269 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000270
Lev Walkinc0e03b92017-08-22 01:48:23 -0700271 /*
272 * Check that the EXPORTS section of this module contains
273 * the symbol we care about, or it is EXPORTS ALL.
274 */
275 if(asn1f_compatible_with_exports(arg, imports_from, identifier)) {
276 errno = EPERM;
277 return NULL;
278 }
Lev Walkin6b3ff542006-03-06 14:51:00 +0000279
Lev Walkinc0e03b92017-08-22 01:48:23 -0700280 my_namespace = asn1_namespace_new_from_module(imports_from, 1);
281 DEBUG("Lookup (%s) in %s for line %d", asn1f_printable_reference(ref),
282 asn1_namespace_string(my_namespace), ref->_lineno);
283 }
Lev Walkina00d6b32006-03-21 03:40:38 +0000284
Lev Walkinc0e03b92017-08-22 01:48:23 -0700285 size_t namespace_switches = 0;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800286
Lev Walkinc0e03b92017-08-22 01:48:23 -0700287 /*
288 * Search through all layers of the namespace.
289 */
290 for(ssize_t ns_item = my_namespace->elements_count - 1; ns_item >= 0;
291 ns_item--) {
292 struct asn1_namespace_element_s *ns_el =
293 &my_namespace->elements[ns_item];
294 asn1p_expr_t *ref_tc; /* Referenced tc */
Bi-Ruei, Chiuaeff7172017-09-11 13:54:45 +0800295 asn1p_expr_t *v = (asn1p_expr_t *)0;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800296
Lev Walkinc0e03b92017-08-22 01:48:23 -0700297 switch(ns_el->selector) {
298 case NAM_SYMBOL:
299 if(modulename) {
300 /*
301 * Trying to match a fully specified "Module.Symbol"
302 * against the "Symbol" parameter. Doesn't match.
303 */
304 continue;
305 }
306 if(strcmp(ns_el->u.symbol.identifier, identifier) != 0) {
307 continue;
308 } else {
309 DEBUG("Lookup (%s) in %s for line %d => found as parameter",
310 asn1f_printable_reference(ref),
311 asn1_namespace_string(my_namespace), ref->_lineno);
312 DISPOSE_OF_MY_NAMESPACE();
313 return ns_el->u.symbol.resolution;
314 }
315 case NAM_SPACE:
316 /*
317 * Do a direct symbol search in the given module.
318 */
319 TQ_FOR(ref_tc, &(ns_el->u.space.module->members), next) {
320 if(ref_tc->Identifier)
321 if(strcmp(ref_tc->Identifier, identifier) == 0) break;
Bi-Ruei, Chiuaeff7172017-09-11 13:54:45 +0800322
323 if(ref_tc->expr_type == ASN_BASIC_ENUMERATED) {
324 v = asn1f_lookup_child(ref_tc, identifier);
325 if(v) {
326 ref_tc = v;
327 break;
328 }
329 }
Lev Walkinc0e03b92017-08-22 01:48:23 -0700330 }
331 if(ref_tc) {
332 /* It is acceptable that we don't use input parameters */
333 if(rhs_pspecs && !ref_tc->lhs_params) {
334 WARNING(
335 "Parameterized type %s expected "
336 "for %s at line %d",
337 ref_tc->Identifier, asn1f_printable_reference(ref),
338 ref->_lineno);
339 }
340 if(!rhs_pspecs && ref_tc->lhs_params) {
341 FATAL(
342 "Type %s expects specialization "
343 "from %s at line %d",
344 ref_tc->Identifier, asn1f_printable_reference(ref),
345 ref->_lineno);
346 errno = EPERM;
347 return NULL;
348 }
349 if(rhs_pspecs && ref_tc->lhs_params) {
350 /* Specialize the target */
351 ref_tc =
352 asn1f_parameterization_fork(arg, ref_tc, rhs_pspecs);
353 }
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800354
Lev Walkinc0e03b92017-08-22 01:48:23 -0700355 DISPOSE_OF_MY_NAMESPACE();
356 return ref_tc;
357 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000358
Lev Walkinc0e03b92017-08-22 01:48:23 -0700359 /*
360 if(!expr && !(arg->expr->_mark & TM_BROKEN)
361 && !(imports_from->_tags & MT_STANDARD_MODULE)) {
362 arg->expr->_mark |= TM_BROKEN;
363 if(modulename) {
364 } else {
365 FATAL(
366 "Module %s referred in IMPORTS section "
367 "for %s of module %s does not contain "
368 "the requested symbol",
369 imports_from->ModuleName,
370 asn1f_printable_reference(ref), mod->ModuleName);
371 }
372 }
373 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000374
Lev Walkinc0e03b92017-08-22 01:48:23 -0700375 /* Search inside the IMPORTS section of the given module */
376 imports_from =
377 asn1f_lookup_in_imports(arg, ns_el->u.space.module, identifier);
378 if(imports_from) {
379
380 if(namespace_switches++ > 10 /* Arbitrary constant */) {
381 FATAL(
382 "Excessive circular referencing detected in namespace "
383 "%s for %s at "
384 "line %d",
385 asn1_namespace_string(arg->ns),
386 asn1f_printable_reference(ref), ref->_lineno);
387 errno = ETOOMANYREFS;
388 return NULL;
389 }
390
391 /* Switch namespace */
392 DISPOSE_OF_MY_NAMESPACE();
393 my_namespace = asn1_namespace_new_from_module(imports_from, 1);
394 DEBUG("Lookup (%s) in %s for line %d",
395 asn1f_printable_reference(ref),
396 asn1_namespace_string(my_namespace), ref->_lineno);
397 ns_item = my_namespace->elements_count;
398
399 continue;
400 } else if(errno != ESRCH) {
401 /*
402 * Return only if the name was not found.
403 * If module was not found or more serious error
404 * encountered, just return preserving the errno.
405 */
406 DISPOSE_OF_MY_NAMESPACE();
407 return NULL;
408 }
409
410 if(modulename) {
411 FATAL(
412 "Module %s referred by %s in module %s "
413 "does not contain the requested symbol",
414 ns_el->u.space.module->ModuleName,
415 asn1f_printable_reference(ref), modulename);
416 break;
417 }
418
419 /* Search failed in the given namespace */
420 continue;
421 }
422 }
423
424 DEBUG(
425 "Namespace %s does not contain \"%s\" "
426 "mentioned at line %d: %s",
427 asn1_namespace_string(my_namespace), identifier, ref->_lineno,
428 strerror(errno));
429
430 DISPOSE_OF_MY_NAMESPACE();
431
432 if(asn1f_check_known_external_type(identifier) == 0) {
Lev Walkin6b3ff542006-03-06 14:51:00 +0000433 errno = EEXIST; /* Exists somewhere */
434 } else {
435 errno = ESRCH;
436 }
437 return NULL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000438}
439
440
441asn1p_expr_t *
Lev Walkinc0e03b92017-08-22 01:48:23 -0700442asn1f_lookup_symbol(arg_t *arg, asn1p_expr_t *rhs_pspecs,
443 const asn1p_ref_t *ref) {
444 return asn1f_lookup_symbol_impl(arg, rhs_pspecs, ref, 0);
Lev Walkin41635d32006-03-18 05:06:57 +0000445}
446
447asn1p_expr_t *
Lev Walkin6fec44d2004-08-22 03:10:23 +0000448asn1f_find_terminal_type(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin33f63f82005-03-20 11:27:19 +0000449 return asn1f_find_terminal_thing(arg, expr, FTT_TYPE);
Lev Walkinf15320b2004-06-03 03:38:44 +0000450}
451
452asn1p_expr_t *
Lev Walkin6fec44d2004-08-22 03:10:23 +0000453asn1f_find_terminal_value(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin33f63f82005-03-20 11:27:19 +0000454 return asn1f_find_terminal_thing(arg, expr, FTT_VALUE);
Lev Walkinf15320b2004-06-03 03:38:44 +0000455}
456
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800457asn1p_expr_t *
458asn1f_find_ancestor_type_with_PER_constraint(arg_t *arg, asn1p_expr_t *expr) {
459 return asn1f_find_terminal_thing(arg, expr, FTT_CONSTR_TYPE);
460}
461
Lev Walkinf15320b2004-06-03 03:38:44 +0000462static asn1p_expr_t *
Lev Walkin33f63f82005-03-20 11:27:19 +0000463asn1f_find_terminal_thing(arg_t *arg, asn1p_expr_t *expr, enum ftt_what what) {
Lev Walkin039a09e2005-03-20 13:17:48 +0000464 asn1p_ref_t *ref = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000465 asn1p_expr_t *tc;
466
Lev Walkinc0e03b92017-08-22 01:48:23 -0700467 if(arg->mod != expr->module) {
468 return WITH_MODULE(expr->module,
469 asn1f_find_terminal_thing(arg, expr, what));
470 }
471
472 switch(what) {
473 case FTT_TYPE:
474 case FTT_CONSTR_TYPE:
475 /* Expression may be a terminal type itself */
476 if(expr->expr_type != A1TC_REFERENCE) {
477 return expr;
478 }
479 ref = expr->reference;
480 break;
481 case FTT_VALUE:
482 assert(expr->meta_type == AMT_VALUE);
483 assert(expr->value);
484 /* Expression may be a terminal type itself */
485 if(expr->value->type != ATV_REFERENCED) {
486 return expr;
487 }
488 ref = expr->value->value.reference;
489 break;
490 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000491
Lev Walkin03850182005-03-10 10:02:50 +0000492 DEBUG("%s(%s->%s) for line %d",
Lev Walkin33f63f82005-03-20 11:27:19 +0000493 (what == FTT_VALUE)?"VALUE":"TYPE",
Lev Walkinf15320b2004-06-03 03:38:44 +0000494 expr->Identifier, asn1f_printable_reference(ref),
495 expr->_lineno);
496
497 assert(ref);
498
499 /*
500 * Lookup inside the type itself (ENUMERATED, INTEGER, etc).
501 */
Lev Walkin33f63f82005-03-20 11:27:19 +0000502 if(what == FTT_VALUE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000503 asn1p_expr_t *val_type_tc;
Lev Walkin6fec44d2004-08-22 03:10:23 +0000504 val_type_tc = asn1f_find_terminal_type(arg, expr);
Lev Walkinc0e03b92017-08-22 01:48:23 -0700505 if(val_type_tc
506 && WITH_MODULE(val_type_tc->module,
507 asn1f_look_value_in_type(arg, val_type_tc, expr))) {
508 return expr;
509 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000510 if(expr->value->type != ATV_REFERENCED) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700511 return expr;
Lev Walkinf15320b2004-06-03 03:38:44 +0000512 }
513 assert(ref == expr->value->value.reference);
514 ref = expr->value->value.reference;
515 }
516
517 /*
Lev Walkind8095522005-03-18 05:20:39 +0000518 * Lookup inside the default module and its IMPORTS section.
Lev Walkinf15320b2004-06-03 03:38:44 +0000519 */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700520 tc = asn1f_lookup_symbol(arg, expr->rhs_pspecs, ref);
521 if(tc == NULL) {
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800522 /*
523 * Lookup inside the ref's module and its IMPORTS section.
524 */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700525 tc = WITH_MODULE(ref->module,
526 asn1f_lookup_symbol(arg, expr->rhs_pspecs, ref));
527 if(tc == NULL) {
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800528 DEBUG("\tSymbol \"%s\" not found: %s",
529 asn1f_printable_reference(ref),
530 strerror(errno));
Lev Walkinc0e03b92017-08-22 01:48:23 -0700531 return NULL;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800532 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000533 }
534
535 /*
536 * Recursive loops detection.
537 */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700538 if(tc->_mark & TM_RECURSION) {
539 DEBUG("Recursion loop detected for %s at line %d",
540 asn1f_printable_reference(ref), ref->_lineno);
541 errno = EPERM;
542 return NULL;
543 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000544
Lev Walkinc0e03b92017-08-22 01:48:23 -0700545 tc->_type_referenced = 1;
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800546
Lev Walkinc0e03b92017-08-22 01:48:23 -0700547 if((what == FTT_CONSTR_TYPE) && (tc->constraints)) {
548 return tc;
549 }
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800550
Lev Walkinc0e03b92017-08-22 01:48:23 -0700551 tc->_mark |= TM_RECURSION;
552 expr = WITH_MODULE(tc->module, asn1f_find_terminal_thing(arg, tc, what));
553 tc->_mark &= ~TM_RECURSION;
Lev Walkinf15320b2004-06-03 03:38:44 +0000554
Lev Walkinc0e03b92017-08-22 01:48:23 -0700555 return expr;
Lev Walkinf15320b2004-06-03 03:38:44 +0000556}
557
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800558
Lev Walkinf15320b2004-06-03 03:38:44 +0000559/*
560 * Make sure that the specified name is present or otherwise does
561 * not contradict with the EXPORTS clause of the specified module.
562 */
563static int
564asn1f_compatible_with_exports(arg_t *arg, asn1p_module_t *mod, const char *name) {
565 asn1p_xports_t *exports;
566 asn1p_expr_t *item;
567
568 assert(mod);
569 assert(name);
570
571 exports = TQ_FIRST(&(mod->exports));
572 if(exports == NULL) {
573 /* No EXPORTS section or EXPORTS ALL; */
574 return 0;
575 }
576
577 TQ_FOR(item, &(exports->members), next) {
578 if(strcmp(item->Identifier, name) == 0)
579 return 0;
580 }
581
Lev Walkind8095522005-03-18 05:20:39 +0000582 /* Conditional debug */
583 if(!(arg->expr->_mark & TM_BROKEN)) {
584 arg->expr->_mark |= TM_BROKEN;
585 FATAL("EXPORTS section of module %s in %s "
586 "does not mention %s at line %d",
Lev Walkinb36317c2005-08-12 10:09:10 +0000587 mod->ModuleName, mod->source_file_name, name,
Lev Walkind8095522005-03-18 05:20:39 +0000588 arg->expr->_lineno);
589 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000590
591 errno = ESRCH;
592 return -1;
593}