blob: 40acbe5a4485932b56a466ae66c0f6610e2653da [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
Lev Walkin1a49ced2017-11-06 00:07:00 -080066 asn1p_expr_t *v = v =
67 asn1f_lookup_in_module(fromModule, tc->Identifier);
68 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
Lev Walkinc0e03b92017-08-22 01:48:23 -0700289 my_namespace = asn1_namespace_new_from_module(imports_from, 1);
290 DEBUG("Lookup (%s) in %s for line %d", asn1f_printable_reference(ref),
291 asn1_namespace_string(my_namespace), ref->_lineno);
292 }
Lev Walkina00d6b32006-03-21 03:40:38 +0000293
Lev Walkinc0e03b92017-08-22 01:48:23 -0700294 size_t namespace_switches = 0;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800295
Lev Walkinc0e03b92017-08-22 01:48:23 -0700296 /*
297 * Search through all layers of the namespace.
298 */
299 for(ssize_t ns_item = my_namespace->elements_count - 1; ns_item >= 0;
300 ns_item--) {
301 struct asn1_namespace_element_s *ns_el =
302 &my_namespace->elements[ns_item];
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800303
Lev Walkinc0e03b92017-08-22 01:48:23 -0700304 switch(ns_el->selector) {
305 case NAM_SYMBOL:
306 if(modulename) {
307 /*
308 * Trying to match a fully specified "Module.Symbol"
309 * against the "Symbol" parameter. Doesn't match.
310 */
311 continue;
312 }
313 if(strcmp(ns_el->u.symbol.identifier, identifier) != 0) {
314 continue;
315 } else {
316 DEBUG("Lookup (%s) in %s for line %d => found as parameter",
317 asn1f_printable_reference(ref),
318 asn1_namespace_string(my_namespace), ref->_lineno);
319 DISPOSE_OF_MY_NAMESPACE();
320 return ns_el->u.symbol.resolution;
321 }
Lev Walkin1a49ced2017-11-06 00:07:00 -0800322 case NAM_SPACE: {
323 asn1p_expr_t *ref_tc; /* Referenced tc */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700324 /*
325 * Do a direct symbol search in the given module.
326 */
Lev Walkin1a49ced2017-11-06 00:07:00 -0800327 ref_tc = asn1f_lookup_in_module(ns_el->u.space.module, identifier);
Lev Walkinc0e03b92017-08-22 01:48:23 -0700328 if(ref_tc) {
329 /* It is acceptable that we don't use input parameters */
330 if(rhs_pspecs && !ref_tc->lhs_params) {
331 WARNING(
332 "Parameterized type %s expected "
333 "for %s at line %d",
334 ref_tc->Identifier, asn1f_printable_reference(ref),
335 ref->_lineno);
336 }
337 if(!rhs_pspecs && ref_tc->lhs_params) {
338 FATAL(
339 "Type %s expects specialization "
340 "from %s at line %d",
341 ref_tc->Identifier, asn1f_printable_reference(ref),
342 ref->_lineno);
343 errno = EPERM;
344 return NULL;
345 }
346 if(rhs_pspecs && ref_tc->lhs_params) {
347 /* Specialize the target */
348 ref_tc =
349 asn1f_parameterization_fork(arg, ref_tc, rhs_pspecs);
350 }
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800351
Lev Walkinc0e03b92017-08-22 01:48:23 -0700352 DISPOSE_OF_MY_NAMESPACE();
353 return ref_tc;
354 }
Lev Walkin1a49ced2017-11-06 00:07:00 -0800355 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000356
Lev Walkinc0e03b92017-08-22 01:48:23 -0700357 /*
358 if(!expr && !(arg->expr->_mark & TM_BROKEN)
359 && !(imports_from->_tags & MT_STANDARD_MODULE)) {
360 arg->expr->_mark |= TM_BROKEN;
361 if(modulename) {
362 } else {
363 FATAL(
364 "Module %s referred in IMPORTS section "
365 "for %s of module %s does not contain "
366 "the requested symbol",
367 imports_from->ModuleName,
368 asn1f_printable_reference(ref), mod->ModuleName);
369 }
370 }
371 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000372
Lev Walkinc0e03b92017-08-22 01:48:23 -0700373 /* Search inside the IMPORTS section of the given module */
374 imports_from =
375 asn1f_lookup_in_imports(arg, ns_el->u.space.module, identifier);
376 if(imports_from) {
377
378 if(namespace_switches++ > 10 /* Arbitrary constant */) {
379 FATAL(
380 "Excessive circular referencing detected in namespace "
381 "%s for %s at "
382 "line %d",
383 asn1_namespace_string(arg->ns),
384 asn1f_printable_reference(ref), ref->_lineno);
385 errno = ETOOMANYREFS;
386 return NULL;
387 }
388
389 /* Switch namespace */
390 DISPOSE_OF_MY_NAMESPACE();
391 my_namespace = asn1_namespace_new_from_module(imports_from, 1);
392 DEBUG("Lookup (%s) in %s for line %d",
393 asn1f_printable_reference(ref),
394 asn1_namespace_string(my_namespace), ref->_lineno);
395 ns_item = my_namespace->elements_count;
396
397 continue;
398 } else if(errno != ESRCH) {
399 /*
400 * Return only if the name was not found.
401 * If module was not found or more serious error
402 * encountered, just return preserving the errno.
403 */
404 DISPOSE_OF_MY_NAMESPACE();
405 return NULL;
406 }
407
408 if(modulename) {
409 FATAL(
410 "Module %s referred by %s in module %s "
411 "does not contain the requested symbol",
412 ns_el->u.space.module->ModuleName,
413 asn1f_printable_reference(ref), modulename);
414 break;
415 }
416
417 /* Search failed in the given namespace */
418 continue;
419 }
420 }
421
422 DEBUG(
423 "Namespace %s does not contain \"%s\" "
424 "mentioned at line %d: %s",
425 asn1_namespace_string(my_namespace), identifier, ref->_lineno,
426 strerror(errno));
427
428 DISPOSE_OF_MY_NAMESPACE();
429
430 if(asn1f_check_known_external_type(identifier) == 0) {
Lev Walkin6b3ff542006-03-06 14:51:00 +0000431 errno = EEXIST; /* Exists somewhere */
432 } else {
433 errno = ESRCH;
434 }
435 return NULL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000436}
437
438
439asn1p_expr_t *
Lev Walkinc0e03b92017-08-22 01:48:23 -0700440asn1f_lookup_symbol(arg_t *arg, asn1p_expr_t *rhs_pspecs,
441 const asn1p_ref_t *ref) {
442 return asn1f_lookup_symbol_impl(arg, rhs_pspecs, ref, 0);
Lev Walkin41635d32006-03-18 05:06:57 +0000443}
444
445asn1p_expr_t *
Lev Walkin6fec44d2004-08-22 03:10:23 +0000446asn1f_find_terminal_type(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin33f63f82005-03-20 11:27:19 +0000447 return asn1f_find_terminal_thing(arg, expr, FTT_TYPE);
Lev Walkinf15320b2004-06-03 03:38:44 +0000448}
449
450asn1p_expr_t *
Lev Walkin6fec44d2004-08-22 03:10:23 +0000451asn1f_find_terminal_value(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin33f63f82005-03-20 11:27:19 +0000452 return asn1f_find_terminal_thing(arg, expr, FTT_VALUE);
Lev Walkinf15320b2004-06-03 03:38:44 +0000453}
454
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800455asn1p_expr_t *
456asn1f_find_ancestor_type_with_PER_constraint(arg_t *arg, asn1p_expr_t *expr) {
457 return asn1f_find_terminal_thing(arg, expr, FTT_CONSTR_TYPE);
458}
459
Lev Walkinf15320b2004-06-03 03:38:44 +0000460static asn1p_expr_t *
Lev Walkin33f63f82005-03-20 11:27:19 +0000461asn1f_find_terminal_thing(arg_t *arg, asn1p_expr_t *expr, enum ftt_what what) {
Lev Walkin039a09e2005-03-20 13:17:48 +0000462 asn1p_ref_t *ref = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000463 asn1p_expr_t *tc;
464
Lev Walkinc0e03b92017-08-22 01:48:23 -0700465 if(arg->mod != expr->module) {
466 return WITH_MODULE(expr->module,
467 asn1f_find_terminal_thing(arg, expr, what));
468 }
469
470 switch(what) {
471 case FTT_TYPE:
472 case FTT_CONSTR_TYPE:
473 /* Expression may be a terminal type itself */
474 if(expr->expr_type != A1TC_REFERENCE) {
475 return expr;
476 }
477 ref = expr->reference;
478 break;
479 case FTT_VALUE:
Lev Walkin1a49ced2017-11-06 00:07:00 -0800480
481 DEBUG("%s(%s->%s) meta %d for line %d",
482 "VALUE", expr->Identifier, asn1f_printable_reference(ref),
483 expr->meta_type, expr->_lineno);
484
Lev Walkinc0e03b92017-08-22 01:48:23 -0700485 assert(expr->meta_type == AMT_VALUE);
486 assert(expr->value);
487 /* Expression may be a terminal type itself */
488 if(expr->value->type != ATV_REFERENCED) {
489 return expr;
490 }
491 ref = expr->value->value.reference;
492 break;
493 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000494
Lev Walkin03850182005-03-10 10:02:50 +0000495 DEBUG("%s(%s->%s) for line %d",
Lev Walkin33f63f82005-03-20 11:27:19 +0000496 (what == FTT_VALUE)?"VALUE":"TYPE",
Lev Walkinf15320b2004-06-03 03:38:44 +0000497 expr->Identifier, asn1f_printable_reference(ref),
498 expr->_lineno);
499
500 assert(ref);
501
502 /*
503 * Lookup inside the type itself (ENUMERATED, INTEGER, etc).
504 */
Lev Walkin33f63f82005-03-20 11:27:19 +0000505 if(what == FTT_VALUE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000506 asn1p_expr_t *val_type_tc;
Lev Walkin6fec44d2004-08-22 03:10:23 +0000507 val_type_tc = asn1f_find_terminal_type(arg, expr);
Lev Walkinc0e03b92017-08-22 01:48:23 -0700508 if(val_type_tc
509 && WITH_MODULE(val_type_tc->module,
510 asn1f_look_value_in_type(arg, val_type_tc, expr))) {
511 return expr;
512 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000513 if(expr->value->type != ATV_REFERENCED) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700514 return expr;
Lev Walkinf15320b2004-06-03 03:38:44 +0000515 }
516 assert(ref == expr->value->value.reference);
517 ref = expr->value->value.reference;
518 }
519
520 /*
Lev Walkind8095522005-03-18 05:20:39 +0000521 * Lookup inside the default module and its IMPORTS section.
Lev Walkinf15320b2004-06-03 03:38:44 +0000522 */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700523 tc = asn1f_lookup_symbol(arg, expr->rhs_pspecs, ref);
524 if(tc == NULL) {
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800525 /*
526 * Lookup inside the ref's module and its IMPORTS section.
527 */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700528 tc = WITH_MODULE(ref->module,
529 asn1f_lookup_symbol(arg, expr->rhs_pspecs, ref));
530 if(tc == NULL) {
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800531 DEBUG("\tSymbol \"%s\" not found: %s",
532 asn1f_printable_reference(ref),
533 strerror(errno));
Lev Walkinc0e03b92017-08-22 01:48:23 -0700534 return NULL;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800535 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000536 }
537
538 /*
539 * Recursive loops detection.
540 */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700541 if(tc->_mark & TM_RECURSION) {
542 DEBUG("Recursion loop detected for %s at line %d",
543 asn1f_printable_reference(ref), ref->_lineno);
544 errno = EPERM;
545 return NULL;
546 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000547
Lev Walkinc0e03b92017-08-22 01:48:23 -0700548 tc->_type_referenced = 1;
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800549
Lev Walkinc0e03b92017-08-22 01:48:23 -0700550 if((what == FTT_CONSTR_TYPE) && (tc->constraints)) {
551 return tc;
552 }
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800553
Lev Walkinc0e03b92017-08-22 01:48:23 -0700554 tc->_mark |= TM_RECURSION;
555 expr = WITH_MODULE(tc->module, asn1f_find_terminal_thing(arg, tc, what));
556 tc->_mark &= ~TM_RECURSION;
Lev Walkinf15320b2004-06-03 03:38:44 +0000557
Lev Walkinc0e03b92017-08-22 01:48:23 -0700558 return expr;
Lev Walkinf15320b2004-06-03 03:38:44 +0000559}
560
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800561
Lev Walkinf15320b2004-06-03 03:38:44 +0000562/*
563 * Make sure that the specified name is present or otherwise does
564 * not contradict with the EXPORTS clause of the specified module.
565 */
566static int
567asn1f_compatible_with_exports(arg_t *arg, asn1p_module_t *mod, const char *name) {
568 asn1p_xports_t *exports;
569 asn1p_expr_t *item;
570
571 assert(mod);
572 assert(name);
573
574 exports = TQ_FIRST(&(mod->exports));
575 if(exports == NULL) {
576 /* No EXPORTS section or EXPORTS ALL; */
577 return 0;
578 }
579
Lev Walkin1a49ced2017-11-06 00:07:00 -0800580 TQ_FOR(item, &(exports->xp_members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000581 if(strcmp(item->Identifier, name) == 0)
582 return 0;
583 }
584
Lev Walkind8095522005-03-18 05:20:39 +0000585 /* Conditional debug */
586 if(!(arg->expr->_mark & TM_BROKEN)) {
587 arg->expr->_mark |= TM_BROKEN;
588 FATAL("EXPORTS section of module %s in %s "
589 "does not mention %s at line %d",
Lev Walkinb36317c2005-08-12 10:09:10 +0000590 mod->ModuleName, mod->source_file_name, name,
Lev Walkind8095522005-03-18 05:20:39 +0000591 arg->expr->_lineno);
592 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000593
594 errno = ESRCH;
595 return -1;
596}