1 ;;; gnus-clfns.el --- compiler macros for emulating cl functions
2 ;; Copyright (C) 2000, 2001 Free Software Foundation, Inc.
4 ;; Author: Kastsumi Yamaoka <yamaoka@jpl.org>
5 ;; Keywords: cl, compile
7 ;; This file is part of GNU Emacs.
9 ;; GNU Emacs is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs; see the file COPYING. If not, write to the
21 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
26 ;; This module is for mainly avoiding cl runtime functions in FSF
27 ;; Emacsen. Function should also be defined as an ordinary function
28 ;; if it will not be provided in cl.
32 (if (featurep 'xemacs)
34 (eval-when-compile (require 'cl))
37 (define-compiler-macro butlast (&whole form x &optional n)
38 (if (and (fboundp 'butlast)
39 (subrp (symbol-function 'butlast)))
50 (if (> n 0) (setcdr (nthcdr (- (1- m) n) x) nil))
56 (setcdr (nthcdr (- m 2) x) nil)
59 (define-compiler-macro coerce (&whole form x type)
60 (if (and (fboundp 'coerce)
61 (subrp (symbol-function 'coerce)))
65 (cond ((eq type 'list) (if (listp x) x (append x nil)))
66 ((eq type 'vector) (if (vectorp x) x (vconcat x)))
67 ((eq type 'string) (if (stringp x) x (concat x)))
68 ((eq type 'array) (if (arrayp x) x (vconcat x)))
69 ((and (eq type 'character) (stringp x) (= (length x) 1))
71 ((and (eq type 'character) (symbolp x)
72 (= (length (symbol-name x)) 1))
73 (aref (symbol-name x) 0))
74 ((eq type 'float) (float x))
76 (t (error "Can't coerce %s to type %s" x type))))))
78 (define-compiler-macro last (&whole form x &optional n)
79 (if (and (fboundp 'last)
80 (subrp (symbol-function 'last)))
96 (while (consp (cdr x))
100 (define-compiler-macro merge (&whole form type seq1 seq2 pred &rest keys)
101 (if (and (fboundp 'merge)
102 (subrp (symbol-function 'merge)))
108 (or (listp seq1) (setq seq1 (append seq1 nil)))
109 (or (listp seq2) (setq seq2 (append seq2 nil)))
111 (while (and seq1 seq2)
112 (if (funcall pred (car seq2) (car seq1))
113 (push (pop seq2) res)
114 (push (pop seq1) res)))
115 (coerce (nconc (nreverse res) seq1 seq2) type)))))
117 (define-compiler-macro string (&whole form &rest args)
118 (if (and (fboundp 'string)
119 (subrp (symbol-function 'string)))
121 (list 'concat (cons 'list args))))
123 (defun-maybe string (&rest args)
124 "Concatenate all the argument characters and make the result a string."
127 (define-compiler-macro subseq (&whole form seq start &optional end)
128 (if (and (fboundp 'subseq)
129 (subrp (symbol-function 'subseq)))
136 (substring seq start end)
139 (setq end (+ end (setq len (length seq)))))
141 (setq start (+ start (or len (setq len (length seq))))))
144 (setq seq (nthcdr start seq)))
146 (while (>= (setq end (1- end)) start)
147 (push (pop seq) res))
150 (let ((res (make-vector (max (- end start) 0) nil))
153 (aset res i (aref seq start))
160 (substring seq start)
163 (setq start (+ start (or len (setq len (length seq))))))
166 (setq seq (nthcdr start seq)))
169 (let* ((end (or len (length seq)))
170 (res (make-vector (max (- end start) 0) nil))
173 (aset res i (aref seq start))
179 ;; A tool for the developers.
181 (defvar cl-run-time-functions
183 Values-list acons assoc-if assoc-if-not build-klist butlast ceiling*
184 coerce common-lisp-indent-function compiler-macroexpand concatenate
185 copy-list count count-if count-if-not delete* delete-duplicates delete-if
186 delete-if-not duplicate-symbols-p elt-satisfies-test-p equalp evenp every
187 extract-from-klist fill find find-if find-if-not floatp-safe floor* gcd
188 gensym gentemp get-setf-method getf hash-table-count hash-table-p
189 intersection isqrt keyword-argument-supplied-p keyword-of keywordp last
190 lcm ldiff lisp-indent-259 lisp-indent-do lisp-indent-function-lambda-hack
191 lisp-indent-report-bad-format lisp-indent-tagbody list-length
192 make-hash-table make-random-state map mapc mapcan mapcar* mapcon mapl
193 maplist member-if member-if-not merge mismatch mod* nbutlast nintersection
194 notany notevery nreconc nset-difference nset-exclusive-or nsublis nsubst
195 nsubst-if nsubst-if-not nsubstitute nsubstitute-if nsubstitute-if-not
196 nunion oddp pair-with-newsyms pairlis position position-if position-if-not
197 proclaim random* random-state-p rassoc* rassoc-if rassoc-if-not
198 reassemble-argslists reduce rem* remove remove* remove-duplicates
199 remove-if remove-if-not remq replace revappend round* safe-idiv search
200 set-difference set-exclusive-or setelt setnth setnthcdr signum some sort*
201 stable-sort sublis subseq subsetp subst subst-if subst-if-not substitute
202 substitute-if substitute-if-not tailp tree-equal truncate* union
203 unzip-lists zip-lists)
204 "A list of CL run-time functions. Some functions were built-in, nowadays.")
207 (defun find-cl-run-time-functions (file-or-directory in-this-emacs)
208 "Find CL run-time functions in the FILE-OR-DIRECTORY. If the optional
209 IN-THIS-EMACS is non-nil, the built-in functions in this emacs will
211 (interactive (list (read-file-name "Find CL run-time functions in: "
212 nil default-directory t)
214 (unless (interactive-p)
215 (error "You should invoke `M-x find-cl-run-time-functions' interactively"))
216 (let (files clfns working file forms fns pt lines form fn buffer
217 buffer-file-format format-alist
218 insert-file-contents-post-hook insert-file-contents-pre-hook
219 jam-zcat-filename-list jka-compr-compression-info-list)
220 (cond ((file-directory-p file-or-directory)
222 (setq files (directory-files file-or-directory t "\\.el$"))
224 (message "No files found in: %s" file-or-directory))))
225 ((file-exists-p file-or-directory)
226 (setq files (list file-or-directory)))
228 (message "No such file or directory: %s" file-or-directory)))
232 (dolist (fn cl-run-time-functions)
233 (unless (and (fboundp fn)
234 (subrp (symbol-function fn)))
236 (setq clfns cl-run-time-functions))
237 (set-buffer (setq working
239 " *Searching for CL run-time functions*")))
240 (let (emacs-lisp-mode-hook)
243 (setq file (pop files)
245 (message "Searching for CL run-time functions in: %s..."
246 (file-name-nondirectory file))
247 (insert-file-contents file nil nil nil t)
248 ;; Why is the following needed for FSF Emacsen???
249 (goto-char (point-min))
251 (while (setq forms (condition-case nil
252 (list (read working))
256 lines (list (cadr lines) (count-lines (point-min) pt)))
260 (setcar lines (+ (count-lines (point-min) (point))
265 (setq form (pop forms)
267 (cond ((eq fn 'define-compiler-macro)
269 ((memq fn '(let let*))
274 (when (and (consp element)
275 (consp (cadr element)))
279 ((memq fn '(defadvice
280 defmacro defsubst defun defmacro-maybe
281 defmacro-maybe-cond defsubst-maybe
282 defun-maybe defun-maybe-cond))
283 (setq form (cddr form)))
285 (setq form (cdr form)))
286 ((memq fn '(\` backquote quote))
287 (setq form (when (consp (car form))
289 ((and (memq fn clfns)
292 (when (and (consp form)
294 ;; Ignore a case `(a b .c)'.
297 (setq forms (append (delq nil
300 (when (consp element)
308 (setq buffer (get-buffer-create
309 (concat "*CL run-time functions in: "
310 file-or-directory "*"))))
316 (insert (format "%5d - %5d: %s"
317 (car lines) (cadr lines)
318 (mapconcat 'symbol-name
319 (nreverse fns) " ")))
320 (while (> (current-column) 78)
321 (skip-chars-backward "^ ")
327 (set-buffer working))))
328 (kill-buffer working)
331 (message "No CL run-time functions found in: %s"
333 (message "No files found"))))
335 (provide 'gnus-clfns)
337 ;;; gnus-clfns.el ends here