[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4 Writing Scheme scripts

When a Scheme program file is given to gosh, it bounds a global varialbe *argv* to the list of the remaining command-line arguments, then loads the Scheme program. If the first line of scheme-file begins with two character sequence "#!", the entire line is ignored by gosh. This is useful to write a Scheme program that works as an executable script in unix-like systems.

Typical Gauche script has the first line like these
#!/usr/bin/env gosh
:; exec gosh -- $0 "$@"
The second and third form uses a "shell trampoline" technique so that the script works as far as gosh is in the PATH. The third form is useful when you want to pass extra arguments to gosh, for typically #!-magic of executable scripts has limitations for the number of arguments to pass the interpreter.

After the file is successfully loaded, gosh calls a procedure named `main' if it is defined in the user module. Main receives a single argument, a list of command line arguments. Its first element is the script name itself.

When main returns, and its value is an integer, gosh uses it for exit code of the program. Otherwise, gosh exits with exit code 70 (EX_SOFTWARE). This behavior is compatible with the SRFI-22.

(Note: this interface has been changed from Gauche release 0.5 in incompatible way. See section 3.4.1 Script compatibility before release 0.5, for details.)

If the main procedure is not defined, gosh exits after loading the script file.

Although you can still write the program main body as toplevel expressions, like shell scripts or Perl scripts, it is much convenient to use this `main' convention, for you can load the script file interactively to debug.

Variable: *argv*
The program arguments passed to the Scheme script is bound to this variable. If gosh is invoked in an interactive mode, this variable always contains ().

STk uses this variable to pass the command line argument as well, but other Scheme implementations use different ways. It is better to define main procedure and uses its argument to receive command line arguments, for it is expected to be more portable.

Variable: *program-name*
This variable is bound to the script file name passed to gosh. If gosh is invoked in the interactive mode, this variable contains the pathname of gosh itself.

STk uses the same variable to access the program/script name. Other Scheme implementations use different ways.

Now I show several simple examples below. First, this script works like cat(1), without any command-line option processing and error handling.

#!/usr/bin/env gosh

(define (main args)   ;entry point
  (if (null? (cdr args))
      (copy-port (current-input-port) (current-output-port))
      (for-each (lambda (file)
                  (call-with-input-file file
                    (lambda (in)
                      (copy-port in (current-output-port)))))
                (cdr args)))

The following script is a simple grep command.

#!/usr/bin/env gosh

(define (usage)
  (format (current-error-port)
          "Usage: ~a regexp file ...\n" *program-name*)
  (exit 2))

(define (grep rx port)
  (with-input-from-port port
    (lambda ()
       (lambda (line)
         (when (rxmatch rx line)
           (format #t "~a:~a: ~a\n"
                   (port-name port)
                   (- (port-current-line port) 1)

(define (main args)
  (if (null? (cdr args))
      (let ((rx (string->regexp (cadr args))))
        (if (null? (cddr args))
            (grep rx (current-input-port))
            (for-each (lambda (f)
                        (call-with-input-file f
                          (lambda (p) (grep rx p))))
                      (cddr args)))))

See also 9.13 gauche.parseopt - Parsing command-line options, for a convenient way to parse command-line options.

3.4.1 Script compatibility before release 0.5  

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

This document was generated by Ken Dickey on November, 28 2002 using texi2html