scm [-a kbytes] [-muvbiq] [--version] [--help] [[-]-no-init-file] [--no-symbol-case-fold] [-p int] [-r feature] [-h feature] [-d filename] [-f filename] [-l filename] [-c expression] [-e expression] [-o dumpname] [-- | - | -s] [filename] [arguments ...]
Upon startup scm loads the file specified by by the environment
variable SCM_INIT_PATH.
If SCM_INIT_PATH is not defined or if the file it names is not
present, scm tries to find the directory containing the
executable file. If it is able to locate the executable, scm
looks for the initialization file (usually
`Init5e5.scm') in platform-dependent directories
relative to this directory. See section File-System Habitat for a
blow-by-blow description.
As a last resort (if initialization file cannot be located), the C compile parameter IMPLINIT (defined in the makefile or `scmfig.h') is tried.
Unless the option -no-init-file or --no-init-file occurs
in the command line, or if scm is being invoked as a script,
`Init5e5.scm' checks to see if there is file
`ScmInit.scm' in the path specified by the environment variable
HOME (or in the current directory if HOME is undefined).
If it finds such a file, then it is loaded.
`Init5e5.scm' then looks for command input from one of three sources: From an option on the command line, from a file named on the command line, or from standard input.
This explanation applies to SCMLIT or other builds of SCM.
Scheme-code files can also invoke SCM and its variants. See section Lexical Conventions.
The options are processed in the order specified on the command line.
scm should allocate an initial heapsize of k
kilobytes. This option, if present, must be the first on the command
line. If not specified, the default is INIT_HEAP_SIZE in source
file `setjump.h' which the distribution sets at
25000*sizeof(cell).
scm
will require the features neccessary to support [R2RS]; [R3RS];
[R4RS]; or [R5RS], respectively.
Scm will load the first (unoptioned)
file named on the command line if no -c, -e, -f,
-l, or -s option preceeds it.
databases feature and opens filename as a
database.
perl and sh
respectively. On Amiga systems the entire option and argument need to be
enclosed in quotes. For instance `"-e(newline)"'.
dump
(see section Dump).
If options appear on the command line after `-o dumpname', then the saved session will continue with processing those options when it is invoked. Otherwise the (new) command line is processed as usual when the saved image is invoked.
scm command (verobse level).
scm will print prompts, evaluation
times, notice of loading files, and garbage collection statistics. This
is the same as -p3.
scm will print no extra
information. This is the same as -p0.
-r macropackage before -m on the command line.
-m on the command line or from
Scheme code.
scm should run interactively. That means that
scm will not terminate until the (quit) or (exit)
command is given, even if there are errors. It also sets the prolixity
level to 2 if it is less than 2. This will print prompts, evaluation
times, and notice of loading files. The prolixity level can be set by
subsequent options. If scm is started from a tty, it will assume
that it should be interactive unless given a subsequent -b
option.
scm should run non-interactively. That means that
scm will terminate after processing the command line or if there
are errors.
sh, that scm should run
interactively and that further options are to be treated as program
aguments.
% scm foo.scm
% scm -f foo.scm arg1 arg2 arg3
arg1, arg2, and arg3 are stored in the
global list *argv*; Loads and executes the contents of
`foo.scm' and exits.
% scm -s foo.scm arg1 arg2
("foo.scm" "arg1" "arg2") and enters interactive
session.
% scm -e `(write (list-ref *argv* *optind*))' bar
% scm -rpretty-print -r format -i
pretty-print and format and enters interactive
session.
% scm -r5
dynamic-wind, values, and syntax-rules macros and
enters interactive (with macros) session.
% scm -r5 -r4
rev4-optional-procedures are also loaded.
scm will look for its initialization
code. The default is the file `Init5e5.scm' in the
source directory.
ed will call. If EDITOR
is not defined, the default is `ed'.
*argv* can change
during argument processing. This list is suitable for use as an argument
to [SLIB] getopt.
-m and
-u options.
-i and -b
options. Define this in `ScmInit.scm' or files specified on the
command line. This can be overridden by subsequent -i and
-b options.
exit (see section `System' in SLIB). On many
systems, SCM can also tail-call another program.
See section I/O-Extensions.
boot-tail is called by scm_top_level just before entering
interactive top-level. If boot-tail calls quit, then
interactive top-level is not entered.
For documentation of the procedures getenv and system
See section `System Interface' in SLIB.
vms-debug will invoke the VMS
debugger.
EDITOR (or just ed
if it isn't defined) is invoked as a command with arguments arg1
....
ed will invoke the editor with a
single the single argument filename.
(ed arg1 ...)
will invoke your editor and return to SCM when you exit the editor. The
following definition is convenient:
(define (e) (ed "work.scm") (load "work.scm"))Typing `(e)' will invoke the editor with the file of interest. After editing, the modified file will be loaded.
The cautious option of build
(see section Build Options) supports debugging in Scheme.
error and
user-interrupt (invoked by C-c) to print stack traces and
conclude by calling breakpoint
(see section `Breakpoints' in SLIB) instead of aborting to top
level. Under either condition, program execution can be resumed by
(continue).
In this configuration one can interrupt a running Scheme program with
C-c, inspect or modify top-level values, trace or untrace
procedures, and continue execution with (continue).
If verbose (see section Internal State) is called with an
argument greater than 2, then the interpreter will check stack size
periodically. If the size of stack in use exceeds the C #define
STACK_LIMIT (default is HEAP_SEG_SIZE), SCM generates a
`stack' segment violation.
There are several SLIB macros which so useful that SCM automatically loads the appropriate module from SLIB if they are invoked.
The routines I use most frequently for debugging are:
Print writes all its arguments, separated by spaces.
Print outputs a newline at the end and returns the value
of the last argument.
One can just insert `(print '<label>' and `)' around an expression in order to see its values as a program operates.
Pprint pretty-prints (see section `Pretty-Print' in SLIB) all
its arguments, separated by newlines. Pprint returns the value
of the last argument.
One can just insert `(pprint '<label>' and `)' around an
expression in order to see its values as a program operates.
Note pretty-print does not format procedures.
When typing at top level, pprint is not a good way to see
nested structure because it will return the last object
pretty-printed, which could be large. pp is a better choice.
Pprint pretty-prints (see section `Pretty-Print' in SLIB) all
its arguments, separated by newlines. pp returns
#<unspecified>.
Print-args.
(define (foo a b) (print-args foo) (+ a b)) (foo 3 6) -| In foo: a = 3; b = 6; => 9
Sometimes more elaborate measures are needed to print values in a useful manner. When the values to be printed may have very large (or infinite) external representations, section `Quick Print' in SLIB, can be used.
When trace is not sufficient to find program flow problems,
SLIB-PSD, the Portable Scheme Debugger
offers source code debugging from
GNU Emacs. PSD runs slowly, so start by instrumenting only a few
functions at a time.
http://swiss.csail.mit.edu/ftpdir/scm/slib-psd1-3.tar.gz swiss.csail.mit.edu:/pub/scm/slib-psd1-3.tar.gz ftp.maths.tcd.ie:pub/bosullvn/jacal/slib-psd1-3.tar.gz ftp.cs.indiana.edu:/pub/scheme-repository/utl/slib-psd1-3.tar.gz
These functions are defined in `debug.c', all operate on captured continuations:
section Errors also now accepts an optional continuation
argument. stack-trace differs from frame-trace in that
it truncates long output using safeports and prints code from all
available frames.
(define k #f) (define (foo x y) (set! k (call-with-current-continuation identity)) #f) (let ((a 3) (b 4)) (foo a b) #f) (stack-trace k) -| ;STACK TRACE 1; ((#@set! #@k (#@call-with-current-continuation #@identity)) #f ... 2; (#@let ((a 3) (b 4)) (#@foo #@a #@b) #f) ... #t
(frame-trace k 0) -| (#@call-with-current-continuation #@identity) ; in scope: ; (x y) procedure foo#<unspecified>
(frame-trace k 1) -| ((#@set! #@k (#@call-with-current-continuation #@identity)) #f) ; in scope: ; (x y) procedure foo#<unspecified>
(frame-trace k 2) -| (#@let ((a 3) (b 4)) (#@foo #@a #@b) #f) ; in scope: ; (a b . #@let)#<unspecified>
(frame-trace k 3) -| (#@let ((a 3) (b 4)) (#@foo #@a #@b) #f) ; in top level environment.
(frame->environment k 0) -| ((x y) 2 foo)
(scope-trace (frame->environment k 0)) -| ; in scope: ; (x y) procedure foo#<unspecified>
(frame-eval k 0 'x) => 3 (frame-eval k 0 '(set! x 8)) (frame-eval k 0 'x) => 8
A computer-language implementation designer faces choices of how reflexive to make the implementation in handling exceptions and errors; that is, how much of the error and exception routines should be written in the language itself. The design of a portable implementation is further constrained by the need to have (almost) all errors print meaningful messages, even when the implementation itself is not functioning correctly. Therefore, SCM implements much of its error response code in C.
The following common error and conditions are handled by C code. Those with callback names after them can also be handled by Scheme code (see section Interrupts). If the callback identifier is not defined at top level, the default error handler (C code) is invoked. There are many other error messages which are not treated specially.
(out-of-storage)
(thrashing)
(end-of-program)
(hang-up)
(user-interrupt)
(arithmetic-error)
(alarm-interrupt)
(virtual-alarm-interrupt)
(profile-alarm-interrupt)
error does
not set errobj.
errno and perror report ANSI C errors encountered during a
call to a system or library function.
errno. When given an argument, errno sets the system
variable errno to n and returns the previous value of
errno. (errno 0) will clear outstanding errors. This is
recommended after try-load returns #f since this occurs
when the file could not be opened.
errno and a newline. The value returned is unspecified.
warn and error provide a uniform way for Scheme code to
signal warnings and errors.
warn is defined in
`Init5e5.scm'.
Error is defined
in `Init5e5.scm'.
If SCM is built with the `CAUTIOUS' flag, then when an error occurs, a stack trace of certain pending calls are printed as part of the default error response. A (memoized) expression and newline are printed for each partially evaluated combination whose procedure is not builtin. See section Memoized Expressions for how to read memoized expressions.
Also as the result of the `CAUTIOUS' flag, both error and
user-interrupt (invoked by C-c) are defined to print stack
traces and conclude by calling breakpoint
(see section `Breakpoints' in SLIB). This allows the user to
interract with SCM as with Lisp systems.
stack-trace returns #t if any lines were
printed and #f otherwise. See `Init5e5.scm'
for an example of the use of stack-trace.
SCM memoizes the address of each occurence of an identifier's value when first encountering it in a source expression. Subsequent executions of that memoized expression is faster because the memoized reference encodes where in the top-level or local environment its value is.
When procedures are displayed, the memoized locations appear in a format different from references which have not yet been executed. I find this a convenient aid to locating bugs and untested expressions.
For instance, open-input-file is defined as follows in
`Init5e5.scm':
(define (open-input-file str)
(or (open-file str open_read)
(and (procedure? could-not-open) (could-not-open) #f)
(error "OPEN-INPUT-FILE couldn't open file " str)))
If open-input-file has not yet been used, the displayed procedure
is similar to the original definition (lines wrapped for readability):
open-input-file => #<CLOSURE (str) (or (open-file str open_read) (and (procedure? could-not-open) (could-not-open) #f) (error "OPEN-INPUT-FILE couldn't open file " str))>
If we open a file using open-input-file, the sections of code
used become memoized:
(open-input-file "r4rstest.scm") => #<input-port 3> open-input-file => #<CLOSURE (str) (#@or (#@open-file #@0+0 #@open_read) (and (procedure? could-not-open) (could-not-open) #f) (error "OPEN-INPUT-FILE couldn't open file " str))>
If we cause open-input-file to execute other sections of code,
they too become memoized:
(open-input-file "foo.scm") => ERROR: No such file or directory ERROR: OPEN-INPUT-FILE couldn't open file "foo.scm" open-input-file => #<CLOSURE (str) (#@or (#@open-file #@0+0 #@open_read) (#@and (#@procedure? #@could-not-open) (could-not-open) #f) (#@error "OPEN-INPUT-FILE couldn't open file " #@0+0))>
Note When running a saved executable (see section Dump),
restart is redefined to be exec-self.
exec-self from restart.
(room #t)
also gives the hexadecimal heap segment and stack bounds.
In order to dump a saved executable or to dynamically-link using DLD,
SCM must know where its executable file is. Sometimes SCM
(see section Executable Pathname) guesses incorrectly the location of the
currently running executable. In that case, the correct path can be set
by calling execpath with the pathname.
#f or newpath, respectively. The old path
is returned.
For other configuration constants and procedures See section `Configuration' in SLIB.
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.
When executing a shell-script, the operating system invokes interpreter with a single argument encapsulating the rest of the first line's contents (if not just whitespace), the pathname of the Scheme Script file, and then any arguments which the shell-script was invoked with.
Put one space character between `#!' and the first character of interpreter (`/'). The interpreter name is followed by ` \'; SCM substitutes the second line of file for `\' (and the rest of the line), then appends any arguments given on the command line invoking this Scheme-Script.
When SCM executes the script, the Scheme variable *script* will be set to the script pathname. The last argument before `!#' on the second line should be `-'; SCM will load the script file, preserve the unprocessed arguments, and set *argv* to a list of the script pathname and the unprocessed arguments.
Note that the interpreter, not the operating system, provides the `\' substitution; this will only take place if interpreter is a SCM or SCSH interpreter.
#! and
a `\' is present before a newline in the file, all characters up
to `!#' will be ignored by SCM read.
This combination of interpretatons allows SCM source files to be used as POSIX shell-scripts if the first line is:
#! /usr/local/bin/scm \
The following Scheme-Script prints factorial of its argument:
#! /usr/local/bin/scm \ %0 %*
- !#
(define (fact.script args)
(cond ((and (= 1 (length args))
(string->number (car args)))
=> (lambda (n) (print (fact n)) #t))
(else (fact.usage))))
(define (fact.usage)
(print *argv*)
(display "\
Usage: fact N
Returns the factorial of N.
"
(current-error-port))
#f)
(define (fact n) (if (< n 2) 1 (* n (fact (+ -1 n)))))
(if *script* (exit (fact.script (list-tail *argv* *optind*))))
./fact 32 => 263130836933693530167218012160000000
If the wrong number of arguments is given, fact prints its
argv with usage information.
./fact 3 2
-|
("./fact" "3" "2")
Usage: fact N
Returns the factorial of N.
It turns out that we can create scheme-scripts which run both under unix
and MS-DOS. To implement this, I have written the MS-DOS programs:
#!.bat and !#.exe,
which are available from:
http://swiss.csail.mit.edu/ftpdir/scm/sharpbang.zip
With these two programs installed in a PATH directory, we have
the following syntax for <program>.BAT files.
The first two characters of the Scheme-Script are `#!'. The interpreter can be either a unix style program path (using `/' between filename components) or a DOS program name or path. The rest of the first line of the Scheme-Script should be literally `\ %0 %*', as shown.
If interpreter has `/' in it, interpreter is converted to a DOS style filename (`/' => `\').
In looking for an executable named interpreter, #! first
checks this (converted) filename; if interpreter doesn't exist, it
then tries to find a program named like the string starting after the
last `\' (or `/') in interpreter. When searching for
executables, #! tries all directories named by environment
variable PATH.
Once the interpreter executable path is found, arguments are
processed in the manner of scheme-shell, with all the text after the
`\' taken as part of the meta-argument. More precisely, #!
calls interpreter with any options on the second line of the
Scheme-Script up to `!#', the name of the Scheme-Script file, and
then any of at most 8 arguments given on the command line invoking this
Scheme-Script.
The previous example Scheme-Script works in both MS-DOS and unix systems.
Scheme-scripts suffer from two drawbacks:
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 :;. 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.
The following example additionally sets *script* to the script argument, making it compatible with the scheme code of the previous example.
#! /bin/sh
:;exec scm -e"(set! *script* \"$0\")" -l$0 "$@"
(define (fact.script args)
(cond ((and (= 1 (length args))
(string->number (car args)))
=> (lambda (n) (print (fact n)) #t))
(else (fact.usage))))
(define (fact.usage)
(print *argv*)
(display "\
Usage: fact N
Returns the factorial of N.
"
(current-error-port))
#f)
(define (fact n) (if (< n 2) 1 (* n (fact (+ -1 n)))))
(if *script* (exit (fact.script (list-tail *argv* *optind*))))
./fact 6 => 720
Words changed since last version are marked in red by HITCH.