File: builtin.5c

package info (click to toggle)
nickle 2.107
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 3,756 kB
  • sloc: ansic: 27,954; yacc: 1,874; lex: 954; sh: 204; makefile: 13; lisp: 1
file content (139 lines) | stat: -rw-r--r-- 3,166 bytes parent folder | download
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);
}