diff options
Diffstat (limited to 'comparse.scm')
-rw-r--r-- | comparse.scm | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/comparse.scm b/comparse.scm new file mode 100644 index 0000000..add47c8 --- /dev/null +++ b/comparse.scm @@ -0,0 +1,92 @@ +;;; "comparse.scm" Break command line into arguments. +;Copyright (C) 1995 Aubrey Jaffer +; +;Permission to copy this software, to redistribute it, and to use it +;for any purpose is granted, subject to the following restrictions and +;understandings. +; +;1. Any copy made of this software must include this copyright notice +;in full. +; +;2. I have made no warrantee or representation that the operation of +;this software will be error-free, and I am under no obligation to +;provide any services, by way of maintenance, update, or otherwise. +; +;3. In conjunction with products arising from the use of this +;material, there shall be no use of my name in any advertising, +;promotional, or sales literature without prior written consent in +;each case. + +;;;; This is a simple command-line reader. It could be made fancier +;;; to handle lots of `shell' syntaxes. + +(require 'string-port) +(define (read-command . port) + (define argv '()) + (define obj "") + (define chars '()) + (define eof #f) + (define readc (lambda () (read-char port))) + (define peekc (lambda () (peek-char port))) + (define s-expression + (lambda () + (splice-arg (call-with-output-string + (lambda (p) (display (slib:eval (read port)) p)))))) + (define (backslash goto) + (readc) + (cond ((char=? #\newline (peekc)) (readc) (goto (peekc))) + (else (set! chars (cons (readc) chars)) + (build-token (peekc))))) + (define loop + (lambda (c) + (case c + ((#\\) (backslash loop)) + ((#\") (splice-arg (read port))) + ((#\( #\') (s-expression)) + ((#\#) + (do ((c (readc) (readc))) + ((or (eof-object? c) (char=? #\newline c) c)))) + ((#\; #\newline) (readc)) + (else + (cond ((eof-object? c) c) + ((char-whitespace? c) (readc) (loop (peekc))) + (else (build-token c))))))) + (define splice-arg + (lambda (arg) + (set! obj (string-append obj (list->string (reverse chars)) arg)) + (set! chars '()) + (build-token (peekc)))) + (define build-token + (lambda (c) + (case c + ((#\") (splice-arg (read port))) + ((#\() (s-expression)) + ((#\\) (backslash build-token)) + ((#\newline #\;) + (readc) + (set! argv (cons (string-append + obj (list->string (reverse chars))) + argv))) + (else + (cond ((or (eof-object? c) + (char-whitespace? c)) + (readc) + (set! argv (cons (string-append + obj (list->string (reverse chars))) + argv)) + (set! obj "") + (set! chars '()) + (loop (peekc))) + (else (set! chars (cons (readc) chars)) + (build-token (peekc)))))))) + (set! port + (cond ((null? port) (current-input-port)) + ((= 1 (length port)) (car port)) + (else + (slib:error + 'read-command-line + "Wrong Number of ARGs:" + port)))) + (let ((c (loop (peekc)))) + (cond ((and (null? argv) (eof-object? c)) c) + (else (reverse argv))))) |