module Utils = struct let find_in_path path name = if not (Filename.is_implicit name) then if Sys.file_exists name then name else raise Not_found else begin let rec try_dir = function [] -> raise Not_found | dir::rem -> let fullname = Filename.concat dir name in if Sys.file_exists fullname then fullname else try_dir rem in try_dir path end end module Log = struct let printf f x = let oc = stderr in Printf.fprintf oc f x; flush oc end let load_path = ref [] let libraries = ref [] (* ref ["stdlib.cma", ["Parsing"];"nums.cma", ["Big_int"]] *) let debug_load = ref true let rec load_module mod_name = if !debug_load then Log.printf "load_module %s\n" mod_name; let filename = (String.uncapitalize mod_name) ^ ".cmo" in try let filename = Utils.find_in_path !load_path filename in load_file filename with Not_found -> if !debug_load then Log.printf "load_module Not_found %s\n" mod_name; try List.iter (fun (filename, list) -> if List.mem mod_name list then let mod_name = ":" ^ mod_name in try let filename = Utils.find_in_path !load_path filename in load_file (filename ^ mod_name); raise Exit with Not_found -> failwith ("Can't find file "^filename) | Sys_error _ -> (* Should only append using the bytecode dynlink library which does not understand the syntax lib:mod *) load_file filename; raise Exit ) !libraries; failwith ("Can't find file "^filename); with Exit -> Log.printf "load_module Exit %s\n" mod_name and load_file filename = if !debug_load then Log.printf "load_file %s\n" filename; try Dynlink.loadfile filename with Dynlink.Error (Dynlink.Unavailable_unit mod_name) -> load_interface mod_name; load_file filename | Dynlink.Error ( Dynlink.Linking_error (_, Dynlink.Undefined_global mod_name)) -> load_module mod_name; load_file filename and load_interface mod_name = if !debug_load then Log.printf "load_interface: %s\n" mod_name; try Dynlink.add_interfaces [mod_name] !load_path; () with Not_found -> failwith (Printf.sprintf "No interface for %s" mod_name) let load mod_name = if !debug_load then Log.printf "load %s\n" mod_name; try load_module mod_name with Dynlink.Error e -> Printf.printf "Dynlink error: %s" (Dynlink.error_message e); print_newline () | e -> Printf.printf "Dynlink runtime error: %s" (Printexc.to_string e); print_newline ()