1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
# 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";
library "prime_sieve.5c"
library "factorial.5c"
library "gamma.5c"
library "math-ext.5c"
import Math;
library "scanf.5c";
library "socket.5c";
library "complex.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);
}
|