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
|
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ ~~ Command-line parameter semantics ~~
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~
~ The Evocation executable runs as a command-line tool. As part of that, it
~ accepts command-line parameters via the POSIX argc/argv interface. The code
~ in this file implements the semantics of those parameters.
~
~ The rule is quite simple: Each parameter is treated as a single word, and
~ run as if by "interpret". When a parameter is neither a regular word nor an
~ integer literal, if it looks like it could be a source code filename, the
~ file it names is read as if by "include", except that the success flag is
~ discarded.
~
~ Nothing special is done to make command-line parameters appear as if
~ they're an input stream; they're not. They're special words that are invoked
~ before standard input is touched. Anything words run as command-line
~ parameters try to do to standard input will draw on standard input as usual,
~ despite that not being where they themselves come from, which will likely
~ cause unwanted behavior. See language/boot-source-footer.e for the exact
~ sequence of events during startup.
~
~ In particular, this means that words such as s" and ', which try to read
~ input, are unlikely to do what you want as command-line parameters.
8 2 * allocate s" argument-scan-state" variable
: argument-scan-state-next-argument-handle ;
: argument-scan-state-n-remaining-arguments 8 + ;
~ (next argument handle, n remaining arguments --)
: save-argument-scan-state
argument-scan-state argument-scan-state-n-remaining-arguments !
argument-scan-state argument-scan-state-next-argument-handle ! ;
~ (-- next argument handle, n remaining arguments)
: restore-argument-scan-state
argument-scan-state argument-scan-state-next-argument-handle @
argument-scan-state argument-scan-state-n-remaining-arguments @ ;
~ This tests whether a string looks like it could be an Evocation
~ source-code filename.
~
~ Specifically, it looks for an extension of *.e. Also, it disallows ".e" by
~ itself as a filename, requiring the length to be at least three characters.
~
~ This comparison is done case-sensitively. This means that, even on a
~ case-insensitive filesystem, from Evocation's perspective we always require
~ the extension to be treated as lowercase.
~
~ (string pointer -- boolean)
: is-possible-source-filename
dup stringlen
~ (string pointer, length)
dup 2 < {
2 - + s" .e" stringcmp 0 =
} {
2drop 0
} if-else ;
~ (argument pointer -- *)
: process-command-line-argument
dup find dup {
~ (argument pointer, entry pointer)
swap drop
interpreter-flags @ 0x01 & {
dup entry-flags@ 1 &
swap entry-to-execution-token swap
{ execute } { , } if-else
} { entry-to-execution-token execute } if-else
} {
drop
~ (argument pointer)
dup read-integer 0 = {
~ (argument pointer, integer value)
interpreter-flags @ 0x01 & {
x' lit , ,
drop
} {
swap drop
} if-else
} {
~ (argument pointer)
dup is-possible-source-filename {
include drop
} {
." No such word: " emitstring newline
} if-else
} if-else
} if-else ;
: process-command-line-arguments
s0 @
dup @
swap 8 +
swap
~ (next argument handle, n remaining arguments)
dup {
~ Skip the executable name.
1- swap 8 + swap
{ dup } {
over @
3unroll save-argument-scan-state
process-command-line-argument
restore-argument-scan-state
1- swap 8 + swap
} while
} if 2drop ;
|