In reading this section, keep in mind that the first line of a script
file has (different) meanings to SCM and the operating system
(execve).
On unix systems, a Shell-Script is a file (with execute
permissions) whose first two characters are `#!'. The
interpreter argument must be the pathname of the program to
process the rest of the file. The directories named by environment
variable PATH are not searched to find interpreter.
The arg is an optional argument encapsulating the rest of the
first line's contents, if not just whitespace.
When executing a shell-script, the operating system invokes interpreter with (if present) arg, the pathname of the shell script file, and then any arguments which the shell-script was invoked with.
#!,
the first line of that file will be ignored.
This combination of interpretatons allows SCM source files to be used as POSIX shell-scripts if the first line is:
#!/usr/local/bin/scm
or
#!/usr/local/bin/scm -l
When such a file is invoked, /usr/local/bin/scm is executed with the name of this file as the first argument.
#!/usr/local/bin/scm
(print (program-arguments))
(quit)
=> ("scm" "./script")
#!/usr/local/bin/scm -l
(print (program-arguments))
=> ("scm" "-l" "./script")
The following shell-script will print factorial of its argument:
#!/usr/local/bin/scm -l (define (fact n) (if (< n 2) 1 (* n (fact (+ -1 n))))) (print (fact (string->number (cadddr (program-arguments)))))
./fact 6 => 720
Shell-scripts suffer from several drawbacks:
#!' interpreter line to the
size of an object file header, which can be as small as 32 bytes.
The following approach solves these problems at the expense of slower
startup. Make `#!/bin/sh' the first line and prepend every
subsequent line to be executed by the shell with :; (type;
in older versions). The last line to be executed by the shell should
contain an exec command; exec tail-calls its argument.
/bin/sh is thus invoked with the name of the script file, which
it executes as a *sh script. Usually the second line starts
`:;exec scm -f$0', which executes scm, which in turn loads the
script file. When SCM loads the script file, it ignores the first and
second lines, and evaluates the rest of the file as Scheme source code.
The second line of the script file does not have the length restriction
mentioned above. Also, /bin/sh searches the directories listed
in the `PATH' environment variable for `scm', eliminating the need
to use absolute locations in order to invoke a program.
#!/bin/sh :;exec scm -l$0 $* (define (fact n) (if (< n 2) 1 (* n (fact (+ -1 n))))) (print (fact (string->number (caddr (program-arguments)))))
./fact 6 => 720