Path: utzoo!attcan!uunet!lll-winken!lll-lcc!ames!husc6!rice!titan!dorai From: dorai@titan.rice.edu (Dorai Sitaram) Newsgroups: comp.lang.scheme Subject: Scheme shellscripts Summary: How to survive without knowing the shell programming language. Keywords: Ch*z Scheme, Un*x commands, cshell, shellscripts Message-ID: <1666@kalliope.rice.edu> Date: 16 Jul 88 08:01:32 GMT Sender: usenet@rice.edu Reply-To: dorai@titan.rice.edu (Dorai Sitaram) Organization: Rice University, Houston Lines: 79 Hi! Thought this might be of interest. If you've tried using shellscripts to build your own Un*x commands, felt the shell language a bit too hairy, and would rather use Scheme instead, here's a short fix. This assumes that the available Scheme interpiler can be called at the Un*x prompt with a file-name which is automatically loaded before producing the interactive loop. E.g., Chez Scheme (copyright R. Kent Dybvig). A shellscript written in Scheme is like any other Scheme file, except that its first line has to be: runschemescript "$*" ' and its last line: ' The quotes are used to delimit the Scheme code which forms the body of the script. The script consists of a call of the Un*x command `runschemescript' with two arguments, the first being the list of arguments to the Scheme script, and the second the text of the Scheme code in the script. Thus, a Scheme shellscript is a *true* schellscript, i.e., it is callable at the Un*x command-line, though the main part of it is a piece of text which is Scheme. The command `runschemescript' used above is a shellscript written in the usual shell language. It is the following relatively simple piece of cshell: ************************************************************************** echo > .tmpfile '(set! $* (quote (' $1 ')))' echo >>.tmpfile $2 echo >>.tmpfile '(exit)' scheme .tmpfile ************************************************************************** In effect, `runschemescript' creates a temp Scheme file which sets a global variable $* to the list of arguments supplied to the Scheme script, runs the script which uses $* to refer to its arguments and exits. This file is then run with the Scheme interpiler. An example Scheme shellscript is the Scheme compiler `sc' which can be invoked at the Un*x command-line, in makefiles, etc [like `cc']. My `sc' looks like ******************************************************************************* runschemescript "$*" ' (case (length $*) [1 (compile-file (symbol->string (car $*)))] [2 (compile-file (symbol->string (car $*)) (symbol->string (cadr $*)))] [3 (let ([$1 (car $*)] [$2 (cadr $*)] [$3 (caddr $*)]) (cond [(eq? $1 `-o) (compile-file (symbol->string $3) (symbol->string $2))] [(eq? $2 `-o) (compile-file (symbol->string $1) (symbol->string $3))] [else (printf "Bad args to sc: ~a~n" $*)]))] [else (printf "Bad args to sc: ~a~n" $*)]) ' ****************************************************************************** $* being a simple Scheme list of symbols, any processing of arguments or options is straightforward. Some nits are: These Scheme shellscripts always have to be enclosed in runschemescript "$*" ' '. The quote- character ' {a common enough character in Scheme!} cannot be used in the script's body as it interferes with the shell's delimiter characters--instead one should use the backquote ` or "quote". Typical shellscripts use other Un*x commands in their bodies: in Ch*z Scheme, there is a function "system" which enables us to call Un*x commands; but this may not be available in other Schemes. Even in this case, calling a Scheme shellscript from within a Scheme shellscript will have multiple invocations of the Scheme interpreter running simultaneously, which doesn't help a whole lot in maintaining efficiency. Strangely, one doesn't have to bother about the same file .tmpfile being used for such nesting--once the file is loaded, it doesn't matter if it is used for something else. On the whole, I've found that in a Un*x environment which supports Ch*z Scheme, the above technique beats writing shellscripts in cshell for sheer ease and maneuvrability. One can then, if one chooses, convert a fully debugged Scheme script to a cshell script (or a C program) to recover efficiency. If anyone can suggest further improvement I'll be glad to hear of it. --dorai