aboutsummaryrefslogtreecommitdiff
path: root/src/interp/unlisp.lisp
diff options
context:
space:
mode:
authordos-reis <gdr@axiomatics.org>2007-10-13 13:02:58 +0000
committerdos-reis <gdr@axiomatics.org>2007-10-13 13:02:58 +0000
commitc4d8dec2eec9c0eb7ae6639ecc0dd607a97b37b7 (patch)
treef8e046150d52c9133457315ad75948d303885160 /src/interp/unlisp.lisp
parent154daf2e85eaa209486de6d41e8a1b067590bb8e (diff)
downloadopen-axiom-c4d8dec2eec9c0eb7ae6639ecc0dd607a97b37b7.tar.gz
Remove more pamphlets
Diffstat (limited to 'src/interp/unlisp.lisp')
-rw-r--r--src/interp/unlisp.lisp1106
1 files changed, 1106 insertions, 0 deletions
diff --git a/src/interp/unlisp.lisp b/src/interp/unlisp.lisp
new file mode 100644
index 00000000..01e722de
--- /dev/null
+++ b/src/interp/unlisp.lisp
@@ -0,0 +1,1106 @@
+;; Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+;; All rights reserved.
+;; Copyright (C) 2007, Gabriel Dos Reis.
+;; All rights reserved.
+;;
+;; Redistribution and use in source and binary forms, with or without
+;; modification, are permitted provided that the following conditions are
+;; met:
+;;
+;; - Redistributions of source code must retain the above copyright
+;; notice, this list of conditions and the following disclaimer.
+;;
+;; - Redistributions in binary form must reproduce the above copyright
+;; notice, this list of conditions and the following disclaimer in
+;; the documentation and/or other materials provided with the
+;; distribution.
+;;
+;; - Neither the name of The Numerical ALgorithms Group Ltd. nor the
+;; names of its contributors may be used to endorse or promote products
+;; derived from this software without specific prior written permission.
+;;
+;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+;; IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+;; TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+;; PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+;; OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+;; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+;; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+;; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+;; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+;; Uncommon 1.6
+;; This package is a Boot interface for Common Lisp.
+;; SMW 1989, 1990
+
+;; Operating system interface
+
+;; The only non-common lisp functions used in this file are in this section.
+;; The following functions are provided:
+
+;; OsRunProgram program &rest args
+;; Run the named program with given arguments.
+;; All I/O is to the current places.
+;; Value returned is implementation-dependent.
+
+;; OsRunProgramToStream program &rest args
+;; Run the named program with given arguments.
+;; Input and error output to the current places.
+;; Value returned is a stream of the program's standard output.
+
+;; OsEnvVarCharacter
+;; The character which indicates OS environment variables in a string.
+;; On Unix this is "$".
+
+;; OsEnvGet name
+;; name is a string or a symbol
+;; The string associated with the given name is returned.
+;; This is from the environment on Unix. On CMS globalvars could be used.
+
+;; OsProcessNumber
+;; Returns a unique number associated with the current session.
+;; On Unix this is the process id.
+;; The same workspace started a second time must give a different result.
+
+
+
+(IMPORT-MODULE "sys-macros")
+(in-package "BOOT")
+
+(defun |OsRunProgram| (program &rest args)
+ #+(and :Lucid (not :ibm/370)) (lucid-os-run-program program args)
+ #+:CmuLisp (cmulisp-os-run-program program args)
+ #+:KCL (kcl-os-run-program program args)
+ #-(or (and :Lucid (not :ibm/370)) :CmuLisp :KCL) nil )
+
+(defun |OsRunProgramToStream| (program &rest args)
+ #+(and :Lcid (not ibm/370))
+ (lucid-os-run-program-to-stream program args)
+ #+:CmuLisp (cmulisp-os-run-program-to-stream program args)
+ #+:KCL (kcl-os-run-program-to-stream program args)
+ #-(or (and :Lucid (not :ibm/370)) :CmuLisp :KCL)
+ (make-string-output-stream "") )
+
+;Unix:
+(defvar |OsEnvVarCharacter| #\$)
+
+(defun |OsEnvGet| (sym)
+ #+(and :Lucid (not :ibm/370)) (lucid-os-env-get sym)
+ #+:CmuLisp (cmulisp-os-env-get sym)
+ #+:KCL (kcl-os-env-get sym)
+ #-(or (and :Lucid (not :ibm/370)) :CmuLisp :KCL) "" )
+
+(defun |OsProcessNumber| ()
+ #+(and :Lucid (not :ibm/370)) (lucid-os-process-number)
+ #+:CmuLisp (cmulisp-os-process-number)
+ #+:KCL (kcl-os-process-number)
+ #-(or (and :Lucid (not :ibm/370)) :CmuLisp :KCL) 42 )
+
+;;;
+;;; Lucid-only implementations
+;;;
+
+#+(and :Lucid (not :ibm/370)) (progn
+(defun lucid-os-run-program (program args)
+ (system:run-aix-program program :arguments args))
+
+(defun lucid-os-run-program-to-stream (program args)
+ (system:run-aix-program program
+ :wait nil
+ :output :stream
+ :arguments args))
+
+(defun lucid-os-env-get (sym)
+ (c-to-lisp-string (getenv (string sym))) )
+
+(defun lucid-os-process-number ()
+ (getpid))
+
+(system:define-foreign-function :c 'getenv :pointer)
+(system:define-foreign-function :c 'sprintf :pointer)
+(system:define-foreign-function :c 'strlen :fixnum)
+(system:define-foreign-function :c 'getpid :fixnum)
+
+(defun c-to-lisp-string (ptr)
+ (let (str len)
+ (setq len (strlen ptr))
+ (setq str (make-array (list len) :element-type 'character))
+ (sprintf str "%s" ptr) ; Cannot use strcpy because it stops in a \0.
+ str ))
+)
+
+;;;
+;;; Cmulisp-only implementations
+;;;
+
+#+:CmuLisp (progn
+(defun cmulisp-os-run-program (program args)
+ (extensions:run-program program args
+ :input 't ; use current standard input -- default is /dev/null
+ :output 't ; use current standard output
+ :error 't )) ; use current standard error
+
+(defun cmulisp-os-run-program-to-stream (program args)
+ (second (multiple-value-list
+ (extensions:run-program program args
+ :wait nil ; don't wait
+ :input 't ; use current standard input
+ :output :stream ; slurp the output of the process
+ :error 't )) )) ; use current standard error
+
+(defun cmulisp-os-env-get (sym)
+ (let ((key (intern (string sym) (find-package "KEYWORD"))))
+ (cdr (assoc key *environment-list* :test #'eq)) ))
+
+(defun cmulisp-os-process-number ()
+ (Aix::Unix-getpid) )
+)
+
+;;;
+;;; KCL-only implementations
+;;;
+
+#+:KCL (progn
+(defun kcl-os-run-program (program args)
+ (system (format nil "~{~a ~}" (cons program args))) )
+
+(defun kcl-os-run-program-to-stream (program args)
+ (system (format nil "~{~a ~}" (cons program args))) )
+
+(defun kcl-os-env-get (sym)
+ (system:getenv (string sym)) )
+
+(defun kcl-os-process-number ()
+ 77 )
+
+;(defentry |getpid| () (int "getpid"))
+)
+
+;;;;
+;;;; Time
+;;;;
+
+(defun |TimeStampString| ()
+ (multiple-value-bind (sec min hr mody mo yr wkdy daylight zone)
+ (get-decoded-time)
+ (declare (ignore wkdy daylight zone))
+ (format nil "~2,'0d/~2,'0d/~2,'0d ~2,'0d:~2,'0d:~2,'0d"
+ yr mo mody hr min sec) ))
+
+;;;;
+;;;; File system interface
+;;;;
+
+;;(defun |FileExists?| (path)
+;; (probe-file path) )
+;;
+;;(defun |FileRemove| (path)
+;; (delete-file path) )
+;;
+;;(defun |FileRename| (oldpath newpath)
+;; (rename-file oldpath newpath) )
+;;
+;;(defun |FileAbsolutePath| (path)
+;; (truename path) )
+;;
+;;(defun |FileDate| (path)
+;; (file-write-date path) )
+;;
+;;(defun |TextFileOpenIn| (path)
+;; (open path
+;; :element-type 'character
+;; :direction :input ))
+;;
+;;(defun |TextFileOpenOut| (path)
+;; (open path
+;; :element-type 'character
+;; :direction :output
+;; :if-exists :supersede
+;; :if-does-not-exist :create ))
+;;
+;;(defun |TextFileOpenIO| (path)
+;; (open path
+;; :element-type 'character
+;; :direction :io
+;; :if-exists :overwrite ; open at beginning
+;; :if-does-not-exist :create ))
+;;
+;;(defun |TextFileOpenAppend| (path)
+;; (open path
+;; :element-type 'character
+;; :direction :output
+;; :if-exists :append
+;; :if-does-not-exist :create ))
+;;
+;;
+;;(defun |ByteFileOpenIn| (path)
+;; (open path
+;; :element-type 'unsigned-byte
+;; :direction :input ))
+;;
+;;(defun |ByteFileOpenOut| (path)
+;; (open path
+;; :element-type 'unsigned-byte
+;; :direction :output
+;; :if-exists :supersede
+;; :if-does-not-exist :create ))
+;;
+;;(defun |ByteFileOpenIO| (path)
+;; (open path
+;; :element-type 'unsigned-byte
+;; :direction :io
+;; :if-exists :overwrite ; open at beginning
+;; :if-does-not-exist :create ))
+;;
+;;(defun |ByteFileOpenAppend| (path)
+;; (open path
+;; :element-type 'unsigned-byte
+;; :direction :output
+;; :if-exists :append
+;; :if-does-not-exist :create ))
+;;
+;;(defun |ReadFileLineAt| (path pos)
+;; (with-open-file (stream path :direction :input)
+;; (file-position stream pos)
+;; (read-line stream) ))
+;;
+;;(defun |UserHomeDirectory| ()
+;; (pathname-directory (user-homedir-pathname)) )
+;;
+;;(defun |DirectoryFiles| (path)
+;; (directory path) )
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;
+;;;; Lisp Interface
+;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun |LispReadFromString| (str &optional (startpos 0))
+ (prog (ob nextpos)
+ (multiple-value-setq
+ (ob nextpos)
+ (read-from-string str nil nil :start startpos) )
+ (return (list ob nextpos)) ))
+
+(defun |LispEval| (expr)
+ (eval expr) )
+
+;;; expr must be a defun, defmacro, etc.
+(defun |LispCompile| (expr)
+ (eval expr)
+ (compile (second expr)) )
+
+(defun |LispLoadFileQuietly| (object)
+ (load object :verbose nil :print nil))
+
+(defun |LispCompileFile| (fname)
+ (compile-file fname) )
+
+(defun |LispLoadFile| (fname)
+ (load fname) )
+
+(defun |LispKeyword| (str)
+ (intern str 'keyword) )
+
+;;;
+;;; Control
+;;;
+
+
+(defmacro |funcall| (&rest args)
+ (cons 'funcall args) )
+
+(defmacro |Catch| (tag expr)
+ `(catch ,tag ,expr) )
+
+(defmacro |Throw| (tag expr)
+ `(Throw ,tag ,expr) )
+
+(defmacro |UnwindProtect| (a b)
+ `(unwind-protect ,a ,b) )
+
+;;; This macro catches as much as it can.
+;;; Systems with a catchall should use it.
+;;; It is legitimate to not catch anything, if there is no system support.
+;;;
+;;; If the result was caught, then tagvar is set to the desination tag
+;;; and the thown value is returned. Otherwise, tagvar is set to nil
+;;; and the first result of the expression is returned.
+
+#+:Lucid
+(defmacro |CatchAsCan| (tagvar expr)
+ `(let ((catch-result nil)
+ (expr-result nil)
+ (normal-exit (gensym)))
+
+ (setq catch-result
+ (catch 'lucid::top-level
+ (setq expr-result ,expr)
+ normal-exit))
+ (cond
+ ((eq catch-result normal-exit)
+ (setq ,tagvar nil)
+ expr-result )
+ ('t
+ (setq ,tagvar 'lucid::top-level)
+ catch-result )) ))
+
+#-:Lucid
+(defmacro |CatchAsCan| (tagvar expr)
+ `(progn
+ (setq tagvar nil)
+ ,expr ))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; General
+;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defmacro |Eq| (a b)
+ `(eq ,a ,b) )
+
+(defvar |Nil| nil)
+
+(defun |DeepCopy| (x)
+ (copy-tree x) )
+
+(defun |SortInPlace| (l pred)
+ (sort l pred) )
+
+(defun |Sort| (l pred)
+ (sort (copy-tree l) pred) )
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; Streams
+;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(defun |Prompt| (line &optional (readfn nil))
+ (format *query-io* "~a" line)
+ (when readfn (apply readfn (list *query-io*))) )
+
+(defun |PlainError| (&rest args)
+ (let ((fmt (plain-print-format-string args)))
+ (error fmt args) ))
+
+(defun |PrettyPrint| (expr &optional (outstream *standard-output*))
+ (write expr :stream outstream :level nil :length nil :pretty 't :escape 't)
+ (finish-output outstream) )
+
+(defun |PlainPrint| (&rest args)
+ (let ((fmt (plain-print-format-string args)))
+ (format *standard-output* fmt args) ))
+
+(defun |PlainPrintOn| (stream &rest args)
+ (let ((fmt (plain-print-format-string args)))
+ (format stream fmt args) ))
+
+(defun plain-print-format-string (l)
+ (format nil "~~~d{~~a~~}~~%" (length l)) )
+
+
+;;; Lucid 1.01 bug: Must flush output after each write or else
+;;; strange errors arise from invalid buffer reuse.
+
+(defmacro |WriteByte| (byte &rest outstream)
+ `(write-byte ,byte ,@outstream) )
+
+(defmacro |WriteChar| (char &rest outstream)
+ `(write-char ,char ,@outstream) )
+
+;; Write a string -- no new line.
+(defun |WriteString| (string &optional (outstream *standard-output*))
+ (format outstream "~a" string)
+ (finish-output outstream) )
+
+;; Write a string then start a new line.
+(defun |WriteLine| (string &optional (outstream *standard-output*))
+ (write-line string outstream)
+ (finish-output outstream) )
+
+(defun |ByteFileWriteLine| (string outstream)
+ (let ((n (length string)))
+ (do ((i 0 (+ i 1)))
+ ((= i n))
+ (write-byte (char-code (char string i)) outstream) ))
+ (write-byte (char-code #\Newline) outstream)
+ (finish-output outstream) )
+
+
+(defmacro |ReadByte| (instream)
+ `(read-byte ,instream nil nil) )
+
+(defmacro |ReadChar| (&rest instream)
+ (if instream
+ `(read-char ,@instream nil nil)
+ '(read-char *standard-input* nil nil) ))
+
+(defun |ReadLine| (&optional (instream *standard-input*))
+ (read-line instream nil nil) )
+
+(defun |ByteFileReadLine| (instream)
+ (do ((buf (make-array '(80)
+ :element-type 'character
+ :fill-pointer 0
+ :adjustable 't ))
+ (b (read-byte instream nil nil) (read-byte instream nil nil))
+ (c) )
+
+ ((or (null b) (char= (setq c (code-char b)) #\Newline)) buf)
+
+ (vector-push-extend c buf) ))
+
+;;; Reads no more than the rest of the current line into the string argument.
+;;; The #\Newline is not included in the string.
+;;;
+;;; The result is an integer, 'T or nil.
+;;; Nil the stream was already exhausted.
+;;; T the string was filled before the end of line was reached.
+;;; k the end of line was reached and k characters were copied.
+;;;
+;;; If the argument "flags" is passed a cons cell, it is updated
+;;; to contain (Eof . Eol).
+;;; Eof indicates whether the end of file was detected.
+;;; Eol indicates whether the line was terminated by a #\newline.
+
+(defun |ReadLineIntoString| (string &optional (instream *standard-input*)
+ (flags nil) )
+
+ (when (consp flags) (rplaca flags nil) (rplacd flags nil))
+
+ (let ((n (length string))
+ (i 0)
+ (c (read-char instream nil nil)) )
+
+ (loop
+ (cond
+ ((null c)
+ (when (consp flags) (rplaca flags 't))
+ (return (if (= i 0) nil i)) )
+ ((char= c #\Newline)
+ (when (consp flags) (rplacd flags 't))
+ (return i) )
+ ((= i n)
+ (unread-char c instream)
+ (return 't) ))
+
+ (setf (char string i) c)
+ (setq i (+ i 1))
+ (setq c (read-char instream nil nil)) )))
+
+
+;;; Similar to ReadLineIntoString but reads from a ByteFile.
+(defun |ByteFileReadLineIntoString| (string instream &optional (flags nil))
+
+ (when (consp flags) (rplaca flags nil) (rplacd flags nil))
+
+ (let ((n (length string))
+ (i 0)
+ (b nil)
+ (c nil) )
+
+ (loop
+ (when (= i n) (return 't) )
+ (setq b (read-byte instream nil nil))
+ (when (null b)
+ (when (consp flags) (rplaca flags 't))
+ (return i) )
+
+ (setq c (code-char b))
+ (when (char= c #\Newline)
+ (when (consp flags) (rplacd flags 't))
+ (return i) )
+
+ (setf (char string i) c)
+ (setq i (+ i 1)) )))
+
+(defun |ReadBytesIntoVector|
+ (vector &optional (instream *standard-input*) (flags nil) )
+
+ (when (consp flags) (rplaca flags nil) (rplacd flags nil))
+
+ (let ((n (length vector))
+ (i 0)
+ (b nil) )
+
+ (loop
+ (when (= i n) (return 't))
+ (setq b (read-byte instream nil nil))
+ (when (null b)
+ (when (consp flags) (rplaca flags 't))
+ (return i) )
+
+ (setf (aref vector i) b)
+ (setq i (+ i 1)) )))
+
+
+(defun |InputStream?| (stream)
+ (input-stream-p stream) )
+
+(defun |OutputStream?| (stream)
+ (output-stream-p stream) )
+
+;;; Whether the position is a record number or character number is
+;;; implementation specific. In Common Lisp it is a character number.
+
+(defun |StreamGetPosition| (stream)
+ (file-position stream) )
+
+(defun |StreamSetPosition| (stream pos)
+ (file-position stream pos))
+
+(defun |StreamSize| (stream)
+ (file-length stream))
+
+(defmacro |WithOpenStream| (var stream-form body)
+ `(with-open-stream (,var ,stream-form) ,body) )
+
+;;; Copy up to n characters or eof.
+;;; Return number of characters actually copied
+(defun |StreamCopyChars| (instream outstream n)
+ (do ((i 0 (+ i 1))
+ (c (read-char instream nil nil) (read-char instream nil nil)) )
+ ((or (null c) (= i n)) (finish-output outstream) i)
+
+ (write-char c outstream) ))
+
+(defun |StreamCopyBytes| (instream outstream n)
+ (do ((i 0 (+ i 1))
+ (b (read-byte instream nil nil) (read-byte instream nil nil)) )
+ ((or (null b) (= i n)) (finish-output outstream) i)
+
+ (write-byte b outstream) ))
+
+(defun |StreamEnd?| (instream)
+ (null (peek-char nil instream nil nil)) )
+
+(defun |StreamFlush| (&optional (outstream *standard-output*))
+ (finish-output outstream) )
+
+(defun |StreamClose| (stream)
+ (close stream) )
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;
+;;;; Types
+;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Functions for manipulating values of type Xxxx are prefixed with Xxxx.
+;;; E.g., CsetUnion
+;;; Values of type Xxxx are suffixed with Xxxx.
+;;; E.g., AlphaCset
+;;; The primary function for creating object of this type is named Xxxx.
+;;; The type-testing predicate is Xxxx?
+
+;;; xx := Xxxx(args)
+;;; val := XxxxGet(xx, key) or XxxxGet(xx, key, default)
+;;; val := XxxxSet(xx, key, val)
+;;; val := XxxxUnset(xx, key)
+;;;
+;;; xx := XxxxRemove(val, xx) XxxxRemoveQ
+;;; truth := XxxxMember?(val, xx) XxxxMemberQ?
+;;; xx := XxxxUnion(xx1, xx2)
+;;;
+;;; The suffix "Q" means the test involved is "EQ". "N" between the
+;;; the type name and the function name proper means the function is
+;;; non-copying (destructive).
+
+;;;
+;;; Pathnames
+;;;
+
+(defvar |TempFileDirectory| (pathname-directory "/tmp/"))
+(defvar |LispFileType| "lisp")
+(defvar |FaslFileType| "bbin")
+
+(defun |Pathname| (name &optional (type nil) (dir 'none))
+ (if (equal dir 'none)
+ (make-pathname :name name :type type :defaults name)
+ (make-pathname :directory dir :name name :type type) ))
+
+(defun |ToPathname| (string)
+ (pathname string) )
+
+;;; System-wide unique name on each call.
+(defvar *new-pathname-counter* 1)
+
+(defun |NewPathname| (&optional (prefix "t")(type nil)(dir '(:relative)))
+ (let ((name
+ (format nil "~a~a-~a"
+ prefix (|OsProcessNumber|) *new-pathname-counter* )))
+ (setq *new-pathname-counter* (+ *new-pathname-counter* 1))
+ (make-pathname :directory dir :name name :type type) ))
+
+;;; System-wide unique name for the current session.
+(defun |SessionPathname| (&optional (prefix "t")(type nil)(dir '(:relative)))
+ (let ((name (format nil "~a~a" prefix (|OsProcessNumber|))))
+ (make-pathname :directory dir :name name :type type) ))
+
+(defun |PathnameDirectory| (path)
+ (pathname-directory path) )
+
+(defun |PathnameName| (path)
+ (pathname-name path) )
+
+(defun |PathnameType| (path)
+ (pathname-type path) )
+
+
+(defun |PathnameWithType| (path type)
+ (make-pathname :type type :defaults path) )
+
+(defun |PathnameWithoutType| (path)
+ (make-pathname :type nil :defaults path) )
+
+
+(defun |PathnameWithDirectory| (path dir)
+ (make-pathname :directory dir :defaults path) )
+
+(defun |PathnameWithoutDirectory| (path)
+ (make-pathname :directory nil :defaults path) )
+
+
+(defun |PathnameString| (path)
+ (namestring path) )
+
+(defun |PathnameToUsualCase| (path)
+ (pathname (|StringLowerCase| (namestring path))) )
+
+
+;; Lucid 1.01 specific -- uses representation of directories.
+(defun |PathnameAbsolute?| (path)
+ (let ((dir (pathname-directory path)))
+ (not (and (consp dir) (or
+ (eq (car dir) :current)
+ (eq (car dir) :relative) ))) ))
+
+;; Lucid 1.01 specific -- uses representation of directories.
+(defun |PathnameWithinDirectory| (dir relpath)
+ (if (|PathnameAbsolute?| relpath)
+ (|PlainError| "The path " relpath " cannot be used within directory " dir)
+ (make-pathname
+ :directory (append dir (cdr (pathname-directory relpath)))
+ :defaults relpath )))
+
+;; Unix specific -- uses unix file syntax.
+(defun |PathnameDirectoryOfDirectoryPathname| (dirpath)
+ (pathname-directory
+ (concatenate 'string (namestring dirpath) "/junk.bar") ))
+
+;; Unix specific -- uses environment variables.
+(defun |PathnameWithinOsEnvVar| (varname relpath)
+ (let ((envstr (|OsEnvGet| varname)))
+ (parse-namestring (concatenate 'string envstr "/" relpath)) ))
+
+;;;
+;;; Symbols
+;;;
+
+
+;;!! Worry about packages a later day.
+;;!! For now, the responsibility of setting *package* is on the caller.
+(defun |MakeSymbol| (str)
+ (let ((a (intern str))) a) ) ; Return only 1 value
+
+(defmacro |Symbol?| (ob)
+ `(and ,ob (symbolp ,ob)) )
+
+(defmacro |SymbolString| (sym)
+ `(string ,sym) )
+
+;;;
+;;; Bits
+;;;
+(defmacro |Bit| (x)
+ (cond
+ ((eq x 1) 1)
+ ((eq x 0) 0)
+ (x 1)
+ (t 0)))
+
+(defun |Bit?| (x)
+ (or (eql x 1) (eql x 0)) )
+
+(defvar |TrueBit| 1)
+(defvar |FalseBit| 0)
+
+(defmacro |BitOn?| (b) `(eq ,b 1))
+
+(defmacro |BitOr| (x y)
+ `(bit-ior ,x ,y) )
+
+;;;
+;;; General Sequences
+;;;
+;; ELT and SETELT work on these.
+
+;; Removed because it clashed with size in vmlisp.lisp
+;; (defun SIZE (x) ;; #x in boot generates (SIZE x)
+;; (length x))
+
+;;;
+;;; Vectors
+;;;
+(defun |FullVector| (size &optional (init nil))
+ (make-array
+ (list size)
+ :element-type 't
+ :initial-element init ))
+
+(defun |Vector?| (x)
+ (vectorp x) )
+
+;;;
+;;; Bit Vectors
+;;;
+
+;; Common Lisp simple bit vectors
+
+(defun |FullBvec| (size &optional (init 0))
+ (make-array
+ (list size)
+ :element-type 'bit
+ :initial-element init ))
+
+;;;
+;;; Characters
+;;;
+
+;;(defun |char| (x)
+;; (char (string x) 0) )
+
+(defmacro |Char| (x)
+ `(char (string ,x) 0) )
+
+(defmacro |Char?| (c)
+ `(characterp ,c) )
+ ;; (or (characterp a)
+ ;; (and (symbolp a) (= (length (symbol-name a)) 1))))
+
+
+(defmacro |CharCode| (c)
+ `(char-code ,c) )
+
+(defmacro |CharGreater?| (c1 c2)
+ `(char> ,c1 ,c2) )
+
+(defun |CharDigit?| (x)
+ (or
+ (and (characterp x) (digit-char-p x))
+ (and (stringp x) (= (length x) 1) (digit-char-p (char x 0)))
+ (and (symbolp x) (|CharDigit?| (string x))) ))
+
+(defvar |SpaceChar| #\Space)
+(defvar |NewlineChar| #\Newline)
+
+;;;
+;;; Character Sets
+;;;
+
+(defun |Cset| (str)
+ (let
+ ((cset (make-array
+ (list char-code-limit)
+ :element-type 'bit
+ :initial-element 0 ))
+ (len (length str)) )
+
+ (do ((i 0 (+ 1 i)))
+ ((= i len))
+ (setf (sbit cset (char-code (char str i))) 1) )
+ cset ))
+
+(defun |CsetMember?| (c cset)
+ (eql 1 (sbit cset (char-code c))) )
+
+(defun |CsetUnion| (cset1 cset2)
+ (bit-ior cset1 cset2) )
+
+(defun |CsetComplement| (cset)
+ (bit-not cset) )
+
+(defun |CsetString| (cset)
+ (let
+ ((chars '())
+ (len (length cset)))
+ (do ((i 0 (+ 1 i)))
+ ((= i len))
+ (if (eql 1 (sbit cset i)) (push (string (code-char i)) chars)) )
+ (apply #'concatenate (cons 'string (nreverse chars))) ))
+
+(defvar |NumericCset| (|Cset| "0123456789") )
+(defvar |LowerCaseCset| (|Cset| "abcdefghijklmnopqrstuvwxyz") )
+(defvar |UpperCaseCset| (|Cset| "ABCDEFGHIJKLMNOPQRSTUVWXYZ") )
+(defvar |AlphaCset| (|CsetUnion| |LowerCaseCset| |UpperCaseCset|))
+(defvar |AlphaNumericCset| (|CsetUnion| |AlphaCset| |NumericCset|) )
+(defvar |WhiteSpaceCset|
+ (|Cset| (coerce
+ (list #\Space #\Newline #\Tab #\Page #\Linefeed #\Return #\Backspace)
+ 'string )) )
+
+;;;
+;;; Character Strings
+;;;
+
+;; Common Lisp simple strings
+;; ELT and SETELT work on these.
+
+
+(defun |FullString| (size &optional (init #\Space))
+ (make-array
+ (list size)
+ :element-type 'character
+ :initial-element init ))
+
+(defun |ToString| (ob)
+ (string ob) )
+
+(defun |StringImage| (ob)
+ (format nil "~a" ob) )
+
+(defun |String?| (ob)
+ (stringp ob) )
+
+(defmacro |StringGetCode| (str ix)
+ `(char-code (char ,str ,ix)) )
+
+(defun |StringConcat| (&rest l)
+ (progn
+ (setq l (mapcar #'string l))
+ (apply #'concatenate 'string l) ))
+
+(defun |StringFromTo| (string from to)
+ (subseq string from (+ to 1)) )
+
+(defun |StringFromToEnd| (string from)
+ (subseq string from) )
+
+(defun |StringFromLong| (string from len)
+ (subseq string from (+ from len)) )
+
+(defun |StringPrefix?| (pref string)
+ (let ((mm (mismatch pref string)))
+ (or (not mm) (eql mm (length pref))) ))
+
+(defun |StringUpperCase| (l)
+ (cond ((stringp l) (string-upcase l))
+ ((symbolp l) (intern (string-upcase (symbol-name l))))
+ ((characterp l) (char-upcase l))
+ ((atom l) l)
+ (t (mapcar #'|StringUpperCase| l)) ))
+
+(defun |StringLowerCase| (l)
+ (cond ((stringp l) (string-downcase l))
+ ((symbolp l) (intern (string-downcase (symbol-name l))))
+ ((characterp l) (char-downcase L))
+ ((atom l) l)
+ (t (mapcar #'|StringLowerCase| l)) ))
+
+(defun |StringGreater?| (s1 s2)
+ (string> s1 s2) )
+
+(defun |StringToInteger| (s)
+ (read-from-string s) )
+
+(defun |StringToFloat| (s)
+ (read-from-string s) )
+
+(defun |StringLength| (s)
+ (length s) )
+
+;;;
+;;; Numbers
+;;;
+
+
+
+(defmacro |Number?| (x) `(numberp ,x))
+(defmacro |Integer?| (x) `(integerp ,x))
+(defmacro |Float?| (x) `(floatp ,x))
+
+(defmacro |Odd?| (n) `(oddp ,n))
+(defmacro |Remainder|(a b) `(rem ,a ,b))
+
+(defmacro |DoublePrecision| (x) `(coerce ,x 'double-precision))
+
+(defmacro |Abs| (x) `(abs ,x))
+(defmacro |Min| (x &rest yz) `(min ,x ,@yz))
+(defmacro |Max| (x &rest yz) `(max ,x ,@yz))
+
+(defmacro |Exp| (x) `(exp ,x))
+(defmacro |Ln| (x) `(log ,x))
+(defmacro |Log10| (x) `(log ,x 10))
+(defmacro |Sin| (x) `(sin ,x))
+(defmacro |Cos| (x) `(cos ,x))
+(defmacro |Tan| (x) `(tan ,x))
+(defmacro |Cotan| (x) `(/ 1.0 (tan ,x)))
+(defmacro |Arctan|(x) `(atan ,x))
+
+;;;
+;;; Pairs
+;;;
+
+(defmacro |Pair?| (x) `(consp ,x))
+
+(defmacro |car| (x) `(car ,x))
+(defmacro |cdr| (x) `(cdr ,x))
+
+(defmacro |caar| (x) `(caar ,x))
+(defmacro |cadr| (x) `(cadr ,x))
+(defmacro |cdar| (x) `(cdar ,x))
+(defmacro |cddr| (x) `(cddr ,x))
+
+(defmacro |caaar| (x) `(caaar ,x))
+(defmacro |caadr| (x) `(caadr ,x))
+(defmacro |cadar| (x) `(cadar ,x))
+(defmacro |caddr| (x) `(caddr ,x))
+(defmacro |cdaar| (x) `(cdaar ,x))
+(defmacro |cdadr| (x) `(cdadr ,x))
+(defmacro |cddar| (x) `(cddar ,x))
+(defmacro |cdddr| (x) `(cdddr ,x))
+
+(defmacro |FastCar| (x) `(car (the cons ,x)))
+(defmacro |FastCdr| (x) `(cdr (the cons ,x)))
+
+(defmacro |FastCaar| (x) `(|FastCar| (|FastCar| ,x)))
+(defmacro |FastCadr| (x) `(|FastCar| (|FastCdr| ,x)))
+(defmacro |FastCdar| (x) `(|FastCdr| (|FastCar| ,x)))
+(defmacro |FastCddr| (x) `(|FastCdr| (|FastCdr| ,x)))
+
+(defmacro |FastCaaar| (x) `(|FastCar| (|FastCaar| ,x)))
+(defmacro |FastCaadr| (x) `(|FastCar| (|FastCadr| ,x)))
+(defmacro |FastCadar| (x) `(|FastCar| (|FastCdar| ,x)))
+(defmacro |FastCaddr| (x) `(|FastCar| (|FastCddr| ,x)))
+(defmacro |FastCdaar| (x) `(|FastCdr| (|FastCaar| ,x)))
+(defmacro |FastCdadr| (x) `(|FastCdr| (|FastCadr| ,x)))
+(defmacro |FastCddar| (x) `(|FastCdr| (|FastCdar| ,x)))
+(defmacro |FastCdddr| (x) `(|FastCdr| (|FastCddr| ,x)))
+
+(defmacro |IfCar| (x) `(if (consp ,x) (car ,x)))
+(defmacro |IfCdr| (x) `(if (consp ,x) (cdr ,x)))
+
+(defmacro |EqCar| (l a) `(eq (car ,l) ,a))
+(defmacro |EqCdr| (l d) `(eq (cdr ,l) ,d))
+
+;;;
+;;; Lists
+;;;
+
+
+(defun |ListNReverse| (l)
+ (nreverse l) )
+
+(defun |ListIsLength?| (l n)
+ (if l (= n 0) (|ListIsLength?| (cdr l) (1- n))) )
+
+;;--------------------> NEW DEFINITION (override in vmlisp.lisp.pamphlet)
+(defun |ListMemberQ?| (ob l)
+ (member ob l :test #'eq) )
+
+(defun |ListRemoveQ| (ob l)
+ (remove ob l :test #'eq :count 1) )
+
+(defun |ListNRemoveQ| (ob l)
+ (delete ob l :test #'eq :count 1) )
+
+(defun |ListRemoveDuplicatesQ| (l)
+ (remove-duplicates l :test #'eq) )
+
+(defun |ListUnion| (l1 l2)
+ (union l1 l2 :test #'equal) )
+
+(defun |ListUnionQ| (l1 l2)
+ (union l1 l2 :test #'eq) )
+
+(defun |ListIntersection| (l1 l2)
+ (intersection l1 l2 :test #'equal) )
+
+(defun |ListIntersectionQ| (l1 l2)
+ (intersection l1 l2 :test #'eq) )
+
+(defun |ListAdjoin| (ob l)
+ (adjoin ob l :test #'equal) )
+
+(defun |ListAdjoinQ| (ob l)
+ (adjoin ob l :test #'eq) )
+
+;;;
+;;; Association lists
+;;;
+
+
+(defun |AlistAssoc| (key l)
+ (assoc key l :test #'equal) )
+
+;;--------------------> NEW DEFINITION (override in vmlisp.lisp.pamphlet)
+(defun |AlistAssocQ| (key l)
+ (assoc key l :test #'eq) )
+
+(defun |AlistRemove| (key l)
+ (let ((pr (assoc key l :test #'equal)))
+ (if pr
+ (remove pr l :test #'equal)
+ l) ))
+
+(defun |AlistRemoveQ| (key l)
+ (let ((pr (assoc key l :test #'eq)))
+ (if pr
+ (remove pr l :test #'eq)
+ l) ))
+
+(defun |AlistAdjoinQ| (pr l)
+ (cons pr (|AlistRemoveQ| (car pr) l)) )
+
+(defun |AlistUnionQ| (l1 l2)
+ (union l1 l2 :test #'eq :key #'car) )
+
+;;;
+;;; Tables
+;;;
+
+;;(defmacro |EqTable| ()
+;; `(make-hash-table :test #'eq) )
+;;(defmacro |EqualTable| ()
+;; `(make-hash-table :test #'equal) )
+;;(defmacro |StringTable| ()
+;; `(make-hash-table :test #'equal) )
+;; following is not used and causes CCL problems
+;;(defmacro |SymbolTable| ()
+;; `(make-hash-table :test #'eq) )
+
+
+(defmacro |Table?| (ob)
+ `(hash-table-p ,ob) )
+
+(defmacro |TableCount| (tab)
+ `(hash-table-count ,tab) )
+
+(defmacro |TableGet| (tab key &rest default)
+ `(gethash ,key ,tab ,@default) )
+
+(defmacro |TableSet| (tab key val)
+ `(setf (gethash ,key ,tab) ,val) )
+
+(defun |TableUnset| (tab key)
+ (let ((val (gethash key tab)))
+ (remhash key tab)
+ val ))
+
+(defun |TableKeys| (tab)
+ (let ((key-list nil))
+ (maphash
+ #'(lambda (key val) (declare (ignore val))
+ (setq key-list (cons key key-list)) )
+ tab )
+ key-list ))
+
+;; CCL supplies a slightly more efficient version of logs to base 10, which
+;; is useful in the WIDTH function. MCD.
+#+:KCL (defun log10 (u) (log u 10))