;"chez.init" Initialization file for SLIB for Chez Scheme 5.0c -*-scheme-*- ; Copyright (C) 1993 dorai@cs.rice.edu (Dorai Sitaram) ; Copyright (C) 1991, 1992, 1993, 1994, 1997 Aubrey Jaffer. ; Adapted to version 5.0c by stone@math.grin.edu (John David Stone) 1997 ; ;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. ;; The SOFTWARE-TYPE procedure returns a symbol indicating the generic ;; operating system type. UNIX, VMS, MACOS, AMIGA and MS-DOS are ;; supported. (define software-type (lambda () 'unix)) ;; The SCHEME-IMPLEMENTATION-TYPE procedure returns a symbol denoting the ;; Scheme implementation that loads this file. (define scheme-implementation-type (lambda () 'chez)) ;; The SCHEME-IMPLEMENTATION-VERSION procedure returns a string describing ;; the version of the Scheme implementation that loads this file. (define scheme-implementation-version (lambda () "5.0c")) ;; The IMPLEMENTATION-VICINITY procedure returns a string giving the ;; pathname of the directory that includes any auxiliary files used by this ;; Scheme implementation. (define implementation-vicinity (lambda () "/usr/local/chez/5.0c/")) ;; The GETENV returns the value of a shell environment variable. ;; In some implementations of Chez Scheme, this can be done with foreign ;; procedures. However, I [JDS] am using the HP version, which does not ;; support them, so a different approach is needed. ;; ;; Here's the version that doesn't work on HPs: ;; ;; (provide-foreign-entries '("getenv")) ;; ;; (define getenv ;; (foreign-procedure "getenv" ;; (string) string)) ;; ;; And here's a version that parses the value out of the output of the ;; /bin/env command: (define getenv (lambda (env-var) (let ((env-port (car (process "exec /bin/env"))) (read-line (lambda (source) (let ((next (peek-char source))) (if (eof-object? next) next (let loop ((ch (read-char source)) (so-far '())) (if (or (eof-object? ch) (char=? ch #\newline)) (apply string (reverse so-far)) (loop (read-char source) (cons ch so-far)))))))) (position-of-copula (lambda (str) (let ((len (string-length str))) (do ((position 0 (+ position 1))) ((or (= position len) (char=? (string-ref str position) #\=)) position)))))) (let loop ((equation (read-line env-port))) (if (eof-object? equation) #f (let ((break (position-of-copula equation)) (len (string-length equation))) (if (string=? (substring equation 0 break) env-var) (if (= break len) "" (substring equation (+ break 1) len)) (loop (read-line env-port))))))))) ;; The LIBRARY-VICINITY procedure returns the pathname of the directory ;; where Scheme library functions reside. (define library-vicinity (let ((library-path (or (getenv "SCHEME_LIBRARY_PATH") "/usr/local/lib/slib/"))) (lambda () library-path))) ;;; (home-vicinity) should return the vicinity of the user's HOME ;;; directory, the directory which typically contains files which ;;; customize a computer environment for a user. (define home-vicinity (let ((home-path (getenv "HOME"))) (lambda () home-path))) ;; The OUTPUT-PORT-WIDTH procedure returns the number of graphic characters ;; that can reliably be displayed on one line of the standard output port. (define output-port-width (lambda arg (let ((env-width-string (getenv "COLUMNS"))) (if (and env-width-string (let loop ((remaining (string-length env-width-string))) (or (zero? remaining) (let ((next (- remaining 1))) (and (char-numeric? (string-ref env-width-string next)) (loop next)))))) (- (string->number env-width-string) 1) 79)))) ;; The OUTPUT-PORT-HEIGHT procedure returns the number of lines of text ;; that can reliably be displayed simultaneously in the standard output ;; port. (define output-port-height (lambda arg (let ((env-height-string (getenv "LINES"))) (if (and env-height-string (let loop ((remaining (string-length env-height-string))) (or (zero? remaining) (let ((next (- remaining 1))) (and (char-numeric? (string-ref env-height-string next)) (loop next)))))) (string->number env-height-string) 24)))) ;; *FEATURES* is a list of symbols describing features of this ;; implementation; SLIB procedures sometimes consult this list to figure ;; out whether to attempt some incompletely standard operation. (define *features* '(source ; Chez Scheme can load Scheme source files, with the ; command (slib:load-source "filename") -- see below. compiled ; Chez Scheme can also load compiled Scheme files, with the ; command (slib:load-compiled "filename") -- see below. char-ready? delay dynamic-wind eval fluid-let format full-continuation getenv ieee-p1178 macro multiarg/and- multiarg-apply pretty-print random random-inexact rationalize rev3-procedures rev3-report rev4-optional-procedures rev4-report sort string-port system transcript values with-file)) ;; Version 5.0c has R4RS macros, but not defmacro. (define *defmacros* (list (cons 'defmacro (lambda (name parms . body) `(set! *defmacros* (cons (cons ',name (lambda ,parms ,@body)) *defmacros*)))))) (define (defmacro? m) (and (assq m *defmacros*) #t)) (define (macroexpand-1 e) (if (pair? e) (let ((a (car e))) (cond ((symbol? a) (set! a (assq a *defmacros*)) (if a (apply (cdr a) (cdr e)) e)) (else e))) e)) (define (macroexpand e) (if (pair? e) (let ((a (car e))) (cond ((symbol? a) (set! a (assq a *defmacros*)) (if a (macroexpand (apply (cdr a) (cdr e))) e)) (else e))) e)) (define base:eval eval) (define (defmacro:eval x) (base:eval (defmacro:expand* x))) (define (defmacro:expand* x) (require 'defmacroexpand) (apply defmacro:expand* x '())) ;; Chez's sorting routines take parameters in the order opposite to SLIB's. ;; The following definitions override the predefined procedures with the ;; parameters-reversed versions. (define chez:sort sort) (define chez:sort! sort!) (define chez:merge merge) (define chez:merge! merge!) (define sort (lambda (s p) (chez:sort p s))) (define sort! (lambda (s p) (chez:sort! p s))) (define merge (lambda (s1 s2 p) (chez:merge p s1 s2))) (define merge! (lambda (s1 s2 p) (chez:merge! p s1 s2))) ;; Chez's (FORMAT F . A) corresponds to SLIB's (FORMAT #F F . A) (define chez:format format) (define format (lambda (where how . args) (let ((str (apply chez:format how args))) (cond ((not where) str) ((eq? where #t) (display str)) (else (display str where)))))) ;; Chez's NIL variable is bound to '(); SLIB's is bound to #F. (define nil #f) ;; SLIB provides identifiers for the TAB (ASCII 9) and FORM-FEED (ASCII 12) ;; characters. (define slib:tab #\tab) (define slib:form-feed #\page) ;; The following definitions implement a few widely useful procedures that ;; Chez Scheme does not provide or provides under a different name. ;; The RENAME-FILE procedure constructs and executes a Unix mv command to ;; change the name of a file. (define rename-file (lambda (src dst) (system (string-append "mv " src " " dst)))) ;; The CURRENT-ERROR-PORT procedure returns a port to which error ;; messages are to be displayed; this is the original standard output ;; port (even if the program subsequently changes the current output port ;; somehow). (define current-error-port (let ((port (current-output-port))) (lambda () port))) ;; SLIB provides its own version of the ERROR procedure. (define slib:error (lambda args (let ((port (current-error-port))) (display "Error: " port) (for-each (lambda (x) (display x port)) args) (error #f "")))) ;; The TMPNAM procedure constructs and returns a temporary file name, ;; presumably unique and not a duplicate of one already existing. (define tmpnam (let ((cntr 100)) (lambda () (set! cntr (+ 1 cntr)) (let ((tmp (string-append "slib_" (number->string cntr)))) (if (file-exists? tmp) (tmpnam) tmp))))) ;; The FORCE-OUTPUT requires buffered output that has been written to a ;; port to be transferred all the way out to its ultimate destination. (define force-output flush-output) ;; CALL-WITH-INPUT-STRING and CALL-WITH-OUTPUT-STRING are the string ;; port versions of CALL-WITH-INPUT-FILE and CALL-WITH-OUTPUT-FILE. (define call-with-output-string (lambda (f) (let ((outsp (open-output-string))) (f outsp) (let ((s (get-output-string outsp))) (close-output-port outsp) s)))) (define call-with-input-string (lambda (s f) (let* ((insp (open-input-string s)) (res (f insp))) (close-input-port insp) res))) ;; CHAR-CODE-LIMIT is the number of characters in the character set; only ;; non-negative integers less than CHAR-CODE-LIMIT are eligible as ;; arguments to INTEGER->CHAR. (define char-code-limit 256) ;; Chez's MOST-POSITIVE-FIXNUM is a thunk rather than a number. (if (procedure? most-positive-fixnum) (set! most-positive-fixnum (most-positive-fixnum))) ;; The IDENTITY procedure returns its argument without change. (define identity (lambda (x) x)) ;; The GENTEMP procedure generates unused symbols and marks them as ;; belonging to the SLIB package. (define gentemp (let ((*gensym-counter* -1)) (lambda () (set! *gensym-counter* (+ *gensym-counter* 1)) (string->symbol (string-append "slib:G" (number->string *gensym-counter*)))))) ;; The IN-VICINITY procedure is simply STRING-APPEND, conventionally used ;; to attach a directory pathname to the name of a file that is expected to ;; be in that directory. (define in-vicinity string-append) ;; For backward compatability, the SCHEME-FILE-SUFFIX procedure is defined ;; to return the string ".scm". Note, however, that ".ss" is a common Chez ;; file suffix. (define scheme-file-suffix (lambda () ".scm")) ;; SLIB appropriates Chez Scheme's EVAL procedure. (define slib:eval eval) (define macro:eval slib:eval) (define slib:eval-load (lambda ( evl) (if (not (file-exists? )) (set! (string-append (scheme-file-suffix)))) (call-with-input-file (lambda (port) (let ((old-load-pathname *load-pathname*)) (set! *load-pathname* ) (do ((o (read port) (read port))) ((eof-object? o)) (evl o)) (set! *load-pathname* old-load-pathname)))))) ;; SLIB:EXIT is the implementation procedure that exits, or returns ;; if exiting is not supported. (define slib:chez:quit (let ((arg (call-with-current-continuation identity))) (cond ((procedure? arg) arg) (arg (exit)) (else (exit 1))))) (define slib:exit (lambda args (cond ((null? args) (slib:chez:quit #t)) ((eqv? #t (car args)) (slib:chez:quit #t)) ((eqv? #f (car args)) (slib:chez:quit #f)) ((zero? (car args)) (slib:chez:quit #t)) (else (slib:chez:quit #f))))) ;; The SLIB:LOAD-SOURCE procedure, given a string argument, should attach ;; the appropriate file suffix to the string and load the file named ;; by the resulting string. (define slib:load-source (lambda (f) (load (string-append f (scheme-file-suffix))))) ;;; defmacro:load and macro:load also need the default suffix. (define macro:load slib:load-source) ;; The SLIB:LOAD-COMPILED procedure, given a string argument, finds and ;; loads the file, assumed to have been compiled. (define slib:load-compiled load) ;; SLIB:LOAD can now be defined to load SLIB files. (define slib:load slib:load-source) ;; Load the REQUIRE package. (slib:load (in-vicinity (library-vicinity) "require")) ;; end of chez.init