# XXX Here there be dragons. # Top-level bootstrap of Nickle builtins in Nickle. # As you might expect, ordering and details are crucial. # Set up the library path correctly and # provide the "library" command. # Lives in this file because it's necessary # for bootstrapping extend namespace Command { /* actually controls library loading */ public string nickle_path = nickle_libdir; if (Environ::check("NICKLEPATH")) nickle_path = Environ::get("NICKLEPATH"); public bool lex_file (string name) /* * Push the file 'name' into the lexer and read input * from there until exhausted. Then return to the current * file. */ { return Command::lex_input (File::open (name, "r"), name, false, false); } /* currently just does ~ expansion */ public string glob(string filename) /* * Expand any leading ~/ in 'filename' to the value of the * HOME environment variable and return the resulting string */ { if (filename[0] == '~' && filename[1] == '/') { exception bad_glob(); if (!Environ::check("HOME")) raise bad_glob(); return Environ::get("HOME") + String::substr(filename, 1, String::length(filename) - 1); } return filename; } string path_first (string path) { int i = String::index (path, ":"); if (i < 0) return glob(path); if (i == 0) return "."; return glob(String::substr (path, 0, i)); } string path_rest (string path) { int i = String::index (path, ":"); if (i < 0) return ""; int l = String::length (path); if (i == l-1) return "."; return String::substr (path, i + 1, l - i - 1); } public bool lex_library (string name) /* * Search 'nickle_path' for the file 'name' and push any * found file into the lexer. Returns whether any * file was found and read. */ { for (string path = nickle_path; path != ""; path = path_rest (path)) { try return lex_file (path_first (path) + "/" + name); catch File::open_error (string name, File::error_type err, string msg) { ; } } return false; } public bool lex_string (string s) /* * Push 's' into the lexer input stack */ { return Command::lex_input (File::string_read (s), s, false, false); } new ("library", lex_library); } # Load the prerequisites for the extra commands. library "ctype.5c"; library "string.5c"; library "file.5c"; library "printf.5c"; # Get abort() in early, even if this means not autoimporting it library "abort.5c"; import Abort; library "history.5c"; # Now load the extra commands. library "parse-args.5c"; library "command.5c"; # Note that some libraries extend namespaces, and # thus aren't autoload/autoimport candidates. library "math.5c"; import Math; library "scanf.5c"; library "socket.5c"; # Now autoload/autoimport the bonus stuff # (But why? Let the users do it.) #autoload Mutex; #autoload ARC4; #autoload PRNG; #autoload Process; # parse the command line extend namespace Command { process_args (&argv); }