+/* The `default-duplicate-binding-procedures' variable. */
+static SCM default_duplicate_binding_procedures_var = SCM_UNSPECIFIED;
+
+/* Return the list of default duplicate binding handlers (procedures). */
+static inline SCM
+default_duplicate_binding_handlers (void)
+{
+ SCM get_handlers;
+
+ get_handlers = SCM_VARIABLE_REF (default_duplicate_binding_procedures_var);
+
+ return (scm_call_0 (get_handlers));
+}
+
+/* Resolve the import of SYM in MODULE, where SYM is currently provided by
+ both IFACE1 as VAR1 and IFACE2 as VAR2. Return the variable chosen by the
+ duplicate binding handlers or `#f'. */
+static inline SCM
+resolve_duplicate_binding (SCM module, SCM sym,
+ SCM iface1, SCM var1,
+ SCM iface2, SCM var2)
+{
+ SCM result = SCM_BOOL_F;
+
+ if (!scm_is_eq (var1, var2))
+ {
+ SCM val1, val2;
+ SCM handlers, h, handler_args;
+
+ val1 = SCM_VARIABLE_REF (var1);
+ val2 = SCM_VARIABLE_REF (var2);
+
+ val1 = (val1 == SCM_UNSPECIFIED) ? SCM_BOOL_F : val1;
+ val2 = (val2 == SCM_UNSPECIFIED) ? SCM_BOOL_F : val2;
+
+ handlers = SCM_MODULE_DUPLICATE_HANDLERS (module);
+ if (scm_is_false (handlers))
+ handlers = default_duplicate_binding_handlers ();
+
+ handler_args = scm_list_n (module, sym,
+ iface1, val1, iface2, val2,
+ var1, val1,
+ SCM_UNDEFINED);
+
+ for (h = handlers;
+ scm_is_pair (h) && scm_is_false (result);
+ h = SCM_CDR (h))
+ {
+ result = scm_apply (SCM_CAR (h), handler_args, SCM_EOL);
+ }
+ }
+ else
+ result = var1;
+
+ return result;
+}
+
+SCM scm_pre_modules_obarray;
+
+/* Lookup SYM as an imported variable of MODULE. */
+static inline SCM
+module_imported_variable (SCM module, SCM sym)
+{
+#define SCM_BOUND_THING_P scm_is_true
+ register SCM var, imports;
+
+ /* Search cached imported bindings. */
+ imports = SCM_MODULE_IMPORT_OBARRAY (module);
+ var = scm_hashq_ref (imports, sym, SCM_UNDEFINED);
+ if (SCM_BOUND_THING_P (var))
+ return var;
+
+ {
+ /* Search the use list for yet uncached imported bindings, possibly
+ resolving duplicates as needed and caching the result in the import
+ obarray. */
+ SCM uses;
+ SCM found_var = SCM_BOOL_F, found_iface = SCM_BOOL_F;
+
+ for (uses = SCM_MODULE_USES (module);
+ scm_is_pair (uses);
+ uses = SCM_CDR (uses))
+ {
+ SCM iface;
+
+ iface = SCM_CAR (uses);
+ var = scm_module_variable (iface, sym);
+
+ if (SCM_BOUND_THING_P (var))
+ {
+ if (SCM_BOUND_THING_P (found_var))
+ {
+ /* SYM is a duplicate binding (imported more than once) so we
+ need to resolve it. */
+ found_var = resolve_duplicate_binding (module, sym,
+ found_iface, found_var,
+ iface, var);
+ if (scm_is_eq (found_var, var))
+ found_iface = iface;
+ }
+ else
+ /* Keep track of the variable we found and check for other
+ occurences of SYM in the use list. */
+ found_var = var, found_iface = iface;
+ }
+ }
+
+ if (SCM_BOUND_THING_P (found_var))
+ {
+ /* Save the lookup result for future reference. */
+ (void) scm_hashq_set_x (imports, sym, found_var);
+ return found_var;
+ }
+ }
+
+ return SCM_BOOL_F;
+#undef SCM_BOUND_THING_P
+}
+
+SCM_DEFINE (scm_module_local_variable, "module-local-variable", 2, 0, 0,
+ (SCM module, SCM sym),
+ "Return the variable bound to @var{sym} in @var{module}. Return "
+ "@code{#f} is @var{sym} is not bound locally in @var{module}.")
+#define FUNC_NAME s_scm_module_local_variable