All of SXEmacs' http URLs are now https. WooHoo!
[sxemacs] / lisp / subr.el
1 ;;; subr.el --- basic lisp subroutines for SXEmacs
2
3 ;; Copyright (C) 1985, 86, 92, 94, 95, 99, 2000, 2001, 2002, 2003
4 ;;   Free Software Foundation, Inc.
5 ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
6 ;; Copyright (C) 1995 Sun Microsystems.
7 ;; Copyright (C) 2000, 2001, 2002, 2003 Ben Wing.
8
9 ;; Maintainer: SXEmacs Development Team
10 ;; Keywords: extensions, dumped, internal
11
12 ;; This file is part of SXEmacs.
13
14 ;; SXEmacs is free software: you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation, either version 3 of the License, or
17 ;; (at your option) any later version.
18
19 ;; SXEmacs is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 ;; GNU General Public License for more details.
23
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
26
27 ;;; Synched up with: FSF 19.34.  Some things synched up with later versions.
28
29 ;;; Commentary:
30
31 ;; This file is dumped with SXEmacs.
32
33 ;; There's not a whole lot in common now with the FSF version,
34 ;; be wary when applying differences.  I've left in a number of lines
35 ;; of commentary just to give diff(1) something to synch itself with to
36 ;; provide useful context diffs. -sb
37
38 ;; BEGIN SYNCHED WITH FSF 21.2
39
40 ;;; Code:
41 (defvar custom-declare-variable-list nil
42   "Record `defcustom' calls made before `custom.el' is loaded to handle them.
43 Each element of this list holds the arguments to one call to `defcustom'.")
44
45 ;; Use this, rather than defcustom, in subr.el and other files loaded
46 ;; before custom.el.  See dumped-lisp.el.
47 (defun custom-declare-variable-early (&rest arguments)
48   (setq custom-declare-variable-list
49         (cons arguments custom-declare-variable-list)))
50
51 \f
52 (defun macro-declaration-function (macro decl)
53   "Process a declaration found in a macro definition.
54 This is set as the value of the variable `macro-declaration-function'.
55 MACRO is the name of the macro being defined.
56 DECL is a list `(declare ...)' containing the declarations.
57 The return value of this function is not used."
58   (dolist (d (cdr decl))
59     (cond ((and (consp d) (eq (car d) 'indent))
60            (put macro 'lisp-indent-function (cadr d)))
61           ((and (consp d) (eq (car d) 'debug))
62            (put macro 'edebug-form-spec (cadr d)))
63           (t
64            (message "Unknown declaration %s" d)))))
65
66 (setq macro-declaration-function 'macro-declaration-function)
67
68 \f
69 ;;;; Lisp language features.
70
71 (defmacro lambda (&rest cdr)
72   "Return a lambda expression.
73 A call of the form (lambda ARGS DOCSTRING INTERACTIVE BODY) is
74 self-quoting; the result of evaluating the lambda expression is the
75 expression itself.  The lambda expression may then be treated as a
76 function, i.e., stored as the function value of a symbol, passed to
77 funcall or mapcar, etc.
78
79 ARGS should take the same form as an argument list for a `defun'.
80 Optional DOCSTRING is a documentation string.
81 If present, it should describe how to call the function.  Docstrings are
82 rarely useful unless the lambda will be named, eg, using `fset'.
83 Optional INTERACTIVE should be a call to the function `interactive'.
84 BODY should be a list of lisp expressions.
85
86 The byte-compiler treats lambda expressions specially.  If the lambda
87 expression is syntactically a function to be called, it will be compiled
88 unless protected by `quote'.  Conversely, quoting a lambda expression with
89 `function' hints to the byte-compiler that it should compile the expression.
90 \(The byte-compiler may or may not actually compile it; for example it will
91 never compile lambdas nested in a data structure: `'(#'(lambda (x) x))').
92
93 The byte-compiler will warn about common problems such as the form
94 `(fset 'f '(lambda (x) x))' (the lambda cannot be byte-compiled; probably
95 the programmer intended `#'', although leaving the lambda unquoted will
96 normally suffice), but in general is it the programmer's responsibility to
97 quote lambda expressions appropriately."
98   `(function (lambda ,@cdr)))
99
100 ;; FSF 21.2 has various basic macros here.  We don't because they're either
101 ;; in cl*.el (which we dump and hence is always available) or built-in.
102
103 ;; More powerful versions in cl.el.
104 ;(defmacro push (newelt listname)
105 ;(defmacro pop (listname)
106
107 ;; Built-in.
108 ;(defmacro when (cond &rest body)
109 ;(defmacro unless (cond &rest body)
110
111 ;; More powerful versions in cl-macs.el.
112 ;(defmacro dolist (spec &rest body)
113 ;(defmacro dotimes (spec &rest body)
114
115 ;; In cl.el.  Ours are defun, but cl arranges for them to be inlined anyway.
116 ;(defsubst caar (x)
117 ;(defsubst cadr (x)
118 ;(defsubst cdar (x)
119 ;(defsubst cddr (x)
120
121 ;; Built-in.  Our `last' is more powerful in that it handles circularity.
122 ;(defun last (x &optional n)
123 ;(defun butlast (x &optional n)
124 ;(defun nbutlast (x &optional n)
125
126 ;; In cl-seq.el.
127 ;(defun remove (elt seq)
128 ;(defun remq (elt list)
129
130 (defmacro defun-when-void (&rest args)
131   "Define a function, just like `defun', unless it's already defined.
132 Used for compatibility among different emacs variants."
133   `(if (fboundp ',(car args))
134        nil
135      (defun ,@args)))
136
137 (defmacro define-function-when-void (&rest args)
138   "Define a function, just like `define-function', unless it's already defined.
139 Used for compatibility among different emacs variants."
140   `(if (fboundp ,(car args))
141        nil
142      (define-function ,@args)))
143
144 \f
145 (defun assoc-default (key alist &optional test default)
146   "Find object KEY in a pseudo-alist ALIST.
147 ALIST is a list of conses or objects.  Each element (or the element's car,
148 if it is a cons) is compared with KEY by evaluating (TEST (car elt) KEY).
149 If that is non-nil, the element matches;
150 then `assoc-default' returns the element's cdr, if it is a cons,
151 or DEFAULT if the element is not a cons.
152
153 If no element matches, the value is nil.
154 If TEST is omitted or nil, `equal' is used."
155   (let (found (tail alist) value)
156     (while (and tail (not found))
157       (let ((elt (car tail)))
158         (when (funcall (or test 'equal) (if (consp elt) (car elt) elt) key)
159           (setq found t value (if (consp elt) (cdr elt) default))))
160       (setq tail (cdr tail)))
161     value))
162
163 (defun assoc-ignore-case (key alist)
164   "Like `assoc', but ignores differences in case and text representation.
165 KEY must be a string.  Upper-case and lower-case letters are treated as equal."
166   (let (element)
167     (while (and alist (not element))
168       (if (string= (downcase key) (downcase (car (car alist))))
169           (setq element (car alist)))
170       (setq alist (cdr alist)))
171     element))
172
173 (defun assoc-ignore-representation (key alist)
174   "Like `assoc', but ignores differences in text representation.
175 KEY must be a string."
176   (let (element)
177     (while (and alist (not element))
178       (if (string= key (car (car alist)))
179           (setq element (car alist)))
180       (setq alist (cdr alist)))
181     element))
182
183 (defun member-ignore-case (elt list)
184   "Like `member', but ignores differences in case and text representation.
185 ELT must be a string.  Upper-case and lower-case letters are treated as equal."
186   (while (and list (not (string= (downcase elt) (downcase (car list)))))
187     (setq list (cdr list)))
188   list)
189
190 \f
191 ;;;; Keymap support.
192 ;; XEmacs: removed to keymap.el
193
194 ;;;; The global keymap tree.
195
196 ;;; global-map, esc-map, and ctl-x-map have their values set up in
197 ;;; keymap.c; we just give them docstrings here.
198
199 ;;;; Event manipulation functions.
200
201 ;; XEmacs: This stuff is done in C Code.
202
203 ;;;; Obsolescent names for functions generally appear elsewhere, in
204 ;;;; obsolete.el or in the files they are related do.  Many very old
205 ;;;; obsolete stuff has been removed entirely (e.g. anything with `dot' in
206 ;;;; place of `point').
207
208 ; alternate names (not obsolete)
209 (if (not (fboundp 'mod)) (define-function 'mod '%))
210 (define-function 'move-marker 'set-marker)
211 (define-function 'beep 'ding)           ; preserve lingual purity
212 (define-function 'indent-to-column 'indent-to)
213 (define-function 'backward-delete-char 'delete-backward-char)
214 (define-function 'search-forward-regexp (symbol-function 're-search-forward))
215 (define-function 'search-backward-regexp (symbol-function 're-search-backward))
216 (define-function 'remove-directory 'delete-directory)
217 (define-function 'set-match-data 'store-match-data)
218 (define-function 'send-string-to-terminal 'external-debugging-output)
219
220 ;; XEmacs:
221 (defun local-variable-if-set-p (sym buffer)
222   "Return t if SYM would be local to BUFFER after it is set.
223 A nil value for BUFFER is *not* the same as (current-buffer), but
224 can be used to determine whether `make-variable-buffer-local' has been
225 called on SYM."
226   (local-variable-p sym buffer t))
227
228 \f
229 ;;;; Hook manipulation functions.
230
231 ;; (defconst run-hooks 'run-hooks ...)
232
233 (defun make-local-hook (hook)
234   "Make the hook HOOK local to the current buffer.
235 The return value is HOOK.
236
237 You never need to call this function now that `add-hook' does it for you
238 if its LOCAL argument is non-nil.
239
240 When a hook is local, its local and global values
241 work in concert: running the hook actually runs all the hook
242 functions listed in *either* the local value *or* the global value
243 of the hook variable.
244
245 This function works by making `t' a member of the buffer-local value,
246 which acts as a flag to run the hook functions in the default value as
247 well.  This works for all normal hooks, but does not work for most
248 non-normal hooks yet.  We will be changing the callers of non-normal
249 hooks so that they can handle localness; this has to be done one by
250 one.
251
252 This function does nothing if HOOK is already local in the current
253 buffer.
254
255 Do not use `make-local-variable' to make a hook variable buffer-local."
256   (if (local-variable-p hook (current-buffer)) ; XEmacs
257       nil
258     (or (boundp hook) (set hook nil))
259     (make-local-variable hook)
260     (set hook (list t)))
261   hook)
262
263 (defun add-hook (hook function &optional append local)
264   "Add to the value of HOOK the function FUNCTION.
265 FUNCTION is not added if already present.
266 FUNCTION is added (if necessary) at the beginning of the hook list
267 unless the optional argument APPEND is non-nil, in which case
268 FUNCTION is added at the end.
269
270 The optional fourth argument, LOCAL, if non-nil, says to modify
271 the hook's buffer-local value rather than its default value.
272 This makes the hook buffer-local if needed.
273 To make a hook variable buffer-local, always use
274 `make-local-hook', not `make-local-variable'.
275
276 HOOK should be a symbol, and FUNCTION may be any valid function.  If
277 HOOK is void, it is first set to nil.  If HOOK's value is a single
278 function, it is changed to a list of functions.
279
280 You can remove this hook yourself using `remove-hook'.
281
282 See also `add-one-shot-hook'."
283   (or (boundp hook) (set hook nil))
284   (or (default-boundp hook) (set-default hook nil))
285   (if local (unless (local-variable-if-set-p hook (current-buffer)) ; XEmacs
286               (make-local-hook hook))
287     ;; Detect the case where make-local-variable was used on a hook
288     ;; and do what we used to do.
289     (unless (and (consp (symbol-value hook)) (memq t (symbol-value hook)))
290       (setq local t)))
291   (let ((hook-value (if local (symbol-value hook) (default-value hook))))
292     ;; If the hook value is a single function, turn it into a list.
293     (when (or (not (listp hook-value)) (eq (car hook-value) 'lambda))
294       (setq hook-value (list hook-value)))
295     ;; Do the actual addition if necessary
296     (unless (member function hook-value)
297       (setq hook-value
298             (if append
299                 (append hook-value (list function))
300               (cons function hook-value))))
301     ;; Set the actual variable
302     (if local (set hook hook-value) (set-default hook hook-value))))
303
304 (defun remove-hook (hook function &optional local)
305   "Remove from the value of HOOK the function FUNCTION.
306 HOOK should be a symbol, and FUNCTION may be any valid function.  If
307 FUNCTION isn't the value of HOOK, or, if FUNCTION doesn't appear in the
308 list of hooks to run in HOOK, then nothing is done.  See `add-hook'.
309
310 The optional third argument, LOCAL, if non-nil, says to modify
311 the hook's buffer-local value rather than its default value.
312 This makes the hook buffer-local if needed.
313 To make a hook variable buffer-local, always use
314 `make-local-hook', not `make-local-variable'."
315   (or (boundp hook) (set hook nil))
316   (or (default-boundp hook) (set-default hook nil))
317   (if local (unless (local-variable-if-set-p hook (current-buffer)) ; XEmacs
318               (make-local-hook hook))
319     ;; Detect the case where make-local-variable was used on a hook
320     ;; and do what we used to do.
321     (unless (and (consp (symbol-value hook)) (memq t (symbol-value hook)))
322       (setq local t)))
323   (let ((hook-value (if local (symbol-value hook) (default-value hook))))
324     ;; Remove the function, for both the list and the non-list cases.
325     ;; XEmacs: add hook-test, for handling one-shot hooks.
326     (flet ((hook-test
327              (fn hel)
328              (or (equal fn hel)
329                  (and (symbolp hel)
330                       (equal fn
331                              (get hel 'one-shot-hook-fun))))))
332       (if (or (not (listp hook-value)) (eq (car hook-value) 'lambda))
333           (if (equal hook-value function) (setq hook-value nil))
334         (setq hook-value (delete* function (copy-sequence hook-value)
335                                   :test 'hook-test)))
336       ;; If the function is on the global hook, we need to shadow it locally
337       ;;(when (and local (member* function (default-value hook)
338       ;;                          :test 'hook-test)
339       ;;               (not (member* (cons 'not function) hook-value
340       ;;                             :test 'hook-test)))
341       ;;  (push (cons 'not function) hook-value))
342       ;; Set the actual variable
343       (if local (set hook hook-value) (set-default hook hook-value)))))
344
345 ;; XEmacs addition
346 ;; #### we need a coherent scheme for indicating compatibility info,
347 ;; so that it can be programmatically retrieved.
348 (defun add-local-hook (hook function &optional append)
349   "Add to the local value of HOOK the function FUNCTION.
350 You don't need this any more.  It's equivalent to specifying the LOCAL
351 argument to `add-hook'."
352   (add-hook hook function append t))
353
354 ;; XEmacs addition
355 (defun remove-local-hook (hook function)
356   "Remove from the local value of HOOK the function FUNCTION.
357 You don't need this any more.  It's equivalent to specifying the LOCAL
358 argument to `remove-hook'."
359   (remove-hook hook function t))
360
361 (defun add-one-shot-hook (hook function &optional append local)
362   "Add to the value of HOOK the one-shot function FUNCTION.
363 FUNCTION will automatically be removed from the hook the first time
364 after it runs (whether to completion or to an error).
365 FUNCTION is not added if already present.
366 FUNCTION is added (if necessary) at the beginning of the hook list
367 unless the optional argument APPEND is non-nil, in which case
368 FUNCTION is added at the end.
369
370 HOOK should be a symbol, and FUNCTION may be any valid function.  If
371 HOOK is void, it is first set to nil.  If HOOK's value is a single
372 function, it is changed to a list of functions.
373
374 You can remove this hook yourself using `remove-hook'.
375
376 See also `add-hook'."
377   (let ((sym (gensym)))
378     (fset sym `(lambda (&rest args)
379                  (unwind-protect
380                      (apply ',function args)
381                    (remove-hook ',hook ',sym ',local))))
382     (put sym 'one-shot-hook-fun function)
383     (add-hook hook sym append local)))
384
385 (defun add-local-one-shot-hook (hook function &optional append)
386   "Add to the local value of HOOK the one-shot function FUNCTION.
387 You don't need this any more.  It's equivalent to specifying the LOCAL
388 argument to `add-one-shot-hook'."
389   (add-one-shot-hook hook function append t))
390
391
392 (defun add-hook-list (function  hook-list &optional append &optional local)
393   "FUNCTION is not added if already present.
394 FUNCTION is added (if necessary) at the beginning of the hook list
395 unless the optional argument APPEND is non-nil, in which case
396 FUNCTION is added at the end.
397
398 The optional fourth argument, LOCAL, if non-nil, says to modify
399 the hook's buffer-local value rather than its default value.
400 This makes the hook buffer-local if needed.
401 To make a hook variable buffer-local, always use
402 `make-local-hook', not `make-local-variable'.
403
404 HOOK-LIST should be a list of symbols, and FUNCTION may be any valid
405 function.  If HOOK is void, it is first set to nil.  If HOOK's value
406 is a single function, it is changed to a list of functions.
407
408 You can remove this hook yourself using `remove-hook-list'.
409
410 See also `add-hook`, `remove-hook` and `add-one-shot-hook'."
411   (mapc (lambda (hook)
412           (add-hook hook function append local))
413         hook-list))
414
415 (defun remove-hook-list (function  hook-list &optional local)
416   "Remove from the value of all members of HOOK-LIST the function FUNCTION.
417 HOOK-LIST should be a list of symbols, and FUNCTION may be any valid
418 function.  If FUNCTION isn't the value of the member of HOOK-LIST, or,
419 if FUNCTION doesn't appear in the list of hooks to run in HOOK, then
420 nothing is done.  See `add-hook-list` and `add-hook'.
421
422 The optional third argument, LOCAL, if non-nil, says to modify
423 the hook's buffer-local value rather than its default value.
424 This makes the hook buffer-local if needed.
425 To make a hook variable buffer-local, always use
426 `make-local-hook', not `make-local-variable'."
427   (mapc (lambda (hook)
428           (remove-hook hook function local))
429         hook-list))
430
431
432 (defun add-to-list (list-var element &optional append)
433   "Add to the value of LIST-VAR the element ELEMENT if it isn't there yet.
434 The test for presence of ELEMENT is done with `equal'.
435 If ELEMENT is added, it is added at the beginning of the list,
436 unless the optional argument APPEND is non-nil, in which case
437 ELEMENT is added at the end.
438
439 If you want to use `add-to-list' on a variable that is not defined
440 until a certain package is loaded, you should put the call to `add-to-list'
441 into a hook function that will be run only after loading the package.
442 `eval-after-load' provides one way to do this.  In some cases
443 other hooks, such as major mode hooks, can do the job."
444   (if (member element (symbol-value list-var))
445       (symbol-value list-var)
446     (set list-var
447          (if append
448              (append (symbol-value list-var) (list element))
449            (cons element (symbol-value list-var))))))
450
451 ;; END SYNCHED WITH FSF 21.2
452
453 ;; XEmacs additions
454
455 (defun add-to-list* (list-var element &optional append)
456     "Add to the value of LIST-VAR the element ELEMENT if it isn't there yet.
457 The test for presence of ELEMENT is done with `equal'.
458 If ELEMENT is added, it is added at the beginning of the list,
459 unless the optional argument APPEND is non-nil, in which case
460 ELEMENT is added at the end.
461
462 If LIST-VAR is not defined as a variable yet, it will set it to a list
463 of just the element.
464
465 If you want to use `add-to-list*' on a variable that is not defined
466 until a certain package is loaded, you should put the call to `add-to-list*'
467 into a hook function that will be run only after loading the package.
468 `eval-after-load' provides one way to do this.  In some cases
469 other hooks, such as major mode hooks, can do the job."
470     (if (boundp list-var)
471         (add-to-list list-var element append)
472       (set list-var (list element))))
473
474 ;; called by Fkill_buffer()
475 (defvar kill-buffer-hook nil
476   "Function or functions to be called when a buffer is killed.
477 The value of this variable may be buffer-local.
478 The buffer about to be killed is current when this hook is run.")
479
480 ;; in C in FSFmacs
481 (defvar kill-emacs-hook nil
482   "Function or functions to be called when `kill-emacs' is called,
483 just before emacs is actually killed.")
484
485 ;; not obsolete.
486 ;; #### These are a bad idea, because the CL RPLACA and RPLACD
487 ;; return the cons cell, not the new CAR/CDR.         -hniksic
488 ;; The proper definition would be:
489 ;; (defun rplaca (conscell newcar)
490 ;;   (setcar conscell newcar)
491 ;;   conscell)
492 ;; ...and analogously for RPLACD.
493 (define-function 'rplaca 'setcar)
494 (define-function 'rplacd 'setcdr)
495
496 (defun copy-symbol (symbol &optional copy-properties)
497   "Return a new uninterned symbol with the same name as SYMBOL.
498 If COPY-PROPERTIES is non-nil, the new symbol will have a copy of
499 SYMBOL's value, function, and property lists."
500   (let ((new (make-symbol (symbol-name symbol))))
501     (when copy-properties
502       ;; This will not copy SYMBOL's chain of forwarding objects, but
503       ;; I think that's OK.  Callers should not expect such magic to
504       ;; keep working in the copy in the first place.
505       (and (boundp symbol)
506            (set new (symbol-value symbol)))
507       (and (fboundp symbol)
508            (fset new (symbol-function symbol)))
509       (setplist new (copy-list (symbol-plist symbol))))
510     new))
511
512 (defun set-symbol-value-in-buffer (sym val buffer)
513   "Set the value of SYM to VAL in BUFFER.  Useful with buffer-local variables.
514 If SYM has a buffer-local value in BUFFER, or will have one if set, this
515 function allows you to set the local value.
516
517 NOTE: At some point, this will be moved into C and will be very fast."
518   (with-current-buffer buffer
519     (set sym val)))
520
521 \f
522 ;; BEGIN SYNCHED WITH FSF 21.2
523
524 ;; #### #### #### AAaargh!  Must be in C, because it is used insanely
525 ;; early in the bootstrap process.
526 ;(defun split-path (path)
527 ;  "Explode a search path into a list of strings.
528 ;The path components are separated with the characters specified
529 ;with `path-separator'."
530 ;  (while (or (not stringp path-separator)
531 ;            (/= (length path-separator) 1))
532 ;    (setq path-separator (signal 'error (list "\
533 ;`path-separator' should be set to a single-character string"
534 ;                                             path-separator))))
535 ;  (split-string-by-char path (aref separator 0)))
536
537 (defmacro with-current-buffer (buffer &rest body)
538   "Temporarily make BUFFER the current buffer and execute the forms in BODY.
539 The value returned is the value of the last form in BODY.
540 See also `with-temp-buffer'."
541   `(save-current-buffer
542     (set-buffer ,buffer)
543     ,@body))
544
545 (defmacro with-temp-file (filename &rest forms)
546   "Create a new buffer, evaluate FORMS there, and write the buffer to FILENAME.
547 The value of the last form in FORMS is returned, like `progn'.
548 See also `with-temp-buffer'."
549   (let ((temp-file (make-symbol "temp-file"))
550         (temp-buffer (make-symbol "temp-buffer")))
551     `(let ((,temp-file ,filename)
552            (,temp-buffer
553             (get-buffer-create (generate-new-buffer-name " *temp file*"))))
554        (unwind-protect
555            (prog1
556                (with-current-buffer ,temp-buffer
557                  ,@forms)
558              (with-current-buffer ,temp-buffer
559                (widen)
560                (write-region (point-min) (point-max) ,temp-file nil 0)))
561          (and (buffer-name ,temp-buffer)
562               (kill-buffer ,temp-buffer))))))
563
564 ;; FSF compatibility
565 (defmacro with-temp-message (message &rest body)
566   "Display MESSAGE temporarily while BODY is evaluated.
567 The original message is restored to the echo area after BODY has finished.
568 The value returned is the value of the last form in BODY.
569 If MESSAGE is nil, the echo area and message log buffer are unchanged.
570 Use a MESSAGE of \"\" to temporarily clear the echo area.
571
572 Note that this function exists for FSF compatibility purposes.  A better way
573 under XEmacs is to give the message a particular label (see `display-message');
574 then, the old message is automatically restored when you clear your message
575 with `clear-message'."
576 ;; FSF additional doc string from 21.2:
577 ;; MESSAGE is written to the message log buffer if `message-log-max' is non-nil.
578   (let ((current-message (make-symbol "current-message"))
579         (temp-message (make-symbol "with-temp-message")))
580     `(let ((,temp-message ,message)
581            (,current-message))
582        (unwind-protect
583            (progn
584              (when ,temp-message
585                (setq ,current-message (current-message))
586                (message "%s" ,temp-message))
587              ,@body)
588          (and ,temp-message ,current-message
589               (message "%s" ,current-message))))))
590
591 (defmacro with-temp-buffer (&rest forms)
592   "Create a temporary buffer, and evaluate FORMS there like `progn'.
593 See also `with-temp-file' and `with-output-to-string'."
594   (let ((temp-buffer (make-symbol "temp-buffer")))
595     `(let ((,temp-buffer
596             (get-buffer-create (generate-new-buffer-name " *temp*"))))
597        (unwind-protect
598            (with-current-buffer ,temp-buffer
599              ,@forms)
600          (and (buffer-name ,temp-buffer)
601               (kill-buffer ,temp-buffer))))))
602
603 (defmacro with-output-to-string (&rest body)
604   "Execute BODY, return the text it sent to `standard-output', as a string."
605   `(let ((standard-output
606           (get-buffer-create (generate-new-buffer-name " *string-output*"))))
607      (let ((standard-output standard-output))
608        ,@body)
609      (with-current-buffer standard-output
610        (prog1
611            (buffer-string)
612          (kill-buffer nil)))))
613
614 (defmacro with-local-quit (&rest body)
615   "Execute BODY with `inhibit-quit' temporarily bound to nil."
616   `(condition-case nil
617        (let ((inhibit-quit nil))
618          ,@body)
619      (quit (setq quit-flag t))))
620
621 ;; FSF 21.3.
622
623 ; (defmacro combine-after-change-calls (&rest body)
624 ;   "Execute BODY, but don't call the after-change functions till the end.
625 ; If BODY makes changes in the buffer, they are recorded
626 ; and the functions on `after-change-functions' are called several times
627 ; when BODY is finished.
628 ; The return value is the value of the last form in BODY.
629
630 ; If `before-change-functions' is non-nil, then calls to the after-change
631 ; functions can't be deferred, so in that case this macro has no effect.
632
633 ; Do not alter `after-change-functions' or `before-change-functions'
634 ; in BODY."
635 ;   (declare (indent 0) (debug t))
636 ;   `(unwind-protect
637 ;        (let ((combine-after-change-calls t))
638 ;        . ,body)
639 ;      (combine-after-change-execute)))
640
641
642 (defvar delay-mode-hooks nil
643   "If non-nil, `run-mode-hooks' should delay running the hooks.")
644 (defvar delayed-mode-hooks nil
645   "List of delayed mode hooks waiting to be run.")
646 (make-variable-buffer-local 'delayed-mode-hooks)
647 (put 'delay-mode-hooks 'permanent-local t)
648
649 (defun run-mode-hooks (&rest hooks)
650   "Run mode hooks `delayed-mode-hooks' and HOOKS, or delay HOOKS.
651 Execution is delayed if `delay-mode-hooks' is non-nil.
652 Major mode functions should use this."
653   (if delay-mode-hooks
654       ;; Delaying case.
655       (dolist (hook hooks)
656         (push hook delayed-mode-hooks))
657     ;; Normal case, just run the hook as before plus any delayed hooks.
658     (setq hooks (nconc (nreverse delayed-mode-hooks) hooks))
659     (setq delayed-mode-hooks nil)
660     (apply 'run-hooks hooks)))
661
662 (defmacro delay-mode-hooks (&rest body)
663   "Execute BODY, but delay any `run-mode-hooks'.
664 Only affects hooks run in the current buffer."
665   `(progn
666      (make-local-variable 'delay-mode-hooks)
667      (let ((delay-mode-hooks t))
668        ,@body)))
669
670 (defmacro with-syntax-table (table &rest body)
671   "Evaluate BODY with syntax table of current buffer set to a copy of TABLE.
672 The syntax table of the current buffer is saved, BODY is evaluated, and the
673 saved table is restored, even in case of an abnormal exit.
674 Value is what BODY returns."
675   (let ((old-table (make-symbol "table"))
676         (old-buffer (make-symbol "buffer")))
677     `(let ((,old-table (syntax-table))
678            (,old-buffer (current-buffer)))
679        (unwind-protect
680            (progn
681              (set-syntax-table (copy-syntax-table ,table))
682              ,@body)
683          (save-current-buffer
684            (set-buffer ,old-buffer)
685            (set-syntax-table ,old-table))))))
686
687 (put 'with-syntax-table 'lisp-indent-function 1)
688 (put 'with-syntax-table 'edebug-form-spec '(form body))
689
690
691 ;; Moved from mule-coding.el.
692 (defmacro with-string-as-buffer-contents (str &rest body)
693   "With the contents of the current buffer being STR, run BODY.
694 Returns the new contents of the buffer, as modified by BODY.
695 The original current buffer is restored afterwards."
696   `(with-temp-buffer
697      (insert ,str)
698      ,@body
699      (buffer-string)))
700
701 \f
702 (defmacro save-match-data (&rest body)
703   "Execute BODY forms, restoring the global value of the match data."
704   (let ((original (make-symbol "match-data")))
705     (list 'let (list (list original '(match-data)))
706           (list 'unwind-protect
707                 (cons 'progn body)
708                 (list 'store-match-data original)))))
709
710
711 (defun match-string (num &optional string)
712   "Return string of text matched by last search.
713 NUM specifies which parenthesized expression in the last regexp.
714  Value is nil if NUMth pair didn't match, or there were less than NUM pairs.
715 Zero means the entire text matched by the whole regexp or whole string.
716 STRING should be given if the last search was by `string-match' on STRING."
717   (if (match-beginning num)
718       (if string
719           (substring string (match-beginning num) (match-end num))
720         (buffer-substring (match-beginning num) (match-end num)))))
721
722 (defun match-string-no-properties (num &optional string)
723   "Return string of text matched by last search, without text properties.
724 NUM specifies which parenthesized expression in the last regexp.
725  Value is nil if NUMth pair didn't match, or there were less than NUM pairs.
726 Zero means the entire text matched by the whole regexp or whole string.
727 STRING should be given if the last search was by `string-match' on STRING."
728   (if (match-beginning num)
729       (if string
730           (let ((result
731                  (substring string (match-beginning num) (match-end num))))
732             (set-text-properties 0 (length result) nil result)
733             result)
734         (buffer-substring-no-properties (match-beginning num)
735                                         (match-end num)))))
736
737 (defconst split-string-default-separators "[ \f\t\n\r\v]+"
738   "The default value of separators for `split-string'.
739
740 A regexp matching strings of whitespace.  May be locale-dependent
741 \(as yet unimplemented).  Should not match non-breaking spaces.
742
743 Warning: binding this to a different value and using it as default is
744 likely to have undesired semantics.")
745
746 ;; specification for `split-string' agreed with rms 2003-04-23
747 ;; xemacs design <87vfx5vor0.fsf@tleepslib.sk.tsukuba.ac.jp>
748
749 ;; The specification says that if both SEPARATORS and OMIT-NULLS are
750 ;; defaulted, OMIT-NULLS should be treated as t.  Simplifying the logical
751 ;; expression leads to the equivalent implementation that if SEPARATORS
752 ;; is defaulted, OMIT-NULLS is treated as t.
753
754 (defun split-string (string &optional separators omit-nulls)
755   "Splits STRING into substrings bounded by matches for SEPARATORS.
756
757 The beginning and end of STRING, and each match for SEPARATORS, are
758 splitting points.  The substrings matching SEPARATORS are removed, and
759 the substrings between the splitting points are collected as a list,
760 which is returned.
761
762 If SEPARATORS is non-`nil', it should be a regular expression matching text
763 which separates, but is not part of, the substrings.  If `nil' it defaults to
764 `split-string-default-separators', normally \"[ \\f\\t\\n\\r\\v]+\", and
765 OMIT-NULLS is forced to `t'.
766
767 If OMIT-NULLS is `t', zero-length substrings are omitted from the list \(so
768 that for the default value of SEPARATORS leading and trailing whitespace
769 are effectively trimmed).  If `nil', all zero-length substrings are retained,
770 which correctly parses CSV format, for example.
771
772 Note that the effect of `(split-string STRING)' is the same as
773 `(split-string STRING split-string-default-separators t)').  In the rare
774 case that you wish to retain zero-length substrings when splitting on
775 whitespace, use `(split-string STRING split-string-default-separators nil)'.
776
777 Modifies the match data when successful; use `save-match-data' if necessary."
778
779   (let ((keep-nulls (not (if separators omit-nulls t)))
780         (rexp (or separators split-string-default-separators))
781         (start 0)
782         notfirst
783         (list nil))
784     (while (and (string-match rexp string
785                               (if (and notfirst
786                                        (= start (match-beginning 0))
787                                        (< start (length string)))
788                                   (1+ start) start))
789                 (< start (length string)))
790       (setq notfirst t)
791       (if (or keep-nulls (< start (match-beginning 0)))
792           (setq list
793                 (cons (substring string start (match-beginning 0))
794                       list)))
795       (setq start (match-end 0)))
796     (if (or keep-nulls (< start (length string)))
797         (setq list
798               (cons (substring string start)
799                     list)))
800     (nreverse list)))
801
802 (defun subst-char-in-string (fromchar tochar string &optional inplace)
803   "Replace FROMCHAR with TOCHAR in STRING each time it occurs.
804 Unless optional argument INPLACE is non-nil, return a new string."
805   (let ((i (length string))
806         (newstr (if inplace string (copy-sequence string))))
807     (while (> i 0)
808       (setq i (1- i))
809       (if (eq (aref newstr i) fromchar)
810           (aset newstr i tochar)))
811     newstr))
812
813
814 ;; XEmacs addition:
815 (defun replace-in-string (str regexp newtext &optional literal)
816   "Replace all matches in STR for REGEXP with NEWTEXT string,
817  and returns the new string.
818 Optional LITERAL non-nil means do a literal replacement.
819 Otherwise treat `\\' in NEWTEXT as special:
820   `\\&' in NEWTEXT means substitute original matched text.
821   `\\N' means substitute what matched the Nth `\\(...\\)'.
822        If Nth parens didn't match, substitute nothing.
823   `\\\\' means insert one `\\'.
824   `\\u' means upcase the next character.
825   `\\l' means downcase the next character.
826   `\\U' means begin upcasing all following characters.
827   `\\L' means begin downcasing all following characters.
828   `\\E' means terminate the effect of any `\\U' or `\\L'."
829   (check-argument-type 'stringp str)
830   (check-argument-type 'stringp newtext)
831   (if (> (length str) 50)
832       (let ((cfs case-fold-search))
833         (with-temp-buffer
834           (setq case-fold-search cfs)
835           (insert str)
836           (goto-char 1)
837           (while (re-search-forward regexp nil t)
838             (replace-match newtext t literal))
839           (buffer-string)))
840     (let ((start 0) newstr)
841       (while (string-match regexp str start)
842         (setq newstr (replace-match newtext t literal str)
843               start (+ (match-end 0) (- (length newstr) (length str)))
844               str newstr))
845       str)))
846
847 (defun replace-regexp-in-string (regexp rep string &optional
848                                         fixedcase literal subexp start)
849   "Replace all matches for REGEXP with REP in STRING.
850
851 Return a new string containing the replacements.
852
853 Optional arguments FIXEDCASE, LITERAL and SUBEXP are like the
854 arguments with the same names of function `replace-match'.  If START
855 is non-nil, start replacements at that index in STRING.
856
857 REP is either a string used as the NEWTEXT arg of `replace-match' or a
858 function.  If it is a function it is applied to each match to generate
859 the replacement passed to `replace-match'; the match-data at this
860 point are such that match 0 is the function's argument.
861
862 To replace only the first match (if any), make REGEXP match up to \\'
863 and replace a sub-expression, e.g.
864   (replace-regexp-in-string \"\\(foo\\).*\\'\" \"bar\" \" foo foo\" nil nil 1)
865     => \" bar foo\"
866 "
867
868   ;; To avoid excessive consing from multiple matches in long strings,
869   ;; don't just call `replace-match' continually.  Walk down the
870   ;; string looking for matches of REGEXP and building up a (reversed)
871   ;; list MATCHES.  This comprises segments of STRING which weren't
872   ;; matched interspersed with replacements for segments that were.
873   ;; [For a `large' number of replacments it's more efficient to
874   ;; operate in a temporary buffer; we can't tell from the function's
875   ;; args whether to choose the buffer-based implementation, though it
876   ;; might be reasonable to do so for long enough STRING.]
877   (let ((l (length string))
878         (start (or start 0))
879         matches str mb me)
880     (save-match-data
881       (while (and (< start l) (string-match regexp string start))
882         (setq mb (match-beginning 0)
883               me (match-end 0))
884         ;; If we matched the empty string, make sure we advance by one char
885         (when (= me mb) (setq me (min l (1+ mb))))
886         ;; Generate a replacement for the matched substring.
887         ;; Operate only on the substring to minimize string consing.
888         ;; Set up match data for the substring for replacement;
889         ;; presumably this is likely to be faster than munging the
890         ;; match data directly in Lisp.
891         (string-match regexp (setq str (substring string mb me)))
892         (setq matches
893               (cons (replace-match (if (stringp rep)
894                                        rep
895                                      (funcall rep (match-string 0 str)))
896                                    fixedcase literal str subexp)
897                     (cons (substring string start mb) ; unmatched prefix
898                           matches)))
899         (setq start me))
900       ;; Reconstruct a string from the pieces.
901       (setq matches (cons (substring string start l) matches)) ; leftover
902       (apply #'concat (nreverse matches)))))
903
904 ;; END SYNCHED WITH FSF 21.2
905
906 \f
907 ;; BEGIN SYNCHED WITH FSF 21.3
908
909 (defun add-to-invisibility-spec (arg)
910   "Add elements to `buffer-invisibility-spec'.
911 See documentation for `buffer-invisibility-spec' for the kind of elements
912 that can be added."
913   (if (eq buffer-invisibility-spec t)
914       (setq buffer-invisibility-spec (list t)))
915   (setq buffer-invisibility-spec
916         (cons arg buffer-invisibility-spec)))
917
918 (defun remove-from-invisibility-spec (arg)
919   "Remove elements from `buffer-invisibility-spec'."
920   (if (consp buffer-invisibility-spec)
921     (setq buffer-invisibility-spec (delete arg buffer-invisibility-spec))))
922
923 ;; END SYNCHED WITH FSF 21.3
924
925 \f
926 ;;; Basic string functions
927
928 ;; XEmacs
929 (defun string-equal-ignore-case (str1 str2)
930   "Return t if two strings have identical contents, ignoring case differences.
931 Case is not significant.  Text properties and extents are ignored.
932 Symbols are also allowed; their print names are used instead.
933
934 See also `equalp'."
935   (if (symbolp str1)
936       (setq str1 (symbol-name str1)))
937   (if (symbolp str2)
938       (setq str2 (symbol-name str2)))
939   (string= (downcase str1) (downcase str2)))
940
941 (defun insert-face (string face)
942   "Insert STRING and highlight with FACE.  Return the extent created."
943   (let ((p (point)) ext)
944     (insert string)
945     (setq ext (make-extent p (point)))
946     (set-extent-face ext face)
947     ext))
948
949 ;; not obsolete.
950 (define-function 'string= 'string-equal)
951 (define-function 'string< 'string-lessp)
952 (define-function 'int-to-string 'number-to-string)
953 (define-function 'string-to-int 'string-to-number)
954
955 ;; These two names are a bit awkward, as they conflict with the normal
956 ;; foo-to-bar naming scheme, but CLtL2 has them, so they stay.
957 (define-function 'char-int 'char-to-int)
958 (define-function 'int-char 'int-to-char)
959
960 ;; XEmacs addition.
961 (defun integer-to-bit-vector (integer &optional minlength)
962   "Return INTEGER converted to a bit vector.
963 Optional argument MINLENGTH gives a minimum length for the returned vector.
964 If MINLENGTH is not given, zero high-order bits will be ignored."
965   (check-argument-type #'integerp integer)
966   (setq minlength (or minlength 0))
967   (check-nonnegative-number minlength)
968   (let* ((tmp (format "%&0.*b" minlength integer)))
969     (aset tmp 1 ?*)
970     (read tmp)))
971
972 ;; XEmacs addition.
973 (defun bit-vector-to-integer (bit-vector)
974   "Return BIT-VECTOR converted to an integer.
975 If bignum support is available, BIT-VECTOR's length is unlimited.
976 Otherwise the limit is the number of value bits in an Lisp integer. "
977   (check-argument-type #'bit-vector-p bit-vector)
978   (setq bit-vector (prin1-to-string bit-vector))
979   (aset bit-vector 1 ?b)
980   (read bit-vector))
981
982 (defun string-width (string)
983   "Return number of columns STRING occupies when displayed.
984 With international (Mule) support, uses the charset-columns attribute of
985 the characters in STRING, which may not accurately represent the actual
986 display width when using a window system.  With no international support,
987 simply returns the length of the string."
988   (if (featurep 'mule)
989       (let ((col 0)
990             (len (length string))
991             (i 0))
992         (with-fboundp '(charset-width char-charset)
993           (while (< i len)
994             (setq col (+ col (charset-width (char-charset (aref string i)))))
995             (setq i (1+ i))))
996         col)
997     (length string)))
998
999 (defun char-width (character)
1000   "Return number of columns a CHARACTER occupies when displayed."
1001   (if (featurep 'mule)
1002       (with-fboundp '(charset-width char-charset)
1003         (charset-width (char-charset character)))
1004     1))
1005
1006 ;; The following several functions are useful in GNU Emacs 20 because
1007 ;; of the multibyte "characters" the internal representation of which
1008 ;; leaks into Lisp.  In XEmacs/Mule they are trivial and unnecessary.
1009 ;; We provide them for compatibility reasons solely.
1010
1011 (defun string-to-sequence (string type)
1012   "Convert STRING to a sequence of TYPE which contains characters in STRING.
1013 TYPE should be `list' or `vector'."
1014   (ecase type
1015     (list
1016      (mapcar #'identity string))
1017     (vector
1018      (mapvector #'identity string))))
1019
1020 (defun string-to-list (string)
1021   "Return a list of characters in STRING."
1022   (mapcar #'identity string))
1023
1024 (defun string-to-vector (string)
1025   "Return a vector of characters in STRING."
1026   (mapvector #'identity string))
1027
1028 (defun store-substring (string idx obj)
1029   "Embed OBJ (string or character) at index IDX of STRING."
1030   (let* ((str (cond ((stringp obj) obj)
1031                     ((characterp obj) (char-to-string obj))
1032                     (t (error
1033                         "Invalid argument (should be string or character): %s"
1034                         obj))))
1035          (string-len (length string))
1036          (len (length str))
1037          (i 0))
1038     (while (and (< i len) (< idx string-len))
1039       (aset string idx (aref str i))
1040       (setq idx (1+ idx) i (1+ i)))
1041     string))
1042
1043 ;; From FSF 21.1; ELLIPSES is XEmacs addition.
1044
1045 (defun truncate-string-to-width (str end-column &optional start-column padding
1046                                  ellipses)
1047   "Truncate string STR to end at column END-COLUMN.
1048 The optional 3rd arg START-COLUMN, if non-nil, specifies
1049 the starting column; that means to return the characters occupying
1050 columns START-COLUMN ... END-COLUMN of STR.
1051
1052 The optional 4th arg PADDING, if non-nil, specifies a padding character
1053 to add at the end of the result if STR doesn't reach column END-COLUMN,
1054 or if END-COLUMN comes in the middle of a character in STR.
1055 PADDING is also added at the beginning of the result
1056 if column START-COLUMN appears in the middle of a character in STR.
1057
1058 If PADDING is nil, no padding is added in these cases, so
1059 the resulting string may be narrower than END-COLUMN.
1060
1061 BUG: Currently assumes that the padding character is of width one.  You
1062 will get weird results if not.
1063
1064 If ELLIPSES is non-nil, add ellipses (specified by ELLIPSES if a string,
1065 else `...') if STR extends past END-COLUMN.  The ellipses will be added in
1066 such a way that the total string occupies no more than END-COLUMN columns
1067 -- i.e. if the string goes past END-COLUMN, it will be truncated somewhere
1068 short of END-COLUMN so that, with the ellipses added (and padding, if the
1069 proper place to truncate the string would be in the middle of a character),
1070 the string occupies exactly END-COLUMN columns."
1071   (or start-column
1072       (setq start-column 0))
1073   (let ((len (length str))
1074         (idx 0)
1075         (column 0)
1076         (head-padding "") (tail-padding "")
1077         ch last-column last-idx from-idx)
1078
1079     ;; find the index of START-COLUMN; bail out if end of string reached.
1080     (condition-case nil
1081         (while (< column start-column)
1082           (setq ch (aref str idx)
1083                 column (+ column (char-width ch))
1084                 idx (1+ idx)))
1085       (args-out-of-range (setq idx len)))
1086     (if (< column start-column)
1087         ;; if string ends before START-COLUMN, return either a blank string
1088         ;; or a string entirely padded.
1089         (if padding (make-string (- end-column start-column) padding) "")
1090       (if (and padding (> column start-column))
1091           (setq head-padding (make-string (- column start-column) padding)))
1092       (setq from-idx idx)
1093       ;; If END-COLUMN is before START-COLUMN, then bail out.
1094       (if (< end-column column)
1095           (setq idx from-idx ellipses "")
1096
1097         ;; handle ELLIPSES
1098         (cond ((null ellipses) (setq ellipses ""))
1099               ((if (<= (string-width str) end-column)
1100                    ;; string fits, no ellipses
1101                    (setq ellipses "")))
1102               (t
1103                ;; else, insert default value and ...
1104                (or (stringp ellipses) (setq ellipses "..."))
1105                ;; ... take away the width of the ellipses from the
1106                ;; destination.  do all computations with new, shorter
1107                ;; width.  the padding computed will get us exactly up to
1108                ;; the shorted width, which is right -- it just gets added
1109                ;; to the right of the ellipses.
1110                (setq end-column (- end-column (string-width ellipses)))))
1111
1112         ;; find the index of END-COLUMN; bail out if end of string reached.
1113         (condition-case nil
1114             (while (< column end-column)
1115               (setq last-column column
1116                     last-idx idx
1117                     ch (aref str idx)
1118                     column (+ column (char-width ch))
1119                     idx (1+ idx)))
1120           (args-out-of-range (setq idx len)))
1121         ;; if we went too far (stopped in middle of character), back up.
1122         (if (> column end-column)
1123             (setq column last-column idx last-idx))
1124         ;; compute remaining padding
1125         (if (and padding (< column end-column))
1126             (setq tail-padding (make-string (- end-column column) padding))))
1127       ;; get substring ...
1128       (setq str (substring str from-idx idx))
1129       ;; and construct result
1130       (if padding
1131           (concat head-padding str tail-padding ellipses)
1132         (concat str ellipses)))))
1133
1134 \f
1135 ;; alist/plist functions
1136 (defun plist-to-alist (plist)
1137   "Convert property list PLIST into the equivalent association-list form.
1138 The alist is returned.  This converts from
1139
1140 \(a 1 b 2 c 3)
1141
1142 into
1143
1144 \((a . 1) (b . 2) (c . 3))
1145
1146 The original plist is not modified.  See also `destructive-plist-to-alist'."
1147   (let (alist)
1148     (while plist
1149       (setq alist (cons (cons (car plist) (cadr plist)) alist))
1150       (setq plist (cddr plist)))
1151     (nreverse alist)))
1152
1153 (defun map-plist (_mp_fun _mp_plist)
1154   "Map _MP_FUN (a function of two args) over each key/value pair in _MP_PLIST.
1155 Return a list of the results."
1156   (let (_mp_result)
1157     (while _mp_plist
1158       (push (funcall _mp_fun (car _mp_plist) (cadr _mp_plist)) _mp_result)
1159       (setq _mp_plist (cddr _mp_plist)))
1160     (nreverse _mp_result)))
1161
1162 (defun destructive-plist-to-alist (plist)
1163   "Convert property list PLIST into the equivalent association-list form.
1164 The alist is returned.  This converts from
1165
1166 \(a 1 b 2 c 3)
1167
1168 into
1169
1170 \((a . 1) (b . 2) (c . 3))
1171
1172 The original plist is destroyed in the process of constructing the alist.
1173 See also `plist-to-alist'."
1174   (let ((head plist)
1175         next)
1176     (while plist
1177       ;; remember the next plist pair.
1178       (setq next (cddr plist))
1179       ;; make the cons holding the property value into the alist element.
1180       (setcdr (cdr plist) (cadr plist))
1181       (setcar (cdr plist) (car plist))
1182       ;; reattach into alist form.
1183       (setcar plist (cdr plist))
1184       (setcdr plist next)
1185       (setq plist next))
1186     head))
1187
1188 (defun alist-to-plist (alist)
1189   "Convert association list ALIST into the equivalent property-list form.
1190 The plist is returned.  This converts from
1191
1192 \((a . 1) (b . 2) (c . 3))
1193
1194 into
1195
1196 \(a 1 b 2 c 3)
1197
1198 The original alist is not modified.  See also `destructive-alist-to-plist'."
1199   (let (plist)
1200     (while alist
1201       (let ((el (car alist)))
1202         (setq plist (cons (cdr el) (cons (car el) plist))))
1203       (setq alist (cdr alist)))
1204     (nreverse plist)))
1205
1206 ;; getf, remf in cl*.el.
1207
1208 (defmacro putf (plist property value)
1209   "Add property PROPERTY to plist PLIST with value VALUE.
1210 Analogous to (setq PLIST (plist-put PLIST PROPERTY VALUE))."
1211   `(setq ,plist (plist-put ,plist ,property ,value)))
1212
1213 (defmacro laxputf (lax-plist property value)
1214   "Add property PROPERTY to lax plist LAX-PLIST with value VALUE.
1215 Analogous to (setq LAX-PLIST (lax-plist-put LAX-PLIST PROPERTY VALUE))."
1216   `(setq ,lax-plist (lax-plist-put ,lax-plist ,property ,value)))
1217
1218 (defmacro laxremf (lax-plist property)
1219   "Remove property PROPERTY from lax plist LAX-PLIST.
1220 Analogous to (setq LAX-PLIST (lax-plist-remprop LAX-PLIST PROPERTY))."
1221   `(setq ,lax-plist (lax-plist-remprop ,lax-plist ,property)))
1222 \f
1223 ;;; Error functions
1224
1225 (defun error (datum &rest args)
1226   "Signal a non-continuable error.
1227 DATUM should normally be an error symbol, i.e. a symbol defined using
1228 `define-error'.  ARGS will be made into a list, and DATUM and ARGS passed
1229 as the two arguments to `signal', the most basic error handling function.
1230
1231 This error is not continuable: you cannot continue execution after the
1232 error using the debugger `r' command.  See also `cerror'.
1233
1234 The correct semantics of ARGS varies from error to error, but for most
1235 errors that need to be generated in Lisp code, the first argument
1236 should be a string describing the *context* of the error (i.e. the
1237 exact operation being performed and what went wrong), and the remaining
1238 arguments or \"frobs\" (most often, there is one) specify the
1239 offending object(s) and/or provide additional details such as the exact
1240 error when a file error occurred, e.g.:
1241
1242 -- the buffer in which an editing error occurred.
1243 -- an invalid value that was encountered. (In such cases, the string
1244    should describe the purpose or \"semantics\" of the value [e.g. if the
1245    value is an argument to a function, the name of the argument; if the value
1246    is the value corresponding to a keyword, the name of the keyword; if the
1247    value is supposed to be a list length, say this and say what the purpose
1248    of the list is; etc.] as well as specifying why the value is invalid, if
1249    that's not self-evident.)
1250 -- the file in which an error occurred. (In such cases, there should be a
1251    second frob, probably a string, specifying the exact error that occurred.
1252    This does not occur in the string that precedes the first frob, because
1253    that frob describes the exact operation that was happening.
1254
1255 For historical compatibility, DATUM can also be a string.  In this case,
1256 DATUM and ARGS are passed together as the arguments to `format', and then
1257 an error is signalled using the error symbol `error' and formatted string.
1258 Although this usage of `error' is very common, it is deprecated because it
1259 totally defeats the purpose of having structured errors.  There is now
1260 a rich set of defined errors you can use:
1261
1262 quit
1263
1264 error
1265   invalid-argument
1266     syntax-error
1267       invalid-read-syntax
1268       invalid-regexp
1269       scan-error
1270       structure-formation-error
1271         list-formation-error
1272           malformed-list
1273             malformed-property-list
1274           circular-list
1275             circular-property-list
1276     invalid-function
1277     no-catch
1278     undefined-keystroke-sequence
1279     invalid-constant
1280     wrong-type-argument
1281     args-out-of-range
1282     wrong-number-of-arguments
1283
1284   invalid-state
1285     void-function
1286     cyclic-function-indirection
1287     void-variable
1288     cyclic-variable-indirection
1289     invalid-byte-code
1290     stack-overflow
1291     out-of-memory
1292     invalid-key-binding
1293     internal-error
1294
1295   invalid-operation
1296     invalid-change
1297       setting-constant
1298       protected-field
1299     editing-error
1300       beginning-of-buffer
1301       end-of-buffer
1302       buffer-read-only
1303     io-error
1304       file-error
1305         file-already-exists
1306         file-locked
1307         file-supersession
1308         end-of-file
1309       process-error
1310       network-error
1311       gui-error
1312         dialog-box-error
1313       sound-error
1314       conversion-error
1315         text-conversion-error
1316         image-conversion-error
1317         base64-conversion-error
1318         selection-conversion-error
1319     arith-error
1320       range-error
1321       domain-error
1322       singularity-error
1323       overflow-error
1324       underflow-error
1325     search-failed
1326     printing-unreadable-object
1327     unimplemented
1328
1329 Note the semantic differences between some of the more common errors:
1330
1331 -- `invalid-argument' is for all cases where a bad value is encountered.
1332 -- `invalid-constant' is for arguments where only a specific set of values
1333    is allowed.
1334 -- `syntax-error' is when complex structures (parsed strings, lists,
1335    and the like) are badly formed.  If the problem is just a single bad
1336    value inside the structure, you should probably be using something else,
1337    e.g. `invalid-constant', `wrong-type-argument', or `invalid-argument'.
1338 -- `invalid-state' means that some settings have been changed in such a way
1339    that their current state is unallowable.  More and more, code is being
1340    written more carefully, and catches the error when the settings are being
1341    changed, rather than afterwards.  This leads us to the next error:
1342 -- `invalid-change' means that an attempt is being made to change some settings
1343    into an invalid state.  `invalid-change' is a type of `invalid-operation'.
1344 -- `invalid-operation' refers to all cases where code is trying to do something
1345    that's disallowed, or when an error occurred during an operation. (These
1346    two concepts are merged because there's no clear distinction between them.)
1347 -- `io-error' refers to errors involving interaction with any external
1348    components (files, other programs, the operating system, etc).
1349
1350 See also `cerror', `signal', and `signal-error'."
1351   (while t (apply
1352             'cerror datum args)))
1353
1354 (defun cerror (datum &rest args)
1355   "Like `error' but signals a continuable error."
1356   (cond ((stringp datum)
1357          (signal 'error (list (apply 'format datum args))))
1358         ((defined-error-p datum)
1359          (signal datum args))
1360         (t
1361          (error 'invalid-argument "datum not string or error symbol" datum))))
1362
1363 (defmacro check-argument-type (predicate argument)
1364   "Check that ARGUMENT satisfies PREDICATE.
1365 This is a macro, and ARGUMENT is not evaluated.  If ARGUMENT is an lvalue,
1366 this function signals a continuable `wrong-type-argument' error until the
1367 returned value satisfies PREDICATE, and assigns the returned value
1368 to ARGUMENT.  Otherwise, this function signals a non-continuable
1369 `wrong-type-argument' error if the returned value does not satisfy PREDICATE."
1370   (if (symbolp argument)
1371       `(if (not (,(eval predicate) ,argument))
1372            (setq ,argument
1373                  (wrong-type-argument ,predicate ,argument)))
1374     `(if (not (,(eval predicate) ,argument))
1375          (signal-error 'wrong-type-argument (list ,predicate ,argument)))))
1376
1377 (defun args-out-of-range (value min max)
1378   "Signal an error until the correct in-range value is given by the user.
1379 This function loops, signalling a continuable `args-out-of-range' error
1380 with VALUE, MIN and MAX as the data associated with the error and then
1381 checking the returned value to make sure it's not outside the given
1382 boundaries \(nil for either means no boundary on that side).  At that
1383 point, the gotten value is returned."
1384   (loop
1385     for newval = (signal 'args-out-of-range (list value min max))
1386     do (setq value newval)
1387     finally return value
1388     while (not (argument-in-range-p value min max))))
1389
1390 (defun argument-in-range-p (argument min max)
1391   "Return true if ARGUMENT is within the range of [MIN, MAX].
1392 This includes boundaries.  nil for either value means no limit on that side."
1393   (and (or (not min) (<= min argument))
1394        (or (not max) (<= argument max))))
1395
1396 (defmacro check-argument-range (argument min max)
1397   "Check that ARGUMENT is within the range [MIN, MAX].
1398 This is a macro, and ARGUMENT is not evaluated.  If ARGUMENT is an lvalue,
1399 this function signals a continuable `args-out-of-range' error until the
1400 returned value is within range, and assigns the returned value
1401 to ARGUMENT.  Otherwise, this function signals a non-continuable
1402 `args-out-of-range' error if the returned value is out of range."
1403   (if (symbolp argument)
1404       `(if (not (argument-in-range-p ,argument ,min ,max))
1405            (setq ,argument
1406                  (args-out-of-range ,argument ,min ,max)))
1407     (let ((newsym (gensym)))
1408       `(let ((,newsym ,argument))
1409          (if (not (argument-in-range-p ,newsym ,min ,max))
1410              (signal-error 'args-out-of-range (list ,newsym ,min ,max)))))))
1411
1412 (defun signal-error (error-symbol data)
1413   "Signal a non-continuable error.  Args are ERROR-SYMBOL, and associated DATA.
1414 An error symbol is a symbol defined using `define-error'.
1415 DATA should be a list.  Its elements are printed as part of the error message.
1416 If the signal is handled, DATA is made available to the handler.
1417 See also `signal', and the functions to handle errors: `condition-case'
1418 and `call-with-condition-handler'."
1419   (while t
1420     (signal error-symbol data)))
1421
1422 (defun define-error (error-sym doc-string &optional inherits-from)
1423   "Define a new error, denoted by ERROR-SYM.
1424 DOC-STRING is an informative message explaining the error, and will be
1425 printed out when an unhandled error occurs.
1426 ERROR-SYM is a sub-error of INHERITS-FROM (which defaults to `error').
1427
1428 \[`define-error' internally works by putting on ERROR-SYM an `error-message'
1429 property whose value is DOC-STRING, and an `error-conditions' property
1430 that is a list of ERROR-SYM followed by each of its super-errors, up
1431 to and including `error'.  You will sometimes see code that sets this up
1432 directly rather than calling `define-error', but you should *not* do this
1433 yourself.]"
1434   (check-argument-type 'symbolp error-sym)
1435   (check-argument-type 'stringp doc-string)
1436   (put error-sym 'error-message doc-string)
1437   (or inherits-from (setq inherits-from 'error))
1438   (let ((conds (get inherits-from 'error-conditions)))
1439     (or conds (signal-error 'error (list "Not an error symbol" error-sym)))
1440     (put error-sym 'error-conditions (cons error-sym conds))))
1441
1442 (defun defined-error-p (sym)
1443   "Returns non-nil if SYM names a currently-defined error."
1444   (and (symbolp sym) (not (null (get sym 'error-conditions)))))
1445
1446 (defun backtrace-in-condition-handler-eliminating-handler (handler-arg-name)
1447   "Return a backtrace inside of a condition handler, eliminating the handler.
1448 This is for use in the condition handler inside of call-with-condition-handler,
1449 when written like this:
1450
1451 \(call-with-condition-handler
1452     #'(lambda (__some_weird_arg__)
1453         do the handling ...)
1454     #'(lambda ()
1455         do the stuff that might cause an error))
1456
1457 Pass in the name (a symbol) of the argument used in the lambda function
1458 that specifies the handler, and make sure the argument name is unique, and
1459 this function generates a backtrace and strips off the part above where the
1460 error occurred (i.e. the handler itself)."
1461   (let* ((bt (with-output-to-string (backtrace nil t)))
1462          (bt (save-match-data
1463                ;; Try to eliminate the part of the backtrace
1464                ;; above where the error occurred.
1465                (if (string-match
1466                     (concat "bind (\\(?:.* \\)?" (symbol-name handler-arg-name)
1467                             "\\(?:.* \\)?)[ \t\n]*\\(?:(lambda \\|#<compiled-function \\)("
1468                             (symbol-name handler-arg-name)
1469                             ").*\n\\(\\(?:.\\|\n\\)*\\)$")
1470                     bt) (match-string 1 bt) bt))))
1471     bt))
1472
1473 (put 'with-trapping-errors 'lisp-indent-function 0)
1474 (defmacro with-trapping-errors (&rest keys-body)
1475   "Trap errors in BODY, outputting a warning and a backtrace.
1476 Usage looks like
1477
1478 \(with-trapping-errors
1479     [:operation OPERATION]
1480     [:error-form ERROR-FORM]
1481     [:no-backtrace NO-BACKTRACE]
1482     [:class CLASS]
1483     [:level LEVEL]
1484     [:resignal RESIGNAL]
1485     BODY)
1486
1487 Return value without error is whatever BODY returns.  With error, return
1488 result of ERROR-FORM (which will be evaluated only when the error actually
1489 occurs), which defaults to nil.  OPERATION is given in the warning message.
1490 CLASS and LEVEL are the warning class and level (default to class
1491 `general', level `warning').  If NO-BACKTRACE is given, no backtrace is
1492 displayed.  If RESIGNAL is given, the error is resignaled after the warning
1493 is displayed and the ERROR-FORM is executed."
1494   (let ((operation "unknown")
1495         (error-form nil)
1496         (no-backtrace nil)
1497         (class ''general)
1498         (level ''warning)
1499         (resignal nil))
1500     (let* ((keys '(operation error-form no-backtrace class level resignal))
1501            (keys-with-colon
1502             (mapcar #'(lambda (sym)
1503                         (intern (concat ":" (symbol-name sym)))) keys)))
1504       (while (memq (car keys-body) keys-with-colon)
1505         (let* ((key-with-colon (pop keys-body))
1506                (key (intern (substring (symbol-name key-with-colon) 1))))
1507           (set key (pop keys-body)))))
1508     `(condition-case ,(if resignal '__cte_cc_var__ nil)
1509          (call-with-condition-handler
1510              #'(lambda (__call_trapping_errors_arg__)
1511                  (let ((errstr (error-message-string
1512                                 __call_trapping_errors_arg__)))
1513                    ,(if no-backtrace
1514                         `(lwarn ,class ,level
1515                            (if (warning-level-<
1516                                 ,level
1517                                 display-warning-minimum-level)
1518                                "Error in %s: %s"
1519                              "Error in %s:\n%s\n")
1520                            ,operation errstr)
1521                       `(lwarn ,class ,level
1522                          "Error in %s: %s\n\nBacktrace follows:\n\n%s"
1523                          ,operation errstr
1524                          (backtrace-in-condition-handler-eliminating-handler
1525                           '__call_trapping_errors_arg__)))))
1526              #'(lambda ()
1527                  (progn ,@keys-body)))
1528        (error
1529         ,error-form
1530         ,@(if resignal '((signal (car __cte_cc_var__) (cdr __cte_cc_var__)))))
1531        )))
1532
1533 ;;;; Miscellanea.
1534
1535 ;; This is now in C.
1536 ;(defun buffer-substring-no-properties (start end)
1537 ;  "Return the text from START to END, without text properties, as a string."
1538 ;  (let ((string (buffer-substring start end)))
1539 ;    (set-text-properties 0 (length string) nil string)
1540 ;    string))
1541
1542 (defun get-buffer-window-list (&optional buffer minibuf frame)
1543   "Return windows currently displaying BUFFER, or nil if none.
1544 BUFFER defaults to the current buffer.
1545 See `walk-windows' for the meaning of MINIBUF and FRAME."
1546   (cond ((null buffer)
1547          (setq buffer (current-buffer)))
1548         ((not (bufferp buffer))
1549          (setq buffer (get-buffer buffer))))
1550   (let (windows)
1551     (walk-windows (lambda (window)
1552                     (if (eq (window-buffer window) buffer)
1553                         (push window windows)))
1554                   minibuf frame)
1555     windows))
1556
1557 (defun ignore (&rest ignore)
1558   "Do nothing and return nil.
1559 This function accepts any number of arguments, but ignores them."
1560   (interactive)
1561   nil)
1562
1563 ;; defined in lisp/bindings.el in GNU Emacs.
1564 (defmacro bound-and-true-p (var)
1565   "Return the value of symbol VAR if it is bound, else nil."
1566   `(and (boundp (quote ,var)) ,var))
1567
1568 ;; `propertize' is a builtin in GNU Emacs 21.
1569 (defun propertize (string &rest properties)
1570   "Return a copy of STRING with text properties added.
1571 First argument is the string to copy.
1572 Remaining arguments form a sequence of PROPERTY VALUE pairs for text
1573 properties to add to the result."
1574   (let ((str (copy-sequence string)))
1575     (add-text-properties 0 (length str)
1576                          properties
1577                          str)
1578     str))
1579
1580 ;; `delete-and-extract-region' is a builtin in GNU Emacs 21.
1581 (defun delete-and-extract-region (start end)
1582   "Delete the text between START and END and return it."
1583   (let ((region (buffer-substring start end)))
1584     (delete-region start end)
1585     region))
1586
1587 (define-function 'eval-in-buffer 'with-current-buffer)
1588 (make-obsolete 'eval-in-buffer 'with-current-buffer)
1589
1590 ;;; The real defn is in abbrev.el but some early callers
1591 ;;;  (eg lisp-mode-abbrev-table) want this before abbrev.el is loaded...
1592
1593 (if (not (fboundp 'define-abbrev-table))
1594     (progn
1595       (setq abbrev-table-name-list '())
1596       (fset 'define-abbrev-table (function (lambda (name defs)
1597                                    ;; These are fixed-up when abbrev.el loads.
1598                                    (setq abbrev-table-name-list
1599                                          (cons (cons name defs)
1600                                                abbrev-table-name-list)))))))
1601
1602 ;;; `functionp' has been moved into C.
1603
1604 ;;(defun functionp (object)
1605 ;;  "Non-nil if OBJECT can be called as a function."
1606 ;;  (or (and (symbolp object) (fboundp object))
1607 ;;      (subrp object)
1608 ;;      (compiled-function-p object)
1609 ;;      (eq (car-safe object) 'lambda)))
1610
1611
1612
1613 (defun function-interactive (function)
1614   "Return the interactive specification of FUNCTION.
1615 FUNCTION can be any funcallable object.
1616 The specification will be returned as the list of the symbol `interactive'
1617  and the specs.
1618 If FUNCTION is not interactive, nil will be returned."
1619   (setq function (indirect-function function))
1620   (cond ((compiled-function-p function)
1621          (compiled-function-interactive function))
1622         ((subrp function)
1623          (subr-interactive function))
1624         ((eq (car-safe function) 'lambda)
1625          (let ((spec (if (stringp (nth 2 function))
1626                          (nth 3 function)
1627                        (nth 2 function))))
1628            (and (eq (car-safe spec) 'interactive)
1629                 spec)))
1630         (t
1631          (error "Non-funcallable object: %s" function))))
1632
1633 (defun function-allows-args (function n)
1634   "Return whether FUNCTION can be called with N arguments."
1635   (and (<= (function-min-args function) n)
1636        (or (null (function-max-args function))
1637            (<= n (function-max-args function)))))
1638
1639 ;; This function used to be an alias to `buffer-substring', except
1640 ;; that FSF Emacs 20.4 added a BUFFER argument in an incompatible way.
1641 ;; The new FSF's semantics makes more sense, but we try to support
1642 ;; both for backward compatibility.
1643 (defun buffer-string (&optional buffer old-end old-buffer)
1644   "Return the contents of the current buffer as a string.
1645 If narrowing is in effect, this function returns only the visible part
1646 of the buffer.
1647
1648 If BUFFER is specified, the contents of that buffer are returned.
1649
1650 The arguments OLD-END and OLD-BUFFER are supported for backward
1651 compatibility with pre-21.2 XEmacsen times when arguments to this
1652 function were (buffer-string &optional START END BUFFER)."
1653   (cond
1654    ((or (stringp buffer) (bufferp buffer))
1655     ;; Most definitely the new way.
1656     (buffer-substring nil nil buffer))
1657    ((or (stringp old-buffer) (bufferp old-buffer)
1658         (natnump buffer) (natnump old-end))
1659     ;; Definitely the old way.
1660     (buffer-substring buffer old-end old-buffer))
1661    (t
1662     ;; Probably the old way.
1663     (buffer-substring buffer old-end old-buffer))))
1664
1665 ;; BEGIN SYNC WITH FSF 21.2
1666
1667 ;; This was not present before.  I think Jamie had some objections
1668 ;; to this, so I'm leaving this undefined for now. --ben
1669
1670 ;;; The objection is this: there is more than one way to load the same file.
1671 ;;; "foo", "foo.elc", "foo.el", and "/some/path/foo.elc" are all different
1672 ;;; ways to load the exact same code.  `eval-after-load' is too stupid to
1673 ;;; deal with this sort of thing.  If this sort of feature is desired, then
1674 ;;; it should work off of a hook on `provide'.  Features are unique and
1675 ;;; the arguments to (load) are not.  --Stig
1676
1677 ;; We provide this for FSFmacs compatibility, at least until we devise
1678 ;; something better.
1679
1680 ;;;; Specifying things to do after certain files are loaded.
1681
1682 (defun eval-after-load (file form)
1683   "Arrange that, if FILE is ever loaded, FORM will be run at that time.
1684 This makes or adds to an entry on `after-load-alist'.
1685 If FILE is already loaded, evaluate FORM right now.
1686 It does nothing if FORM is already on the list for FILE.
1687 FILE must match exactly.  Normally FILE is the name of a library,
1688 with no directory or extension specified, since that is how `load'
1689 is normally called.
1690 For compatibility with FSF, FILE can also be a feature, i.e, a symbol.
1691
1692 Please be aware that if FILE is a lib that is dumped then you are not
1693 gaining anything by using this, you may as well simply call FORM directly
1694 without `eval-after-load'."
1695   ;; FSFmacs allows FILE to be a symbol (provided feature). I can't
1696   ;; decide if that's a good thing or not, or even how to go about it
1697   ;; in a smart way.  So, for now, look it up from #'feature-file or
1698   ;; use #'symbol-name failing that. --SY.
1699   (when (symbolp file)
1700     ;; Lets at least try to get a real filename
1701     (setq file (or (ignore-errors
1702                      (file-name-sans-extension
1703                       (file-basename (feature-file file))))
1704                    (symbol-name file))))
1705   ;; Make sure there is an element for FILE.
1706   (or (assoc file after-load-alist)
1707       (setq after-load-alist (cons (list file) after-load-alist)))
1708   ;; Add FORM to the element if it isn't there.
1709   (let ((elt (assoc file after-load-alist)))
1710     (or (member form (cdr elt))
1711         (progn
1712           (nconc elt (list form))
1713           ;; If the file has been loaded already, run FORM right away.
1714           (and (or (assoc file load-history)
1715                    (member file preloaded-file-list))
1716                (eval form)))))
1717   form)
1718 (make-compatible 'eval-after-load "")
1719
1720 (defun eval-next-after-load (file)
1721   "Read the following input sexp, and run it whenever FILE is loaded.
1722 This makes or adds to an entry on `after-load-alist'.
1723 FILE should be the name of a library, with no directory name."
1724   (eval-after-load file (read)))
1725 (make-compatible 'eval-next-after-load "")
1726
1727 ;; END SYNC WITH FSF 21.2
1728
1729 ;; BEGIN SYNC WITH FSF 22.0.50.1 (CVS)
1730 (defun delete-dups (list)
1731   "Destructively remove `equal' duplicates from LIST.
1732 Store the result in LIST and return it.  LIST must be a proper list.
1733 Of several `equal' occurrences of an element in LIST, the first
1734 one is kept."
1735   (let ((tail list))
1736     (while tail
1737       (setcdr tail (delete (car tail) (cdr tail)))
1738       (setq tail (cdr tail))))
1739   list)
1740
1741 ;; END SYNC WITH FSF 22.0.50.1 (CVS)
1742
1743 ;; (defun shell-quote-argument (argument) in process.el.
1744
1745 ;; (defun make-syntax-table (&optional oldtable) in syntax.el.
1746
1747 ;; (defun syntax-after (pos) #### doesn't exist.
1748
1749 ;; global-set-key, local-set-key, global-unset-key, local-unset-key in
1750 ;; keymap.el.
1751
1752 ;; frame-configuration-p is in frame.el.
1753
1754 ;; functionp is built-in.
1755
1756 ;; interactive-form in obsolete.el.
1757
1758 ;; assq-del-all in obsolete.el.
1759
1760 ;; (defun make-temp-file (prefix &optional dir-flag suffix) #### doesn't exist.
1761
1762 ;; add-minor-mode in modeline.el.
1763
1764 ;; text-clone stuff #### doesn't exist; should go in text-props.el and
1765 ;; requires changes to extents.c (modification hooks).
1766
1767 ;; play-sound is built-in.
1768
1769 ;; define-mail-user-agent is in simple.el.
1770
1771 ;; XEmacs; added.
1772 (defun skip-chars-quote (string)
1773   "Return a string that means all characters in STRING will be skipped,
1774 if passed to `skip-chars-forward' or `skip-chars-backward'.
1775
1776 Ranges and carets are not treated specially.  This implementation is
1777 in Lisp; do not use it in performance-critical code."
1778   (let ((list (delete-duplicates (string-to-list string) :test #'=)))
1779     (when (equal list '((?- ?\[) (?\[ ?\-)))
1780       (error 'invalid-argument
1781              "Cannot create `skip-chars-forward' arg from string"
1782              string))
1783     (when (memq ?\] list)
1784       (setq list (cons ?\] (delq ?\] list))))
1785     (when (eq ?^ (car list))
1786       (setq list (nconc (cdr list) '(?^))))
1787     (when (memq ?- list)
1788       (setq list (delq ?- list)
1789             list (nconc list (list (second list) ?- (second list) ?-))))
1790     (apply #'string list)))
1791
1792 (provide 'subr)
1793 ;;; subr.el ends here