;;;; -*- mode:emacs-lisp;coding:utf-8;lexical-binding:t -*- ;;;;***************************************************************************** ;;;;FILE: pjb-cl.el ;;;;LANGUAGE: emacs lisp ;;;;SYSTEM: emacs ;;;;USER-INTERFACE: emacs ;;;;DESCRIPTION ;;;; ;;;; This module exports a few Common Lisp operators missing from cl. ;;;; ;;;;AUTHORS ;;;; Pascal J. Bourguignon ;;;;MODIFICATIONS ;;;; 2006-11-14 Removed most of CL functions and downcased the rest ;;;; to avoid collision with emacs-cl. ;;;; 2004-11-01 Upcased COMMON-LISP symbols. This will avoid name ;;;; collision between Common-Lisp and emacs-lisp. ;;;; 2003-01-20 Replaced pjb-cl%%string-replace ;;;; by regexp-replace-in-string. ;;;; 2002-04-10 Creation. ;;;;BUGS ;;;; ;;;; encode-time/decode-time have a range too limited (32-bit around 1/1/1970) ;;;; we should implement our own version. ;;;; ;;;; ;;;;LEGAL ;;;; LGPL ;;;; ;;;; Copyright Pascal J. Bourguignon 2002 - 2011 ;;;; ;;;; This library is free software; you can redistribute it and/or ;;;; modify it under the terms of the GNU Lesser General Public ;;;; License as published by the Free Software Foundation; either ;;;; version 2 of the License, or (at your option) any later version. ;;;; ;;;; This library is distributed in the hope that it will be useful, ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;;; Lesser General Public License for more details. ;;;; ;;;; You should have received a copy of the GNU Lesser General Public ;;;; License along with this library; if not, write to the Free Software ;;;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ;;;; ;;;;***************************************************************************** (require 'cl) (load "cl-seq" nil t) (load "cl-extra" nil t) (require 'eieio) (require 'eieio-opt) (require 'parse-time) (setf lexical-binding t) ;; Let's teach emacs how to format Common-Lisp: (mapc (lambda (sym) (put sym 'lisp-indent-function 1)) '(concatenate with-open-file with-open-stream with-input-from-string with-output-to-string dolist lambda when unless while until if let let* handler-case)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Private functions. (defconst pjb-cl%%epoch 2208988800.0 "I compute 25567 days, or 2208988800 seconds from 1900-01-01 00:00:00 to 1970-01-01 00:00:00. Please correct me if I'm wrong.") (defun pjb-cl%%leap-year (year) "PRIVATE. RETURN: Whether the `year' is a leap-year. NOTE: `year' should be 2002 if it's the third year of the XXth century... " (or (= 0 (mod year 400)) (and (/= 0 (mod year 100)) (= 0 (mod year 4)) ))) (defun pjb-cl%%days-in-year (year) "PRIVATE. RETURN: The number of days in the given year. " (if (pjb-cl%%leap-year year) 366 365)) (defun pjb-cl%%seconds-to-emacs-time (secs) "PRIVATE. PRE: secs is a number of seconds. RETURN: The time represented by secs in emacs time format, ie. a list ( h l us ) with h=secs/2^16, l=secs%2^16, us=(secs*1e6)%1e6. " (let* ( (h (truncate (/ secs 65536))) (lf (- secs (* h 65536.0))) (l (truncate lf)) (us (truncate (* 1000000.0 (- lf l)))) ) (list h l us) )) (defun pjb-cl%%emacs-time-to-seconds (et) "PRIVATE. PRE: et is a time in emacs time format, ie. a list ( h l [us]) with h and l being in [0..65535] and us in [0..999999]. RETURN: et expressed as a scalar." (+ (let ((h (nth 0 et))) (if (< h 1024) (* h 65536) (* h 65536.0))) (nth 1 et) (let ((us (nth 2 et))) (if (or (null us) (= 0 us)) 0 (/ us 1000000.0))))) (defun pjb-cl%%char-in-bag (char bag) "PRIVATE. RETURN: Whether `char' is in `bag'. " (let ( (len (length bag)) (i 0) ) (while (and (< i len) (/= char (elt bag i))) (setq i (1+ i))) (< i len))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Common-Lisp ;; ----------------------------- ;; - 5 - Data and Control Flow - ;; ----------------------------- (defmacro defconstant (symbol initvalue &optional docstring) `(defconst ,symbol ,initvalue ,docstring)) (defmacro defparameter (symbol &optional initvalue docstring) `(progn (defvar ,symbol nil ,docstring) (setq ,symbol ,initvalue))) (defmacro multiple-value-prog1 (first-form &rest forms) ;; Multiple values are implemented as list of values. BAD. `(prog1 ,first-form ,@forms)) (defconstant multiple-value-limit 4098) ;; From: Stefan Monnier ;; Subject: Re: condition-case ;; Newsgroups: gnu.emacs.help ;; Date: Thu, 09 Dec 2010 10:04:12 -0500 ;; Organization: A noiseless patient Spider ;; Message-ID: ;; ;; Oh wait, I just noticed this one: `subst' is wrong here. I know CL ;; already uses it for similar purposes elsewhere, but it's simply wrong ;; because `subst' doesn't know about Elisp binding rules. ;; So (subst 'b 'a '(lambda () '(a b c))) will happily return ;; (lambda () '(b b c)). Better simply use `let', even if it has ;; a performance cost. ;; (defmacro handler-case (expression &rest clauses) ;; "Evaluate expression with `condition-case' and catch errors with CLAUSES. ;; ;; Longer explanation here..." ;; (let* ((var (gensym)) ;; (neclause (assoc :NO-ERROR clauses)) ;; (nell (cadr neclause)) ;; (nebody (cddr neclause)) ;; (handlers (mapcar (lambda (clause) ;; (let ((typespec (car clause)) ;; (clausvar (cadr clause)) ;; (body (cddr clause))) ;; (cons (if (and (consp typespec) ;; (eq 'or (car typespec))) ;; (cdr typespec) ;; typespec) ;; (if (null clausvar) ;; body ;; (let ((var (car clausvar))) ;; body))))) ;; (remove neclause clauses)))) ;; (if neclause ;; `(condition-case ,var ;; (multiple-value-bind ,nell ,expression ,@nebody) ;; ,@handlers) ;; `(condition-case ,var ;; ,expression ;; ,@handlers)))) (defun complement (fun) (lambda (&rest arguments) (not (apply fun arguments)))) ;; ------------------ ;; - 9 - Conditions - ;; ------------------ ;; (condition-case VAR BODYFORM HANDLERS...) ;; ;; Regain control when an error is signaled. ;; Executes BODYFORM and returns its value if no error happens. ;; Each element of HANDLERS looks like (CONDITION-NAME BODY...) ;; where the BODY is made of Lisp expressions. ;; ;; A handler is applicable to an error ;; if CONDITION-NAME is one of the error's condition names. ;; If an error happens, the first applicable handler is run. ;; ;; The car of a handler may be a list of condition names ;; instead of a single condition name. ;; ;; When a handler handles an error, ;; control returns to the condition-case and the handler BODY... is executed ;; with VAR bound to (SIGNALED-CONDITIONS . SIGNAL-DATA). ;; VAR may be nil; then you do not get access to the signal information. ;; ;; The value of the last BODY form is returned from the condition-case. ;; See also the function `signal' for more info. (defmacro handler-case (expression &rest clauses) "Common-Lisp IMPLEMENTATION: The clause variable symbols are substituted by one single condition-case variable symbol. This may cause problems if the same symbol is used as data or if it's a dynamic variable. " (let* ((var (gensym)) (neclause (assoc :NO-ERROR clauses)) (nell (cadr neclause)) (nebody (cddr neclause)) (handlers (mapcar (lambda (clause) (let ((typespec (car clause)) (clausvar (cadr clause)) (body (cddr clause))) (cons (if (and (consp typespec) (eq 'or (car typespec))) (cdr typespec) typespec) (if (null clausvar) body (subst var (car clausvar) body))))) (remove neclause clauses)))) (if neclause `(condition-case ,var (multiple-value-bind ,nell ,expression ,@nebody) ,@handlers) `(condition-case ,var ,expression ,@handlers)))) (defmacro cl:ignore-errors (&rest body) `(handler-case (progn ,@body) (error (err) (message "cl:ignore-errors %S" err) (values nil err)))) ;; ---------------- ;; - 10 - Symbols - ;; ---------------- (defun copy-symbol (symbol &optional copy-properties) (let ((new (make-symbol (cl:string symbol)))) (when copy-properties (setf (symbol-plist new) (COPY-SEQ (symbol-plist symbol)))) (setf (symbol-value new) (symbol-value symbol) (symbol-function new) (symbol-function symbol)) new)) (defun cl:symbol-package (sym) "Return the name of the package of the symbol. This is \"emacs-lisp\" if the symbol doesn't contain any colon, \"keyword\" if it starts with a colon, or the substring before the colon if it contains one." (let* ((name (symbol-name sym)) (colon (position (character ":") name))) (case colon ((nil) "emacs-lisp") ((0) "keyword") (otherwise (subseq name 0 colon))))) (defun cl:symbol-name (sym) "Return the name of the symbol. This is what's after the colon or double colon if any, or the symbol name." (let* ((name (symbol-name sym)) (colon (position (character ":") name))) (cond ((and colon (char= (character ":") (char name (1+ colon)))) (subseq name (+ 2 colon))) (colon (subseq name (+ 1 colon))) (t name)))) ;; ----------------- ;; - 11 - Packages - ;; ----------------- (defun intern* (string &optional package) (cond ((and (stringp package) (string= "KEYWORD" package)) (intern (format ":%s" string))) (t (intern string)))) ;; ---------------- ;; - 12 - Numbers - ;; ---------------- (defun compute-most-positive-fixnum () (loop for p from 0 for i = 1 then (* 2 i) while (plusp i) finally (return (+ (expt 2 (1- p)) (1- (expt 2 (1- p))))))) (unless (boundp 'most-positive-fixnum) (defconstant most-positive-fixnum (compute-most-positive-fixnum) "Common-Lisp: most-positive-fixnum is that fixnum closest in value to positive infinity provided by the implementation, and greater than or equal to both 2^15 - 1 and array-dimension-limit. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/v_most_p.htm#most-positive-fixnum")) (unless (boundp 'most-negative-fixnum) (defconstant most-negative-fixnum (- -1 (compute-most-positive-fixnum)) "Common-Lisp: most-negative-fixnum is that fixnum closest in value to negative infinity provided by the implementation, and less than or equal to both -2^15. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/v_most_p.htm#most-negative-fixnum")) (defun integer-length (x) "Returns the number of bits needed to represent integer in binary two's-complement format." (if (minusp x) (integer-length (- x)) (loop until (zerop x) do (setf x (ash x -1)) sum 1 into result finally (return result)))) (defun* cl:digit-char-p (char &optional (radix 10)) (let ((value (position (upcase char) "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"))) (and value (< value radix) value))) (defun* cl:parse-integer (string &key (start 0) end (radix 10) junk-allowed) (let ((end (or end (length string))) (n 0) (sign 1) (plus (character "+")) (minus (character "-")) (space (character " "))) (labels ((parse-integer-error () (error "Not an integer string %S (:start %d :end %d :radix %d)" string start end radix)) (check-range () (unless (< start end) (parse-integer-error))) (eat-spaces (i) (loop while (and (< i end) (char= space (aref string i))) do (incf i) finally (return i)))) (setf start (eat-spaces start)) (check-range) (cond ((char= plus (aref string start)) (setf sign +1) (incf start) (check-range)) ((char= minus (aref string start)) (setf sign -1) (incf start) (check-range))) (loop for i from start below end for digit = (cl:digit-char-p (aref string i) radix) while digit do (setf n (+ (* n radix) digit)) finally (when (< i end) (setf i (eat-spaces i))) (when (and (not junk-allowed) (< i end)) (parse-integer-error)) (return (values (* sign n) i)))))) ;; ------------------- ;; - 13 - Characters - ;; ------------------- (unless (fboundp 'characterp) (defun characterp (x) "Common-Lisp: Returns true if object is of type character; otherwise, returns false. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_chp.htm#characterp RETURN: Whether the argument is a character. NOTE: With emacs, characters are integers." (integerp x))) (defun character (character) "Common-Lisp: Returns the denoted character URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_ch.htm RETURN: An emacs character. EXAMPLES: (CHARACTER #\\a) => ?a INVALID: # is invalid read syntax for emacs! (CHARACTER \"a\") => ?a (CHARACTER 'a) => ?A WARNING: emacs symbols are multicase! (CHARACTER '\\a) => ?a (CHARACTER 65.) is an error. (CHARACTER 'apple) is an error. " (cond ((characterp character) character) ((symbolp character) (if (= 1 (length (cl:symbol-name character))) (string-to-char (cl:symbol-name character)) (error "character does not accept symbols of more than one character."))) ((stringp character) (string-to-char character)) (t (error "Unexpected type fo character argument.")))) (defun upper-case-p (character) "common-lisp: " (and (equal (upcase character) character) (not (equal (downcase character) character)))) (defun lower-case-p (character) "common-lisp: " (and (equal (downcase character) character) (not (equal (upcase character) character)))) (defun both-case-p (character) "common-lisp: " (or (upper-case-p character) (lower-case-p character))) (defun char-upcase (character) (upcase character)) (defun char-downcase (character) (downcase character)) (defun code-char* (code) "Common-Lisp: " (if (numberp code) (coerce code 'character) (error "%s is not a character code." code))) (defun char-code* (character) "Common-Lisp: Return the code attribute of character. RETURN: character (emacs characters are numbers). " character) (defun char= (&rest characters) "common-lisp: compare character arguments. url: http://www.informatimago.com/local/lisp/hyperspec/body/f_chareq.htm " (unless characters (error "too few arguments given to char=.")) (let ((a (car characters))) (every (lambda (b) (= a b)) (cdr characters)))) (defun char/= (&rest characters) "common-lisp: compare character arguments. Returns true if all characters are different (no two equal). url: http://www.informatimago.com/local/lisp/hyperspec/body/f_chareq.htm " (unless characters (error "too few arguments given to char/=.")) (if (= 1 (length characters)) t (loop with already-seen = nil with result = t for c in characters while result do (if (memq c already-seen) (setq result nil) (push c already-seen)) finally (return result)))) (defmacro pjb-cl%%compare-chars (name order characters) `(progn (unless ,characters (error "Too few arguments given to %s." ',name)) (let ((prev (car ,characters)) (result t)) (loop for next in (cdr ,characters) while result do (unless (,order (char-code* prev) (char-code* next)) (setq result nil)) (setq prev next)) result))) (defun char< (&rest characters) "Common-Lisp: returns true if the characters are monotonically increasing; \ otherwise, it returns false. If two characters have identical implementation-defined attributes, then their ordering by char< is consistent with the numerical ordering by the predicate < on their codes. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_chareq.htm " (pjb-cl%%compare-chars char< < characters)) (defun char> (&rest characters) "Common-Lisp: returns true if the characters are monotonically decreasing; \ otherwise, it returns false. If two characters have identical implementation-defined attributes, then their ordering by char> is consistent with the numerical ordering by the predicate > on their codes. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_chareq.htm " (pjb-cl%%compare-chars char> > characters)) (defun char<= (&rest characters) "Common-Lisp: returns true if the characters are monotonically nondecreasing;\ otherwise, it returns false. If two characters have identical implementation-defined attributes, then their ordering by char<= is consistent with the numerical ordering by the predicate <= on their codes. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_chareq.htm " (pjb-cl%%compare-chars char<= <= characters)) (defun char>= (&rest characters) "Common-Lisp: returns true if the characters are monotonically nonincreasing;\ otherwise, it returns false. If two characters have identical implementation-defined attributes, then their ordering by char>= is consistent with the numerical ordering by the predicate >= on their codes. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_chareq.htm " (pjb-cl%%compare-chars char>= >= characters)) (defun char-equal (&rest characters) "Common-Lisp: similar to char= except it ignores differences in case and \ might have an implementation-defined behavior for non-simple characters. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_chareq.htm " (apply (function char=) (mapcar 'upcase characters))) (defun char-not-equal (&rest characters) "Common-Lisp: similar to char/= except it ignores differences in case and \ might have an implementation-defined behavior for non-simple characters. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_chareq.htm " (apply (function char/=) (mapcar 'upcase characters))) (defun char-lessp (&rest characters) "Common-Lisp: similar to char< except it ignores differences in case and \ might have an implementation-defined behavior for non-simple characters. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_chareq.htm " (apply (function char<) (mapcar 'upcase characters))) (defun char-greaterp (&rest characters) "Common-Lisp: similar to char> except it ignores differences in case and \ might have an implementation-defined behavior for non-simple characters. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_chareq.htm " (apply (function char>) (mapcar 'upcase characters))) (defun char-not-greaterp (&rest characters) "Common-Lisp: similar to char<= except it ignores differences in case and \ might have an implementation-defined behavior for non-simple characters. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_chareq.htm " (apply (function char<=) (mapcar 'upcase characters))) (defun char-not-lessp (&rest characters) "Common-Lisp: similar to char>= except it ignores differences in case and \ might have an implementation-defined behavior for non-simple characters. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_chareq.htm " (apply (function char>=) (mapcar 'upcase characters))) (defun ensure-character (ch) (cond ((characterp ch) ch) ((stringp ch) (char ch 0)) ((symbolp ch) (char (cl:symbol-name ch) 0)) ((numberp ch) (code-char* ch)) (t (error "Expected a character, not: %S" ch)))) (defun alpha-char-p (ch) " COMMON-LISP IMPLEMENTATION: Assumes ISO-8859-1! " ;;; (string-match ;;; "\\(\\c0\\|\\c1\\|\\c2\\|\\c3\\|\\c4\\|\\c6\\|\\c7\\|\\c8\\|\\c9\\)" ;;; (format "%c" ch)) ;; 0: consonant ;; 1: base (independent) vowel ;; 2: upper diacritical mark (including upper vowel) ;; 3: lower diacritical mark (including lower vowel) ;; 4: tone mark ;; 5: symbol ;; 6: digit ;; 7: vowel-modifying diacritical mark ;; 8: vowel-signs ;; 9: semivowel lower (let ((ch (ensure-character ch))) (or (and (char<= (character "A") ch) (char<= ch (character "Z"))) (and (char<= (character "a") ch) (char<= ch (character "z"))) (and (char<= (character "à") ch) (char<= ch (character "ö"))) (and (char<= (character "ø") ch) (char<= ch (character "ö"))) (and (char<= (character "ø") ch) (char<= ch (character "ÿ")))))) (defun alphanumericp (ch) " COMMON-LISP IMPLEMENTATION: Assumes ISO-8859-1! " (let ((ch (ensure-character ch))) (or (digit-char-p ch) (alpha-char-p ch)))) (defun* cl:digit-char-p (char &optional (radix 10)) (let ((value (position (upcase char) "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"))) (and value (< value radix) value))) (defun* cl:parse-integer (string &key (start 0) end (radix 10) junk-allowed) (let ((end (or end (length string))) (n 0) (sign 1) (plus (character "+")) (minus (character "-")) (space (character " "))) (labels ((parse-integer-error () (error "Not an integer string %S (:start %d :end %d :radix %d)" string start end radix)) (check-range () (unless (< start end) (parse-integer-error))) (eat-spaces (i) (loop while (and (< i end) (char= space (aref string i))) do (incf i) finally (return i)))) (setf start (eat-spaces start)) (check-range) (cond ((char= plus (aref string start)) (setf sign +1) (incf start) (check-range)) ((char= minus (aref string start)) (setf sign -1) (incf start) (check-range))) (loop for i from start below end for digit = (cl:digit-char-p (aref string i) radix) while digit do (setf n (+ (* n radix) digit)) finally (when (< i end) (setf i (eat-spaces i))) (when (and (not junk-allowed) (< i end)) (parse-integer-error)) (return (values (* sign n) i)))))) ;; --------------- ;; - 14 - Conses - ;; --------------- ;; c[ad]{2,4}r are defined in cl-macs.el ;; butlast, nbutlast are primitives in emacs 21.2. ;; --------------- ;; - 15 - Arrays - ;; --------------- ;; TODO: We should store the dimensions of the array somewhere! ;; TODO: We should add the fill-pointer! (defconstant array-dimension-limit 16777216 "Common-Lisp: A positive fixnum, the exact magnitude of which is implementation-dependent, but which is not less than 1024. IMPLEMENTATION: Actually, it seems the limit depends on the available memory somewhat around 2^27 in 32-bit emacs, or less depending on the current memory usage.") (defconstant array-rank-limit 16777216 "Common-Lisp: A positive fixnum, the exact magnitude of which is implementation-dependent, but which is not less than 8. IMPLEMENTATION: Since we make vector of vectors, there's no other limit than available memory.") (defun* make-array (dimensions &key element-type initial-element initial-contents adjustable fill-pointer displaced-to displaced-index-offset) "Common-Lisp: Creates and returns an array constructed of the most \ specialized type that can accommodate elements of type given by element-type. \ If dimensions is nil then a zero-dimensional array is created. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_mk_ar.htm#MAKE-ARRAY RETURN: A vector {of vectors}. NOTE: :element-type is ignored. :adjustable is ignored. :fill-pointer is not supported. :displaced-to is not supported. :displaced-index-offset is not supported. " (when (numberp dimensions) (setq dimensions (list dimensions))) (when (and displaced-to (or initial-element initial-contents)) (error (concatenate 'string ":displaced-to must not be specified along with " ":initial-element or :initial-contents."))) (when (and initial-element (or displaced-to initial-contents)) (error (concatenate 'string ":initial-element must not be specified along with " " or :displaced-to :initial-contents."))) (when (and displaced-index-offset (null displaced-to)) (error (concatenate 'string ":displaced-index-offset must not be specified " "without :displaced-to."))) (when (and fill-pointer (/= 1 (length dimensions))) (error (concatenate 'string ":fill-pointer can only be specified for vectors " " (uni-dimensional arrays)."))) (when fill-pointer (error "fill-pointers not implemented. Sorry.")) (when displaced-to (error "displaced-to arrays are not implemented. Sorry.")) (cond ((null dimensions) (error "a-dimensional arrays are not implemented. Sorry.")) (initial-contents (if (= 1 (length dimensions)) (loop with result = (make-vector (car dimensions) initial-element) for i from 0 below (length initial-contents) do (setf (aref result i) (elt initial-contents i)) finally return result) (loop with result = (make-vector (car dimensions) initial-element) for i from 0 below (length initial-contents) do (setf (aref result i) (make-array (cdr dimensions) :initial-contents (elt initial-contents i) :adjustable adjustable ;; the rest is not implemented. )) finally return result))) (t ;; let's use initial-element (if (= 1 (length dimensions)) (make-vector (car dimensions) initial-element) (loop with result = (make-vector (car dimensions) initial-element) for i from 0 below (car dimensions) do (setf (aref result i) (make-array (cdr dimensions) :initial-element initial-element :adjustable adjustable ;; the rest is not implemented. )) finally return result))))) (defun array-dimension (array axis-number) "Common-Lisp: array-dimension returns the axis-number dimension[1] of array. Any fill pointer is ignored. " (if (= 0 axis-number) (length array) (array-dimension (aref array 0) (1- axis-number)))) (defadvice aref (around pjb-cl-aref first (array &rest subscripts) activate) "Common-Lisp: Accesses the array element specified by the subscripts. \ If no subscripts are supplied and array is zero rank, aref accesses the \ sole element of array. NOTE: zero rank arrays are not supported. " (setq ad-return-value (if (= 1 (length subscripts)) ad-do-it (loop for vector = array then (aref vector index) for index in subscripts ;;do (printf "vector = %S index = %S\n" vector index) finally return vector)))) (ad-activate 'aref) (defun pjb-cl%%aset (array &rest subscripts-and-value) "PRIVATE DO: sets the value of the element in array at subcripts. NOTE: Used as (defsetf aref pjb-cl%%aset). " (let ((value (car (last subscripts-and-value))) (subscripts (butlast subscripts-and-value))) (aset (apply 'aref array (butlast subscripts)) (car (last subscripts)) value))) (defsetf aref pjb-cl%%aset) (deftype vector* () '(or string vector)) (defun vectorp* (item) (or (vectorp item) (stringp item))) ;; ----------------- ;; - 16 - Strings - http://.../cltl/clm/node165.html ;; ----------------- (defun cl:string (x) "Common-Lisp: If X is a string, then X, else if it's a symbol, then (cl:symbol-name X). X---a string, a symbol, or a character. Returns a string described by x; specifically: * If X is a string, it is returned. * If X is a symbol, its name is returned. * If X is a character, then a string containing that one character is returned. * string might perform additional, implementation-defined conversions. If there are more than one arguments, then emacs string is called. " (cond ((stringp x) x) ((symbolp x) (cl:symbol-name x)) ((characterp x) (make-string* 1 :initial-element x)) (t (signal 'type-error "Expected a string, a symbol or a character.")))) (defun char (str index) "Common-Lisp: The character at position index of the string is returned \ as a character object. RETURN: [cltl2] The given index must be a non-negative integer less than the length of string, which must be a string. The character at position index of the string is returned as a character object. " (setq str (cl:string str)) (aref (the string str) index)) (defsetf char aset) (defun schar (simple-string index) "Common-Lisp: The character at position index of the string is returned \ as a character object. RETURN: [cltl2] The given index must be a non-negative integer less than the length of string, which must be a string. The character at position index of the string is returned as a character object. (This character will necessarily satisfy the predicate string-char-p.) " (setq simple-string (cl:string simple-string)) (aref simple-string index)) (defsetf schar aset) (defun cl:string-equal (string1 string2 &rest cl-keys) (setq string1 (cl:string string1) string2 (cl:string string2)) (let ((start1 (or (cadr (memq :start1 cl-keys)) 0)) (end1 (or (cadr (memq :end1 cl-keys)) (length string1))) (start2 (or (cadr (memq :start2 cl-keys)) 0)) (end2 (or (cadr (memq :end2 cl-keys)) (length string2)))) (if (/= (- end1 start1) (- end2 start2)) nil (string-equal (string-upcase (substring string1 start1 end1)) (string-upcase (substring string2 start2 end2)))))) (defun cl:string-lessp (string1 string2 &rest cl-keys) (setq string1 (cl:string string1) string2 (cl:string string2)) (let ((start1 (or (cadr (memq :start1 cl-keys)) 0)) (end1 (or (cadr (memq :end1 cl-keys)) (length string1))) (start2 (or (cadr (memq :start2 cl-keys)) 0)) (end2 (or (cadr (memq :end2 cl-keys)) (length string2))) ) (if (/= (- end1 start1) (- end2 start2)) nil (string-lessp (string-upcase (substring string1 start1 end1)) (string-upcase (substring string2 start2 end2)))))) (defun string-greaterp* (string1 string2 &rest cl-keys) (not (string-not-lessp string2 string1 :start1 (or (cadr (memq :start2 cl-keys)) nil) :end1 (or (cadr (memq :end2 cl-keys)) (length string2)) :start2 (or (cadr (memq :start1 cl-keys)) nil) :end2 (or (cadr (memq :end1 cl-keys)) (length string1))))) (defun string-not-lessp (string1 string2 &rest cl-keys) (not (apply (function string-lessp) string1 string2 cl-keys))) (defun string-not-greaterp (string1 string2 &rest cl-keys) (not (apply (function string-greaterp) string1 string2 cl-keys))) (defun string-not-equal (string1 string2 &rest cl-keys) (not (apply (function string-equal) string1 string2 cl-keys))) (defun cl:string= (string1 string2 &rest cl-keys) ;; &key :start1 :end1 :start2 :end2) "Common-Lisp: compares two strings and is true if they are the \ same (corresponding characters are identical) but is false if they are not. DO: [cltl2] string= compares two strings and is true if they are the same (corresponding characters are identical) but is false if they are not. The function equal calls string= if applied to two strings. The keyword arguments :start1 and :start2 are the places in the strings to start the comparison. The arguments :end1 and :end2 are the places in the strings to stop comparing; comparison stops just before the position specified by a limit. The ``start'' arguments default to zero (beginning of string), and the ``end'' arguments (if either omitted or nil) default to the lengths of the strings (end of string), so that by default the entirety of each string is examined. These arguments are provided so that substrings can be compared efficiently. string= is necessarily false if the (sub)strings being compared are of unequal length; that is, if (not (= (- end1 start1) (- end2 start2))) is true, then string= is false. " ;; TODO: should use compare-string (setq string1 (cl:string string1) string2 (cl:string string2)) (let ((start1 (or (cadr (memq :start1 cl-keys)) 0)) (end1 (or (cadr (memq :end1 cl-keys)) (length string1))) (start2 (or (cadr (memq :start2 cl-keys)) 0)) (end2 (or (cadr (memq :end2 cl-keys)) (length string2)))) (if (/= (- end1 start1) (- end2 start2)) nil (string-equal (substring string1 start1 end1) (substring string2 start2 end2))))) (defun cl:string< (string1 string2 &rest cl-keys) ;; &key :start1 :end1 :start2 :end2) "Common-Lisp: compares two strings. The keyword arguments :start1 and :start2 are the places in the strings to start the comparison. The arguments :end1 and :end2 are the places in the strings to stop comparing; comparison stops just before the position specified by a limit. The ``start'' arguments default to zero (beginning of string), and the ``end'' arguments (if either omitted or nil) default to the lengths of the strings (end of string), so that by default the entirety of each string is examined. These arguments are provided so that substrings can be compared efficiently. " ;; TODO: should use compare-string (setq string1 (cl:string string1) string2 (cl:string string2)) (let ((start1 (or (cadr (memq :start1 cl-keys)) 0)) (end1 (or (cadr (memq :end1 cl-keys)) (length string1))) (start2 (or (cadr (memq :start2 cl-keys)) 0)) (end2 (or (cadr (memq :end2 cl-keys)) (length string2)))) (string-lessp (substring string1 start1 end1) (substring string2 start2 end2)))) (defun cl:string> (string1 string2 &rest cl-keys) ;; &key :start1 :end1 :start2 :end2) "Common-Lisp: compares two strings. The keyword arguments :start1 and :start2 are the places in the strings to start the comparison. The arguments :end1 and :end2 are the places in the strings to stop comparing; comparison stops just before the position specified by a limit. The ``start'' arguments default to zero (beginning of string), and the ``end'' arguments (if either omitted or nil) default to the lengths of the strings (end of string), so that by default the entirety of each string is examined. These arguments are provided so that substrings can be compared efficiently. " ;; TODO: should use compare-string (setq string1 (cl:string string1) string2 (cl:string string2)) (let ((start1 (or (cadr (memq :start1 cl-keys)) 0)) (end1 (or (cadr (memq :end1 cl-keys)) (length string1))) (start2 (or (cadr (memq :start2 cl-keys)) 0)) (end2 (or (cadr (memq :end2 cl-keys)) (length string2)))) (string-lessp (substring string2 start2 end2) (substring string1 start1 end1)))) (defun cl:string<= (string1 string2 &rest cl-keys) ;; &key :start1 :end1 :start2 :end2) "Common-Lisp: compares two strings. The keyword arguments :start1 and :start2 are the places in the strings to start the comparison. The arguments :end1 and :end2 are the places in the strings to stop comparing; comparison stops just before the position specified by a limit. The ``start'' arguments default to zero (beginning of string), and the ``end'' arguments (if either omitted or nil) default to the lengths of the strings (end of string), so that by default the entirety of each string is examined. These arguments are provided so that substrings can be compared efficiently. " ;; TODO: should use compare-string (setq string1 (cl:string string1) string2 (cl:string string2)) (let ( (start1 (or (cadr (memq :start1 cl-keys)) 0)) (end1 (or (cadr (memq :end1 cl-keys)) (length string1))) (start2 (or (cadr (memq :start2 cl-keys)) 0)) (end2 (or (cadr (memq :end2 cl-keys)) (length string2)))) (not (string-lessp (substring string2 start2 end2) (substring string1 start1 end1))))) (defun cl:string>= (string1 string2 &rest cl-keys) ;; &key :start1 :end1 :start2 :end2) "Common-Lisp: compares two strings. The keyword arguments :start1 and :start2 are the places in the strings to start the comparison. The arguments :end1 and :end2 are the places in the strings to stop comparing; comparison stops just before the position specified by a limit. The ``start'' arguments default to zero (beginning of string), and the ``end'' arguments (if either omitted or nil) default to the lengths of the strings (end of string), so that by default the entirety of each string is examined. These arguments are provided so that substrings can be compared efficiently. " ;; TODO: should use compare-string (setq string1 (cl:string string1) string2 (cl:string string2)) (let ((start1 (or (cadr (memq :start1 cl-keys)) 0)) (end1 (or (cadr (memq :end1 cl-keys)) (length string1))) (start2 (or (cadr (memq :start2 cl-keys)) 0)) (end2 (or (cadr (memq :end2 cl-keys)) (length string2)))) (not (string-lessp (substring string1 start1 end1) (substring string2 start2 end2))))) (defun cl:string/= (string1 string2 &rest cl-keys) ;; &key :start1 :end1 :start2 :end2) "Common-Lisp: compares two strings and return whether they're different. The keyword arguments :start1 and :start2 are the places in the strings to start the comparison. The arguments :end1 and :end2 are the places in the strings to stop comparing; comparison stops just before the position specified by a limit. The ``start'' arguments default to zero (beginning of string), and the ``end'' arguments (if either omitted or nil) default to the lengths of the strings (end of string), so that by default the entirety of each string is examined. These arguments are provided so that substrings can be compared efficiently. " ;; TODO: should use compare-string (not (apply 'string= string1 string2 cl-keys))) (defun* make-string* (size &key (initial-element 0) (element-type 'character)) "Common-Lisp: MAKE-STRING takes a key :initial-element argument " (make-string size initial-element)) (defun cl:string-trim (character-bag string-designator) "Common-Lisp: returns a substring of string, with all characters in \ character-bag stripped off the beginning and end. " (unless (sequencep character-bag) (signal 'type-error "Expected a sequence for `character-bag'.")) (let* ((string (cl:string string-designator)) (margin (format "[%s]*" (regexp-quote (if (stringp character-bag) character-bag (map 'string 'identity character-bag))))) (trimer (format "\\`%s\\(\\(.\\|\n\\)*?\\)%s\\'" margin margin))) (replace-regexp-in-string trimer "\\1" string))) (defun string-left-trim (character-bag string-designator) "Common-Lisp: returns a substring of string, with all characters in \ character-bag stripped off the beginning. " (unless (sequencep character-bag) (signal 'type-error "Expected a sequence for `character-bag'.")) (let* ((string (cl:string string-designator)) (margin (format "[%s]*" (regexp-quote (if (stringp character-bag) character-bag (map 'string 'identity character-bag))))) (trimer (format "\\`%s\\(\\(.\\|\n\\)*?\\)\\'" margin))) (replace-regexp-in-string trimer "\\1" string))) (defun string-right-trim (character-bag string-designator) "Common-Lisp: returns a substring of string, with all characters in \ `character-bag' stripped off the end. " (unless (sequencep character-bag) (signal 'type-error "Expected a sequence for `character-bag'.")) (let* ((string (cl:string string-designator)) (margin (format "[%s]*" (regexp-quote (if (stringp character-bag) character-bag (map 'string 'identity character-bag))))) (trimer (format "\\`\\(\\(.\\|\n\\)*?\\)%s\\'" margin))) (replace-regexp-in-string trimer "\\1" string))) (defun string-upcase (str &rest cl-keys) ;; &key :start :end "Common-Lisp: returns a string just like `str' with all lowercase \ characters replaced by the corresponding uppercase characters. The keyword argument :start specifies the place in the string where to start the upcase. The argument :end specifies the place in the string where to stop upcase; upcase stops just before the position specified by a limit. The ``start'' arguments default to zero (beginning of string), and the ``end'' arguments (if either omitted or nil) default to the lengths of the strings (end of string), so that by default the entirety of each string is upcased. " (setq str (cl:string str)) (let ( (start (or (cadr (memq :start cl-keys)) 0)) (end (or (cadr (memq :end cl-keys)) (length str))) ) (concat (substring str 0 start) (upcase (substring str start end)) (substring str end)))) (defun string-downcase (str &rest cl-keys) ;; &key :start :end "Common-Lisp: returns a string just like `str' with all uppercase \ characters replaced by the corresponding lowercase characters. The keyword argument :start specifies the place in the string where to start the downcase. The argument :end specifies the place in the string where to stop downcase; downcase stops just before the position specified by a limit. The ``start'' arguments default to zero (beginning of string), and the ``end'' arguments (if either omitted or nil) default to the lengths of the strings (end of string), so that by default the entirety of each string is downcased. " (setq str (cl:string str)) (let ( (start (or (cadr (memq :start cl-keys)) 0)) (end (or (cadr (memq :end cl-keys)) (length str))) ) (concat (substring str 0 start) (downcase (substring str start end)) (substring str end)))) (defun string-capitalize (str &rest cl-keys) ;; &key :start :end "Common-Lisp: returns a string just like `str' with all words capitalized. The keyword argument :start specifies the place in the string where to start the capitalization. The argument :end specifies the place in the string where to stop capitalization; capitalization stops just before the position specified by a limit. The ``start'' arguments default to zero (beginning of string), and the ``end'' arguments (if either omitted or nil) default to the lengths of the strings (end of string), so that by default the entirety of each string is capitalized. " (setq str (cl:string str)) (let ( (start (or (cadr (memq :start cl-keys)) 0)) (end (or (cadr (memq :end cl-keys)) (length str))) ) (concat (substring str 0 start) (capitalize (substring str start end)) (substring str end)))) (defun nstring-upcase (str &rest cl-keys) ;; &key :start :end "Common-Lisp: modify `str' replacing lowercase characters \ by the corresponding uppercase characters. The keyword argument :start specifies the place in the string where to start the upcase. The argument :end specifies the place in the string where to stop upcase; upcase stops just before the position specified by a limit. The ``start'' arguments default to zero (beginning of string), and the ``end'' arguments (if either omitted or nil) default to the lengths of the strings (end of string), so that by default the entirety of each string is upcased. " (unless (stringp str) (signal 'type-error "Expected a string.")) (let ( (start (or (cadr (memq :start cl-keys)) 0)) (end (or (cadr (memq :end cl-keys)) (length str))) ) (do ((i start (1+ i))) ((<= end i) str) (setf (aref str i) (upcase (aref str i)))))) (defun nstring-downcase (str &rest cl-keys) ;; &key :start :end "Common-Lisp: modify `str' replacing uppercase characters \ by the corresponding lowercase characters. The keyword argument :start specifies the place in the string where to start the downcase. The argument :end specifies the place in the string where to stop downcase; downcase stops just before the position specified by a limit. The ``start'' arguments default to zero (beginning of string), and the ``end'' arguments (if either omitted or nil) default to the lengths of the strings (end of string), so that by default the entirety of each string is downcased. " (unless (stringp str) (signal 'type-error "Expected a string.")) (let ( (start (or (cadr (memq :start cl-keys)) 0)) (end (or (cadr (memq :end cl-keys)) (length str))) ) (do ((i start (1+ i))) ((<= end i) str) (setf (aref str i) (downcase (aref str i)))))) (defun nstring-capitalize (str &rest cl-keys) ;; &key :start :end "Common-Lisp: modify `str' capitalizing words. The keyword argument :start specifies the place in the string where to start the capitalization. The argument :end specifies the place in the string where to stop capitalization; capitalization stops just before the position specified by a limit. The ``start'' arguments default to zero (beginning of string), and the ``end'' arguments (if either omitted or nil) default to the lengths of the strings (end of string), so that by default the entirety of each string is capitalized. " (unless (stringp str) (signal 'type-error "Expected a string.")) (let* ( (start (or (cadr (memq :start cl-keys)) 0)) (end (or (cadr (memq :end cl-keys)) (length str))) (capit (capitalize (substring str start end))) (len (length capit)) ) (do ((i 0 (1+ i))) ((<= len i) str) (setf (aref str (+ start i)) (aref capit i))))) ;; -------------------------------- ;; - 17 - Sequences ;; -------------------------------- (defclass iterator () ()) (defclass iterator-list (iterator) ((head :initarg :sequence :type list))) (defclass iterator-vector (iterator) ((vector :initarg :sequence :type VECTOR) (index :initform 0))) (defmethod end-of-sequence-p ((self iterator-list)) (null (slot-value self 'head))) (defmethod end-of-sequence-p ((self iterator-vector)) (>= (slot-value self 'index) (length (slot-value self 'vector)))) (defmethod current-item ((self iterator-list)) (car (slot-value self 'head))) (defmethod current-item ((self iterator-vector)) (aref (slot-value self 'vector) (slot-value self 'index))) (defmethod set-current-item ((self iterator-list) value) (setf (car (slot-value self 'head)) value)) (defmethod set-current-item ((self iterator-vector) value) (setf (aref (slot-value self 'vector) (slot-value self 'index)) value)) (defmethod advance ((self iterator-list)) (setf (slot-value self 'head) (cdr (slot-value self 'head)))) (defmethod advance ((self iterator-vector)) (incf (slot-value self 'index))) (defun map-into (result-sequence function &rest sequences) (cond ((every (function listp) sequences) (cond ((listp result-sequence) (do ((sequences sequences (mapcar (function cdr) sequences)) (target result-sequence (cdr target))) ((or (null target) (some (function null) sequences)) result-sequence) (setf (car target) (apply function (mapcar (function car) sequences))))) ((vectorp* result-sequence) (do ((sequences sequences (mapcar (function cdr) sequences)) (target 0 (1+ target))) ((or (>= target (length result-sequence)) (some (function null) sequences)) result-sequence) (setf (aref result-sequence target) (apply function (mapcar (function car) sequences))))) (t (error "RESULT-SEQUENCE is neither a LIST or a VECTOR.")))) ((every (function vectorp*) sequences) (cond ((listp result-sequence) (do ((source 0 (1+ source)) (min (apply (function min) (mapcar (function length) sequences))) (target result-sequence (cdr target))) ((or (null target) (>= source min)) result-sequence) (setf (car target) (apply function (mapcar (lambda (seq) (aref seq source)) sequences))))) ((vectorp* result-sequence) (do ((index 0 (1+ index)) (min (apply (function min) (length result-sequence) (mapcar (function length) sequences)))) ((>= index min) result-sequence) (setf (aref result-sequence index) (apply function (mapcar (lambda (seq) (aref seq index)) sequences))))) (t (error "RESULT-SEQUENCE is neither a LIST or a VECTOR.")))) (t (do ((res (make-instance (cond ((listp result-sequence) 'iterator-list) ((vectorp* result-sequence) 'iterator-vector) (t (error "RESULT-SEQUENCE is neither a LIST or a VECTOR."))) :sequence result-sequence)) (sequences (mapcar (lambda (seq) (make-instance (cond ((listp seq) 'iterator-list) ((vectorp* seq) 'iterator-vector) (t (error "A SEQUENCE is neither a LIST or a VECTOR."))) :sequence seq)) sequences))) ((some (function end-of-sequence-p) (cons res sequences)) result-sequence) (set-current-item res (apply function (mapcar (function current-item) sequences))) (dolist (seq (cons res sequences)) (advance seq)))))) ;; (MAP-INTO [0 0 0 0] (function +) "ABCD" '(1 1 1)) ;; (MAP-INTO [0 0 0 0] (function +) '(1 2 3 4) '(1 1 1)) ;; (MAP-INTO [0 0 0 0] (function +) '(1 2 3 4) '(1 1 1)) ;; (MAP-INTO [0 0 0 0] (function +) '(1 2 3 4 5) [1 1 1]) ;; (MAP-INTO (copy-seq '(0 0 0 0)) (function +) '(1 2 3 4 5) [1 1 1]) ;; (MAP-INTO (copy-seq "------") (function +) '(1 1 1 1) "HAL") ;; (MAP-INTO (copy-seq "------") (function +) [1 1 1 1] "HAL") ;; -------------------------------- ;; - 19.4 - Pathnames - Filenames - ;; -------------------------------- (defun namestring (pathname) "Common-Lisp: returns the full form of pathname. These functions convert pathname into a namestring. The name represented by pathname is returned as a namestring in an implementation-dependent canonical form. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_namest.htm NOTE: in current implementation pathname=namestring. " pathname) (defun file-namestring (pathname) "Common-Lisp: returns just the name, type, and version components of pathname. These functions convert pathname into a namestring. The name represented by pathname is returned as a namestring in an implementation-dependent canonical form. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_namest.htm NOTE: in current implementation pathname=namestring. RETURN: the 'basename' of the pathname. " ;; (if (string-match "\\(^.*/\\([^/][^/]*\\)/*$\\)\\|\\(^\\([^/][^/]*\\)/*$\\)" ;; pathname) ;; (let ((res (match-string 2 pathname))) ;; (if res res (match-string 4 pathname))) ;; pathname) (file-name-nondirectory pathname)) (defun directory-namestring (pathname) "Common-Lisp: returns the directory name portion. These functions convert pathname into a namestring. The name represented by pathname is returned as a namestring in an implementation-dependent canonical form. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_namest.htm NOTE: in current implementation pathname=namestring. RETURN: the 'basename' of the pathname. " ;; (if (string-match "\\(^.*[^/].*\\)/[^/][^/]*/*$" pathname) ;; (match-string 1 pathname) ;; (if (= ?/ (aref pathname 0)) "/" ".")) (file-name-directory pathname)) (defun host-namestring (pathname) "Common-Lisp: returns the host name. These functions convert pathname into a namestring. The name represented by pathname is returned as a namestring in an implementation-dependent canonical form. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_namest.htm NOTE: in current implementation pathname=namestring. RETURN: (system-name) " (system-name)) (defun pathname-host (path) nil) (defun pathname-directory (path) (directory-namestring path)) (defun pathname-name (path) (setq path (file-namestring path)) (cond ((string-match "^\\(.*\\)\\.\\([^.]*\\)\\(\\.~[0-9]+~\\)$" path) (match-string 1 path)) ((string-match "^\\(.*\\)\\.\\([^.]*\\)$" path) (match-string 1 path)) (t :unspecific))) ;; (mapcar (lambda (x) (list (dirname x) (basename x) (pathname-name x))) ;; '("abc" "abc.def" "abc.def.ghi" ;; "/abc" "/abc.def" "/abc.def.ghi" ;; "./abc" "./abc.def" "./abc.def.ghi" ;; "ddd/abc" "ddd/abc.def" "ddd/abc.def.ghi" ;; "eee/ddd/abc" "eee/ddd/abc.def" "eee/ddd/abc.def.ghi" ;; "/eee/ddd/abc" "/eee/ddd/abc.def" "/eee/ddd/abc.def.ghi")) (defun pathname-type (path) "RETURN: The file name extension (excluding the version number .~N~)." (cond ((string-match ".*\\.\\([^.]*\\)\\(\\.~[0-9]+~\\)$" path) (match-string 1 path)) ((string-match ".*\\.\\([^.]*\\)$" path) (match-string 1 path)) (t :unspecific))) (defun pathname-version (path) "RETURN: The version number." (if (string-match ".*\\.[^\\.]*?\\.~\\([0-9]+\\)~$" path) (nth-value 0 (cl:parse-integer (match-string 1 path))) :unspecific)) ;;; (defun enough-namestring (pathname &optional defaults) ;;; "Common-Lisp: returns an abbreviated namestring that is just sufficient to identify the \ ;;; file named by pathname when considered relative to the defaults. ;;; It is required that: ;;; (merge-pathnames (enough-namestring pathname defaults) defaults) ;;; == (merge-pathnames (parse-namestring pathname nil defaults) defaults) ;;; in all cases, and the result of enough-namestring is the shortest reasonable string that will ;;; satisfy this criterion. ;;; It is not necessarily possible to construct a valid namestring by concatenating some of the ;;; three shorter namestrings in some order. ;;; These functions convert pathname into a namestring. The name represented by pathname is ;;; returned as a namestring in an implementation-dependent canonical form. ;;; URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_namest.htm ;;; NOTE: in current implementation pathname=namestring. ;;; RETURN: (system-name) ;;; " ;;; ) ;; -------------- ;; - 20 - Files - ;; -------------- (defun* directory (pathspec &key relative-paths) "Common-Lisp: Determines which, if any, files that are present in the \ file system have names matching pathspec, and returns a fresh list of \ pathnames corresponding to the truenames of those files. pathspec: a pathname designator, which may contain wild components. pathnames: a list of physical pathnames. NOTE: An implementation may be extended to accept implementation-defined keyword arguments to directory. NOTE: this implementation accepts an :relative-paths key that can be set to t to avoid forcing absolute paths result. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_dir.htm " (when (search "**" pathspec) (error "CL ** wild-inferior is not implemented.")) (file-expand-wildcards pathspec (not relative-paths))) (defun probe-file (pathspec) "Common-Lisp: Returns false if there is no file named pathspec, and otherwise returns the truename of pathspec. RETURN: nil, or pathspec (we don't distinguish truename for now). URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_probe_.htm " (when (file-exists-p pathspec) pathspec)) (defun* ensure-directories-exist (pathspec &key verbose) (make-directory pathspec t)) (defun truename (filespec) " RETURN: The absolute path name corresponding to fielspec. " (car (file-expand-wildcards (shell-quote-argument filespec) t))) (defun file-author (pathspec) "Common-Lisp: Returns a string naming the author of the file specified \ by pathspec, or nil if the author's name cannot be determined. RETURN: nil (we cannot determine no author on unix systems. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_file_a.htm#file-author " nil) (defun file-write-date (pathspec) "Common-lisp: Returns a universal time representing the time at which \ the file specified by pathspec was last written (or created), \ or returns nil if such a time cannot be determined. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/f_file_w.htm NOTE: Current implementation does not accept a stream for a pathspec. " (let ((attributes (file-attributes pathspec))) (unless attributes ;; TODO: see the error processing. We should signal a file-error here. ;; (signal 'file-error ;; (FORMAT nil "file-write-date cannot get attributes for file ~S" ;; pathspec)) (error "file-write-date cannot get attributes for file %S" pathspec)) (+ pjb-cl%%epoch (pjb-cl%%emacs-time-to-seconds (nth 5 attributes))))) ;; TODO: rename-file exists but does not return the same. ;; http://www.informatimago.com/local/lisp/HyperSpec/Body/f_rn_fil.htm ;; TODO: delete-file exists but does not return the same. ;; http://www.informatimago.com/local/lisp/HyperSpec/Body/f_del_fi.htm ;; file-error ;; http://www.informatimago.com/local/lisp/HyperSpec/Body/e_file_e.htm ;; file-error-pathname (condition) ;; http://www.informatimago.com/local/lisp/HyperSpec/Body/f_file_e.htm ;; ---------------- ;; - 21 - Streams - ;; ---------------- (defvar *debug-io* :stderr "The value of *DEBUG-IO*, called debug I/O, is a stream to be used for interactive debugging purposes. Bi-directional stream.") (defvar *error-output* :stderr "The value of *ERROR-OUTPUT*, called error output, is a stream to which warnings and non-interactive error messages should be sent. Output stream.") (defvar *query-io* t "The value of *QUERY-IO*, called query I/O, is a bidirectional stream to be used when asking questions of the user. The question should be output to this stream, and the answer read from it. Bi-directional stream.") (defvar *standard-input* t "The value of *STANDARD-INPUT*, called standard input, is a stream that is used by many operators as a default source of input when no specific input stream is explicitly supplied. Input stream.") (defvar *standard-output* :stdout "The value of *STANDARD-OUTPUT*, called standard output, is a stream that is used by many operators as a default destination for output when no specific output stream is explicitly supplied. Output stream.") (defvar *trace-output* :stderr "The value of *TRACE-OUTPUT*, called trace output, is the stream on which traced functions (see trace) and the time macro print their output. Output stream.") (defvar *terminal-io* t "The value of *TERMINAL-IO*, called terminal I/O, is ordinarily a bidirectional stream that connects to the user's console. Typically, writing to this stream would cause the output to appear on a display screen, for example, and reading from the stream would accept input from a keyboard. It is intended that standard input functions such as read and read-char, when used with this stream, cause echoing of the input into the output side of the stream. The means by which this is accomplished are implementation-dependent. Bi-directional stream.") ;; -------------------- ;; - 25 - Environment - ;; -------------------- ;; Time functions - http://.../cltl/clm/node232.html (defun get-internal-real-time () (destructuring-bind (high low microsec &rest ignored) (current-time) (declare (ignore ignored)) (+ (* high 65536.0) low (* 1e-6 microsec)))) (defmacro time (&rest body) "Common-Lisp: time evaluates form in the current environment (lexical and \ dynamic). A call to time can be compiled. DO: time prints various timing data and other information to trace output. The nature and format of the printed information is implementation-defined . Implementations are encouraged to provide such information as elapsed real time, machine run time, and storage management statistics. URL: http://www.informatimago.com/local/lisp/HyperSpec/Body/m_time.htm " (let ((start (gensym)) (result (gensym)) (stop (gensym)) (time (gensym))) `(let* ((,start (get-internal-real-time)) (,result (progn ,@body)) (,stop (get-internal-real-time)) (,time (- ,stop ,start)) ) (printf *trace-output* "Time: %e ms\n" ,time)))) (defun sleep (seconds) "Common-Lisp: Sleeps a specified number of seconds. DO: (sleep n) causes execution to cease and become dormant for approximately n seconds of real time, whereupon execution is resumed. The argument may be any non-negative non-complex number. sleep returns nil. " (sleep-for seconds)) (defmacro trace (&rest function-names) "Common-Lisp:" (map nil (function trace-function-background) function-names)) (defmacro untrace (&rest function-names) "Common-Lisp:" (map nil (function untrace-function) function-names)) ;;- Other Environment Inquiries - http://.../cltl/clm/node233.html (defun lisp-implementation-type () "Common-Lisp: A string is returned that identifies this Common Lisp implementation. RETURN: \"emacs\" " "emacs") (defun lisp-implementation-version () "Common-Lisp: A string is returned that identifies the version of this Common Lisp implementation. RETURN: emacs-version. " emacs-version) (defun machine-type () "Common-Lisp: A string is returned that identifies the generic name of the computer hardware. RETURN: The first part of system-configuration NOTE: This is not exactly the machine-type, but rather, the type of machine this emacs was compiled for. More information could be got with (shell-command ...) and OS-specific commands. " (substring system-configuration 0 (string-match "-" system-configuration 0))) (defun machine-version () "Common-Lisp: A string is returned that identifies the version of the \ computer hardware. RETURN: The same as (machine-type). Sorry about that. " (machine-type)) (defun machine-instance () "Common-Lisp: A string is returned that identifies the particular instance \ of the computer hardware on which Common Lisp is running. RETURN: (system-name) " (system-name)) (defun software-type () "Common-Lisp: A string is returned that identifies the generic name of \ any relevant supporting software. RETURN: The rest of system-configuration. " (substring system-configuration (1+ (string-match "-" system-configuration 0)))) (defun software-version () "Common-Lisp: A string is returned that identifies the version of any \ relevant supporting software; this information should be of use to \ maintainers of the implementation. RETURN: \"\" " emacs-version) (defun short-site-name () "Common-Lisp: A string is returned that identifies the physical location \ of the computer hardware. RETURN: (machine-instance). " (machine-instance)) (defun long-site-name () "Common-Lisp: A string is returned that identifies the physical location \ of the computer hardware. RETURN: (machine-instance). " (machine-instance)) (defun dirname (path) (if (string-match "^\\(.*/\\)\\([^/]*\\)$" path) (match-string 1 path) "./")) (defun basename (path &optional extension) (let ((extension (or extension ""))) (if (string-match (format "^\\(.*/\\)\\([^/]*\\)%s$" (regexp-quote extension)) path) (match-string 2 path) path))) (defvar cl::*user-homedir-pathname*) (setf cl::*user-homedir-pathname* (cond (user-init-file (dirname user-init-file)) ((getenv "HOME") (concat (getenv "HOME") "/")) (t (dirname (first (file-expand-wildcards "~/.emacs")))))) (defun user-homedir-pathname (&optional host) cl::*user-homedir-pathname*) ;; ------------------------------------------------------------------------ (defun cl-indent (symbol num-forms) " Put on the SYMBOL and its lower case and upper case variants a 'lisp-indent-function property set to NUM-FORMS. " (dolist (property '(lisp-indent-function common-lisp-indent-function)) (put symbol property num-forms) (put (intern (string-downcase (cl:symbol-name symbol))) property num-forms) (put (intern (string-upcase (cl:symbol-name symbol))) property num-forms))) (defun loop-doc (&rest args) "(loop CLAUSE...): The Common Lisp `loop' macro. Valid clauses are: for VAR from/upfrom/downfrom NUM to/upto/downto/above/below NUM by NUM for VAR in LIST by FUNC for VAR on LIST by FUNC for VAR = INIT then EXPR for VAR across ARRAY with VAR = INIT Miscellaneous Clauses: named NAME initially EXPRS... Accumulation Clauses: collect EXPR into VAR append EXPR into VAR nconc EXPR into VAR sum EXPR into VAR count EXPR into VAR maximize EXPR into VAR minimize EXPR into VAR Termination Test Clauses: repeat NUM while COND until COND always COND never COND thereis COND Unconditional Execution Clause: do EXPRS... Conditional Execution Clauses: if COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...] unless COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...] Miscellaneous Clauses: finally EXPRS... return EXPR finally return EXPR ;;; (loop for i in '(1 2 3 4) ;;; collect i into col ;;; append i into app ;;; nconc i into nco ;;; sum i into sum ;;; count i into cnt ;;; maximize i into max ;;; minimize i into min ;;; do (printf \"%d \" i) ;;; return (progn (printf \"\n\" i) ;;; (values col app nco sum cnt max min))) ") (defconst +common-lisp-external-symbols+ '( &ALLOW-OTHER-KEYS *PRINT-MISER-WIDTH* &AUX *PRINT-PPRINT-DISPATCH* &BODY *PRINT-PRETTY* &ENVIRONMENT *PRINT-RADIX* &KEY *PRINT-READABLY* &OPTIONAL *PRINT-RIGHT-MARGIN* &REST *QUERY-IO* &WHOLE *RANDOM-STATE* * *READ-BASE* ** *READ-DEFAULT-FLOAT-FORMAT* *** *READ-EVAL* *BREAK-ON-SIGNALS* *READ-SUPPRESS* *COMPILE-FILE-PATHNAME* *READTABLE* *COMPILE-FILE-TRUENAME* *STANDARD-INPUT* *COMPILE-PRINT* *STANDARD-OUTPUT* *COMPILE-VERBOSE* *TERMINAL-IO* *DEBUG-IO* *TRACE-OUTPUT* *DEBUGGER-HOOK* + *DEFAULT-PATHNAME-DEFAULTS* ++ *ERROR-OUTPUT* +++ *FEATURES* - *GENSYM-COUNTER* / *LOAD-PATHNAME* // *LOAD-PRINT* /// *LOAD-TRUENAME* /= *LOAD-VERBOSE* 1+ *MACROEXPAND-HOOK* 1- *MODULES* < *PACKAGE* <= *PRINT-ARRAY* = *PRINT-BASE* > *PRINT-CASE* >= *PRINT-CIRCLE* ABORT *PRINT-ESCAPE* ABS *PRINT-GENSYM* ACONS *PRINT-LENGTH* ACOS *PRINT-LEVEL* ACOSH *PRINT-LINES* ADD-METHOD ADJOIN ATOM BOUNDP ADJUST-ARRAY BASE-CHAR BREAK ADJUSTABLE-ARRAY-P BASE-STRING BROADCAST-STREAM ALLOCATE-INSTANCE BIGNUM BROADCAST-STREAM-STREAMS ALPHA-CHAR-P BIT BUILT-IN-CLASS ALPHANUMERICP BIT-AND BUTLAST AND BIT-ANDC1 BYTE APPEND BIT-ANDC2 BYTE-POSITION APPLY BIT-EQV BYTE-SIZE APROPOS BIT-IOR CAAAAR APROPOS-LIST BIT-NAND CAAADR AREF BIT-NOR CAAAR ARITHMETIC-ERROR BIT-NOT CAADAR ARITHMETIC-ERROR-OPERANDS BIT-ORC1 CAADDR ARITHMETIC-ERROR-OPERATION BIT-ORC2 CAADR ARRAY BIT-VECTOR CAAR ARRAY-DIMENSION BIT-VECTOR-P CADAAR ARRAY-DIMENSION-LIMIT BIT-XOR CADADR ARRAY-DIMENSIONS BLOCK CADAR ARRAY-DISPLACEMENT BOOLE CADDAR ARRAY-ELEMENT-TYPE BOOLE-1 CADDDR ARRAY-HAS-FILL-POINTER-P BOOLE-2 CADDR ARRAY-IN-BOUNDS-P BOOLE-AND CADR ARRAY-RANK BOOLE-ANDC1 CALL-ARGUMENTS-LIMIT ARRAY-RANK-LIMIT BOOLE-ANDC2 CALL-METHOD ARRAY-ROW-MAJOR-INDEX BOOLE-C1 CALL-NEXT-METHOD ARRAY-TOTAL-SIZE BOOLE-C2 CAR ARRAY-TOTAL-SIZE-LIMIT BOOLE-CLR CASE ARRAYP BOOLE-EQV CATCH ASH BOOLE-IOR CCASE ASIN BOOLE-NAND CDAAAR ASINH BOOLE-NOR CDAADR ASSERT BOOLE-ORC1 CDAAR ASSOC BOOLE-ORC2 CDADAR ASSOC-IF BOOLE-SET CDADDR ASSOC-IF-NOT BOOLE-XOR CDADR ATAN BOOLEAN CDAR ATANH BOTH-CASE-P CDDAAR CDDADR CLEAR-INPUT COPY-TREE CDDAR CLEAR-OUTPUT COS CDDDAR CLOSE COSH CDDDDR CLRHASH COUNT CDDDR CODE-CHAR COUNT-IF CDDR COERCE COUNT-IF-NOT CDR COMPILATION-SPEED CTYPECASE CEILING COMPILE DEBUG CELL-ERROR COMPILE-FILE DECF CELL-ERROR-NAME COMPILE-FILE-PATHNAME DECLAIM CERROR COMPILED-FUNCTION DECLARATION CHANGE-CLASS COMPILED-FUNCTION-P DECLARE CHAR COMPILER-MACRO DECODE-FLOAT CHAR-CODE COMPILER-MACRO-FUNCTION DECODE-UNIVERSAL-TIME CHAR-CODE-LIMIT COMPLEMENT DEFCLASS CHAR-DOWNCASE COMPLEX DEFCONSTANT CHAR-EQUAL COMPLEXP DEFGENERIC CHAR-GREATERP COMPUTE-APPLICABLE-METHODS DEFINE-COMPILER-MACRO CHAR-INT COMPUTE-RESTARTS DEFINE-CONDITION CHAR-LESSP CONCATENATE DEFINE-METHOD-COMBINATION CHAR-NAME CONCATENATED-STREAM DEFINE-MODIFY-MACRO CHAR-NOT-EQUAL CONCATENATED-STREAM-STREAMS DEFINE-SETF-EXPANDER CHAR-NOT-GREATERP COND DEFINE-SYMBOL-MACRO CHAR-NOT-LESSP CONDITION DEFMACRO CHAR-UPCASE CONJUGATE DEFMETHOD CHAR/= CONS DEFPACKAGE CHAR< CONSP DEFPARAMETER CHAR<= CONSTANTLY DEFSETF CHAR= CONSTANTP DEFSTRUCT CHAR> CONTINUE DEFTYPE CHAR>= CONTROL-ERROR DEFUN CHARACTER COPY-ALIST DEFVAR CHARACTERP COPY-LIST DELETE CHECK-TYPE COPY-PPRINT-DISPATCH DELETE-DUPLICATES CIS COPY-READTABLE DELETE-FILE CLASS COPY-SEQ DELETE-IF CLASS-NAME COPY-STRUCTURE DELETE-IF-NOT CLASS-OF COPY-SYMBOL DELETE-PACKAGE DENOMINATOR EQ DEPOSIT-FIELD EQL DESCRIBE EQUAL DESCRIBE-OBJECT EQUALP DESTRUCTURING-BIND ERROR DIGIT-CHAR ETYPECASE DIGIT-CHAR-P EVAL DIRECTORY EVAL-WHEN DIRECTORY-NAMESTRING EVENP DISASSEMBLE EVERY DIVISION-BY-ZERO EXP DO EXPORT DO* EXPT DO-ALL-SYMBOLS EXTENDED-CHAR DO-EXTERNAL-SYMBOLS FBOUNDP DO-SYMBOLS FCEILING DOCUMENTATION FDEFINITION DOLIST FFLOOR DOTIMES FIFTH DOUBLE-FLOAT FILE-AUTHOR DOUBLE-FLOAT-EPSILON FILE-ERROR DOUBLE-FLOAT-NEGATIVE-EPSILON FILE-ERROR-PATHNAME DPB FILE-LENGTH DRIBBLE FILE-NAMESTRING DYNAMIC-EXTENT FILE-POSITION ECASE FILE-STREAM ECHO-STREAM FILE-STRING-LENGTH ECHO-STREAM-INPUT-STREAM FILE-WRITE-DATE ECHO-STREAM-OUTPUT-STREAM FILL ED FILL-POINTER EIGHTH FIND ELT FIND-ALL-SYMBOLS ENCODE-UNIVERSAL-TIME FIND-CLASS END-OF-FILE FIND-IF ENDP FIND-IF-NOT ENOUGH-NAMESTRING FIND-METHOD ENSURE-DIRECTORIES-EXIST FIND-PACKAGE ENSURE-GENERIC-FUNCTION FIND-RESTART FIND-SYMBOL GET-INTERNAL-RUN-TIME FINISH-OUTPUT GET-MACRO-CHARACTER FIRST GET-OUTPUT-STREAM-STRING FIXNUM GET-PROPERTIES FLET GET-SETF-EXPANSION FLOAT GET-UNIVERSAL-TIME FLOAT-DIGITS GETF FLOAT-PRECISION GETHASH FLOAT-RADIX GO FLOAT-SIGN GRAPHIC-CHAR-P FLOATING-POINT-INEXACT HANDLER-BIND FLOATING-POINT-INVALID-OPERATION HANDLER-CASE FLOATING-POINT-OVERFLOW HASH-TABLE FLOATING-POINT-UNDERFLOW HASH-TABLE-COUNT FLOATP HASH-TABLE-P FLOOR HASH-TABLE-REHASH-SIZE FMAKUNBOUND HASH-TABLE-REHASH-THRESHOLD FORCE-OUTPUT HASH-TABLE-SIZE FORMAT HASH-TABLE-TEST FORMATTER HOST-NAMESTRING FOURTH IDENTITY FRESH-LINE IF FROUND IGNORABLE FTRUNCATE IGNORE FTYPE IGNORE-ERRORS FUNCALL IMAGPART FUNCTION IMPORT FUNCTION-KEYWORDS IN-PACKAGE FUNCTION-LAMBDA-EXPRESSION INCF FUNCTIONP INITIALIZE-INSTANCE GCD INLINE GENERIC-FUNCTION INPUT-STREAM-P GENSYM INSPECT GENTEMP INTEGER GET INTEGER-DECODE-FLOAT GET-DECODED-TIME INTEGER-LENGTH GET-DISPATCH-MACRO-CHARACTER INTEGERP GET-INTERNAL-REAL-TIME INTERACTIVE-STREAM-P INTERN LISP-IMPLEMENTATION-TYPE INTERNAL-TIME-UNITS-PER-SECOND LISP-IMPLEMENTATION-VERSION INTERSECTION LIST INVALID-METHOD-ERROR LIST* INVOKE-DEBUGGER LIST-ALL-PACKAGES INVOKE-RESTART LIST-LENGTH INVOKE-RESTART-INTERACTIVELY LISTEN ISQRT LISTP KEYWORD LOAD KEYWORDP LOAD-LOGICAL-PATHNAME-TRANSLATIONS LABELS LOAD-TIME-VALUE LAMBDA LOCALLY LAMBDA-LIST-KEYWORDS LOG LAMBDA-PARAMETERS-LIMIT LOGAND LAST LOGANDC1 LCM LOGANDC2 LDB LOGBITP LDB-TEST LOGCOUNT LDIFF LOGEQV LEAST-NEGATIVE-DOUBLE-FLOAT LOGICAL-PATHNAME LEAST-NEGATIVE-LONG-FLOAT LOGICAL-PATHNAME-TRANSLATIONS LEAST-NEGATIVE-NORMALIZED-DOUBLE-FLOAT LOGIOR LEAST-NEGATIVE-NORMALIZED-LONG-FLOAT LOGNAND LEAST-NEGATIVE-NORMALIZED-SHORT-FLOAT LOGNOR LEAST-NEGATIVE-NORMALIZED-SINGLE-FLOAT LOGNOT LEAST-NEGATIVE-SHORT-FLOAT LOGORC1 LEAST-NEGATIVE-SINGLE-FLOAT LOGORC2 LEAST-POSITIVE-DOUBLE-FLOAT LOGTEST LEAST-POSITIVE-LONG-FLOAT LOGXOR LEAST-POSITIVE-NORMALIZED-DOUBLE-FLOAT LONG-FLOAT LEAST-POSITIVE-NORMALIZED-LONG-FLOAT LONG-FLOAT-EPSILON LEAST-POSITIVE-NORMALIZED-SHORT-FLOAT LONG-FLOAT-NEGATIVE-EPSILON LEAST-POSITIVE-NORMALIZED-SINGLE-FLOAT LONG-SITE-NAME LEAST-POSITIVE-SHORT-FLOAT LOOP LEAST-POSITIVE-SINGLE-FLOAT LOOP-FINISH LENGTH LOWER-CASE-P LET MACHINE-INSTANCE LET* MACHINE-TYPE MACHINE-VERSION MASK-FIELD MACRO-FUNCTION MAX MACROEXPAND MEMBER MACROEXPAND-1 MEMBER-IF MACROLET MEMBER-IF-NOT MAKE-ARRAY MERGE MAKE-BROADCAST-STREAM MERGE-PATHNAMES MAKE-CONCATENATED-STREAM METHOD MAKE-CONDITION METHOD-COMBINATION MAKE-DISPATCH-MACRO-CHARACTER METHOD-COMBINATION-ERROR MAKE-ECHO-STREAM METHOD-QUALIFIERS MAKE-HASH-TABLE MIN MAKE-INSTANCE MINUSP MAKE-INSTANCES-OBSOLETE MISMATCH MAKE-LIST MOD MAKE-LOAD-FORM MOST-NEGATIVE-DOUBLE-FLOAT MAKE-LOAD-FORM-SAVING-SLOTS MOST-NEGATIVE-FIXNUM MAKE-METHOD MOST-NEGATIVE-LONG-FLOAT MAKE-PACKAGE MOST-NEGATIVE-SHORT-FLOAT MAKE-PATHNAME MOST-NEGATIVE-SINGLE-FLOAT MAKE-RANDOM-STATE MOST-POSITIVE-DOUBLE-FLOAT MAKE-SEQUENCE MOST-POSITIVE-FIXNUM MAKE-STRING MOST-POSITIVE-LONG-FLOAT MAKE-STRING-INPUT-STREAM MOST-POSITIVE-SHORT-FLOAT MAKE-STRING-OUTPUT-STREAM MOST-POSITIVE-SINGLE-FLOAT MAKE-SYMBOL MUFFLE-WARNING MAKE-SYNONYM-STREAM MULTIPLE-VALUE-BIND MAKE-TWO-WAY-STREAM MULTIPLE-VALUE-CALL MAKUNBOUND MULTIPLE-VALUE-LIST MAP MULTIPLE-VALUE-PROG1 MAP-INTO MULTIPLE-VALUE-SETQ MAPC MULTIPLE-VALUES-LIMIT MAPCAN NAME-CHAR MAPCAR NAMESTRING MAPCON NBUTLAST MAPHASH NCONC MAPL NEXT-METHOD-P MAPLIST NIL NINTERSECTION PACKAGE-ERROR NINTH PACKAGE-ERROR-PACKAGE NO-APPLICABLE-METHOD PACKAGE-NAME NO-NEXT-METHOD PACKAGE-NICKNAMES NOT PACKAGE-SHADOWING-SYMBOLS NOTANY PACKAGE-USE-LIST NOTEVERY PACKAGE-USED-BY-LIST NOTINLINE PACKAGEP NRECONC PAIRLIS NREVERSE PARSE-ERROR NSET-DIFFERENCE PARSE-INTEGER NSET-EXCLUSIVE-OR PARSE-NAMESTRING NSTRING-CAPITALIZE PATHNAME NSTRING-DOWNCASE PATHNAME-DEVICE NSTRING-UPCASE PATHNAME-DIRECTORY NSUBLIS PATHNAME-HOST NSUBST PATHNAME-MATCH-P NSUBST-IF PATHNAME-NAME NSUBST-IF-NOT PATHNAME-TYPE NSUBSTITUTE PATHNAME-VERSION NSUBSTITUTE-IF PATHNAMEP NSUBSTITUTE-IF-NOT PEEK-CHAR NTH PHASE NTH-VALUE PI NTHCDR PLUSP NULL POP NUMBER POSITION NUMBERP POSITION-IF NUMERATOR POSITION-IF-NOT NUNION PPRINT ODDP PPRINT-DISPATCH OPEN PPRINT-EXIT-IF-LIST-EXHAUSTED OPEN-STREAM-P PPRINT-FILL OPTIMIZE PPRINT-INDENT OR PPRINT-LINEAR OTHERWISE PPRINT-LOGICAL-BLOCK OUTPUT-STREAM-P PPRINT-NEWLINE PACKAGE PPRINT-POP PPRINT-TAB READ-CHAR PPRINT-TABULAR READ-CHAR-NO-HANG PRIN1 READ-DELIMITED-LIST PRIN1-TO-STRING READ-FROM-STRING PRINC READ-LINE PRINC-TO-STRING READ-PRESERVING-WHITESPACE PRINT READ-SEQUENCE PRINT-NOT-READABLE READER-ERROR PRINT-NOT-READABLE-OBJECT READTABLE PRINT-OBJECT READTABLE-CASE PRINT-UNREADABLE-OBJECT READTABLEP PROBE-FILE REAL PROCLAIM REALP PROG REALPART PROG* REDUCE PROG1 REINITIALIZE-INSTANCE PROG2 REM PROGN REMF PROGRAM-ERROR REMHASH PROGV REMOVE PROVIDE REMOVE-DUPLICATES PSETF REMOVE-IF PSETQ REMOVE-IF-NOT PUSH REMOVE-METHOD PUSHNEW REMPROP QUOTE RENAME-FILE RANDOM RENAME-PACKAGE RANDOM-STATE REPLACE RANDOM-STATE-P REQUIRE RASSOC REST RASSOC-IF RESTART RASSOC-IF-NOT RESTART-BIND RATIO RESTART-CASE RATIONAL RESTART-NAME RATIONALIZE RETURN RATIONALP RETURN-FROM READ REVAPPEND READ-BYTE REVERSE ROOM SIMPLE-BIT-VECTOR ROTATEF SIMPLE-BIT-VECTOR-P ROUND SIMPLE-CONDITION ROW-MAJOR-AREF SIMPLE-CONDITION-FORMAT-ARGUMENTS RPLACA SIMPLE-CONDITION-FORMAT-CONTROL RPLACD SIMPLE-ERROR SAFETY SIMPLE-STRING SATISFIES SIMPLE-STRING-P SBIT SIMPLE-TYPE-ERROR SCALE-FLOAT SIMPLE-VECTOR SCHAR SIMPLE-VECTOR-P SEARCH SIMPLE-WARNING SECOND SIN SEQUENCE SINGLE-FLOAT SERIOUS-CONDITION SINGLE-FLOAT-EPSILON SET SINGLE-FLOAT-NEGATIVE-EPSILON SET-DIFFERENCE SINH SET-DISPATCH-MACRO-CHARACTER SIXTH SET-EXCLUSIVE-OR SLEEP SET-MACRO-CHARACTER SLOT-BOUNDP SET-PPRINT-DISPATCH SLOT-EXISTS-P SET-SYNTAX-FROM-CHAR SLOT-MAKUNBOUND SETF SLOT-MISSING SETQ SLOT-UNBOUND SEVENTH SLOT-VALUE SHADOW SOFTWARE-TYPE SHADOWING-IMPORT SOFTWARE-VERSION SHARED-INITIALIZE SOME SHIFTF SORT SHORT-FLOAT SPACE SHORT-FLOAT-EPSILON SPECIAL SHORT-FLOAT-NEGATIVE-EPSILON SPECIAL-OPERATOR-P SHORT-SITE-NAME SPEED SIGNAL SQRT SIGNED-BYTE STABLE-SORT SIGNUM STANDARD SIMPLE-ARRAY STANDARD-CHAR SIMPLE-BASE-STRING STANDARD-CHAR-P STANDARD-CLASS SUBLIS STANDARD-GENERIC-FUNCTION SUBSEQ STANDARD-METHOD SUBSETP STANDARD-OBJECT SUBST STEP SUBST-IF STORAGE-CONDITION SUBST-IF-NOT STORE-VALUE SUBSTITUTE STREAM SUBSTITUTE-IF STREAM-ELEMENT-TYPE SUBSTITUTE-IF-NOT STREAM-ERROR SUBTYPEP STREAM-ERROR-STREAM SVREF STREAM-EXTERNAL-FORMAT SXHASH STREAMP SYMBOL STRING SYMBOL-FUNCTION STRING-CAPITALIZE SYMBOL-MACROLET STRING-DOWNCASE SYMBOL-NAME STRING-EQUAL SYMBOL-PACKAGE STRING-GREATERP SYMBOL-PLIST STRING-LEFT-TRIM SYMBOL-VALUE STRING-LESSP SYMBOLP STRING-NOT-EQUAL SYNONYM-STREAM STRING-NOT-GREATERP SYNONYM-STREAM-SYMBOL STRING-NOT-LESSP T STRING-RIGHT-TRIM TAGBODY STRING-STREAM TAILP STRING-TRIM TAN STRING-UPCASE TANH STRING/= TENTH STRING< TERPRI STRING<= THE STRING= THIRD STRING> THROW STRING>= TIME STRINGP TRACE STRUCTURE TRANSLATE-LOGICAL-PATHNAME STRUCTURE-CLASS TRANSLATE-PATHNAME STRUCTURE-OBJECT TREE-EQUAL STYLE-WARNING TRUENAME TRUNCATE VALUES-LIST TWO-WAY-STREAM VARIABLE TWO-WAY-STREAM-INPUT-STREAM VECTOR TWO-WAY-STREAM-OUTPUT-STREAM VECTOR-POP TYPE VECTOR-PUSH TYPE-ERROR VECTOR-PUSH-EXTEND TYPE-ERROR-DATUM VECTORP TYPE-ERROR-EXPECTED-TYPE WARN TYPE-OF WARNING TYPECASE WHEN TYPEP WILD-PATHNAME-P UNBOUND-SLOT WITH-ACCESSORS UNBOUND-SLOT-INSTANCE WITH-COMPILATION-UNIT UNBOUND-VARIABLE WITH-CONDITION-RESTARTS UNDEFINED-FUNCTION WITH-HASH-TABLE-ITERATOR UNEXPORT WITH-INPUT-FROM-STRING UNINTERN WITH-OPEN-FILE UNION WITH-OPEN-STREAM UNLESS WITH-OUTPUT-TO-STRING UNREAD-CHAR WITH-PACKAGE-ITERATOR UNSIGNED-BYTE WITH-SIMPLE-RESTART UNTRACE WITH-SLOTS UNUSE-PACKAGE WITH-STANDARD-IO-SYNTAX UNWIND-PROTECT WRITE UPDATE-INSTANCE-FOR-DIFFERENT-CLASS WRITE-BYTE UPDATE-INSTANCE-FOR-REDEFINED-CLASS WRITE-CHAR UPGRADED-ARRAY-ELEMENT-TYPE WRITE-LINE UPGRADED-COMPLEX-PART-TYPE WRITE-SEQUENCE UPPER-CASE-P WRITE-STRING USE-PACKAGE WRITE-TO-STRING USE-VALUE Y-OR-N-P USER-HOMEDIR-PATHNAME YES-OR-NO-P VALUES ZEROP )) (provide 'pjb-cl) ;;;; THE END ;;;;