~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ ~~ 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 ;