blob: 16f5c1c3ea89ebb268c51d85b383c6b81c522a42 [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
Lev Walkin1a49ced2017-11-06 00:07:00 -080031static asn1p_expr_t *
32asn1f_lookup_in_module(asn1p_module_t *mod, const char *name) {
33 asn1p_expr_t *expr = genhash_get(mod->members_hash, name);
34 if(!expr) {
35 asn1p_expr_t *memb;
36 TQ_FOR(memb, &mod->members, next) {
37 if(memb->expr_type == ASN_BASIC_ENUMERATED) {
38 asn1p_expr_t *v = asn1f_lookup_child(memb, name);
39 if(v) return v;
40 }
41 }
42 }
43
44 return expr;
45}
46
Lev Walkinf15320b2004-06-03 03:38:44 +000047asn1p_module_t *
Lev Walkin163db362004-09-15 11:46:47 +000048asn1f_lookup_in_imports(arg_t *arg, asn1p_module_t *mod, const char *name) {
Lev Walkinf15320b2004-06-03 03:38:44 +000049 asn1p_xports_t *xp;
Lev Walkinf15320b2004-06-03 03:38:44 +000050
51 /*
52 * Search in which exactly module this name is defined.
53 */
Lev Walkin163db362004-09-15 11:46:47 +000054 TQ_FOR(xp, &(mod->imports), xp_next) {
Lev Walkin1a49ced2017-11-06 00:07:00 -080055 asn1p_module_t *fromModule =
56 asn1f_lookup_module(arg, xp->fromModuleName, NULL);
57 asn1p_expr_t *tc = (asn1p_expr_t *)0;
58
59 TQ_FOR(tc, &(xp->xp_members), next) {
60 if(strcmp(name, tc->Identifier) == 0)
Lev Walkinf15320b2004-06-03 03:38:44 +000061 break;
Bi-Ruei, Chiuaeff7172017-09-11 13:54:45 +080062
63 if(!fromModule)
64 continue;
65
Bi-Ruei, Chiu288e95d2017-11-14 15:16:24 +080066 asn1p_expr_t *v =
67 asn1f_lookup_in_module(fromModule, name);
Lev Walkin1a49ced2017-11-06 00:07:00 -080068 if(v) break;
Lev Walkinf15320b2004-06-03 03:38:44 +000069 }
70 if(tc) break;
71 }
72 if(xp == NULL) {
73 errno = ESRCH;
74 return NULL;
75 }
76
77 /*
78 * Okay, right now we have a module name and, hopefully, an OID.
79 * Search the arg->asn for the specified module.
80 */
Lev Walkinb36317c2005-08-12 10:09:10 +000081 mod = asn1f_lookup_module(arg, xp->fromModuleName, xp->identifier.oid);
Lev Walkinf15320b2004-06-03 03:38:44 +000082 if(mod == NULL) {
Lev Walkind8095522005-03-18 05:20:39 +000083 /* Conditional debug */
84 if(!(arg->expr->_mark & TM_BROKEN)) {
85 arg->expr->_mark |= TM_BROKEN;
Lev Walkin9e366ba2005-04-12 17:46:30 +000086 FATAL("Cannot find external module \"%s\" "
87 "mentioned for "
Lev Walkin41635d32006-03-18 05:06:57 +000088 "\"%s\" at line %d. "
89 "Obtain this module and instruct compiler to process it too.",
Lev Walkinb36317c2005-08-12 10:09:10 +000090 xp->fromModuleName, name, arg->expr->_lineno);
Lev Walkind8095522005-03-18 05:20:39 +000091 }
Lev Walkinf15320b2004-06-03 03:38:44 +000092 /* ENOENT/ETOOMANYREFS */
93 return NULL;
94 }
95
96 /*
97 * Check that the EXPORTS section of this module contains
98 * the symbol we care about, or it is EXPORTS ALL.
99 */
100 if(asn1f_compatible_with_exports(arg, mod, name)) {
101 errno = EPERM;
102 return NULL;
103 }
104
105 return mod;
106}
107
108asn1p_module_t *
Lev Walkinea6635b2017-08-06 23:23:04 -0700109asn1f_lookup_module(arg_t *arg, const char *module_name, const asn1p_oid_t *oid) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000110 asn1p_module_t *mod;
111
112 assert(module_name);
113
114 /*
115 * If OID is given, the module_name is unused.
116 * If OID is not given, the module_name may mean
117 * either the real module's name, or the symbol which is the
118 * result of renaming. Check this first.
119 */
120 if(oid == 0) {
121 asn1p_xports_t *xp;
122 /*
123 * Check inside the IMPORTS section for possible renaming.
124 * Renaming practically means that a module_name is mentioned
125 * somewhere in the IMPORTS section AND OID is given.
126 */
127 TQ_FOR(xp, &(arg->mod->imports), xp_next) {
Lev Walkinb36317c2005-08-12 10:09:10 +0000128 if(strcmp(module_name, xp->fromModuleName))
Lev Walkinf15320b2004-06-03 03:38:44 +0000129 continue;
130 if(oid) {
131 FATAL("Ambiguous reference: "
132 "%s "
133 "matches several modules",
134 module_name);
135 errno = ETOOMANYREFS;
136 return NULL;
137 }
138 /*
139 * Yes, there is a renaming.
140 * Make lookup use OID instead.
141 */
Lev Walkinb36317c2005-08-12 10:09:10 +0000142 oid = xp->identifier.oid;
Lev Walkinf15320b2004-06-03 03:38:44 +0000143 }
144 }
145
146 /*
147 * Perform lookup using OID or module_name.
148 */
149 TQ_FOR(mod, &(arg->asn->modules), mod_next) {
150 if(oid) {
151 if(mod->module_oid) {
152 if(asn1p_oid_compare(oid,
153 mod->module_oid)) {
154 continue;
155 } else {
156 /* Match! Even if name doesn't. */
157 return mod;
158 }
159 } else {
160 /* Not match, even if name is the same. */
161 continue;
162 }
163 }
164
Lev Walkinb36317c2005-08-12 10:09:10 +0000165 if(strcmp(module_name, mod->ModuleName) == 0)
Lev Walkinf15320b2004-06-03 03:38:44 +0000166 return mod;
167 }
168
169 DEBUG("\tModule \"%s\" not found", module_name);
170
171 errno = ENOENT;
172 return NULL;
173}
174
Lev Walkin41635d32006-03-18 05:06:57 +0000175static asn1p_expr_t *
Lev Walkinc0e03b92017-08-22 01:48:23 -0700176asn1f_lookup_symbol_impl(arg_t *arg, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t *ref, int recursion_depth) {
177 asn1_namespace_t *initial_namespace = arg->ns;
178 asn1p_ref_t tmp_ref;
Lev Walkin163db362004-09-15 11:46:47 +0000179 asn1p_module_t *imports_from;
Lev Walkinf15320b2004-06-03 03:38:44 +0000180 char *modulename;
181 char *identifier;
182
Lev Walkinc0e03b92017-08-22 01:48:23 -0700183 if(ref->module && arg->mod != ref->module) {
184 return WITH_MODULE(
185 ref->module,
186 asn1f_lookup_symbol_impl(arg, rhs_pspecs, ref, recursion_depth));
187 }
188
Lev Walkinf15320b2004-06-03 03:38:44 +0000189 /*
190 * First of all, a reference to a symbol may be specified
191 * using several possible forms:
192 * a) simple identifier
193 * v INTEGER ::= value
194 * b) external reference
195 * v INTEGER ::= Module1.value
196 * c) class-related stuff (the most complex stuff)
197 * v ::= <[A-Z][A-Z0-9a-z-]*>.&<[A-Z0-9a-z-]+>.
198 * All other forms are not implemented at this moment.
199 */
200
Lev Walkinc0e03b92017-08-22 01:48:23 -0700201 DEBUG("Lookup (%s) in %s for line %d",
Lev Walkinf15320b2004-06-03 03:38:44 +0000202 asn1f_printable_reference(ref),
Lev Walkinc0e03b92017-08-22 01:48:23 -0700203 asn1_namespace_string(initial_namespace),
Lev Walkinf15320b2004-06-03 03:38:44 +0000204 ref->_lineno);
205
Lev Walkin41635d32006-03-18 05:06:57 +0000206 if(recursion_depth++ > 30 /* Arbitrary constant */) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700207 FATAL(
208 "Excessive circular referencing detected in namespace %s for %s at "
209 "line %d",
210 asn1_namespace_string(initial_namespace),
211 asn1f_printable_reference(ref), ref->_lineno);
212 errno = ETOOMANYREFS;
Lev Walkin41635d32006-03-18 05:06:57 +0000213 return NULL;
214 }
215
Lev Walkinf15320b2004-06-03 03:38:44 +0000216 if(ref->comp_count == 1) {
217 modulename = NULL;
218 identifier = ref->components[0].name;
219 } else if(ref->comp_count == 2
220 && ref->components[1].name[0] != '&') {
221 modulename = ref->components[0].name;
222 identifier = ref->components[1].name;
223 } else if(ref->comp_count > 1
224 && isupper(ref->components[0].name[0])
225 && ref->components[1].name[0] == '&') {
226 asn1p_expr_t *extract;
227 /*
228 * This is a reference to a CLASS-related stuff.
229 * Employ a separate function for that.
230 */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700231 extract = asn1f_class_access(arg, rhs_pspecs, ref);
Lev Walkinf15320b2004-06-03 03:38:44 +0000232
233 return extract;
234 } else {
235 DEBUG("\tToo many components: %d", ref->comp_count);
236 errno = EINVAL;
237 return NULL;
238 }
239
Lev Walkinc0e03b92017-08-22 01:48:23 -0700240 if(modulename) {
241 /*
242 * The modulename is specified inside this reference.
243 * To avoid recursion, reformat the reference
244 * as it were local to that module.
245 */
246 tmp_ref = *ref;
247 tmp_ref.components++; /* Hide the first element */
248 tmp_ref.comp_count--;
249 assert(tmp_ref.comp_count > 0);
250 ref = &tmp_ref;
251 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000252
Lev Walkinc0e03b92017-08-22 01:48:23 -0700253 asn1_namespace_t *my_namespace = initial_namespace;
Lev Walkinf15320b2004-06-03 03:38:44 +0000254
Lev Walkinc0e03b92017-08-22 01:48:23 -0700255#define DISPOSE_OF_MY_NAMESPACE() \
256 do { \
257 int tmp_errno = errno; \
258 if(my_namespace != initial_namespace) { \
259 asn1_namespace_free(my_namespace); \
260 my_namespace = NULL; \
261 } \
262 errno = tmp_errno; \
263 } while(0)
Lev Walkind8095522005-03-18 05:20:39 +0000264
Lev Walkinc0e03b92017-08-22 01:48:23 -0700265 /*
266 * If module name is specified explicitly
267 * OR the current module's IMPORTS clause contains the identifier,
268 * switch namespace to that module.
269 */
270 if(modulename) {
271 imports_from = asn1f_lookup_module(arg, modulename, 0);
272 if(imports_from == NULL) {
273 FATAL(
274 "Module \"%s\" "
275 "mentioned at line %d is not found",
276 modulename, ref->_lineno);
277 return NULL;
278 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000279
Lev Walkinc0e03b92017-08-22 01:48:23 -0700280 /*
281 * Check that the EXPORTS section of this module contains
282 * the symbol we care about, or it is EXPORTS ALL.
283 */
284 if(asn1f_compatible_with_exports(arg, imports_from, identifier)) {
285 errno = EPERM;
286 return NULL;
287 }
Lev Walkin6b3ff542006-03-06 14:51:00 +0000288
Bi-Ruei, Chiu02990372017-11-13 00:34:27 +0800289 DISPOSE_OF_MY_NAMESPACE();
Lev Walkinc0e03b92017-08-22 01:48:23 -0700290 my_namespace = asn1_namespace_new_from_module(imports_from, 1);
291 DEBUG("Lookup (%s) in %s for line %d", asn1f_printable_reference(ref),
292 asn1_namespace_string(my_namespace), ref->_lineno);
293 }
Lev Walkina00d6b32006-03-21 03:40:38 +0000294
Lev Walkinc0e03b92017-08-22 01:48:23 -0700295 size_t namespace_switches = 0;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800296
Lev Walkinc0e03b92017-08-22 01:48:23 -0700297 /*
298 * Search through all layers of the namespace.
299 */
300 for(ssize_t ns_item = my_namespace->elements_count - 1; ns_item >= 0;
301 ns_item--) {
302 struct asn1_namespace_element_s *ns_el =
303 &my_namespace->elements[ns_item];
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800304
Lev Walkinc0e03b92017-08-22 01:48:23 -0700305 switch(ns_el->selector) {
306 case NAM_SYMBOL:
307 if(modulename) {
308 /*
309 * Trying to match a fully specified "Module.Symbol"
310 * against the "Symbol" parameter. Doesn't match.
311 */
312 continue;
313 }
314 if(strcmp(ns_el->u.symbol.identifier, identifier) != 0) {
315 continue;
316 } else {
317 DEBUG("Lookup (%s) in %s for line %d => found as parameter",
318 asn1f_printable_reference(ref),
319 asn1_namespace_string(my_namespace), ref->_lineno);
320 DISPOSE_OF_MY_NAMESPACE();
321 return ns_el->u.symbol.resolution;
322 }
Lev Walkin1a49ced2017-11-06 00:07:00 -0800323 case NAM_SPACE: {
324 asn1p_expr_t *ref_tc; /* Referenced tc */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700325 /*
326 * Do a direct symbol search in the given module.
327 */
Lev Walkin1a49ced2017-11-06 00:07:00 -0800328 ref_tc = asn1f_lookup_in_module(ns_el->u.space.module, identifier);
Lev Walkinc0e03b92017-08-22 01:48:23 -0700329 if(ref_tc) {
330 /* It is acceptable that we don't use input parameters */
331 if(rhs_pspecs && !ref_tc->lhs_params) {
332 WARNING(
333 "Parameterized type %s expected "
334 "for %s at line %d",
335 ref_tc->Identifier, asn1f_printable_reference(ref),
336 ref->_lineno);
337 }
338 if(!rhs_pspecs && ref_tc->lhs_params) {
339 FATAL(
340 "Type %s expects specialization "
341 "from %s at line %d",
342 ref_tc->Identifier, asn1f_printable_reference(ref),
343 ref->_lineno);
344 errno = EPERM;
Bi-Ruei, Chiu02990372017-11-13 00:34:27 +0800345 DISPOSE_OF_MY_NAMESPACE();
Lev Walkinc0e03b92017-08-22 01:48:23 -0700346 return NULL;
347 }
348 if(rhs_pspecs && ref_tc->lhs_params) {
349 /* Specialize the target */
350 ref_tc =
351 asn1f_parameterization_fork(arg, ref_tc, rhs_pspecs);
352 }
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800353
Lev Walkinc0e03b92017-08-22 01:48:23 -0700354 DISPOSE_OF_MY_NAMESPACE();
355 return ref_tc;
356 }
Lev Walkin1a49ced2017-11-06 00:07:00 -0800357 }
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;
Bi-Ruei, Chiu02990372017-11-13 00:34:27 +0800388 DISPOSE_OF_MY_NAMESPACE();
Lev Walkinc0e03b92017-08-22 01:48:23 -0700389 return NULL;
390 }
391
392 /* Switch namespace */
393 DISPOSE_OF_MY_NAMESPACE();
394 my_namespace = asn1_namespace_new_from_module(imports_from, 1);
395 DEBUG("Lookup (%s) in %s for line %d",
396 asn1f_printable_reference(ref),
397 asn1_namespace_string(my_namespace), ref->_lineno);
398 ns_item = my_namespace->elements_count;
399
400 continue;
401 } else if(errno != ESRCH) {
402 /*
403 * Return only if the name was not found.
404 * If module was not found or more serious error
405 * encountered, just return preserving the errno.
406 */
407 DISPOSE_OF_MY_NAMESPACE();
408 return NULL;
409 }
410
411 if(modulename) {
412 FATAL(
413 "Module %s referred by %s in module %s "
414 "does not contain the requested symbol",
415 ns_el->u.space.module->ModuleName,
416 asn1f_printable_reference(ref), modulename);
417 break;
418 }
419
420 /* Search failed in the given namespace */
421 continue;
422 }
423 }
424
425 DEBUG(
426 "Namespace %s does not contain \"%s\" "
427 "mentioned at line %d: %s",
428 asn1_namespace_string(my_namespace), identifier, ref->_lineno,
429 strerror(errno));
430
431 DISPOSE_OF_MY_NAMESPACE();
432
433 if(asn1f_check_known_external_type(identifier) == 0) {
Lev Walkin6b3ff542006-03-06 14:51:00 +0000434 errno = EEXIST; /* Exists somewhere */
435 } else {
436 errno = ESRCH;
437 }
438 return NULL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000439}
440
441
442asn1p_expr_t *
Lev Walkinc0e03b92017-08-22 01:48:23 -0700443asn1f_lookup_symbol(arg_t *arg, asn1p_expr_t *rhs_pspecs,
444 const asn1p_ref_t *ref) {
445 return asn1f_lookup_symbol_impl(arg, rhs_pspecs, ref, 0);
Lev Walkin41635d32006-03-18 05:06:57 +0000446}
447
448asn1p_expr_t *
Lev Walkin6fec44d2004-08-22 03:10:23 +0000449asn1f_find_terminal_type(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin33f63f82005-03-20 11:27:19 +0000450 return asn1f_find_terminal_thing(arg, expr, FTT_TYPE);
Lev Walkinf15320b2004-06-03 03:38:44 +0000451}
452
453asn1p_expr_t *
Lev Walkin6fec44d2004-08-22 03:10:23 +0000454asn1f_find_terminal_value(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin33f63f82005-03-20 11:27:19 +0000455 return asn1f_find_terminal_thing(arg, expr, FTT_VALUE);
Lev Walkinf15320b2004-06-03 03:38:44 +0000456}
457
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800458asn1p_expr_t *
459asn1f_find_ancestor_type_with_PER_constraint(arg_t *arg, asn1p_expr_t *expr) {
460 return asn1f_find_terminal_thing(arg, expr, FTT_CONSTR_TYPE);
461}
462
Lev Walkinf15320b2004-06-03 03:38:44 +0000463static asn1p_expr_t *
Lev Walkin33f63f82005-03-20 11:27:19 +0000464asn1f_find_terminal_thing(arg_t *arg, asn1p_expr_t *expr, enum ftt_what what) {
Lev Walkin039a09e2005-03-20 13:17:48 +0000465 asn1p_ref_t *ref = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000466 asn1p_expr_t *tc;
467
Lev Walkinc0e03b92017-08-22 01:48:23 -0700468 if(arg->mod != expr->module) {
469 return WITH_MODULE(expr->module,
470 asn1f_find_terminal_thing(arg, expr, what));
471 }
472
473 switch(what) {
474 case FTT_TYPE:
475 case FTT_CONSTR_TYPE:
476 /* Expression may be a terminal type itself */
477 if(expr->expr_type != A1TC_REFERENCE) {
478 return expr;
479 }
480 ref = expr->reference;
481 break;
482 case FTT_VALUE:
Lev Walkin1a49ced2017-11-06 00:07:00 -0800483
484 DEBUG("%s(%s->%s) meta %d for line %d",
485 "VALUE", expr->Identifier, asn1f_printable_reference(ref),
486 expr->meta_type, expr->_lineno);
487
Lev Walkinc0e03b92017-08-22 01:48:23 -0700488 assert(expr->meta_type == AMT_VALUE);
489 assert(expr->value);
490 /* Expression may be a terminal type itself */
491 if(expr->value->type != ATV_REFERENCED) {
492 return expr;
493 }
494 ref = expr->value->value.reference;
495 break;
496 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000497
Lev Walkin03850182005-03-10 10:02:50 +0000498 DEBUG("%s(%s->%s) for line %d",
Lev Walkin33f63f82005-03-20 11:27:19 +0000499 (what == FTT_VALUE)?"VALUE":"TYPE",
Lev Walkinf15320b2004-06-03 03:38:44 +0000500 expr->Identifier, asn1f_printable_reference(ref),
501 expr->_lineno);
502
503 assert(ref);
504
505 /*
506 * Lookup inside the type itself (ENUMERATED, INTEGER, etc).
507 */
Lev Walkin33f63f82005-03-20 11:27:19 +0000508 if(what == FTT_VALUE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000509 asn1p_expr_t *val_type_tc;
Lev Walkin6fec44d2004-08-22 03:10:23 +0000510 val_type_tc = asn1f_find_terminal_type(arg, expr);
Lev Walkinc0e03b92017-08-22 01:48:23 -0700511 if(val_type_tc
512 && WITH_MODULE(val_type_tc->module,
513 asn1f_look_value_in_type(arg, val_type_tc, expr))) {
514 return expr;
515 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000516 if(expr->value->type != ATV_REFERENCED) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700517 return expr;
Lev Walkinf15320b2004-06-03 03:38:44 +0000518 }
519 assert(ref == expr->value->value.reference);
520 ref = expr->value->value.reference;
521 }
522
523 /*
Lev Walkind8095522005-03-18 05:20:39 +0000524 * Lookup inside the default module and its IMPORTS section.
Lev Walkinf15320b2004-06-03 03:38:44 +0000525 */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700526 tc = asn1f_lookup_symbol(arg, expr->rhs_pspecs, ref);
527 if(tc == NULL) {
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800528 /*
529 * Lookup inside the ref's module and its IMPORTS section.
530 */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700531 tc = WITH_MODULE(ref->module,
532 asn1f_lookup_symbol(arg, expr->rhs_pspecs, ref));
533 if(tc == NULL) {
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800534 DEBUG("\tSymbol \"%s\" not found: %s",
535 asn1f_printable_reference(ref),
536 strerror(errno));
Lev Walkinc0e03b92017-08-22 01:48:23 -0700537 return NULL;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800538 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000539 }
540
541 /*
542 * Recursive loops detection.
543 */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700544 if(tc->_mark & TM_RECURSION) {
545 DEBUG("Recursion loop detected for %s at line %d",
546 asn1f_printable_reference(ref), ref->_lineno);
547 errno = EPERM;
548 return NULL;
549 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000550
Lev Walkinc0e03b92017-08-22 01:48:23 -0700551 tc->_type_referenced = 1;
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800552
Lev Walkinc0e03b92017-08-22 01:48:23 -0700553 if((what == FTT_CONSTR_TYPE) && (tc->constraints)) {
554 return tc;
555 }
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800556
Lev Walkinc0e03b92017-08-22 01:48:23 -0700557 tc->_mark |= TM_RECURSION;
558 expr = WITH_MODULE(tc->module, asn1f_find_terminal_thing(arg, tc, what));
559 tc->_mark &= ~TM_RECURSION;
Lev Walkinf15320b2004-06-03 03:38:44 +0000560
Lev Walkinc0e03b92017-08-22 01:48:23 -0700561 return expr;
Lev Walkinf15320b2004-06-03 03:38:44 +0000562}
563
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800564
Lev Walkinf15320b2004-06-03 03:38:44 +0000565/*
566 * Make sure that the specified name is present or otherwise does
567 * not contradict with the EXPORTS clause of the specified module.
568 */
569static int
570asn1f_compatible_with_exports(arg_t *arg, asn1p_module_t *mod, const char *name) {
571 asn1p_xports_t *exports;
572 asn1p_expr_t *item;
573
574 assert(mod);
575 assert(name);
576
577 exports = TQ_FIRST(&(mod->exports));
578 if(exports == NULL) {
579 /* No EXPORTS section or EXPORTS ALL; */
580 return 0;
581 }
582
Lev Walkin1a49ced2017-11-06 00:07:00 -0800583 TQ_FOR(item, &(exports->xp_members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000584 if(strcmp(item->Identifier, name) == 0)
585 return 0;
586 }
587
Lev Walkind8095522005-03-18 05:20:39 +0000588 /* Conditional debug */
589 if(!(arg->expr->_mark & TM_BROKEN)) {
590 arg->expr->_mark |= TM_BROKEN;
591 FATAL("EXPORTS section of module %s in %s "
592 "does not mention %s at line %d",
Lev Walkinb36317c2005-08-12 10:09:10 +0000593 mod->ModuleName, mod->source_file_name, name,
Lev Walkind8095522005-03-18 05:20:39 +0000594 arg->expr->_lineno);
595 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000596
597 errno = ESRCH;
598 return -1;
599}