blob: 1700914fcc2138800a49d02f6d4e2d418f2bcaa1 [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 *
83asn1f_lookup_module(arg_t *arg, const char *module_name, asn1p_oid_t *oid) {
84 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 Walkina00d6b32006-03-21 03:40:38 +0000150asn1f_lookup_symbol_impl(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, asn1p_ref_t *ref, int recursion_depth) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000151 asn1p_expr_t *ref_tc; /* Referenced tc */
Lev Walkin163db362004-09-15 11:46:47 +0000152 asn1p_module_t *imports_from;
Lev Walkinf15320b2004-06-03 03:38:44 +0000153 char *modulename;
154 char *identifier;
155
156 /*
157 * First of all, a reference to a symbol may be specified
158 * using several possible forms:
159 * a) simple identifier
160 * v INTEGER ::= value
161 * b) external reference
162 * v INTEGER ::= Module1.value
163 * c) class-related stuff (the most complex stuff)
164 * v ::= <[A-Z][A-Z0-9a-z-]*>.&<[A-Z0-9a-z-]+>.
165 * All other forms are not implemented at this moment.
166 */
167
Lev Walkin03850182005-03-10 10:02:50 +0000168 DEBUG("(%s) in %s for line %d",
Lev Walkinf15320b2004-06-03 03:38:44 +0000169 asn1f_printable_reference(ref),
Lev Walkinb36317c2005-08-12 10:09:10 +0000170 mod->ModuleName,
Lev Walkinf15320b2004-06-03 03:38:44 +0000171 ref->_lineno);
172
Lev Walkin41635d32006-03-18 05:06:57 +0000173 if(recursion_depth++ > 30 /* Arbitrary constant */) {
174 FATAL("Excessive circular referencing detected in module %s for %s at line %d",
175 mod->ModuleName,
176 asn1f_printable_reference(ref),
177 ref->_lineno);
178 errno = ETOOMANYREFS;
179 return NULL;
180 }
181
Lev Walkinf15320b2004-06-03 03:38:44 +0000182 if(ref->comp_count == 1) {
183 modulename = NULL;
184 identifier = ref->components[0].name;
185 } else if(ref->comp_count == 2
186 && ref->components[1].name[0] != '&') {
187 modulename = ref->components[0].name;
188 identifier = ref->components[1].name;
189 } else if(ref->comp_count > 1
190 && isupper(ref->components[0].name[0])
191 && ref->components[1].name[0] == '&') {
192 asn1p_expr_t *extract;
193 /*
194 * This is a reference to a CLASS-related stuff.
195 * Employ a separate function for that.
196 */
Lev Walkina00d6b32006-03-21 03:40:38 +0000197 extract = asn1f_class_access(arg, mod, rhs_pspecs, ref);
Lev Walkinf15320b2004-06-03 03:38:44 +0000198
199 return extract;
200 } else {
201 DEBUG("\tToo many components: %d", ref->comp_count);
202 errno = EINVAL;
203 return NULL;
204 }
205
206 /*
207 * If module name is specified explicitly
208 * OR the current module's IMPORTS clause contains the identifier,
209 * fetch that module.
210 */
211 if(modulename) {
Lev Walkin163db362004-09-15 11:46:47 +0000212 imports_from = asn1f_lookup_module(arg, modulename, 0);
213 if(imports_from == NULL) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000214 FATAL("Module \"%s\" "
215 "mentioned at line %d is not found",
216 modulename, ref->_lineno);
217 return NULL;
218 }
219
220 /*
221 * Check that the EXPORTS section of this module contains
222 * the symbol we care about, or it is EXPORTS ALL.
223 */
Lev Walkin163db362004-09-15 11:46:47 +0000224 if(asn1f_compatible_with_exports(arg,imports_from,identifier)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000225 errno = EPERM;
226 return NULL;
227 }
228 } else {
Lev Walkin6b3ff542006-03-06 14:51:00 +0000229 /* Search inside the IMPORTS section of the current module */
Lev Walkin163db362004-09-15 11:46:47 +0000230 imports_from = asn1f_lookup_in_imports(arg, mod, identifier);
231 if(imports_from == NULL && errno != ESRCH) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000232 /*
233 * Return only of the name was not found.
234 * If module was not found or more serious error
235 * encountered, just return preserving the errno.
236 */
237 return NULL;
238 }
239 }
240
Lev Walkin163db362004-09-15 11:46:47 +0000241 /*
242 * The symbol is being imported from another module.
243 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000244 importing:
Lev Walkin163db362004-09-15 11:46:47 +0000245 if(imports_from) {
246 asn1p_ref_t tmpref = *ref;
Lev Walkind8095522005-03-18 05:20:39 +0000247 asn1p_expr_t *expr;
Lev Walkin163db362004-09-15 11:46:47 +0000248 if(modulename) {
249 /*
250 * The modulename is specified inside this reference.
251 * To avoid recursion, reformat the reference
252 * as it were local to that module.
253 */
254 tmpref.components++; /* Hide the first element */
255 tmpref.comp_count--;
256 assert(tmpref.comp_count > 0);
257 }
Lev Walkind8095522005-03-18 05:20:39 +0000258
Lev Walkina00d6b32006-03-21 03:40:38 +0000259 expr = asn1f_lookup_symbol_impl(arg, imports_from,
260 rhs_pspecs, &tmpref, recursion_depth);
Lev Walkindc4376d2006-03-16 11:04:55 +0000261 if(!expr && !(arg->expr->_mark & TM_BROKEN)
262 && !(imports_from->_tags & MT_STANDARD_MODULE)) {
Lev Walkind8095522005-03-18 05:20:39 +0000263 arg->expr->_mark |= TM_BROKEN;
264 if(modulename) {
265 FATAL("Module %s referred by %s in module %s "
266 "does not contain the requested symbol",
Lev Walkinb36317c2005-08-12 10:09:10 +0000267 imports_from->ModuleName,
Lev Walkind8095522005-03-18 05:20:39 +0000268 asn1f_printable_reference(ref),
Lev Walkinb36317c2005-08-12 10:09:10 +0000269 mod->ModuleName);
Lev Walkind8095522005-03-18 05:20:39 +0000270 } else {
271 FATAL("Module %s referred in IMPORTS section "
272 "for %s of module %s does not contain "
273 "the requested symbol",
Lev Walkinb36317c2005-08-12 10:09:10 +0000274 imports_from->ModuleName,
Lev Walkind8095522005-03-18 05:20:39 +0000275 asn1f_printable_reference(ref),
Lev Walkinb36317c2005-08-12 10:09:10 +0000276 mod->ModuleName);
Lev Walkind8095522005-03-18 05:20:39 +0000277 }
278 }
279 return expr;
Lev Walkin163db362004-09-15 11:46:47 +0000280 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000281
282 /*
Lev Walkin163db362004-09-15 11:46:47 +0000283 * Now we know where to search for a value: in the current module.
Lev Walkinf15320b2004-06-03 03:38:44 +0000284 */
Lev Walkin163db362004-09-15 11:46:47 +0000285 TQ_FOR(ref_tc, &(mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000286 if(ref_tc->Identifier)
287 if(strcmp(ref_tc->Identifier, identifier) == 0)
288 break;
289 }
Lev Walkina00d6b32006-03-21 03:40:38 +0000290 if(ref_tc) {
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800291 /* It is acceptable that we don't use input parameters */
Lev Walkina00d6b32006-03-21 03:40:38 +0000292 if(rhs_pspecs && !ref_tc->lhs_params) {
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800293 WARNING("Parameterized type %s expected "
Lev Walkina00d6b32006-03-21 03:40:38 +0000294 "for %s at line %d",
295 ref_tc->Identifier,
296 asn1f_printable_reference(ref),
297 ref->_lineno);
Lev Walkina00d6b32006-03-21 03:40:38 +0000298 }
299 if(!rhs_pspecs && ref_tc->lhs_params) {
300 FATAL("Type %s expects specialization "
301 "from %s at line %d",
302 ref_tc->Identifier,
303 asn1f_printable_reference(ref),
304 ref->_lineno);
305 errno = EPERM;
306 return NULL;
307 }
308 if(rhs_pspecs && ref_tc->lhs_params) {
309 /* Specialize the target */
310 ref_tc = asn1f_parameterization_fork(arg,
311 ref_tc, rhs_pspecs);
312 }
Lev Walkin6b3ff542006-03-06 14:51:00 +0000313
Lev Walkina00d6b32006-03-21 03:40:38 +0000314 return ref_tc;
315 }
316
317 /*
318 * Not found in the current module.
319 * Search in our default standard module.
320 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000321 {
322 /* Search inside standard module */
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800323 asn1p_oid_t *uioc_oid;
324 asn1p_oid_arc_t arcs[] = {
325 { 1, "iso" },
326 { 3, "org" },
327 { 6, "dod" },
328 { 1, "internet" },
329 { 4, "private" },
330 { 1, "enterprise" },
331 { 9363, "spelio" },
332 { 1, "software" },
333 { 5, "asn1c" },
334 { 3, "standard-modules" },
335 { 0, "auto-imported" },
336 { 1, 0 }
337 };
338
339 if(!imports_from) {
Lev Walkin6b3ff542006-03-06 14:51:00 +0000340 uioc_oid = asn1p_oid_construct(arcs,
341 sizeof(arcs)/sizeof(arcs[0]));
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800342
343 if(!mod->module_oid
344 || asn1p_oid_compare(mod->module_oid, uioc_oid))
345 imports_from = asn1f_lookup_module(arg,
346 "ASN1C-UsefulInformationObjectClasses",
347 uioc_oid);
348
349 asn1p_oid_free(uioc_oid);
Lev Walkin6b3ff542006-03-06 14:51:00 +0000350 if(imports_from) goto importing;
351 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000352 }
353
Lev Walkin6b3ff542006-03-06 14:51:00 +0000354 DEBUG("Module \"%s\" does not contain \"%s\" "
355 "mentioned at line %d: %s",
356 mod->ModuleName,
357 identifier,
358 ref->_lineno,
359 strerror(errno));
360
361 if(asn1f_check_known_external_type(identifier) == 0) {
362 errno = EEXIST; /* Exists somewhere */
363 } else {
364 errno = ESRCH;
365 }
366 return NULL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000367}
368
369
370asn1p_expr_t *
Lev Walkina00d6b32006-03-21 03:40:38 +0000371asn1f_lookup_symbol(arg_t *arg,
372 asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, asn1p_ref_t *ref) {
373 return asn1f_lookup_symbol_impl(arg, mod, rhs_pspecs, ref, 0);
Lev Walkin41635d32006-03-18 05:06:57 +0000374}
375
376asn1p_expr_t *
Lev Walkin6fec44d2004-08-22 03:10:23 +0000377asn1f_find_terminal_type(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin33f63f82005-03-20 11:27:19 +0000378 return asn1f_find_terminal_thing(arg, expr, FTT_TYPE);
Lev Walkinf15320b2004-06-03 03:38:44 +0000379}
380
381asn1p_expr_t *
Lev Walkin6fec44d2004-08-22 03:10:23 +0000382asn1f_find_terminal_value(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin33f63f82005-03-20 11:27:19 +0000383 return asn1f_find_terminal_thing(arg, expr, FTT_VALUE);
Lev Walkinf15320b2004-06-03 03:38:44 +0000384}
385
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800386asn1p_expr_t *
387asn1f_find_ancestor_type_with_PER_constraint(arg_t *arg, asn1p_expr_t *expr) {
388 return asn1f_find_terminal_thing(arg, expr, FTT_CONSTR_TYPE);
389}
390
Lev Walkinf15320b2004-06-03 03:38:44 +0000391static asn1p_expr_t *
Lev Walkin33f63f82005-03-20 11:27:19 +0000392asn1f_find_terminal_thing(arg_t *arg, asn1p_expr_t *expr, enum ftt_what what) {
Lev Walkin039a09e2005-03-20 13:17:48 +0000393 asn1p_ref_t *ref = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000394 asn1p_expr_t *tc;
395
Lev Walkin33f63f82005-03-20 11:27:19 +0000396 switch(what) {
397 case FTT_TYPE:
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800398 case FTT_CONSTR_TYPE:
Lev Walkin33f63f82005-03-20 11:27:19 +0000399 /* Expression may be a terminal type itself */
400 if(expr->expr_type != A1TC_REFERENCE)
401 return expr;
402 ref = expr->reference;
403 break;
404 case FTT_VALUE:
Lev Walkinf15320b2004-06-03 03:38:44 +0000405 assert(expr->meta_type == AMT_VALUE);
406 assert(expr->value);
Lev Walkin6fec44d2004-08-22 03:10:23 +0000407 /* Expression may be a terminal type itself */
408 if(expr->value->type != ATV_REFERENCED)
Lev Walkinf15320b2004-06-03 03:38:44 +0000409 return expr;
Lev Walkinf15320b2004-06-03 03:38:44 +0000410 ref = expr->value->value.reference;
Lev Walkin33f63f82005-03-20 11:27:19 +0000411 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000412 }
413
Lev Walkin03850182005-03-10 10:02:50 +0000414 DEBUG("%s(%s->%s) for line %d",
Lev Walkin33f63f82005-03-20 11:27:19 +0000415 (what == FTT_VALUE)?"VALUE":"TYPE",
Lev Walkinf15320b2004-06-03 03:38:44 +0000416 expr->Identifier, asn1f_printable_reference(ref),
417 expr->_lineno);
418
419 assert(ref);
420
421 /*
422 * Lookup inside the type itself (ENUMERATED, INTEGER, etc).
423 */
Lev Walkin33f63f82005-03-20 11:27:19 +0000424 if(what == FTT_VALUE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000425 asn1p_expr_t *val_type_tc;
Lev Walkin6fec44d2004-08-22 03:10:23 +0000426 val_type_tc = asn1f_find_terminal_type(arg, expr);
Lev Walkinf15320b2004-06-03 03:38:44 +0000427 if(val_type_tc
428 && asn1f_look_value_in_type(arg, val_type_tc, expr))
429 return NULL;
430 if(expr->value->type != ATV_REFERENCED) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000431 return expr;
432 }
433 assert(ref == expr->value->value.reference);
434 ref = expr->value->value.reference;
435 }
436
437 /*
Lev Walkind8095522005-03-18 05:20:39 +0000438 * Lookup inside the default module and its IMPORTS section.
Lev Walkinf15320b2004-06-03 03:38:44 +0000439 */
Lev Walkina00d6b32006-03-21 03:40:38 +0000440 tc = asn1f_lookup_symbol(arg, expr->module, expr->rhs_pspecs, ref);
Lev Walkinf15320b2004-06-03 03:38:44 +0000441 if(tc == NULL) {
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800442 /*
443 * Lookup inside the ref's module and its IMPORTS section.
444 */
445 tc = asn1f_lookup_symbol(arg, ref->module, expr->rhs_pspecs, ref);
446 if(tc == NULL) {
447 DEBUG("\tSymbol \"%s\" not found: %s",
448 asn1f_printable_reference(ref),
449 strerror(errno));
450 return NULL;
451 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000452 }
453
454 /*
455 * Recursive loops detection.
456 */
457 if(tc->_mark & TM_RECURSION) {
458 DEBUG("Recursion loop detected for %s at line %d",
459 asn1f_printable_reference(ref), ref->_lineno);
460 errno = EPERM;
461 return NULL;
462 }
463
Lev Walkin59b176e2005-11-26 11:25:14 +0000464 tc->_type_referenced = 1;
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800465
466 if((what == FTT_CONSTR_TYPE) && (tc->constraints))
467 return tc;
468
Lev Walkinf15320b2004-06-03 03:38:44 +0000469 tc->_mark |= TM_RECURSION;
Lev Walkin6fec44d2004-08-22 03:10:23 +0000470 WITH_MODULE(tc->module,
Lev Walkin33f63f82005-03-20 11:27:19 +0000471 expr = asn1f_find_terminal_thing(arg, tc, what));
Lev Walkinf15320b2004-06-03 03:38:44 +0000472 tc->_mark &= ~TM_RECURSION;
473
474 return expr;
475}
476
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800477
Lev Walkinf15320b2004-06-03 03:38:44 +0000478/*
479 * Make sure that the specified name is present or otherwise does
480 * not contradict with the EXPORTS clause of the specified module.
481 */
482static int
483asn1f_compatible_with_exports(arg_t *arg, asn1p_module_t *mod, const char *name) {
484 asn1p_xports_t *exports;
485 asn1p_expr_t *item;
486
487 assert(mod);
488 assert(name);
489
490 exports = TQ_FIRST(&(mod->exports));
491 if(exports == NULL) {
492 /* No EXPORTS section or EXPORTS ALL; */
493 return 0;
494 }
495
496 TQ_FOR(item, &(exports->members), next) {
497 if(strcmp(item->Identifier, name) == 0)
498 return 0;
499 }
500
Lev Walkind8095522005-03-18 05:20:39 +0000501 /* Conditional debug */
502 if(!(arg->expr->_mark & TM_BROKEN)) {
503 arg->expr->_mark |= TM_BROKEN;
504 FATAL("EXPORTS section of module %s in %s "
505 "does not mention %s at line %d",
Lev Walkinb36317c2005-08-12 10:09:10 +0000506 mod->ModuleName, mod->source_file_name, name,
Lev Walkind8095522005-03-18 05:20:39 +0000507 arg->expr->_lineno);
508 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000509
510 errno = ESRCH;
511 return -1;
512}