blob: 97e77fed0c9800e935f6a46b134b789332934589 [file] [log] [blame]
vlmfa67ddc2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
vlm2e0c1942004-08-22 03:10:23 +00003static asn1p_expr_t *asn1f_find_terminal_thing(arg_t *arg, asn1p_expr_t *expr, int type_or_value);
vlmfa67ddc2004-06-03 03:38:44 +00004static int asn1f_compatible_with_exports(arg_t *arg, asn1p_module_t *mod, const char *name);
5
6
7/*
8 * Lookup a child by its name.
9 */
10asn1p_expr_t *
11asn1f_lookup_child(asn1p_expr_t *tc, const char *name) {
12 asn1p_expr_t *child_tc;
13
14 TQ_FOR(child_tc, &(tc->members), next) {
15 if(child_tc->Identifier
16 && strcmp(child_tc->Identifier, name) == 0) {
17 return child_tc;
18 }
19 }
20
21 errno = ESRCH;
22 return NULL;
23}
24
25asn1p_module_t *
26asn1f_lookup_in_imports(arg_t *arg, const char *name) {
27 asn1p_module_t *mod;
28 asn1p_xports_t *xp;
29 asn1p_expr_t *tc;
30
31 /*
32 * Search in which exactly module this name is defined.
33 */
34 TQ_FOR(xp, &(arg->mod->imports), xp_next) {
35 TQ_FOR(tc, &(xp->members), next) {
36 if(strcmp(name, tc->Identifier) == 0)
37 break;
38 }
39 if(tc) break;
40 }
41 if(xp == NULL) {
42 errno = ESRCH;
43 return NULL;
44 }
45
46 /*
47 * Okay, right now we have a module name and, hopefully, an OID.
48 * Search the arg->asn for the specified module.
49 */
50 mod = asn1f_lookup_module(arg, xp->from, xp->from_oid);
51 if(mod == NULL) {
52 /* ENOENT/ETOOMANYREFS */
53 return NULL;
54 }
55
56 /*
57 * Check that the EXPORTS section of this module contains
58 * the symbol we care about, or it is EXPORTS ALL.
59 */
60 if(asn1f_compatible_with_exports(arg, mod, name)) {
61 errno = EPERM;
62 return NULL;
63 }
64
65 return mod;
66}
67
68asn1p_module_t *
69asn1f_lookup_module(arg_t *arg, const char *module_name, asn1p_oid_t *oid) {
70 asn1p_module_t *mod;
71
72 assert(module_name);
73
74 /*
75 * If OID is given, the module_name is unused.
76 * If OID is not given, the module_name may mean
77 * either the real module's name, or the symbol which is the
78 * result of renaming. Check this first.
79 */
80 if(oid == 0) {
81 asn1p_xports_t *xp;
82 /*
83 * Check inside the IMPORTS section for possible renaming.
84 * Renaming practically means that a module_name is mentioned
85 * somewhere in the IMPORTS section AND OID is given.
86 */
87 TQ_FOR(xp, &(arg->mod->imports), xp_next) {
88 if(strcmp(module_name, xp->from))
89 continue;
90 if(oid) {
91 FATAL("Ambiguous reference: "
92 "%s "
93 "matches several modules",
94 module_name);
95 errno = ETOOMANYREFS;
96 return NULL;
97 }
98 /*
99 * Yes, there is a renaming.
100 * Make lookup use OID instead.
101 */
102 oid = xp->from_oid;
103 }
104 }
105
106 /*
107 * Perform lookup using OID or module_name.
108 */
109 TQ_FOR(mod, &(arg->asn->modules), mod_next) {
110 if(oid) {
111 if(mod->module_oid) {
112 if(asn1p_oid_compare(oid,
113 mod->module_oid)) {
114 continue;
115 } else {
116 /* Match! Even if name doesn't. */
117 return mod;
118 }
119 } else {
120 /* Not match, even if name is the same. */
121 continue;
122 }
123 }
124
125 if(strcmp(module_name, mod->Identifier) == 0)
126 return mod;
127 }
128
129 DEBUG("\tModule \"%s\" not found", module_name);
130
131 errno = ENOENT;
132 return NULL;
133}
134
135
136
137asn1p_expr_t *
vlm2e0c1942004-08-22 03:10:23 +0000138asn1f_lookup_symbol(arg_t *arg, asn1p_module_t *mod, asn1p_ref_t *ref) {
vlmfa67ddc2004-06-03 03:38:44 +0000139 asn1p_expr_t *ref_tc; /* Referenced tc */
140 asn1p_module_t *src_mod;
141 char *modulename;
142 char *identifier;
143
144 /*
145 * First of all, a reference to a symbol may be specified
146 * using several possible forms:
147 * a) simple identifier
148 * v INTEGER ::= value
149 * b) external reference
150 * v INTEGER ::= Module1.value
151 * c) class-related stuff (the most complex stuff)
152 * v ::= <[A-Z][A-Z0-9a-z-]*>.&<[A-Z0-9a-z-]+>.
153 * All other forms are not implemented at this moment.
154 */
155
156 DEBUG("%s(%s) in %s for line %d", __func__,
157 asn1f_printable_reference(ref),
vlm2e0c1942004-08-22 03:10:23 +0000158 mod->Identifier,
vlmfa67ddc2004-06-03 03:38:44 +0000159 ref->_lineno);
160
161 if(ref->comp_count == 1) {
162 modulename = NULL;
163 identifier = ref->components[0].name;
164 } else if(ref->comp_count == 2
165 && ref->components[1].name[0] != '&') {
166 modulename = ref->components[0].name;
167 identifier = ref->components[1].name;
168 } else if(ref->comp_count > 1
169 && isupper(ref->components[0].name[0])
170 && ref->components[1].name[0] == '&') {
171 asn1p_expr_t *extract;
172 /*
173 * This is a reference to a CLASS-related stuff.
174 * Employ a separate function for that.
175 */
vlm2e0c1942004-08-22 03:10:23 +0000176 extract = asn1f_class_access(arg, mod, ref);
vlmfa67ddc2004-06-03 03:38:44 +0000177
178 return extract;
179 } else {
180 DEBUG("\tToo many components: %d", ref->comp_count);
181 errno = EINVAL;
182 return NULL;
183 }
184
185 /*
186 * If module name is specified explicitly
187 * OR the current module's IMPORTS clause contains the identifier,
188 * fetch that module.
189 */
190 if(modulename) {
191 src_mod = asn1f_lookup_module(arg, modulename, 0);
192 if(src_mod == NULL) {
193 FATAL("Module \"%s\" "
194 "mentioned at line %d is not found",
195 modulename, ref->_lineno);
196 return NULL;
197 }
198
199 /*
200 * Check that the EXPORTS section of this module contains
201 * the symbol we care about, or it is EXPORTS ALL.
202 */
203 if(asn1f_compatible_with_exports(arg, src_mod, identifier)) {
204 errno = EPERM;
205 return NULL;
206 }
207 } else {
208 src_mod = asn1f_lookup_in_imports(arg, identifier);
209 if(src_mod == NULL && errno != ESRCH) {
210 /*
211 * Return only of the name was not found.
212 * If module was not found or more serious error
213 * encountered, just return preserving the errno.
214 */
215 return NULL;
216 }
217 }
218
vlm2e0c1942004-08-22 03:10:23 +0000219 if(src_mod == 0) src_mod = mod;
vlmfa67ddc2004-06-03 03:38:44 +0000220
221 /*
222 * Now we know where to search for a value.
223 */
224 TQ_FOR(ref_tc, &(src_mod->members), next) {
225 if(ref_tc->Identifier)
226 if(strcmp(ref_tc->Identifier, identifier) == 0)
227 break;
228 }
229 if(ref_tc == NULL) {
230 DEBUG("Module \"%s\" does not contain \"%s\" "
vlmd9cd3f92004-06-28 21:21:24 +0000231 "mentioned at line %d: %s",
vlmfa67ddc2004-06-03 03:38:44 +0000232 src_mod->Identifier,
233 identifier,
vlmd9cd3f92004-06-28 21:21:24 +0000234 ref->_lineno,
235 strerror(errno)
vlmfa67ddc2004-06-03 03:38:44 +0000236 );
vlmd9cd3f92004-06-28 21:21:24 +0000237 if(asn1f_check_known_external_type(identifier) == 0) {
238 errno = EEXIST; /* Exists somewhere */
239 } else {
240 errno = ESRCH;
241 }
vlmfa67ddc2004-06-03 03:38:44 +0000242 return NULL;
243 }
244
vlmfa67ddc2004-06-03 03:38:44 +0000245 return ref_tc;
246}
247
248
249asn1p_expr_t *
vlm2e0c1942004-08-22 03:10:23 +0000250asn1f_find_terminal_type(arg_t *arg, asn1p_expr_t *expr) {
251 return asn1f_find_terminal_thing(arg, expr, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000252}
253
254asn1p_expr_t *
vlm2e0c1942004-08-22 03:10:23 +0000255asn1f_find_terminal_value(arg_t *arg, asn1p_expr_t *expr) {
256 return asn1f_find_terminal_thing(arg, expr, 1);
vlmfa67ddc2004-06-03 03:38:44 +0000257}
258
259static asn1p_expr_t *
vlm2e0c1942004-08-22 03:10:23 +0000260asn1f_find_terminal_thing(arg_t *arg, asn1p_expr_t *expr, int type_or_value) {
vlmfa67ddc2004-06-03 03:38:44 +0000261 asn1p_ref_t *ref;
262 asn1p_expr_t *tc;
263
264 if(type_or_value) {
265 /* VALUE */
266 assert(expr->meta_type == AMT_VALUE);
267 assert(expr->value);
vlm2e0c1942004-08-22 03:10:23 +0000268 /* Expression may be a terminal type itself */
269 if(expr->value->type != ATV_REFERENCED)
vlmfa67ddc2004-06-03 03:38:44 +0000270 return expr;
vlmfa67ddc2004-06-03 03:38:44 +0000271 ref = expr->value->value.reference;
272 } else {
273 /* TYPE */
vlm2e0c1942004-08-22 03:10:23 +0000274 /* Expression may be a terminal type itself */
275 if(expr->expr_type != A1TC_REFERENCE)
vlmfa67ddc2004-06-03 03:38:44 +0000276 return expr;
vlmfa67ddc2004-06-03 03:38:44 +0000277 ref = expr->reference;
278 }
279
280 DEBUG("%s:%s(%s->%s) for line %d",
281 __func__, type_or_value?"VALUE":"TYPE",
282 expr->Identifier, asn1f_printable_reference(ref),
283 expr->_lineno);
284
285 assert(ref);
286
287 /*
288 * Lookup inside the type itself (ENUMERATED, INTEGER, etc).
289 */
290 if(type_or_value) {
291 asn1p_expr_t *val_type_tc;
vlm2e0c1942004-08-22 03:10:23 +0000292 val_type_tc = asn1f_find_terminal_type(arg, expr);
vlmfa67ddc2004-06-03 03:38:44 +0000293 if(val_type_tc
294 && asn1f_look_value_in_type(arg, val_type_tc, expr))
295 return NULL;
296 if(expr->value->type != ATV_REFERENCED) {
vlmfa67ddc2004-06-03 03:38:44 +0000297 return expr;
298 }
299 assert(ref == expr->value->value.reference);
300 ref = expr->value->value.reference;
301 }
302
303 /*
304 * Lookup inside the default module.
305 */
vlm2e0c1942004-08-22 03:10:23 +0000306 tc = asn1f_lookup_symbol(arg, expr->module, ref);
vlmfa67ddc2004-06-03 03:38:44 +0000307 if(tc == NULL) {
vlmd9cd3f92004-06-28 21:21:24 +0000308 DEBUG("\tSymbol \"%s\" not found: %s",
309 asn1f_printable_reference(ref),
310 strerror(errno));
vlmfa67ddc2004-06-03 03:38:44 +0000311 return NULL;
312 }
313
314 /*
315 * Recursive loops detection.
316 */
317 if(tc->_mark & TM_RECURSION) {
318 DEBUG("Recursion loop detected for %s at line %d",
319 asn1f_printable_reference(ref), ref->_lineno);
320 errno = EPERM;
321 return NULL;
322 }
323
324 tc->_mark |= TM_RECURSION;
vlm2e0c1942004-08-22 03:10:23 +0000325 WITH_MODULE(tc->module,
326 expr = asn1f_find_terminal_thing(arg, tc, type_or_value));
vlmfa67ddc2004-06-03 03:38:44 +0000327 tc->_mark &= ~TM_RECURSION;
328
329 return expr;
330}
331
332/*
333 * Make sure that the specified name is present or otherwise does
334 * not contradict with the EXPORTS clause of the specified module.
335 */
336static int
337asn1f_compatible_with_exports(arg_t *arg, asn1p_module_t *mod, const char *name) {
338 asn1p_xports_t *exports;
339 asn1p_expr_t *item;
340
341 assert(mod);
342 assert(name);
343
344 exports = TQ_FIRST(&(mod->exports));
345 if(exports == NULL) {
346 /* No EXPORTS section or EXPORTS ALL; */
347 return 0;
348 }
349
350 TQ_FOR(item, &(exports->members), next) {
351 if(strcmp(item->Identifier, name) == 0)
352 return 0;
353 }
354
355 DEBUG("Symbol \"%s\" contradicts with EXPORTS of module %s",
356 name, mod->Identifier);
357
358 errno = ESRCH;
359 return -1;
360}