which included commits to RCS files with non-trunk default branches.
+2000-12-05 Martin Buchholz <martin@xemacs.org>
+
+ * XEmacs 21.2.38 is released.
+
+2000-11-13 Yoshiki Hayashi <yoshiki@xemacs.org>
+
+ * Makefile.in.in: Define emacs iff it's necessary.
+
2000-11-14 Martin Buchholz <martin@xemacs.org>
* XEmacs 21.2.37 is released.
## Where will the generated files like config.h be included from?
## This is also why you _must_ use <...> instead of "..."
## when #include'ing generated files.
-cppflags = -Demacs -I. -I../src -I$(srcdir) -I$(top_srcdir)/src $(CPPFLAGS)
+cppflags = -I. -I../src -I$(srcdir) -I$(top_srcdir)/src $(CPPFLAGS)
cflags = $(CFLAGS) $(cppflags) $(c_switch_general)
ldflags = $(LDFLAGS) $(ld_switch_general) $(ld_libs_general)
${CC} -c $(cflags) ${srcdir}/../src/alloca.c
regex.o: ${srcdir}/../src/regex.c ${top_srcdir}/src/regex.h
- $(CC) -c `echo $(cflags) | sed 's/-Demacs/ /'` \
+ $(CC) -c $(cflags) \
-DINHIBIT_STRING_HEADER ${top_srcdir}/src/regex.c
etags_args = $(cflags) -DVERSION='"${version}"' ${srcdir}/etags.c \
$(CC) $(cflags) ${srcdir}/make-docfile.c $(ldflags) -o $@
digest-doc: ${srcdir}/digest-doc.c
- $(CC) $(cflags) ${srcdir}/digest-doc.c $(ldflags) -o $@
+ $(CC) -Demacs $(cflags) ${srcdir}/digest-doc.c $(ldflags) -o $@
sorted-doc: ${srcdir}/sorted-doc.c
$(CC) $(cflags) ${srcdir}/sorted-doc.c $(ldflags) -o $@
## because XEmacs provides built-in timer facilities.
make-path: ${srcdir}/make-path.c ../src/config.h
- $(CC) $(cflags) ${srcdir}/make-path.c -o $@
+ $(CC) -Demacs $(cflags) ${srcdir}/make-path.c -o $@
## These are NOT included in INSTALLABLES or UTILITIES.
## See ../src/Makefile.in.in.
"Define an abbrev in TABLE named NAME, to expand to EXPANSION or call HOOK.
NAME and EXPANSION are strings. Hook is a function or `nil'.
To undefine an abbrev, define it with an expansion of `nil'."
- (unless (or (null expansion) (stringp expansion))
- (setq expansion (wrong-type-argument 'stringp expansion)))
-
- (unless (or (null count) (integerp count))
- (setq count (wrong-type-argument 'fixnump count)))
-
- (unless (vectorp table)
- (setq table (wrong-type-argument 'vectorp table)))
-
+ (check-type expansion (or null string))
+ (check-type count (or null integer))
+ (check-type table vector)
(let* ((sym (intern name table))
(oexp (and (boundp sym) (symbol-value sym)))
(ohook (and (fboundp sym) (symbol-function sym))))
(buffer-substring
(point)
(if (= arg 0) (mark)
- (save-excursion (forward-word (- arg)) (point))))))
+ (save-excursion (backward-word arg) (point))))))
(defun add-mode-abbrev (arg)
"Define mode-specific abbrev for last word(s) before point.
ARG is the argument to `inverse-add-global-abbrev' or
`inverse-add-mode-abbrev'."
(save-excursion
- (forward-word (- arg))
+ (backward-word arg)
(buffer-substring (point) (progn (forward-word 1) (point)))))
(defun inverse-add-mode-abbrev (arg)
(defun inverse-add-abbrev (table type arg)
(let (name nameloc exp)
(save-excursion
- (forward-word (- arg))
+ (backward-word arg)
(setq name (buffer-substring (point) (progn (forward-word 1)
(setq nameloc (point))))))
(set-text-properties 0 (length name) nil name)
(if (abbrev-expansion
(setq string
(buffer-substring
- (save-excursion (forward-word -1) (point))
+ (save-excursion (backward-word) (point))
pnt)))
(if (or noquery (y-or-n-p (format "Expand `%s'? " string)))
(expand-abbrev)))))))
(let ((buff-menu-buffer (current-buffer))
(buffer-read-only nil))
(while (search-forward "\nD" nil t)
- (forward-char -1)
+ (backward-char 1)
(let ((buf (Buffer-menu-buffer nil)))
(or (eq buf nil)
(eq buf buff-menu-buffer)
(progn (delete-char 1)
(insert ? ))
(delete-region (point) (progn (forward-line 1) (point)))
- (forward-char -1))))))
+ (backward-char 1))))))
(defun Buffer-menu-select ()
"Select this line's buffer; also display buffers marked with `>'.
;;; Copyright (c) 1991, 1994 Free Software Foundation, Inc.
-;; Author: Jamie Zawinski <jwz@jwz.org>
-;; Hallvard Furuseth <hbf@ulrik.uio.no>
+;; Authors: Jamie Zawinski <jwz@jwz.org>
+;; Hallvard Furuseth <hbf@ulrik.uio.no>
+;; Martin Buchholz <martin@xemacs.org>
;; Keywords: internal
;; This file is part of XEmacs.
(progn
;; (if (equal form new) (error "bogus optimizer -- %s" opt))
(byte-compile-log " %s\t==>\t%s" form new)
- (setq new (byte-optimize-form new for-effect))
- new)
+ (byte-optimize-form new for-effect))
form)))
(list (apply fun (nreverse constants)))))))))
form))
+;;; It is not safe to optimize calls to arithmetic ops with one arg
+;;; away entirely (actually, it would be safe if we know the sole arg
+;;; is not a marker or if it appears in other arithmetic).
+
+;;; But this degree of paranoia is normally unjustified, so optimize unless
+;;; the user has done (declaim (safety 3)). Implemented in bytecomp.el.
+
(defun byte-optimize-plus (form)
- (setq form (byte-optimize-delay-constants-math form 1 '+))
- (if (memq 0 form) (setq form (delq 0 (copy-sequence form))))
- ;;(setq form (byte-optimize-associative-two-args-math form))
-
- (case (length (cdr form))
- ((0) ; (+)
- (condition-case ()
- (eval form)
- (error form)))
-
- ;; It is not safe to delete the function entirely
- ;; (actually, it would be safe if we knew the sole arg
- ;; is not a marker).
- ;; ((1)
- ;; (nth 1 form))
-
- ((2) ; (+ x y)
- (byte-optimize-predicate
- (cond
- ;; `add1' and `sub1' are a marginally fewer instructions
- ;; than `plus' and `minus', so use them when possible.
- ((eq (nth 1 form) 1) `(1+ ,(nth 2 form))) ; (+ 1 x) --> (1+ x)
- ((eq (nth 2 form) 1) `(1+ ,(nth 1 form))) ; (+ x 1) --> (1+ x)
- ((eq (nth 1 form) -1) `(1- ,(nth 2 form))) ; (+ -1 x) --> (1- x)
- ((eq (nth 2 form) -1) `(1- ,(nth 1 form))) ; (+ x -1) --> (1- x)
- (t form))))
+ (byte-optimize-predicate (byte-optimize-delay-constants-math form 1 '+)))
+
+(defun byte-optimize-multiply (form)
+ (setq form (byte-optimize-delay-constants-math form 1 '*))
+ ;; If there is a constant integer in FORM, it is now the last element.
+ (case (car (last form))
+ ;; (* x y 0) --> (progn x y 0)
+ (0 (cons 'progn (cdr form)))
(t (byte-optimize-predicate form))))
(defun byte-optimize-minus (form)
- ;; Put constants at the end, except the last constant.
+ ;; Put constants at the end, except the first arg.
(setq form (byte-optimize-delay-constants-math form 2 '+))
- ;; Now only first and last element can be an integer.
- (let ((last (last (nthcdr 3 form))))
- (cond ((eq 0 last)
- ;; (- x y ... 0) --> (- x y ...)
- (setq form (copy-sequence form))
- (setcdr (cdr (cdr form)) (delq 0 (nthcdr 3 form))))
- ;; If form is (- CONST foo... CONST), merge first and last.
- ((and (numberp (nth 1 form))
- (numberp last))
- (setq form (nconc (list '- (- (nth 1 form) last) (nth 2 form))
- (delq last (copy-sequence (nthcdr 3 form))))))))
-
- (case (length (cdr form))
- ((0) ; (-)
- (condition-case ()
- (eval form)
- (error form)))
-
- ;; It is not safe to delete the function entirely
- ;; (actually, it would be safe if we knew the sole arg
- ;; is not a marker).
- ;; ((1)
- ;; (nth 1 form)
-
- ((2) ; (+ x y)
- (byte-optimize-predicate
- (cond
- ;; `add1' and `sub1' are a marginally fewer instructions than `plus'
- ;; and `minus', so use them when possible.
- ((eq (nth 2 form) 1) `(1- ,(nth 1 form))) ; (- x 1) --> (1- x)
- ((eq (nth 2 form) -1) `(1+ ,(nth 1 form))) ; (- x -1) --> (1+ x)
- ((eq (nth 1 form) 0) `(- ,(nth 2 form))) ; (- 0 x) --> (- x)
- (t form))))
+ ;; Now only the first and last args can be integers.
+ (let ((last (car (last (nthcdr 3 form)))))
+ (cond
+ ;; If form is (- CONST foo... CONST), merge first and last.
+ ((and (numberp (nth 1 form)) (numberp last))
+ (decf (nth 1 form) last)
+ (butlast form))
- (t (byte-optimize-predicate form))))
+ ;; (- 0 x ...) --> (- (- x) ...)
+ ((and (eq 0 (nth 1 form)) (>= (length form) 3))
+ `(- (- ,(nth 2 form)) ,@(nthcdr 3 form)))
-(defun byte-optimize-multiply (form)
- (setq form (byte-optimize-delay-constants-math form 1 '*))
- ;; If there is a constant integer in FORM, it is now the last element.
- (cond ((null (cdr form)) 1)
-;;; It is not safe to delete the function entirely
-;;; (actually, it would be safe if we know the sole arg
-;;; is not a marker or if it appears in other arithmetic).
-;;; ((null (cdr (cdr form))) (nth 1 form))
- ((let ((last (last form)))
- (byte-optimize-predicate
- (cond ((eq 0 last) (cons 'progn (cdr form)))
- ((eq 1 last) (delq 1 (copy-sequence form)))
- ((eq -1 last) (list '- (delq -1 (copy-sequence form))))
- ((and (eq 2 last)
- (memq t (mapcar 'symbolp (cdr form))))
- (prog1 (setq form (delq 2 (copy-sequence form)))
- (while (not (symbolp (car (setq form (cdr form))))))
- (setcar form (list '+ (car form) (car form)))))
- (form)))))))
+ (t (byte-optimize-predicate form)))))
(defun byte-optimize-divide (form)
+ ;; Put constants at the end, except the first arg.
(setq form (byte-optimize-delay-constants-math form 2 '*))
- ;; If there is a constant integer in FORM, it is now the last element.
- (let ((last (last (cdr (cdr form)))))
- (if (numberp last)
- (cond ((= (length form) 3)
- (if (and (numberp (nth 1 form))
- (not (zerop last))
- (condition-case nil
- (/ (nth 1 form) last)
- (error nil)))
- (setq form (list 'progn (/ (nth 1 form) last)))))
- ((= last 1)
- (setq form (butlast form)))
- ((numberp (nth 1 form))
- (setq form (cons (car form)
- (cons (/ (nth 1 form) last)
- (butlast (cdr (cdr form)))))
- last nil))))
+ ;; Now only the first and last args can be integers.
+ (let ((last (car (last (nthcdr 3 form)))))
(cond
-;;; ((null (cdr (cdr form)))
-;;; (nth 1 form))
+ ;; If form is (/ CONST foo... CONST), merge first and last.
+ ((and (numberp (nth 1 form)) (numberp last))
+ (condition-case nil
+ (cons (nth 0 form)
+ (cons (/ (nth 1 form) last)
+ (butlast (cdr (cdr form)))))
+ (error form)))
+
+ ;; (/ 0 x y) --> (progn x y 0)
((eq (nth 1 form) 0)
(append '(progn) (cdr (cdr form)) '(0)))
- ((eq last -1)
- (list '- (if (nthcdr 3 form)
- (butlast form)
- (nth 1 form))))
- (form))))
+
+ ;; We don't have to check for divide-by-zero because `/' does.
+ (t (byte-optimize-predicate form)))))
(defun byte-optimize-logmumble (form)
(setq form (byte-optimize-delay-constants-math form 1 (car form)))
(setq ok (byte-compile-constp (car rest))
rest (cdr rest)))
(if ok
- (condition-case ()
+ (condition-case err
(list 'quote (eval form))
- (error form))
+ (error
+ (byte-compile-warn "evaluating %s: %s" form err)
+ form))
form)))
(defun byte-optimize-identity (form)
(put '* 'byte-optimizer 'byte-optimize-multiply)
(put '- 'byte-optimizer 'byte-optimize-minus)
(put '/ 'byte-optimizer 'byte-optimize-divide)
+(put '% 'byte-optimizer 'byte-optimize-predicate)
(put 'max 'byte-optimizer 'byte-optimize-associative-math)
(put 'min 'byte-optimizer 'byte-optimize-associative-math)
(put 'if 'byte-optimizer 'byte-optimize-if)
(put 'while 'byte-optimizer 'byte-optimize-while)
-;; Remove any reason for avoiding `char-before'.
-(defun byte-optimize-char-before (form)
- `(char-after (1- ,(or (nth 1 form) '(point))) ,@(cdr (cdr form))))
+;; The supply of bytecodes is small and constrained by backward compatibility.
+;; Several functions have byte-coded versions and hence are very efficient.
+;; Related functions which can be expressed in terms of the byte-coded
+;; ones should be transformed into bytecoded calls for efficiency.
+;; This is especially the case for functions with a backward- and
+;; forward- version, but with a bytecode only for the forward one.
-(put 'char-before 'byte-optimizer 'byte-optimize-char-before)
+;; Some programmers have hand-optimized calls like (backward-char)
+;; into the call (forward-char -1).
+;; But it's so much nicer for the byte-compiler to do this automatically!
+
+;; (char-before) ==> (char-after (1- (point)))
+(put 'char-before 'byte-optimizer 'byte-optimize-char-before)
+(defun byte-optimize-char-before (form)
+ `(char-after
+ ,(cond
+ ((null (nth 1 form))
+ '(1- (point)))
+ ((equal '(point) (nth 1 form))
+ '(1- (point)))
+ (t `(1- (or ,(nth 1 form) (point)))))
+ ,@(cdr (cdr form))))
+
+;; (backward-char n) ==> (forward-char (- n))
+(put 'backward-char 'byte-optimizer 'byte-optimize-backward-char)
+(defun byte-optimize-backward-char (form)
+ `(forward-char
+ ,(typecase (nth 1 form)
+ (null -1)
+ (integer (- (nth 1 form)))
+ (t `(- (or ,(nth 1 form) 1))))
+ ,@(cdr (cdr form))))
+
+;; (backward-word n) ==> (forward-word (- n))
+(put 'backward-word 'byte-optimizer 'byte-optimize-backward-word)
+(defun byte-optimize-backward-word (form)
+ `(forward-word
+ ,(typecase (nth 1 form)
+ (null -1)
+ (integer (- (nth 1 form)))
+ (t `(- (or ,(nth 1 form) 1))))
+ ,@(cdr (cdr form))))
+
+;; The following would be a valid optimization of the above kind, but
+;; the gain in performance is very small, since the saved funcall is
+;; counterbalanced by the necessity of adding a bytecode for (point).
+;;
+;; Also, users are more likely to have modified the behavior of
+;; delete-char via advice or some similar mechanism. This is much
+;; less of a problem for the previous functions because it wouldn't
+;; make sense to modify the behaviour of `backward-char' without also
+;; modifying `forward-char', for example.
+
+;; (delete-char n) ==> (delete-region (point) (+ (point) n))
+;; (put 'delete-char 'byte-optimizer 'byte-optimize-delete-char)
+;; (defun byte-optimize-delete-char (form)
+;; (case (length (cdr form))
+;; (0 `(delete-region (point) (1+ (point))))
+;; (1 `(delete-region (point) (+ (point) ,(nth 1 form))))
+;; (t form)))
;; byte-compile-negation-optimizer lives in bytecomp.el
;(put '/= 'byte-optimizer 'byte-compile-negation-optimizer)
(put 'atom 'byte-optimizer 'byte-compile-negation-optimizer)
(put 'nlistp 'byte-optimizer 'byte-compile-negation-optimizer)
-
(defun byte-optimize-funcall (form)
;; (funcall '(lambda ...) ...) ==> ((lambda ...) ...)
;; (funcall 'foo ...) ==> (foo ...)
(defun byte-compile-splice-in-already-compiled-code (form)
;; form is (byte-code "..." [...] n)
- (if (not (memq byte-optimize '(t lap)))
+ (if (not (memq byte-optimize '(t byte)))
(byte-compile-normal-call form)
(byte-inline-lapcode
(byte-decompile-bytecode-1 (nth 1 form) (nth 2 form) t))
((eq type 'array) (if (arrayp x) x (vconcat x)))
((and (eq type 'character) (stringp x) (= (length x) 1)) (aref x 0))
((and (eq type 'character) (symbolp x)) (coerce (symbol-name x) type))
- ((and (eq type 'character) (numberp x) (char-or-char-int-p x)
- (int-char x)))
+ ((and (eq type 'character) (char-int-p x)) (int-char x))
+ ((and (eq type 'integer) (characterp x)) (char-int x))
((eq type 'float) (float x))
((eq type 'bit-vector) (if (bit-vector-p x) x
(apply 'bit-vector (append x nil))))
((eq (car-safe spec) 'optimize)
(let ((speed (assq (nth 1 (assq 'speed (cdr spec)))
- '((0 nil) (1 t) (2 t) (3 t))))
+ '((0 . nil) (1 . t) (2 . t) (3 . t))))
(safety (assq (nth 1 (assq 'safety (cdr spec)))
- '((0 t) (1 t) (2 t) (3 nil)))))
- (if speed (setq cl-optimize-speed (car speed)
- byte-optimize (nth 1 speed)))
- (if safety (setq cl-optimize-safety (car safety)
- byte-compile-delete-errors (nth 1 safety)))))
+ '((0 . t) (1 . t) (2 . t) (3 . nil)))))
+ (when speed
+ (setq cl-optimize-speed (car speed)
+ byte-optimize (cdr speed)))
+ (when safety
+ (setq cl-optimize-safety (car safety)
+ byte-compile-delete-errors (cdr safety)))))
((and (eq (car-safe spec) 'warn) (boundp 'byte-compile-warnings))
(if (eq byte-compile-warnings t)
(eval (cl-make-type-test 'object type)))
;;;###autoload
-(defmacro check-type (form type &optional string)
- "Verify that FORM is of type TYPE; signal an error if not.
+(defmacro check-type (place type &optional string)
+ "Verify that PLACE is of type TYPE; signal a continuable error if not.
STRING is an optional description of the desired type."
- (and (or (not (cl-compiling-file))
- (< cl-optimize-speed 3) (= cl-optimize-safety 3))
- (let* ((temp (if (cl-simple-expr-p form 3) form (gensym)))
- (body (list 'or (cl-make-type-test temp type)
- (list 'signal '(quote wrong-type-argument)
- (list 'list (or string (list 'quote type))
- temp (list 'quote form))))))
- (if (eq temp form) (list 'progn body nil)
- (list 'let (list (list temp form)) body nil)))))
+ (when (or (not (cl-compiling-file))
+ (< cl-optimize-speed 3)
+ (= cl-optimize-safety 3))
+ (let* ((temp (if (cl-simple-expr-p place 3) place (gensym)))
+ (test (cl-make-type-test temp type))
+ (signal-error `(signal 'wrong-type-argument
+ ,(list 'list (or string (list 'quote type))
+ temp (list 'quote place))))
+ (body
+ (condition-case nil
+ `(while (not ,test)
+ ,(macroexpand `(setf ,place ,signal-error)))
+ (error
+ `(if ,test (progn ,signal-error nil))))))
+ (if (eq temp place)
+ body
+ `(let ((,temp ,place)) ,body)))))
;;;###autoload
(defmacro assert (form &optional show-args string &rest args)
(fifth 'nth 4 x) (sixth 'nth 5 x) (seventh 'nth 6 x)
(eighth 'nth 7 x) (ninth 'nth 8 x) (tenth 'nth 9 x)
(rest 'cdr x) (endp 'null x) (plusp '> x 0) (minusp '< x 0)
+ (oddp 'eq (list 'logand x 1) 1)
+ (evenp 'eq (list 'logand x 1) 0)
(caar car car) (cadr car cdr) (cdar cdr car) (cddr cdr cdr)
(caaar car caar) (caadr car cadr) (cadar car cdar)
(caddr car cddr) (cdaar cdr caar) (cdadr cdr cadr)
(proclaim '(inline floatp-safe acons map concatenate notany notevery
;; XEmacs change
cl-set-elt revappend nreconc
- plusp minusp oddp evenp
))
;;; Things that are side-effect-free. Moved to byte-optimize.el
;;; Numbers.
-(defun floatp-safe (x)
- "Return t if OBJECT is a floating point number.
-On Emacs versions that lack floating-point support, this function
-always returns nil."
- ;;(and (numberp x) (not (integerp x)))
- ;; XEmacs: use floatp. XEmacs is always compiled with
- ;; floating-point, anyway.
- (floatp x))
-
-(defun plusp (x)
+(defun floatp-safe (object)
+ "Return t if OBJECT is a floating point number."
+ (floatp object))
+
+(defun plusp (number)
"Return t if NUMBER is positive."
- (> x 0))
+ (> number 0))
-(defun minusp (x)
+(defun minusp (number)
"Return t if NUMBER is negative."
- (< x 0))
+ (< number 0))
-(defun oddp (x)
+(defun oddp (integer)
"Return t if INTEGER is odd."
- (eq (logand x 1) 1))
+ (eq (logand integer 1) 1))
-(defun evenp (x)
+(defun evenp (integer)
"Return t if INTEGER is even."
- (eq (logand x 1) 0))
+ (eq (logand integer 1) 0))
-(defun cl-abs (x)
- "Return the absolute value of ARG."
- (if (>= x 0) x (- x)))
+(defun cl-abs (number)
+ "Return the absolute value of NUMBER."
+ (if (>= number 0) number (- number)))
(or (fboundp 'abs) (defalias 'abs 'cl-abs)) ; This is built-in to Emacs 19
(defvar *random-state* (vector 'cl-random-state-tag -1 30 (cl-random-time)))
If the optional FRAME argument is provided, change only
in that frame; otherwise change each frame."
(while (not (find-face face))
- (setq face (signal 'wrong-type-argument (list 'facep face))))
+ (setq face (wrong-type-argument 'facep face)))
(let ((bitmap-path (ecase (console-type)
(x x-bitmap-file-path)
(mswindows mswindows-bitmap-file-path)))
(and (listp pixmap) (= (length pixmap) 3)))))
(setq pixmap (signal 'wrong-type-argument
(list 'stipple-pixmap-p pixmap)))))
- (while (and frame (not (framep frame)))
- (setq frame (signal 'wrong-type-argument (list 'framep frame))))
+ (check-type frame (or null frame))
(set-face-background-pixmap face instantiator frame)))
\f
[jpeg :data nil] 2)))
,@(if (featurep 'png) '(("\\.png\\'" [png :file nil] 2)))
,@(if (featurep 'png) '(("\\`\211PNG" [png :data nil] 2)))
- ("" [autodetect :data nil] 2))))
+ ("" [string :data nil] 2)
+ ("" [nothing]))))
;; #### this should really be formatted-string, not string but we
;; don't have it implemented yet
;;
(let ((tabend (* (/ (current-column) tab-width) tab-width)))
(while (and (> (current-column) tabend)
(eq (char-before (point)) ?\ ))
- (forward-char -1))
+ (backward-char 1))
(delete-region (point) before))))))))
;(define-key global-map "\t" 'indent-for-tab-command)
;; Kludge.
;; Allow dots in node name not followed by whitespace.
(re-search-forward
- (concat "\\(([^)]+)[^."
+ (concat "\\(([^)]+)[^.,"
(if multi-line "" "\n")
"]*\\|\\([^.,\t"
(if multi-line "" "\n")
(forward-char 1)
(insert "\n")
(just-one-space)
- (backward-delete-char 1)
+ (delete-backward-char 1)
(setq p (point)
len 0))))
(toggle-read-only 1)
(defun itimer-live-p (object)
"Return non-nil if OBJECT is an itimer and is active.
``Active'' means Emacs will run it when it expires.
-`activate-timer' must be called on an itimer to make it active.
+`activate-itimer' must be called on an itimer to make it active.
Itimers started with `start-itimer' are automatically active."
(and (itimerp object) (memq object itimer-list)))
(if (and (looking-at "\\s<") (not (looking-at "\\s<\\s<")))
;; Single-semicolon comment lines should be indented
;; as comment lines, not as code.
- (progn (indent-for-comment) (forward-char -1))
+ (progn (indent-for-comment) (backward-char 1))
(if (listp indent) (setq indent (car indent)))
(setq shift-amt (- indent (current-column)))
(if (zerop shift-amt)
(end-of-line 1)
(beginning-of-defun-raw 1)))
nil
- (or (bobp) (forward-char -1))
+ (or (bobp) (backward-char 1))
(beginning-of-defun-raw -1))
(setq first nil)
(forward-list 1)
"Move past next `)', delete indentation before it, then indent after it."
(interactive)
(up-list 1)
- (forward-char -1)
+ (backward-char 1)
(while (save-excursion ; this is my contribution
(let ((before-paren (point)))
(back-to-indentation)
under the toplevel \"File\" menu. (\"Menu\" \"Foo\" \"Item\") means the
menu item called \"Item\" under the \"Foo\" submenu of \"Menu\".
NEW-NAME is the string that the menu item will be printed as from now on."
- (or (stringp new-name)
- (setq new-name (wrong-type-argument 'stringp new-name)))
+ (check-type new-name string)
(let* ((menubar current-menubar)
(pair (find-menu-item menubar path))
(item (car pair))
(let* ((edges (window-pixel-edges window))
(row (event-y-pixel event))
(text-start (nth 1 edges))
- (text-end (+ (nth 3 edges))))
+ (text-end (nth 3 edges)))
(if (or (< row text-start)
(> row text-end))
nil ;; Scroll
(and (save-excursion (re-search-backward page-delimiter nil t))
(= (match-end 0) (point))
(goto-char (match-beginning 0)))
- (forward-char -1)
+ (backward-char 1)
(if (re-search-backward page-delimiter nil t)
;; We found one--move to the end of it.
(goto-char (match-end 0))
nil
(setq start (point))
;; Move back over paragraph-separating lines.
- (forward-char -1) (beginning-of-line)
+ (backward-char 1) (beginning-of-line)
(while (and (not (bobp))
(progn (move-to-left-margin)
(looking-at paragraph-separate)))
(defun end-of-paragraph-text ()
(let ((opoint (point)))
(forward-paragraph 1)
- (if (eq (char-before (point)) ?\n) (forward-char -1))
+ (if (eq (char-before (point)) ?\n) (backward-char 1))
(if (<= (point) opoint)
(progn
(forward-char 1)
;; but we might as well let the user move across them.
(and (< arg 0)
(> (current-column) target-column)
- (forward-char -1))))
+ (backward-char 1))))
(defun picture-backward-column (arg)
"Move cursor left, making whitespace if necessary.
(delete-char -1)
;; FSF changes the following to last-command-event.
(insert last-command-char)
- (forward-char -1)
+ (backward-char 1)
(picture-move)
;; XEmacs addition:
(setq zmacs-region-stays nil)))
(goto-char start)
(while (search-forward "\t" end t)
(let ((width (- (current-column)
- (save-excursion (forward-char -1)
+ (save-excursion (backward-char 1)
(current-column)))))
(setq line (concat (substring line 0 (- (point) end 1))
(spaces-string width)
(save-excursion
(delete-horizontal-space)
(if (or (looking-at "^\\|\\s)")
- (save-excursion (forward-char -1)
+ (save-excursion (backward-char 1)
(looking-at "$\\|\\s(\\|\\s'")))
nil
(insert ?\ ))))
(while (and (> count 0) (not (bobp)))
(if (eq (char-before (point)) ?\t) ; XEmacs
(let ((col (current-column)))
- (forward-char -1)
+ (backward-char 1)
(setq col (- col (current-column)))
(insert-char ?\ col)
(delete-char 1)))
- (forward-char -1)
+ (backward-char 1)
(setq count (1- count)))))
(delete-backward-char arg killp)
;; XEmacs: In overwrite mode, back over columns while clearing them out,
:type 'boolean
:group 'editing-basics)
-(defcustom backward-delete-function 'backward-delete-char
+(defcustom backward-delete-function 'delete-backward-char
"*Function called to delete backwards on a delete keypress.
If `delete-key-deletes-forward' is nil, `backward-or-forward-delete-char'
calls this function to erase one character backwards. Default value
-is 'backward-delete-char, with 'backward-delete-char-untabify being a
+is `delete-backward-char', with `backward-delete-char-untabify' being a
popular alternate setting."
:type 'function
:group 'editing-basics)
and drag it forward past ARG other characters (backward if ARG negative).
If no argument and at end of line, the previous two chars are exchanged."
(interactive "*P")
- (and (null arg) (eolp) (forward-char -1))
+ (and (null arg) (eolp) (backward-char 1))
(transpose-subr 'forward-char (prefix-numeric-value arg)))
;;; A very old implementation of transpose-chars from the old days ...
and drag it forward past ARG other characters (backward if ARG negative).
If no argument and not at start of line, the previous two chars are exchanged."
(interactive "*P")
- (and (null arg) (not (bolp)) (forward-char -1))
+ (and (null arg) (not (bolp)) (backward-char 1))
(transpose-subr 'forward-char (prefix-numeric-value arg)))
(forward-char 1)))))
\f
-;; XEmacs - extra parameter
-(defun backward-word (arg &optional buffer)
- "Move backward until encountering the end of a word.
-With argument, do this that many times.
-In programs, it is faster to call `forward-word' with negative arg."
- (interactive "_p") ; XEmacs
- (forward-word (- arg) buffer))
-
-(defun mark-word (arg)
- "Set mark arg words away from point."
+(defun backward-word (&optional count buffer)
+ "Move point backward COUNT words (forward if COUNT is negative).
+Normally t is returned, but if an edge of the buffer is reached,
+point is left there and nil is returned.
+
+COUNT defaults to 1, and BUFFER defaults to the current buffer."
+ (interactive "_p")
+ (forward-word (- (or count 1)) buffer))
+
+(defun mark-word (&optional count)
+ "Mark the text from point until encountering the end of a word.
+With optional argument COUNT, mark COUNT words."
(interactive "p")
- (mark-something 'mark-word 'forward-word arg))
+ (mark-something 'mark-word 'forward-word count))
-;; XEmacs modified
-(defun kill-word (arg)
+(defun kill-word (&optional count)
"Kill characters forward until encountering the end of a word.
-With argument, do this that many times."
+With optional argument COUNT, do this that many times."
(interactive "*p")
- (kill-region (point) (save-excursion (forward-word arg) (point))))
+ (kill-region (point) (save-excursion (forward-word count) (point))))
-(defun backward-kill-word (arg)
+(defun backward-kill-word (&optional count)
"Kill characters backward until encountering the end of a word.
With argument, do this that many times."
- (interactive "*p") ; XEmacs
- (kill-word (- arg)))
+ (interactive "*p")
+ (kill-word (- (or count 1))))
(defun current-word (&optional strict)
"Return the word point is on (or a nearby word) as a string.
(and (not (bobp))
(not bounce)
sentence-end-double-space
- (save-excursion (forward-char -1)
+ (save-excursion (backward-char 1)
(and (looking-at "\\. ")
(not (looking-at "\\. "))))))
(setq first nil)
; (and (not (bobp))
; (not bounce)
; sentence-end-double-space
-; (save-excursion (forward-char -1)
+; (save-excursion (backward-char 1)
; (and (looking-at "\\. ")
; (not (looking-at "\\. "))))))
; (setq first nil)
(and comment-end (not (equal comment-end ""))
; (if (not comment-multi-line)
(progn
- (forward-char -1)
+ (backward-char 1)
(insert comment-end)
(forward-char 1))
; (setq comment-column (+ comment-column (length comment-start))
(if (not (eolp))
(setq comment-end ""))
(insert ?\n)
- (forward-char -1)
+ (backward-char 1)
(indent-for-comment)
(save-excursion
;; Make sure we delete the newline inserted above.
;; Verify an even number of quoting characters precede the close.
(= 1 (logand 1 (- (point)
(save-excursion
- (forward-char -1)
+ (backward-char 1)
(skip-syntax-backward "/\\")
(point)))))
(let* ((oldpos (point))
(indent-according-to-mode))
;; In Lisp assume double-quote is closing; in Text assume opening.
;; Why? Because it does the right thing most often.
- ((save-excursion (forward-char -1)
+ ((save-excursion (backward-char 1)
(and (not (looking-at "\\s\""))
(looking-at "[`'\"\\]\\|\\s(")))
nil)
(while (= (following-char) ?\C-h)
(delete-char 1))
(while (search-forward "\C-h" nil t)
- (forward-char -2)
+ (backward-char 2)
(cond ((looking-at "_\C-h\\|\\(.\\)\C-h\\1\\||\C-h\\^")
(delete-char 2))
((looking-at ".\C-h_\\|\\^\C-h|")
(t
(when (and (null arg)
(= last-non-space (point)))
- (forward-char -1))
+ (backward-char 1))
(transpose-chars arg)))))
(defcustom widget-complete-field (lookup-key global-map "\M-\t")
nil
(set-glyph-image text-pointer-glyph
(or (x-get-resource "textPointer" "Cursor" 'string device nil 'warn)
- "xterm"))
+ [cursor-font :data "xterm"]))
(set-glyph-image selection-pointer-glyph
(or (x-get-resource "selectionPointer" "Cursor" 'string device
nil 'warn)
- "top_left_arrow"))
+ [cursor-font :data "top_left_arrow"]))
(set-glyph-image nontext-pointer-glyph
(or (x-get-resource "spacePointer" "Cursor" 'string device nil 'warn)
- "xterm")) ; was "crosshair"
+ [cursor-font :data "xterm"])) ; was "crosshair"
(set-glyph-image modeline-pointer-glyph
(or (x-get-resource "modeLinePointer" "Cursor" 'string device
nil 'warn)
;; "fleur"))
- "sb_v_double_arrow"))
+ [cursor-font :data "sb_v_double_arrow"]))
(set-glyph-image gc-pointer-glyph
(or (x-get-resource "gcPointer" "Cursor" 'string device nil 'warn)
- "watch"))
+ [cursor-font :data "watch"]))
(when (featurep 'scrollbar)
(set-glyph-image
scrollbar-pointer-glyph
(or (x-get-resource "scrollbarPointer" "Cursor" 'string device
nil 'warn)
- "top_left_arrow")))
+ ;; bizarrely if we don't specify the specific locale (x) this
+ ;; gets instantiated on the stream device. Bad puppy.
+ [cursor-font :data "top_left_arrow"]) 'global '(default x)))
(set-glyph-image busy-pointer-glyph
(or (x-get-resource "busyPointer" "Cursor" 'string device nil 'warn)
- "watch"))
+ [cursor-font :data "watch"]))
(set-glyph-image toolbar-pointer-glyph
(or (x-get-resource "toolBarPointer" "Cursor" 'string device
nil 'warn)
- "left_ptr"))
+ [cursor-font :data "left_ptr"]))
(set-glyph-image divider-pointer-glyph
(or (x-get-resource "dividerPointer" "Cursor" 'string device
nil 'warn)
- "sb_h_double_arrow"))
+ [cursor-font :data "sb_h_double_arrow"]))
(let ((fg
(x-get-resource "pointerColor" "Foreground" 'string device
nil 'warn)))
+2000-12-05 Martin Buchholz <martin@xemacs.org>
+
+ * XEmacs 21.2.38 is released.
+
+2000-11-30 Andy Piper <andy@xemacs.org>
+
+ * lwlib-Xm.c (xm_update_label): Hack to stop %_ labels until
+ someone fixes it properly.
+
+2000-11-24 Andy Piper <andy@xemacs.org>
+
+ * xlwtabsP.h: add visible flag, realRows and remove displayChildren.
+
+ * xlwtabs.c (TabVisible): new macro. Consults visible flag.
+ (TabsInit): remove displayChildren, add realRows.
+ (TabsConstraintInitialize): ditto.
+ (TabsResize): ditto.
+ (TabsGeometryManager): ditto.
+ (TabsChangeManaged): ditto.
+ (TabsSelect): ditto.
+ (TabsPage): ditto.
+ (TabsHighlight): ditto.
+ (DrawTabs): ditto.
+ (TabLayout): Caclulate rows for all children and whether they
+ should be visible or not..
+ (TabsShuffleRows): shuffle rows based on both real and displayed
+ rows. Adjust visibility of all children.
+ (PreferredSize): ditto.
+
+2000-11-19 Martin Buchholz <martin@xemacs.org>
+
+ * xlwtabs.c (TabsResize): Don't delete `tab', mark unused instead.
+
+2000-11-18 Martin Buchholz <martin@xemacs.org>
+
+ * xlwmenu.c (make_windows_if_needed):
+ (XlwMenuRealize):
+ The proper type for `mask' is `unsigned long', not `int'.
+
+2000-11-18 Martin Buchholz <martin@xemacs.org>
+
+ * xlwtabs.c (defaultAccelerators): Add #### to unused var.
+ (TabsResize): Remove unused var.
+ * xlwmenu.c (XlwMenuInitialize): Remove unused vars.
+ * lwlib-Xlw.c (xlw_update_one_widget): Add #### for probable bug.
+
2000-11-14 Martin Buchholz <martin@xemacs.org>
* XEmacs 21.2.37 is released.
else
mw = (XlwMenuWidget)widget;
XtSetArg (al [0], XtNmenu, val);
- XtSetValues (widget, al, 1);
+ XtSetValues (widget, al, 1); /* #### mw unused! */
}
#endif
#ifdef LWLIB_SCROLLBARS_LUCID
if (val->value)
{
+ /* #### Temporary fix. I though Motif was supposed to grok %_
+ type things. */
+ lw_remove_accelerator_spec (val->value);
+
#ifdef LWLIB_DIALOGS_MOTIF
/*
* Sigh. The main text of a label is the name field for menubar
int start_at;
XSetWindowAttributes xswa;
Widget p;
- int mask;
+ unsigned long mask;
int depth;
Visual *visual;
window_state *windows;
{
/* Get the GCs and the widget size */
XlwMenuWidget mw = (XlwMenuWidget)new;
-
- XSetWindowAttributes xswa;
- int mask;
-
Window window = RootWindowOfScreen (DefaultScreenOfDisplay (XtDisplay (mw)));
Display *display = XtDisplay (mw);
make_shadow_gcs (mw);
extract_font_extents (mw);
- xswa.background_pixel = mw->core.background_pixel;
- xswa.border_pixel = mw->core.border_pixel;
- mask = CWBackPixel | CWBorderPixel;
-
mw->menu.popped_up = False;
mw->menu.pointer_grabbed = False;
mw->menu.next_release_must_exit = False;
{
XlwMenuWidget mw = (XlwMenuWidget)w;
XSetWindowAttributes xswa;
- int mask;
+ unsigned long mask;
(*xlwMenuWidgetClass->core_class.superclass->core_class.realize)
(w, valueMask, attributes);
+2000-12-05 Martin Buchholz <martin@xemacs.org>
+
+ * XEmacs 21.2.38 is released.
+
+2000-12-01 Martin Buchholz <martin@xemacs.org>
+
+ * lispref/compile.texi:
+ Document differences between compiler and interpreter.
+
+2000-11-29 Stephen J. Turnbull <stephen@xemacs.org>
+
+ * internals/index.texi:
+ internals/internals.texi:
+ Change "X Windows" to "the X Window System" randomly.
+ * internals/internals.texi (Glyphs): fiddling, move lwlib to new node.
+ (Lucid Widget Library): new node, added new text, ASCII art, subnode
+ structure.
+ * xemacs/frame.texi (GUI Components): new node.
+ * xemacs/packages.texi: minor updates.
+
+2000-11-10 Stephen J. Turnbull <stephen@xemacs.org>
+
+ * info.texi (Creating an Info File): Fix typos in xrefs.
+
+2000-11-08 Stephen J. Turnbull <stephen@xemacs.org>
+
+ * xemacs/cmdargs.texi (Command Switches): Add documentation of
+ portable dumper switches. Other minor edits.
+
+2000-11-21 Martin Buchholz <martin@xemacs.org>
+
+ * lispref/positions.texi (Word Motion):
+ forward-word arg is now optional.
+ backward-word arg is now optional.
+ Remove vile comment advising lisp programmer to use (forward-word -1)
+ instead of (backward-word 1).
+ * lispref/syntax.texi (Parsing Expressions):
+ Similarly for forward-comment.
+ * lispref/text.texi (Deletion):
+ Similarly for delete-char.
+ Similarly for delete-backward-char.
+
+2000-11-09 Martin Buchholz <martin@xemacs.org>
+
+ * cl.texi (Assertions):
+ Remove claim that elisp doesn't have continuable errors.
+ Document check-type as being continuable.
+
+2000-11-14 Adrian Aichner <adrian@xemacs.org>
+
+ * xemacs/calendar.texi (Calendar/Diary): Correct INFO-FILE-NAME
+ from elisp to lispref and from emacs to xemacs in relevant ?xefs.
+ This should also serve as a reminder for future merges with GNU
+ Emacs.
+ Unify PRINTED-MANUAL-TITLE to "XEmacs Lisp Reference Manual" and
+ "XEmacs User's Manual" for lispref and xemacs respectively.
+
+2000-11-14 Adrian Aichner <adrian@xemacs.org>
+
+ * lispref/abbrevs.texi (Abbrevs): Ditto.
+ * lispref/backups.texi (Auto-Saving): Ditto.
+ * lispref/backups.texi (Reverting): Ditto.
+ * lispref/display.texi (The Echo Area): Ditto.
+ * lispref/help.texi (Documentation Basics): Ditto.
+ * lispref/help.texi (Help Functions): Ditto.
+ * lispref/keymaps.texi (Scanning Keymaps): Ditto.
+ * lispref/locals.texi (Standard Buffer-Local Variables): Ditto.
+ * lispref/modes.texi (Auto Major Mode): Ditto.
+ * lispref/positions.texi (List Motion): Ditto.
+ * lispref/searching.texi (Regexp Search): Ditto.
+ * lispref/symbols.texi (Symbol Components): Ditto.
+ * lispref/tips.texi (Comment Tips): Ditto.
+ * lispref/tips.texi (Library Headers): Ditto.
+
+2000-11-14 Adrian Aichner <adrian@xemacs.org>
+
+ * internals/internals.texi (The Buffer Object): Ditto.
+
+2000-11-14 Adrian Aichner <adrian@xemacs.org>
+
+ * cl.texi (Hash Tables): Ditto.
+ * texinfo.texi (Other Info Files): Ditto.
+ * xemacs-faq.texi (Q1.0.14): Ditto.
+
2000-11-14 Martin Buchholz <martin@xemacs.org>
* XEmacs 21.2.37 is released.
strictly speaking redundant now that @code{setf} exists. Many
programmers continue to prefer @code{setq} for setting simple
variables, though, purely for stylistic or historical reasons.
-The macro @code{(setf x y)} actually expands to @code{(setq x y)},
+The form @code{(setf x y)} actually expands to @code{(setq x y)},
so there is no performance penalty for using it in compiled code.
@item
@noindent
Hash tables are now implemented directly in the C code and documented in
-@ref{Hash Tables,,, lispref, XEmacs Lisp Programmer's Manual}.
+@ref{Hash Tables,,, lispref, XEmacs Lisp Reference Manual}.
@ignore
A @dfn{hash table} is a data structure that maps ``keys'' onto
(assert (> x 10) t "x is too small: %d")
@end example
-This usage of @var{show-args} is an extension to Common Lisp. In
+This usage of @var{show-args} is a change to Common Lisp. In
true Common Lisp, the second argument gives a list of @var{places}
which can be @code{setf}'d by the user before continuing from the
-error. Since Emacs Lisp does not support continuable errors, it
-makes no sense to specify @var{places}.
+error.
@end defspec
-@defspec check-type form type [string]
-This form verifies that @var{form} evaluates to a value of type
+@defspec check-type place type &optional string
+This form verifies that @var{place} evaluates to a value of type
@var{type}. If so, it returns @code{nil}. If not, @code{check-type}
-signals a @code{wrong-type-argument} error. The default error message
-lists the erroneous value along with @var{type} and @var{form}
-themselves. If @var{string} is specified, it is included in the
-error message in place of @var{type}. For example:
+signals a continuable @code{wrong-type-argument} error. The default
+error message lists the erroneous value along with @var{type} and
+@var{place} themselves. If @var{string} is specified, it is included in
+the error message in place of @var{type}. For example:
@example
(check-type x (integer 1 *) "a positive integer")
@xref{Type Predicates}, for a description of the type specifiers
that may be used for @var{type}.
-Note that in Common Lisp, the first argument to @code{check-type}
-must be a @var{place} suitable for use by @code{setf}, because
-@code{check-type} signals a continuable error that allows the
-user to modify @var{place}.
+Note that as in Common Lisp, the first argument to @code{check-type}
+should be a @var{place} suitable for use by @code{setf}, because
+@code{check-type} signals a continuable error that allows the user to
+modify @var{place}, most simply by returning a value from the debugger.
@end defspec
The following error-related macro is also defined:
@setfilename ../info/info.info
@settitle Info
@comment %**end of header
-@comment $Id: info.texi,v 1.4.2.5 2000/09/13 10:57:18 martinb Exp $
+@comment $Id: info.texi,v 1.4.2.6 2000/11/29 08:27:28 stephent Exp $
@dircategory Texinfo documentation system
@direntry
@xref{Top,, Overview of Texinfo, texinfo, Texinfo}, to learn how to
write a Texinfo file.
-@xref{Creating an Info File,,, texinfo, Texinfo}, to learn how to create
-an Info file from a Texinfo file.
+@xref{Create an Info File, , Creating an Info File, texinfo, Texinfo},
+to learn how to create an Info file from a Texinfo file.
-@xref{Installing an Info File,,, texinfo, Texinfo}, to learn how to
-install an Info file after you have created one.
+@xref{Install an Info File, , Installing an Info File, texinfo, Texinfo},
+to learn how to install an Info file after you have created one.
@bye
* Specifiers::
* Menus::
* Subprocesses::
-* Interface to X Windows::
+* Interface to the X Window System::
* Index::
@detailmenu
@table @code
@item name
The buffer name is a string that names the buffer. It is guaranteed to
-be unique. @xref{Buffer Names,,, lispref, XEmacs Lisp Programmer's
+be unique. @xref{Buffer Names,,, lispref, XEmacs Lisp Reference
Manual}.
@item save_modified
This field contains the time when the buffer was last saved, as an
-integer. @xref{Buffer Modification,,, lispref, XEmacs Lisp Programmer's
+integer. @xref{Buffer Modification,,, lispref, XEmacs Lisp Reference
Manual}.
@item modtime
This field contains the modification time of the visited file. It is
set when the file is written or read. Every time the buffer is written
to the file, this field is compared to the modification time of the
-file. @xref{Buffer Modification,,, lispref, XEmacs Lisp Programmer's
+file. @xref{Buffer Modification,,, lispref, XEmacs Lisp Reference
Manual}.
@item auto_save_modified
@item undo_list
This field points to the buffer's undo list. @xref{Undo,,, lispref,
-XEmacs Lisp Programmer's Manual}.
+XEmacs Lisp Reference Manual}.
@item syntax_table_v
This field contains the syntax table for the buffer. @xref{Syntax
-Tables,,, lispref, XEmacs Lisp Programmer's Manual}.
+Tables,,, lispref, XEmacs Lisp Reference Manual}.
@item downcase_table
This field contains the conversion table for converting text to lower
-case. @xref{Case Tables,,, lispref, XEmacs Lisp Programmer's Manual}.
+case. @xref{Case Tables,,, lispref, XEmacs Lisp Reference Manual}.
@item upcase_table
This field contains the conversion table for converting text to upper
-case. @xref{Case Tables,,, lispref, XEmacs Lisp Programmer's Manual}.
+case. @xref{Case Tables,,, lispref, XEmacs Lisp Reference Manual}.
@item case_canon_table
This field contains the conversion table for canonicalizing text for
case-folding search. @xref{Case Tables,,, lispref, XEmacs Lisp
-Programmer's Manual}.
+Reference Manual}.
@item case_eqv_table
This field contains the equivalence table for case-folding search.
-@xref{Case Tables,,, lispref, XEmacs Lisp Programmer's Manual}.
+@xref{Case Tables,,, lispref, XEmacs Lisp Reference Manual}.
@item display_table
This field contains the buffer's display table, or @code{nil} if it
doesn't have one. @xref{Display Tables,,, lispref, XEmacs Lisp
-Programmer's Manual}.
+Reference Manual}.
@item markers
This field contains the chain of all markers that currently point into
the buffer. Deletion of text in the buffer, and motion of the buffer's
gap, must check each of these markers and perhaps update it.
-@xref{Markers,,, lispref, XEmacs Lisp Programmer's Manual}.
+@xref{Markers,,, lispref, XEmacs Lisp Reference Manual}.
@item backed_up
This field is a flag that tells whether a backup file has been made for
@item mark
This field contains the mark for the buffer. The mark is a marker,
hence it is also included on the list @code{markers}. @xref{The Mark,,,
-lispref, XEmacs Lisp Programmer's Manual}.
+lispref, XEmacs Lisp Reference Manual}.
@item mark_active
This field is non-@code{nil} if the buffer's mark is active.
in this buffer, and their values, with the exception of local variables
that have special slots in the buffer object. (Those slots are omitted
from this table.) @xref{Buffer-Local Variables,,, lispref, XEmacs Lisp
-Programmer's Manual}.
+Reference Manual}.
@item modeline_format
This field contains a Lisp object which controls how to display the mode
line for this buffer. @xref{Modeline Format,,, lispref, XEmacs Lisp
-Programmer's Manual}.
+Reference Manual}.
@item base_buffer
This field holds the buffer's base buffer (if it is an indirect buffer),
Glyphs are graphical elements that can be displayed in XEmacs buffers or
gutters. We use the term graphical element here in the broadest possible
-sense since glyphs can be as mundane as text to as arcane as a native
+sense since glyphs can be as mundane as text or as arcane as a native
tab widget.
In XEmacs, glyphs represent the uninstantiated state of graphical
elements, i.e. they hold all the information necessary to produce an
-image on-screen but the image does not exist at this stage.
+image on-screen but the image need not exist at this stage, and multiple
+screen images can be instantiated from a single glyph.
Glyphs are lazily instantiated by calling one of the glyph
functions. This usually occurs within redisplay when
Widget-glyphs (a.k.a native widgets) are not cached in this way. This is
because widget-glyph image-instances on screen are toolkit windows, and
thus cannot be reused in multiple XEmacs domains. Thus widget-glyphs are
-cached on a window basis.
+cached on an XEmacs window basis.
Any action on a glyph first consults the cache before actually
instantiating a widget.
@section Widget-Glyphs in the X Environment
-Widget-glyphs under X make heavy use of lwlib for manipulating the
-native toolkit objects. This is primarily so that different toolkits can
-be supported for widget-glyphs, just as they are supported for features
-such as menubars etc.
-
-Lwlib is extremely poorly documented and quite hairy so here is my
-understanding of what goes on.
-
-Lwlib maintains a set of widget_instances which mirror the hierarchical
-state of Xt widgets. I think this is so that widgets can be updated and
-manipulated generically by the lwlib library. For instance
-update_one_widget_instance can cope with multiple types of widget and
-multiple types of toolkit. Each element in the widget hierarchy is updated
-from its corresponding widget_instance by walking the widget_instance
-tree recursively.
-
-This has desirable properties such as lw_modify_all_widgets which is
-called from @file{glyphs-x.c} and updates all the properties of a widget
-without having to know what the widget is or what toolkit it is from.
-Unfortunately this also has hairy properties such as making the lwlib
-code quite complex. And of course lwlib has to know at some level what
-the widget is and how to set its properties.
+Widget-glyphs under X make heavy use of lwlib (@pxref{Lucid Widget
+Library}) for manipulating the native toolkit objects. This is primarily
+so that different toolkits can be supported for widget-glyphs, just as
+they are supported for features such as menubars etc.
@node Specifiers, Menus, Glyphs, Top
@chapter Specifiers
its argument, which is the callback function or form given in the menu's
description.
-@node Subprocesses, Interface to X Windows, Menus, Top
+@node Subprocesses, Interface to the X Window System, Menus, Top
@chapter Subprocesses
The fields of a process are:
or @code{nil} if it is using pipes.
@end table
-@node Interface to X Windows, Index , Subprocesses, Top
-@chapter Interface to X Windows
+@node Interface to the X Window System, Index, Subprocesses, Top
+@chapter Interface to the X Window System
-Not yet documented.
+Mostly undocumented.
+
+@menu
+* Lucid Widget Library:: An interface to various widget sets.
+@end menu
+
+@node Lucid Widget Library, , , Interface to the X Window System
+@section Lucid Widget Library
+
+Lwlib is extremely poorly documented and quite hairy. The author(s)
+blame that on X, Xt, and Motif, with some justice, but also sufficient
+hypocrisy to avoid drawing the obvious conclusion about their own work.
+
+The Lucid Widget Library is composed of two more or less independent
+pieces. The first, as the name suggests, is a set of widgets. These
+widgets are intended to resemble and improve on widgets provided in the
+Motif toolkit but not in the Athena widgets, including menubars and
+scrollbars. Recent additions by Andy Piper integrate some ``modern''
+widgets by Edward Falk, including checkboxes, radio buttons, progress
+gauges, and index tab controls (aka notebooks).
+
+The second piece of the Lucid widget library is a generic interface to
+several toolkits for X (including Xt, the Athena widget set, and Motif,
+as well as the Lucid widgets themselves) so that core XEmacs code need
+not know which widget set has been used to build the graphical user
+interface.
+
+@menu
+* Generic Widget Interface:: The lwlib generic widget interface.
+* Scrollbars::
+* Menubars::
+* Checkboxes and Radio Buttons::
+* Progress Bars::
+* Tab Controls::
+@end menu
+
+@node Generic Widget Interface, Scrollbars, , Lucid Widget Library
+@subsection Generic Widget Interface
+
+In general in any toolkit a widget may be a composite object. In Xt,
+all widgets have an X window that they manage, but typically a complex
+widget will have widget children, each of which manages a subwindow of
+the parent widget's X window. These children may themselves be
+composite widgets. Thus a widget is actually a tree or hierarchy of
+widgets.
+
+For each toolkit widget, lwlib maintains a tree of @code{widget_values}
+which mirror the hierarchical state of Xt widgets (including Motif,
+Athena, 3D Athena, and Falk's widget sets). Each @code{widget_value}
+has @code{contents} member, which points to the head of a linked list of
+its children. The linked list of siblings is chained through the
+@code{next} member of @code{widget_value}.
+
+@example
+ +-----------+
+ | composite |
+ +-----------+
+ |
+ | contents
+ V
+ +-------+ next +-------+ next +-------+
+ | child |----->| child |----->| child |
+ +-------+ +-------+ +-------+
+ |
+ | contents
+ V
+ +-------------+ next +-------------+
+ | grand child |----->| grand child |
+ +-------------+ +-------------+
+
+The @code{widget_value} hierarchy of a composite widget with two simple
+children and one composite child.
+@end example
+
+The @code{widget_instance} structure maintains the inverse view of the
+tree. As for the @code{widget_value}, siblings are chained through the
+@code{next} member. However, rather than naming children, the
+@code{widget_instance} tree links to parents.
+
+@example
+ +-----------+
+ | composite |
+ +-----------+
+ A
+ | parent
+ |
+ +-------+ next +-------+ next +-------+
+ | child |----->| child |----->| child |
+ +-------+ +-------+ +-------+
+ A
+ | parent
+ |
+ +-------------+ next +-------------+
+ | grand child |----->| grand child |
+ +-------------+ +-------------+
+
+The @code{widget_value} hierarchy of a composite widget with two simple
+children and one composite child.
+@end example
+
+This permits widgets derived from different toolkits to be updated and
+manipulated generically by the lwlib library. For instance
+@code{update_one_widget_instance} can cope with multiple types of widget
+and multiple types of toolkit. Each element in the widget hierarchy is
+updated from its corresponding @code{widget_value} by walking the
+@code{widget_value} tree. This has desirable properties. For example,
+@code{lw_modify_all_widgets} is called from @file{glyphs-x.c} and
+updates all the properties of a widget without having to know what the
+widget is or what toolkit it is from. Unfortunately this also has its
+hairy properties; the lwlib code quite complex. And of course lwlib has
+to know at some level what the widget is and how to set its properties.
+
+The @code{widget_instance} structure also contains a pointer to the root
+of its tree. Widget instances are further confi
+
+
+@node Scrollbars, Menubars, Generic Widget Interface, Lucid Widget Library
+@subsection Scrollbars
+
+@node Menubars, Checkboxes and Radio Buttons, Scrollbars, Lucid Widget Library
+@subsection Menubars
+
+@node Checkboxes and Radio Buttons, Progress Bars, Menubars, Lucid Widget Library
+@subsection Checkboxes and Radio Buttons
+
+@node Progress Bars, Tab Controls, Checkboxes and Radio Buttons, Lucid Widget Library
+@subsection Progress Bars
+
+@node Tab Controls, , Progress Bars, Lucid Widget Library
+@subsection Tab Controls
@include index.texi
@xref{Creating Symbols}.
For the user-level commands for abbrevs, see @ref{Abbrevs,, Abbrev
-Mode, emacs, The XEmacs Reference Manual}.
+Mode, xemacs, The XEmacs User's Manual}.
@menu
* Abbrev Mode:: Setting up XEmacs for abbreviation.
than a limited amount of work if the system crashes. By default,
auto-saves happen every 300 keystrokes, or after around 30 seconds of
idle time. @xref{Auto-Save, Auto-Save, Auto-Saving: Protection Against
-Disasters, emacs, The XEmacs Reference Manual}, for information on auto-save
-for users. Here we describe the functions used to implement auto-saving
-and the variables that control them.
+Disasters, xemacs, The XEmacs Lisp Reference Manual}, for information on
+auto-save for users. Here we describe the functions used to implement
+auto-saving and the variables that control them.
@defvar buffer-auto-save-file-name
This buffer-local variable is the name of the file used for
If you have made extensive changes to a file and then change your mind
about them, you can get rid of them by reading in the previous version
of the file with the @code{revert-buffer} command. @xref{Reverting, ,
-Reverting a Buffer, emacs, The XEmacs Reference Manual}.
+Reverting a Buffer, xemacs, The XEmacs Lisp Reference Manual}.
@deffn Command revert-buffer &optional check-auto-save noconfirm preserve-modes
This command replaces the buffer text with the text of the visited
* Eval During Compile:: Code to be evaluated when you compile.
* Compiled-Function Objects:: The data type used for byte-compiled functions.
* Disassembly:: Disassembling byte-code; how to read byte-code.
+* Different Behavior:: When compiled code gives different results.
@end menu
@node Speed of Byte-Code
@end example
+@node Different Behavior
+@section Different Behavior
+
+The intent is that compiled byte-code and the corresponding code
+executed by the Lisp interpreter produce identical results. However,
+there are some circumstances where the results will differ.
+
+@itemize @bullet
+@item
+Arithmetic operations may be rearranged for efficiency or compile-time
+evaluation. When floating point numbers are involved, this may produce
+different values or an overflow.
+@item
+Some arithmetic operations may be optimized away. For example, the
+expression @code{(+ x)} may be optimized to simply @code{x}. If the
+value of @code{x} is a marker, then the value will be a marker instead
+of an integer. If the value of @samp{x} is a cons cell, then the
+interpreter will issue an error, while the bytecode will not.
+
+If you're trying to use @samp{(+ @var{object} 0)} to convert
+@var{object} to integer, consider using an explicit conversion function,
+which is clearer and guaranteed to work.
+Instead of @samp{(+ @var{marker} 0)}, use @samp{(marker-position @var{marker})}.
+Instead of @samp{(+ @var{char} 0)}, use @samp{(char-int @var{char})}.
+@end itemize
+
+For maximal equivalence between interpreted and compiled code, the
+variables @code{byte-compile-delete-errors} and
+@code{byte-compile-optimize} can be set to @code{nil}, but this is not
+recommended.
@code{message} primitive, and for echoing keystrokes. It is not the
same as the minibuffer, despite the fact that the minibuffer appears
(when active) in the same place on the screen as the echo area. The
-@cite{XEmacs Reference Manual} specifies the rules for resolving conflicts
+@cite{XEmacs Lisp Reference Manual} specifies the rules for resolving conflicts
between the echo area and the minibuffer for use of that screen space
-(@pxref{Minibuffer,, The Minibuffer, emacs, The XEmacs Reference Manual}).
+(@pxref{Minibuffer,, The Minibuffer, xemacs, The XEmacs Lisp Reference Manual}).
Error messages appear in the echo area; see @ref{Errors}.
You can write output in the echo area by using the Lisp printing
transparent to the user.
For information on the uses of documentation strings, see @ref{Help, ,
-Help, emacs, The XEmacs Reference Manual}.
+Help, xemacs, The XEmacs Reference Manual}.
@c Wordy to prevent overfull hbox. --rjc 15mar92
The @file{emacs/lib-src} directory contains two utilities that you can
XEmacs provides a variety of on-line help functions, all accessible to
the user as subcommands of the prefix @kbd{C-h}, or on some keyboards,
@kbd{help}. For more information about them, see @ref{Help, , Help,
-emacs, The XEmacs Reference Manual}. Here we describe some
+emacs, The XEmacs Lisp Reference Manual}. Here we describe some
program-level interfaces to the same information.
@deffn Command apropos regexp &optional do-all predicate
follow indirect keymap bindings. This makes it possible to search for
an indirect definition itself.
-This function is used by @code{where-is} (@pxref{Help, , Help, emacs,
-The XEmacs Reference Manual}).
+This function is used by @code{where-is} (@pxref{Help, , Help, xemacs,
+The XEmacs Lisp Reference Manual}).
@smallexample
@group
Byte Compilation
-* Compilation Functions:: Byte compilation functions.
-* Disassembly:: Disassembling byte-code; how to read byte-code.
+* Speed of Byte-Code:: An example of speedup from byte compilation.
+* Compilation Functions:: Byte compilation functions.
+* Docs and Compilation:: Dynamic loading of documentation strings.
+* Dynamic Loading:: Dynamic loading of individual functions.
+* Eval During Compile:: Code to be evaluated when you compile.
+* Compiled-Function Objects:: The data type used for byte-compiled functions.
+* Disassembly:: Disassembling byte-code; how to read byte-code.
+* Different Behavior:: When compiled code gives different results.
Debugging Lisp Programs
@pxref{Usual Display}
@item comment-column
-@pxref{Comments,,, emacs, The XEmacs User's Manual}
+@pxref{Comments,,, xemacs, The XEmacs User's Manual}
@item default-directory
@pxref{System Environment}
@pxref{Auto Filling}
@item goal-column
-@pxref{Moving Point,,, emacs, The XEmacs User's Manual}
+@pxref{Moving Point,,, xemacs, The XEmacs User's Manual}
@item left-margin
@pxref{Indentation}
If you run @code{normal-mode} interactively, the argument
@var{find-file} is normally @code{nil}. In this case,
@code{normal-mode} unconditionally processes any local variables list.
-@xref{File variables, , Local Variables in Files, emacs, The XEmacs
+@xref{File variables, , Local Variables in Files, xemacs, The XEmacs
Reference Manual}, for the syntax of the local variables section of a file.
@cindex file mode specification error
value of a local variable. However, this function does not look for
the @samp{mode:} local variable near the end of a file; the
@code{hack-local-variables} function does that. @xref{Choosing Modes, ,
-How Major Modes are Chosen, emacs, The XEmacs Reference Manual}.
+How Major Modes are Chosen, xemacs, The XEmacs Lisp Reference Manual}.
@end defun
@defopt default-major-mode
These functions for parsing words use the syntax table to decide
whether a given character is part of a word. @xref{Syntax Tables}.
-@deffn Command forward-word count &optional buffer
+@deffn Command forward-word &optional count buffer
This function moves point forward @var{count} words (or backward if
@var{count} is negative). Normally it returns @code{t}. If this motion
encounters the beginning or end of the buffer, or the limits of the
accessible portion when narrowing is in effect, point stops there and
-the value is @code{nil}. @var{buffer} defaults to the current buffer if
-omitted.
+the value is @code{nil}.
+
+@var{count} defaults to @code{1} and @var{buffer} defaults to the
+current buffer.
In an interactive call, @var{count} is set to the numeric prefix
argument.
@end deffn
-@deffn Command backward-word count &optional buffer
+@deffn Command backward-word &optional count buffer
This function is just like @code{forward-word}, except that it moves
backward until encountering the front of a word, rather than forward.
@var{buffer} defaults to the current buffer if omitted.
In an interactive call, @var{count} is set to the numeric prefix
argument.
-
-This function is rarely used in programs, as it is more efficient to
-call @code{forward-word} with a negative argument.
@end deffn
@defvar words-include-escapes
them in XEmacs). The syntax table controls how these functions interpret
various characters; see @ref{Syntax Tables}. @xref{Parsing
Expressions}, for lower-level primitives for scanning sexps or parts of
-sexps. For user-level commands, see @ref{Lists and Sexps,,, emacs, XEmacs
+sexps. For user-level commands, see @ref{Lists and Sexps,,, xemacs, XEmacs
Reference Manual}.
@deffn Command forward-list &optional arg
In XEmacs, you can search for the next match for a regexp either
incrementally or not. Incremental search commands are described in the
-@cite{The XEmacs Reference Manual}. @xref{Regexp Search, , Regular Expression
-Search, emacs, The XEmacs Reference Manual}. Here we describe only the search
+@cite{The XEmacs Lisp Reference Manual}. @xref{Regexp Search, , Regular Expression
+Search, xemacs, The XEmacs Lisp Reference Manual}. Here we describe only the search
functions useful in programs. The principal one is
@code{re-search-forward}.
@noindent
Because this symbol is the variable which holds the name of the file
being visited in the current buffer, the value cell contents we see are
-the name of the source file of this chapter of the XEmacs Lisp Manual.
+the name of the source file of this chapter of the XEmacs Lisp Reference
+Manual.
The property list cell contains the list @code{(variable-documentation
29529)} which tells the documentation functions where to find the
documentation string for the variable @code{buffer-file-name} in the
You can use @code{forward-comment} to move forward or backward over
one comment or several comments.
-@defun forward-comment count &optional buffer
+@defun forward-comment &optional count buffer
This function moves point forward across @var{count} comments (backward,
if @var{count} is negative). If it finds anything other than a comment
or whitespace, it stops, leaving point at the place where it stopped.
-It also stops after satisfying @var{count}.
+It also stops after satisfying @var{count}. @var{count} defaults to @code{1}.
- Optional argument @var{buffer} defaults to the current buffer.
+Optional argument @var{buffer} defaults to the current buffer.
@end defun
To move forward over all comments and whitespace following point, use
argument @var{buffer} is @code{nil}, the current buffer is assumed.
@end deffn
-@deffn Command delete-char count &optional killp
+@deffn Command delete-char &optional count killp
This command deletes @var{count} characters directly after point, or
-before point if @var{count} is negative. If @var{killp} is
-non-@code{nil}, then it saves the deleted characters in the kill ring.
+before point if @var{count} is negative. @var{count} defaults to @code{1}.
+If @var{killp} is non-@code{nil}, then it saves the deleted characters
+in the kill ring.
In an interactive call, @var{count} is the numeric prefix argument, and
@var{killp} is the unprocessed prefix argument. Therefore, if a prefix
The value returned is always @code{nil}.
@end deffn
-@deffn Command delete-backward-char count &optional killp
+@deffn Command delete-backward-char &optional count killp
@cindex delete previous char
This command deletes @var{count} characters directly before point, or
-after point if @var{count} is negative. If @var{killp} is
-non-@code{nil}, then it saves the deleted characters in the kill ring.
+after point if @var{count} is negative. @var{count} defaults to 1.
+If @var{killp} is non-@code{nil}, then it saves the deleted characters
+in the kill ring.
In an interactive call, @var{count} is the numeric prefix argument, and
@var{killp} is the unprocessed prefix argument. Therefore, if a prefix
(@code{indent-for-comment}) and @key{TAB} (@code{lisp-indent-line})
automatically indent comments according to these conventions,
depending on the number of semicolons. @xref{Comments,,
-Manipulating Comments, emacs, The XEmacs Reference Manual}.
+Manipulating Comments, xemacs, The XEmacs User's Manual}.
@node Library Headers
@section Conventional Headers for XEmacs Libraries
\input texinfo.tex @c -*-texinfo-*-
-@c $Id: texinfo.texi,v 1.8.2.4 1999/12/05 19:02:24 martinb Exp $
+@c $Id: texinfo.texi,v 1.8.2.5 2000/11/14 23:29:15 adrian Exp $
@c %**start of header
@c All text is ignored before the setfilename.
@end example
For example, to refer directly to the @samp{Outlining} and
-@samp{Rebinding} nodes in the @cite{Emacs Manual}, you would write a
-menu like this:@refill
+@samp{Rebinding} nodes in the @cite{XEmacs User's Manual}, you would
+write a menu like this:@refill
@example
@group
@@menu
-* Outlining: (emacs)Outline Mode. The major mode for
- editing outlines.
-* Rebinding: (emacs)Rebinding. How to redefine the
- meaning of a key.
+* Outlining: (xemacs)Outline Mode. The major mode for
+ editing outlines.
+* Rebinding: (xemacs)Rebinding. How to redefine the
+ meaning of a key.
@@end menu
@end group
@end example
@finalout
@titlepage
@title XEmacs FAQ
-@subtitle Frequently asked questions about XEmacs @* Last Modified: $Date: 2000/11/02 21:51:16 $
+@subtitle Frequently asked questions about XEmacs @* Last Modified: $Date: 2000/11/14 23:29:27 $
@sp 1
@author Tony Rossini <rossini@@biostat.washington.edu>
@author Ben Wing <ben@@xemacs.org>
No, but Alexander Nikolaev <avn_1251@@mail.ru> is working on it.
@node Q1.0.14, Q1.1.1, Q1.0.13, Introduction
-@unnumberedsubsec Q1.0.14: Where can I obtain a printed copy of the XEmacs users manual?
+@unnumberedsubsec Q1.0.14: Where can I obtain a printed copy of the XEmacs User's Manual?
Pre-printed manuals are not available. If you are familiar with
TeX, you can generate your own manual from the XEmacs sources.
particular date; @kbd{Buttons3} brings up a menu of commonly used
calendar features that are independent of any particular date. To exit
the calendar, type @kbd{q}. @xref{Calendar, Customizing the Calendar
-and Diary,, elisp, The Emacs Lisp Reference Manual}, for customization
+and Diary,, lispref, The XEmacs Lisp Reference Manual}, for customization
information about the calendar and diary.
@menu
standard Xt command line arguments. Command line arguments are not usually
needed for editing with Emacs; new users can skip this section.
-Many editors are designed to be started afresh each time you want to
+ Many editors are designed to be started afresh each time you want to
edit. You start the editor to edit one file; then exit the editor. The
next time you want to edit either another file or the same one, you
start the editor again. Under these circumstances, it makes sense to use a
needed.
Emacs accepts command-line arguments that specify files to visit,
-functions to call, and other activities and operating modes. If you are
-running XEmacs under the X window system, a number of standard
-Xt command line arguments are available as well.
+functions to call, and other activities and operating modes. If you
+are running XEmacs under the X window system, a number of standard Xt
+command line arguments are available, as well as a few X parameters
+that are XEmacs-specific.
+
+ Options with long names with a single initial hyphen are also
+recognized with the GNU double initial hyphen syntax. (The reverse
+is not true.)
The following subsections list:
@itemize @bullet
what @kbd{M-x insert-buffer} does; @xref{Misc File Ops}.
@item -kill
-Exit from Emacs without asking for confirmation.
+Exit from Emacs without asking for confirmation. Always the last
+argument processed, no matter where it appears in the command line.
@item -version
@itemx -V
order in which they appear in this table.
@table @samp
-@item -t @var{file}
+@item --show-dump-id
+@itemx -sd
+Print the ID for the new portable dumper's dump file on the terminal and
+exit. (Prints an error message and exits if XEmacs was not configured
+@samp{--pdump}.)
+
+@item --no-dump-file
+@itemx -nd
+Don't load the dump file. Roughly equivalent to old temacs. (Ignored if
+XEmacs was not configured @samp{--pdump}.)
+
+@item --terminal @var{file}
+@itemx -t @var{file}
Use @var{file} instead of the terminal for input and output. This
implies the @samp{-nw} option, documented below.
processed. In addition, auto-saving is not done except in buffers for
which it has been explicitly requested.
-@item -nw
+@item --no-windows
+@itemx -nw
Start up XEmacs in TTY mode (using the TTY XEmacs was started from),
rather than trying to connect to an X display. Note that this happens
automatically if the @samp{DISPLAY} environment variable is not set.
@itemx -u @var{user}
Equivalent to @samp{-user-init-file ~@var{user}/.xemacs/init.el
-user-init-directory ~@var{user}/.xemacs}, or @samp{-user-init-file
-~@var{user}/.emacs -user-init-directory ~@var{user}/.xemacs}. whichever
+~@var{user}/.emacs -user-init-directory ~@var{user}/.xemacs}, whichever
init file comes first. @xref{Init File}.
@end table
menu bar at the top of the frame makes shortcuts to several of the
commands available (@pxref{Pull-down Menus}).
@item
-If you are running XEmacs under a graphical windowing system, a
+Under a graphical windowing system, a
toolbar at the top of the frame, just under the menu bar if it exists,
provides ``one-touch'' shortcuts to several commands. (Not yet
documented.)
@item
-If you are running XEmacs under a graphical windowing system, a
+Under a graphical windowing system, a
gutter at the top (under the toolbar) and/or bottom of the frame
provides advanced GUI facilities like tab controls for rapid switching
among related windows and progress bars for time-consuming operations
@menu
* Point:: The place in the text where editing commands operate.
* Echo Area:: Short messages appear at the bottom of the frame.
-* Mode Line:: Interpreting the mode line.
+* Mode Line:: Interpreting the mode line.
+* GUI Components:: Menubar, toolbars, gutters.
* XEmacs under X:: Some information on using XEmacs under the X
Window System.
+* XEmacs under MS Windows:: Some information on using XEmacs under
+ Microsoft Windows.
@end menu
@node Point, Echo Area, Frame, Frame
typing @kbd{C-g}. @xref{Minibuffer}.
@end itemize
-@node Mode Line, XEmacs under X, Echo Area, Frame
+@node Mode Line, GUI Components, Echo Area, Frame
@comment node-name, next, previous, up
@section The Mode Line
@cindex mode line
default is @code{t}. For X frames, simply set the foreground and
background colors appropriately.
-@node XEmacs under X, , Mode Line, Frame
+@node GUI Components, XEmacs under X, Mode Line, Frame
+@comment node-name, next, previous, up
+@section GUI Components
+
+When executed in a graphical windowing environment such as the X Window
+System or Microsoft Windows, XEmacs displays several graphical user
+interface components such as scrollbars, menubars, toolbars, and
+gutters. By default there is a vertical scrollbar at the right of each
+frame, and at the top of the frame there is a menubar, a toolbar, and a
+gutter, in that order. Gutters can contain any of several widgets, but
+the default configuration puts a set of "notebook tabs" which you can
+use as a shortcut for selecting any of several related buffers in a
+given frame. Operating the GUI components is "obvious": click on the
+menubar to pull down a menu, on a button in the toolbar to invoke a
+function, and on a tab in the gutter to switch buffers.
+
+@menu
+* Menubar Basics:: How XEmacs uses the menubar.
+* Scrollbar Basics:: How XEmacs uses scrollbars.
+* Toolbar Basics:: How XEmacs uses toolbars.
+* Gutter Basics:: How XEmacs uses gutters.
+* Inhibiting:: What if you don't like GUI?
+* Customizing:: Position, orientation, and appearance of GUI objects.
+@end menu
+
+@node Menubar Basics, Scrollbar Basics, , GUI Components
+@comment node-name, next, previous, up
+@section The XEmacs Menubar
+
+The XEmacs menubar is intended to be conformant to the usual conventions
+for menubars, although conformance is not yet perfect. The menu at the
+extreme right is the @samp{Help} menu, which should always be
+available. It provides access to all the XEmacs help facilities
+available through @kbd{C-h}, as well as samples of various configuration
+files like @samp{~/.Xdefaults} and @samp{~/.emacs}. At the extreme left
+is the @samp{Files} menu, which provides the usual file reading,
+writing, and printing operations, as well as operations like revert
+buffer from most recent save. The next menu from the left is the
+@samp{Edit} menu, which provides the @samp{Undo} operation as well as
+cutting and pasting, searching, and keyboard macro definition and
+execution.
+
+@c #### w3.el and VM should get cross-references here.
+XEmacs provides a very dynamic environment, and the Lisp language makes
+for highly flexible applications. The menubar reflects this: many menus
+(eg, the @samp{Buffers} menu, @pxref{Buffers Menu}) contain items
+determined by the current state of XEmacs, and most major modes and many
+minor modes add items to menus and even whole menus to the menubar. In
+fact, some applications like w3.el and VM provide so many menus that
+they define a whole new menubar and add a button that allows convenient
+switching between the ``XEmacs menubar'' and the ``application
+menubar''. Such applications normally bind themselves to a particular
+frame, and this switching only takes place on frames where such an
+application is active (ie, the current window of the frame is displaying
+a buffer in the appropriate major mode).
+
+Other menus which are typically available are the @samp{Options},
+@samp{Tools}, @samp{Buffers}, @samp{Apps}, and @samp{Mule} menus. For
+detailed descriptions of these menus, @ref{Pull-down Menus}. (In 21.2
+XEmacsen, the @samp{Mule} menu will be moved under @samp{Options}.)
+
+@node Scrollbar Basics, Toolbar Basics, Menubar Basics, GUI Components
+@comment node-name, next, previous, up
+@section XEmacs Scrollbars
+
+XEmacs scrollbars provide the usual interface. Arrow buttons at either
+end allow for line by line scrolling, including autorepeat. Clicking in
+the scrollbar itself provides scrolling by windowsfull, depending on
+which side of the slider is clicked. The slider itself may be dragged
+for smooth scrolling.
+
+The position of the slider corresponds to the position of the window in
+the buffer. In particular, the length of the slider is proportional to
+the fraction of the buffer which appears in the window.
+
+The presence of the scrollbars is under control of the application or
+may be customized by the user. By default a vertical scrollbar is
+present in all windows (except the minibuffer), and there is no
+horizontal scrollbar.
+
+@node Toolbar Basics, Gutter Basics, Scrollbar Basics, GUI Components
+@comment node-name, next, previous, up
+@section XEmacs Toolbars
+
+XEmacs has a default toolbar which provides shortcuts for some of the
+commonly used operations (such as opening files) and applications (such
+as the Info manual reader). Operations which require arguments will pop
+up dialogs to get them.
+
+The position of the default toolbar can be customized. Also, several
+toolbars may be present simultaneously (in different positions). VM,
+for example, provides an application toolbar which shortcuts for
+mail-specific operations like sending, saving, and deleting messages.
+
+@node Gutter Basics, Inhibiting, Toolbar Basics, GUI Components
+@comment node-name, next, previous, up
+@section XEmacs Gutters
+
+Gutters are the most flexible of the GUI components described in this
+section. In theory, the other GUI components could be implemented by
+customizing a gutter, but in practice the other components were
+introduced earlier and have their own special implementations. Gutters
+tend to be more transient than the other components. Buffer tabs, for
+example, change every time the selected buffer in the frame changes.
+And for progress gauges a gutter to contain the gauge is typically
+created on the fly when needed, then destroyed when the operation whose
+staus is being displayed is completed.
+
+Buffer tabs, having somewhat complex behavior, deserve a closer look.
+By default, a row of buffer tabs is displayed at the top of every frame.
+(The tabs could be placed in the bottom gutter, but would be oriented
+the same way and look rather odd. The horizontal orientation makes
+putting them in a side gutter utterly impractical.) The buffer
+displayed in the current window of a frame can be changed to a specific
+buffer by clicking [mouse-1] on the corresponding tab in the gutter.
+
+Each tab contains the name of its buffer. The tab for the current
+buffer in each frame is displayed in raised relief. The list of buffers
+chosen for display in the buffer tab row is derived by filtering the
+buffer list (like the @code{Buffers} menu). The list starts out with
+all existing buffers, with more recently selected buffers coming earlier
+in the list.
+
+Then "uninteresting" buffers, like internal XEmacs buffers, the
+@code{*Message Log*} buffer, and so on are deleted from the list. Next,
+the frame's selected buffer is determined. Buffers with a different
+major mode from the selected buffer are removed from the list. Finally,
+if the list is too long, the least recently used buffers are deleted
+from the list. By default up to 6 most recently used buffers with the
+same mode are displayed on tabs in the gutter.
+
+@node Inhibiting, Customizing, Gutter Basics, GUI Components
+@comment node-name, next, previous, up
+@section Inhibiting Display of GUI Components
+
+Use of GUI facilities is a personal thing. Almost everyone agrees that
+drawing via keyboard-based "turtle graphics" is acceptable to hardly
+anyone if a mouse is available, but conversely emulating a keyboard with
+a screenful of buttons is a painful experience. But between those
+extremes the complete novice will require a fair amount of time before
+toolbars and menus become dispensable, but many an "Ancien Haquer" sees
+them as a complete waste of precious frame space that could be filled
+with text.
+
+Display of all of the GUI components created by XEmacs can be inhibited
+through the use of Customize. Customize can be accessed through
+@samp{Options | Customize} in the menu bar, or via @kbd{M-x customize}.
+Then navigate through the Customize tree to @samp{Emacs | Environment}.
+Scrollbar and toolbar visibility is controlled via the @samp{Display}
+group, options @samp{Scrollbars visible} and @samp{Toolbar visible}
+respectively. Gutter visibility is controlled by group @samp{Gutter},
+option @samp{Visible}.
+
+Or they can be controlled directly by @kbd{M-x customize-variable}, by
+changing the values of the variables @code{menubar-visible-p},
+@code{scrollbars-visible-p}, @code{toolbar-visible-p}, or
+@code{gutter-buffers-tab-visible-p} respectively. (The strange form of
+the last variable is due to the fact that gutters are often used to
+display transient widgets like progress gauges, which you probably don't
+want to inhibit. It is more likely that you want to inhibit the default
+display of the buffers tab widget, which is what that variable controls.
+This interface is subject to change depending on developer experience
+and user feedback.)
+
+Control of frame configuration can controlled automatically according to
+various parameters such as buffer or frame because these are
+@dfn{specifiers} @ref{Specifiers, , , lispref}. Using these features
+requires programming in Lisp; Customize is not yet that sophisticated.
+Also, components that appear in various positions and orientations can
+have display suppressed according to position. @kbd{C-h a visible-p}
+gives a list of variables which can be customized. E.g., to control the
+visibility of specifically the left-side toolbar only, customize
+@code{left-toolbar-visible-p}.
+
+@node Customizing, , Inhibiting, GUI Components
+@comment node-name, next, previous, up
+@section Changing the Position, Orientation, and Appearance of GUI Components
+
+ #### Not documented yet.
+
+@node XEmacs under X, XEmacs under MS Windows, GUI Components, Frame
@section Using XEmacs Under the X Window System
@comment node-name, next, previous, up
title; the name is used for resource lookup, among other things, and the
title is simply what appears above the window.)
@end itemize
+
+@node XEmacs under MS Windows, , XEmacs under X, Frame
+@section Using XEmacs Under Microsoft Windows
+@comment node-name, next, previous, up
+
+Use of XEmacs under MS Windows is not separately documented here, but
+most operations available under the X Window System are also available
+with MS Windows.
+
+Where possible, native MS Windows GUI components and capabilities are
+used in XEmacs.
+
CVS frontend.
@item prog-modes
-Miscellaneous single-file lisp files for various programming languages.
+Miscellaneous Lisp libraries for various programming languages.
@item scheme
Front-end support for Inferior Scheme.
Support for editing shell scripts.
@item vc
-Version Control for Free systems.
+Version control for free systems.
@item vc-cc
-Version Control for ClearCase. This package must be installed prior
-to building XEmacs [broken as of XEmacs 20.5-beta19].
+Version control for ClearCase.
@item vhdl
Support for VHDL.
+2000-12-05 Martin Buchholz <martin@xemacs.org>
+
+ * XEmacs 21.2.38 is released.
+
2000-11-14 Martin Buchholz <martin@xemacs.org>
* XEmacs 21.2.37 is released.
buffer's current directory. We can't just have the child check
for an error when it does the chdir, since it's in a vfork. */
- NGCPRO2 (current_dir, path); /* Caller gcprotects args[] */
current_dir = current_buffer->directory;
+ NGCPRO2 (current_dir, path); /* Caller gcprotects args[] */
current_dir = Funhandled_file_name_directory (current_dir);
current_dir = expand_and_dir_to_file (current_dir, Qnil);
#if 0
ldm_current->printer_name = xstrdup (ldm_new->printer_name);
}
+ UNGCPRO;
return DEVICE_MSPRINTER_DEVMODE (d);
}
\f
/* PATTERN might be a flawed regular expression. Rather than
catching and signalling our own errors, we just call
compile_pattern to do the work for us. */
- bufp = compile_pattern (pattern, 0, 0, 0, ERROR_ME);
+ bufp = compile_pattern (pattern, 0, Qnil, 0, ERROR_ME);
}
/* Now *bufp is the compiled form of PATTERN; don't call anything
which might compile a new regexp until we're done with the loop! */
/* MATCH might be a flawed regular expression. Rather than
catching and signalling our own errors, we just call
compile_pattern to do the work for us. */
- bufp = compile_pattern (match, 0, 0, 0, ERROR_ME);
+ bufp = compile_pattern (match, 0, Qnil, 0, ERROR_ME);
}
/* Now *bufp is the compiled form of MATCH; don't call anything
/* !!#### This function has not been Mule-ized */
REGISTER int fd;
REGISTER char *name_nonreloc = 0;
- int minsize;
EMACS_INT position;
Lisp_Object file, tem;
Lisp_Object name_reloc = Qnil;
tem = Ffile_name_absolute_p (file);
if (NILP (tem))
{
+ size_t minsize;
/* XEmacs: Move this check here. OK if called during loadup to
load byte code instructions. */
if (!STRINGP (Vdoc_directory))
#include "frame.h"
#include "insdel.h"
#include "window.h"
+#include "casetab.h"
#include "chartab.h"
#include "line-number.h"
REGISTER Charcount len1, len2, length, i;
struct buffer *bp1, *bp2;
Lisp_Object trt = ((!NILP (current_buffer->case_fold_search)) ?
- current_buffer->case_canon_table : Qnil);
+ XCASE_TABLE_CANON (current_buffer->case_table) : Qnil);
/* Find the first buffer and its substring. */
Lisp_Object values = Qnil;
struct gcpro gcpro1, gcpro2;
- GCPRO2 (current, values);
-
/* Do all the parameter checking */
CHECK_LIVE_LDAP (ldap);
ld = XLDAP (ldap)->ld;
ldap_mods = alloca_array (LDAPMod, len);
ldap_mods_ptrs = alloca_array (LDAPMod *, 1 + len);
i = 0;
+
+ GCPRO2 (current, values);
EXTERNAL_LIST_LOOP (mods, mods)
{
current = XCAR (mods);
Lisp_Object l_dndlist = Qnil, l_item = Qnil;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
- GCPRO4 (l_type, l_data, l_dndlist, l_item);
-
if (! frame)
return 0; /* not for us */
+
+ GCPRO4 (l_type, l_data, l_dndlist, l_item);
XSETFRAME (emacs_event->channel, frame);
emacs_event->event_type = misc_user_event;
case CBN_SELCHANGE:
if (!NILP (mswindows_handle_gui_wm_command (frame, cid, id)))
return 0;
- case BN_SETFOCUS:
-
}
/* menubars always must come last since the hashtables do not
always exist*/
{
Vrecent_keys_ring = make_vector (recent_keys_ring_size, Qnil);
/* And return nothing in particular. */
- return make_vector (0, Qnil);
+ RETURN_UNGCPRO (make_vector (0, Qnil));
}
if (NILP (XVECTOR_DATA (Vrecent_keys_ring)[recent_keys_ring_index]))
Lisp_Object new_vector = Qnil;
int i, j, nkeys, start, min;
struct gcpro gcpro1;
- GCPRO1 (new_vector);
CHECK_INT (size);
if (XINT (size) <= 0)
if (XINT (size) == recent_keys_ring_size)
return size;
+ GCPRO1 (new_vector);
new_vector = make_vector (XINT (size), Qnil);
if (NILP (Vrecent_keys_ring))
{
Vrecent_keys_ring = new_vector;
- return size;
+ RETURN_UNGCPRO (size);
}
if (NILP (XVECTOR_DATA (Vrecent_keys_ring)[recent_keys_ring_index]))
*/
(name, default_directory))
{
- /* This function can GC. GC-checked 2000-07-11 ben */
+ /* This function can GC. GC-checked 2000-11-18 */
Bufbyte *nm;
Bufbyte *newdir, *p, *o;
struct passwd *pw;
#endif /* WIN32_NATIVE */
int length;
- Lisp_Object handler;
+ Lisp_Object handler = Qnil;
#ifdef CYGWIN
char *user;
#endif
- struct gcpro gcpro1, gcpro2;
+ struct gcpro gcpro1, gcpro2, gcpro3;
/* both of these get set below */
- GCPRO2 (name, default_directory);
+ GCPRO3 (name, default_directory, handler);
CHECK_STRING (name);
call the corresponding file handler. */
handler = Ffind_file_name_handler (name, Qexpand_file_name);
if (!NILP (handler))
- {
- UNGCPRO;
- return call3_check_string (handler, Qexpand_file_name, name,
- default_directory);
- }
+ RETURN_UNGCPRO (call3_check_string (handler, Qexpand_file_name,
+ name, default_directory));
/* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */
if (NILP (default_directory))
{
handler = Ffind_file_name_handler (default_directory, Qexpand_file_name);
if (!NILP (handler))
- {
- UNGCPRO;
- return call3 (handler, Qexpand_file_name, name, default_directory);
- }
+ RETURN_UNGCPRO (call3 (handler, Qexpand_file_name,
+ name, default_directory));
}
o = XSTRING_DATA (default_directory);
we just use our own version in realpath.c. */
for (;;)
{
- p = (Extbyte *) memchr (p + 1, '/', elen - (p + 1 - path));
- if (p)
- *p = 0;
+ Extbyte *pos;
+
+#ifdef WIN32_NATIVE
+ if (IS_DRIVE (p[0]) && IS_DEVICE_SEP (p[1])
+ && IS_DIRECTORY_SEP (p[2]))
+ /* don't test c: on windows */
+ p = p+2;
+ else if (IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1]))
+ /* start after // */
+ p = p+1;
+#endif
+ for (pos = p + 1; pos < path + elen; pos++)
+ if (IS_DIRECTORY_SEP (*pos))
+ {
+ *(p = pos) = 0;
+ break;
+ }
+ if (p != pos)
+ p = 0;
if (xrealpath ((char *) path, resolved_path))
{
if (p)
- *p = '/';
+ *p = DIRECTORY_SEP;
else
break;
{
int plen = elen - (p - path);
- if (rlen > 1 && resolved_path[rlen - 1] == '/')
+ if (rlen > 1 && IS_DIRECTORY_SEP (resolved_path[rlen - 1]))
rlen = rlen - 1;
if (plen + rlen + 1 > countof (resolved_path))
goto toolong;
- resolved_path[rlen] = '/';
+ resolved_path[rlen] = DIRECTORY_SEP;
memcpy (resolved_path + rlen + 1, p + 1, plen + 1 - 1);
}
break;
{
Lisp_Object resolved_name;
int rlen = strlen (resolved_path);
- if (elen > 0 && XSTRING_BYTE (expanded_name, elen - 1) == '/'
- && !(rlen > 0 && resolved_path[rlen - 1] == '/'))
+ if (elen > 0 && IS_DIRECTORY_SEP (XSTRING_BYTE (expanded_name, elen - 1))
+ && !(rlen > 0 && IS_DIRECTORY_SEP (resolved_path[rlen - 1])))
{
if (rlen + 1 > countof (resolved_path))
goto toolong;
- resolved_path[rlen++] = '/';
+ resolved_path[rlen++] = DIRECTORY_SEP;
resolved_path[rlen] = '\0';
}
TO_INTERNAL_FORMAT (DATA, (resolved_path, rlen),
message ("Wrote %s", XSTRING_DATA (visit_file));
else
{
- Lisp_Object fsp;
+ Lisp_Object fsp = Qnil;
struct gcpro nngcpro1;
NNGCPRO1 (fsp);
}
else
{
- Lisp_Object filename;
+ Lisp_Object filename = Qnil;
struct stat st;
Lisp_Object handler;
struct gcpro gcpro1, gcpro2, gcpro3;
return;
XSETBUFFER (old_current_buffer, current_buffer);
+ subject_buf = Qnil;
GCPRO3 (fn, subject_buf, old_current_buffer);
orig_fn = fn;
fn = Fexpand_file_name (fn, Qnil);
if (value == gcprolist->next->next) goto OK;
if (! gcprolist->next->next) abort ();
if (value == gcprolist->next->next->next) goto OK;
+ if (! gcprolist->next->next->next) abort ();
+ if (value == gcprolist->next->next->next->next) goto OK;
abort ();
OK:;
}
gcprohist[j].type == gcpro2_type ? "GCPRO2" :
gcprohist[j].type == gcpro3_type ? "GCPRO3" :
gcprohist[j].type == gcpro4_type ? "GCPRO4" :
+ gcprohist[j].type == gcpro5_type ? "GCPRO5" :
gcprohist[j].type == ungcpro_type ? "UNGCPRO" : "???"),
gcprohist[j].value);
}
IIFORMAT_HAS_METHOD (autodetect, validate);
IIFORMAT_HAS_METHOD (autodetect, normalize);
IIFORMAT_HAS_METHOD (autodetect, possible_dest_types);
+ /* #### autodetect is flawed IMO:
+ 1. It makes the assumption that you can detect whether the user
+ wanted a cursor or a string based on the data, since the data is a
+ string you have to prioritise cursors. Instead we will force users
+ to pick the appropriate image type, this is what we do under
+ MS-Windows anyway.
+ 2. It doesn't fit with the new domain model - you cannot tell which
+ domain it needs to be instantiated in until you've actually
+ instantiated it, which mucks up caching.
+ 3. It only copes with cursors and strings which seems bogus. */
+ IIFORMAT_HAS_SHARED_METHOD (autodetect, governing_domain, subwindow);
IIFORMAT_HAS_METHOD (autodetect, instantiate);
IIFORMAT_VALID_CONSOLE (x, autodetect);
Gpm_Event ev;
int modifiers = 0;
int button = 1;
- Lisp_Object fake_event;
+ Lisp_Object fake_event = Qnil;
Lisp_Event *event = NULL;
struct gcpro gcpro1;
static int num_events;
struct device *d = decode_device (Qnil);
int fd = DEVICE_INFD (d);
char c = 3;
- Lisp_Object output_stream;
- Lisp_Object terminal_stream;
- Lisp_Object output_string;
+ Lisp_Object output_stream = Qnil;
+ Lisp_Object terminal_stream = Qnil ;
+ Lisp_Object output_string = Qnil;
struct gcpro gcpro1,gcpro2,gcpro3;
GCPRO3(output_stream,terminal_stream,output_string);
#include "lisp.h"
#include "buffer.h"
#include "bytecode.h"
+#include "casetab.h"
#include "chartab.h"
#include "console.h"
#include "device.h"
int
event_matches_key_specifier_p (Lisp_Event *event, Lisp_Object key_specifier)
{
- Lisp_Object event2;
+ Lisp_Object event2 = Qnil;
int retval;
struct gcpro gcpro1;
if (menubar_widget
&& CONSP (Vmenu_accelerator_modifiers))
{
- Lisp_Object fake;
+ Lisp_Object fake = Qnil;
Lisp_Object last = Qnil;
struct gcpro gcpro1;
Lisp_Object matchp;
}
#endif /* LISP_FLOAT_TYPE */
-/* Print NUMBER to BUFFER. This is equivalent to sprintf(buffer,
- "%ld", number), only much faster.
+/* Print NUMBER to BUFFER.
+ This is equivalent to sprintf (buffer, "%ld", number), only much faster.
BUFFER should accept 24 bytes. This should suffice for the longest
numbers on 64-bit machines, including the `-' sign and the trailing
- \0. */
-void
+ '\0'. Returns a pointer to the trailing '\0'. */
+char *
long_to_string (char *buffer, long number)
{
#if (SIZEOF_LONG != 4) && (SIZEOF_LONG != 8)
/* Huh? */
sprintf (buffer, "%ld", number);
+ return buffer + strlen (buffer);
#else /* (SIZEOF_LONG == 4) || (SIZEOF_LONG == 8) */
char *p = buffer;
int force = 0;
#undef FROB
*p++ = number + '0';
*p = '\0';
+ return p;
#endif /* (SIZEOF_LONG == 4) || (SIZEOF_LONG == 8) */
}
\f
write_char_internal ("#", printcharfun);
print_internal (XCDR (tem), printcharfun, escapeflag);
write_char_internal ("#", printcharfun);
+ UNGCPRO;
return;
}
else
/* Synched up with: Not in FSF. */
#include <config.h>
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <string.h>
+#include "lisp.h"
#include <errno.h>
-#include <limits.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#if defined (HAVE_SYS_PARAM_H)
+#if defined (HAVE_SYS_PARAM_H) && !defined (WIN32_NATIVE)
#include <sys/param.h>
#endif
#include <sys/stat.h> /* for S_IFLNK */
+/* First char after start of absolute filename. */
+#define ABS_START(name) (name + ABS_LENGTH (name))
+
+#if defined (WIN32_NATIVE)
+/* Length of start of absolute filename. */
+# define ABS_LENGTH(name) (win32_abs_start (name))
+static int win32_abs_start (const char * name);
+/* System dependent version of readlink. */
+# define system_readlink win32_readlink
+#else
+# ifdef CYGWIN
+# define ABS_LENGTH(name) (IS_DIRECTORY_SEP (*name) ? \
+ (IS_DIRECTORY_SEP (name[1]) ? 2 : 1) : 0)
+# define system_readlink cygwin_readlink
+# else
+# define ABS_LENGTH(name) (IS_DIRECTORY_SEP (*name) ? 1 : 0)
+# define system_readlink readlink
+# endif /* CYGWIN */
+#endif /* WIN32_NATIVE */
+
+#if defined (WIN32_NATIVE) || defined (CYGWIN)
+#include "syswindows.h"
+/* Emulate readlink on win32 - finds real name (i.e. correct case) of
+ a file. UNC servers and shares are lower-cased. Directories must be
+ given without trailing '/'. One day, this could read Win2K's
+ reparse points. */
+static int
+win32_readlink (const char * name, char * buf, int size)
+{
+ WIN32_FIND_DATA find_data;
+ HANDLE dir_handle = NULL;
+ int len = 0;
+ int err = 0;
+ const char* lastname;
+ int count = 0;
+ const char* tmp;
+ char* res = NULL;
+
+ assert (*name);
+
+ /* Sort of check we have a valid filename. */
+ if (strpbrk (name, "*?|<>\"") || strlen (name) >= MAX_PATH)
+ {
+ errno = EIO;
+ return -1;
+ }
+
+ /* Find start of filename */
+ lastname = name + strlen (name);
+ while (lastname > name && !IS_DIRECTORY_SEP (lastname[-1]))
+ --lastname;
+
+ /* Count slashes in unc path */
+ if (ABS_LENGTH (name) == 2)
+ for (tmp = name; *tmp; tmp++)
+ if (IS_DIRECTORY_SEP (*tmp))
+ count++;
+
+ if (count >= 2 && count < 4)
+ {
+ /* UNC server or share name: just copy lowercased name. */
+ res = find_data.cFileName;
+ for (tmp = lastname; *tmp; tmp++)
+ *res++ = tolower (*tmp);
+ *res = '\0';
+ }
+ else
+ dir_handle = FindFirstFile (name, &find_data);
+
+ if (res || dir_handle != INVALID_HANDLE_VALUE)
+ {
+ if ((len = strlen (find_data.cFileName)) < size)
+ {
+ if (strcmp (lastname, find_data.cFileName) == 0)
+ /* Signal that the name is already OK. */
+ err = EINVAL;
+ else
+ memcpy (buf, find_data.cFileName, len + 1);
+ }
+ else
+ err = ENAMETOOLONG;
+ if (!res) FindClose (dir_handle);
+ }
+ else
+ err = ENOENT;
+
+ errno = err;
+ return err ? -1 : len;
+}
+#endif /* WIN32_NATIVE || CYGWIN */
+
+#ifdef CYGWIN
+/* Call readlink and try to find out the correct case for the file. */
+static int
+cygwin_readlink (const char * name, char * buf, int size)
+{
+ int n = readlink (name, buf, size);
+ if (n < 0)
+ {
+ /* The file may exist, but isn't a symlink. Try to find the
+ right name. */
+ char* tmp = alloca (cygwin_posix_to_win32_path_list_buf_size (name));
+ cygwin_posix_to_win32_path_list (name, tmp);
+ n = win32_readlink (tmp, buf, size);
+ }
+ return n;
+}
+#endif /* CYGWIN */
+
+#ifdef WIN32_NATIVE
+#ifndef ELOOP
+#define ELOOP 10062 /* = WSAELOOP in winsock.h */
+#endif
+/* Length of start of absolute filename. */
+static int
+win32_abs_start (const char * name)
+{
+ if (isalpha (*name) && IS_DEVICE_SEP (name[1])
+ && IS_DIRECTORY_SEP (name[2]))
+ return 3;
+ else if (IS_DIRECTORY_SEP (*name))
+ return IS_DIRECTORY_SEP (name[1]) ? 2 : 1;
+ else
+ return 0;
+}
+#endif /* WIN32_NATIVE */
+
#if !defined (HAVE_GETCWD) && defined (HAVE_GETWD)
#undef getcwd
#define getcwd(buffer, len) getwd (buffer)
char copy_path[PATH_MAX];
char *new_path = resolved_path;
char *max_path;
-#ifdef S_IFLNK
+#if defined (S_IFLNK) || defined (WIN32_NATIVE)
int readlinks = 0;
char link_path[PATH_MAX];
int n;
+ int abslen = ABS_LENGTH (path);
#endif
/* Make a copy of the source path since we may need to modify it. */
strcpy (copy_path, path);
path = copy_path;
max_path = copy_path + PATH_MAX - 2;
+
#ifdef WIN32_NATIVE
- /*
- ** In NT we have two different cases: (1) the path name begins
- ** with a drive letter, e.g., "C:"; and (2) the path name begins
- ** with just a slash, which roots to the current drive. In the
- ** first case we are going to leave things alone, in the second
- ** case we will prepend the drive letter to the given path.
- ** Note: So far in testing, I'm only seeing case #1, even though
- ** I've tried to get the other cases to happen.
- ** August Hill, 31 Aug 1997.
- **
- ** Check for a driver letter...C:/...
- */
- if (*(path + 1) == ':')
+ /* Check for c:/... or //server/... */
+ if (abslen == 2 || abslen == 3)
{
- strncpy(new_path, path, 3);
- new_path += 3;
- path += 3;
+ strncpy (new_path, path, abslen);
+ new_path += abslen;
+ path += abslen;
}
-
- /*
- ** No drive letter, but a beginning slash? Prepend the drive
- ** letter...
- */
- else if (*path == '/')
+ /* No drive letter, but a beginning slash? Prepend drive letter. */
+ else if (abslen == 1)
{
getcwd (new_path, PATH_MAX - 1);
new_path += 3;
path++;
}
-
- /*
- ** Just a path name, prepend the current directory
- */
+ /* Just a path name, prepend the current directory */
else
{
getcwd (new_path, PATH_MAX - 1);
- new_path += strlen(new_path);
- if (new_path[-1] != '/')
- *new_path++ = '/';
+ new_path += strlen (new_path);
+ if (!IS_DIRECTORY_SEP (new_path[-1]))
+ *new_path++ = DIRECTORY_SEP;
}
-
#else
/* If it's a relative pathname use getcwd for starters. */
- if (*path != '/')
+ if (abslen == 0)
{
getcwd (new_path, PATH_MAX - 1);
- new_path += strlen(new_path);
- if (new_path[-1] != '/')
- *new_path++ = '/';
+ new_path += strlen (new_path);
+ if (!IS_DIRECTORY_SEP (new_path[-1]))
+ *new_path++ = DIRECTORY_SEP;
}
else
{
- *new_path++ = '/';
- path++;
+ /* Copy first directory sep. May have two on cygwin. */
+ strncpy (new_path, path, abslen);
+ new_path += abslen;
+ path += abslen;
}
#endif
/* Expand each slash-separated pathname component. */
while (*path != '\0')
{
/* Ignore stray "/". */
- if (*path == '/')
+ if (IS_DIRECTORY_SEP (*path))
{
path++;
continue;
if (*path == '.')
{
/* Ignore ".". */
- if (path[1] == '\0' || path[1] == '/')
+ if (path[1] == '\0' || IS_DIRECTORY_SEP (path[1]))
{
path++;
continue;
/* Handle ".." */
if (path[1] == '.' &&
- (path[2] == '\0' || path[2] == '/'))
+ (path[2] == '\0' || IS_DIRECTORY_SEP (path[2])))
{
path += 2;
/* Ignore ".." at root. */
- if (new_path == resolved_path + 1)
+ if (new_path == ABS_START (resolved_path))
continue;
/* Handle ".." by backing up. */
- while ((--new_path)[-1] != '/')
- ;
+ --new_path;
+ while (!IS_DIRECTORY_SEP (new_path[-1]))
+ --new_path;
continue;
}
}
/* Safely copy the next pathname component. */
- while (*path != '\0' && *path != '/')
+ while (*path != '\0' && !IS_DIRECTORY_SEP (*path))
{
if (path > max_path)
{
*new_path++ = *path++;
}
-#ifdef S_IFLNK
+#if defined (S_IFLNK) || defined (WIN32_NATIVE)
/* See if latest pathname component is a symlink. */
*new_path = '\0';
- n = readlink (resolved_path, link_path, PATH_MAX - 1);
+ n = system_readlink (resolved_path, link_path, PATH_MAX - 1);
if (n < 0)
{
/* Note: readlink doesn't add the null byte. */
link_path[n] = '\0';
-
- if (*link_path == '/')
+
+ if (ABS_LENGTH (link_path) > 0)
/* Start over for an absolute symlink. */
- new_path = resolved_path;
+ new_path = resolved_path + ABS_LENGTH (link_path) - 1;
else
/* Otherwise back up over this component. */
- while (*(--new_path) != '/')
- ;
+ for (--new_path; !IS_DIRECTORY_SEP (*new_path); --new_path)
+ assert (new_path > resolved_path);
/* Safe sex check. */
if (strlen(path) + n >= PATH_MAX)
strcpy(copy_path, link_path);
path = copy_path;
}
-#endif /* S_IFLNK */
- *new_path++ = '/';
+#endif /* S_IFLNK || WIN32_NATIVE */
+ *new_path++ = DIRECTORY_SEP;
}
/* Delete trailing slash but don't whomp a lone slash. */
- if (new_path != resolved_path + 1 && new_path[-1] == '/')
+ if (new_path != ABS_START (resolved_path) && IS_DIRECTORY_SEP (new_path[-1]))
new_path--;
/* Make sure it's null terminated. */
*new_path = '\0';
+
+#ifdef WIN32_NATIVE
+ if (ABS_LENGTH (resolved_path) == 3)
+ /* Lowercase drive letter. */
+ *resolved_path = tolower (*resolved_path);
+#endif
return resolved_path;
}
#ifndef INCLUDED_regex_h_
#define INCLUDED_regex_h_
+#ifdef emacs
+#define RE_TRANSLATE_TYPE Lisp_Object
+#else
+#define RE_TRANSLATE_TYPE char *
+#endif /* emacs */
+
/* POSIX says that <sys/types.h> must be included (by the caller) before
<regex.h>. */
comparing them, or zero for no translation. The translation
is applied to a pattern when it is compiled and to a string
when it is matched. */
- char *translate;
+ RE_TRANSLATE_TYPE translate;
/* Number of subexpressions found by the compiler. */
size_t re_nsub;
#define NO_MATHERR
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+#define HAVE_PTYS
+
/* define MAIL_USE_FLOCK if the mailer uses flock
to interlock access to /usr/spool/mail/$USER.
The alternative is that a lock file named
#define DEFVAR_BOOL_MAGIC(lname, c_location, magicfun) \
DEFVAR_SYMVAL_FWD_INT (lname, c_location, SYMVAL_BOOLEAN_FORWARD, magicfun)
+void flush_all_buffer_local_cache (void);
+
#endif /* INCLUDED_symeval_h_ */
((((unsigned long)addr) + ALLOC_UNIT) & ALLOC_MASK)
/* Note that all sections must be aligned on a 0x1000 boundary so
this is the minimum size that our dummy bss can be. */
+#ifdef BROKEN_GDB
#define BSS_PAD_SIZE 0x1000
+#else
+#define BSS_PAD_SIZE 0
+#endif
/* To prevent zero-initialized variables from being placed into the bss
section, use non-zero values to represent an uninitialized state. */
}
if ((a_new = open (new_name, O_WRONLY | O_TRUNC | O_CREAT | OPEN_BINARY,
- CREAT_MODE)) < 0)
+ 0755)) < 0)
{
PERROR (new_name);
}
lseek (a_new, 0, SEEK_SET);
/* write file header */
f_hdr.f_symptr += file_sz_change;
+#ifndef BROKEN_GDB
+ f_hdr.f_nscns--;
+#endif
printf("writing file header\n");
if (write(a_new, &f_hdr, sizeof(f_hdr)) != sizeof(f_hdr))
{
PERROR("failed to write text header");
}
-
+#ifdef BROKEN_GDB
/* Write small bss section. */
if (!sections_reversed)
{
PERROR("failed to write bss header");
}
}
-
+#endif
/* write new data header */
printf("writing .data header\n");
{
PERROR("failed to write data header");
}
-
+#ifdef BROKEN_GDB
/* Write small bss section. */
if (sections_reversed)
{
PERROR("failed to write bss header");
}
}
-
+#endif
printf("writing following data header\n");
f_nextdata.s_scnptr += file_sz_change;
if (f_nextdata.s_lnnoptr != 0) f_nextdata.s_lnnoptr += file_sz_change;
PERROR("failed to write data header");
}
}
-
+#ifndef BROKEN_GDB
+ /* dump bss to maintain offsets */
+ memset(&f_bss, 0, sizeof(f_bss));
+ if (write(a_new, &f_bss, sizeof(f_bss)) != sizeof(f_bss))
+ {
+ PERROR("failed to write bss header");
+ }
+#endif
size=lseek(a_new, 0, SEEK_CUR);
CHECK_AOUT_POS(size);
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
-#if !defined (__NetBSD__) && !defined (__OpenBSD__)
+#ifdef HAVE_ELF_H
#include <elf.h>
#endif
#include <sys/mman.h>
/* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992, 1999, 2000
Free Software Foundation, Inc.
-This file is part of XEmacs.
+ This file is part of XEmacs.
-XEmacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+ XEmacs is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-GNU Emacs 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 General Public License for more details.
+ GNU Emacs 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
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
+ You should have received a copy of the GNU General Public License
+ along with GNU Emacs; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
-In other words, you are welcome to use, share and improve this program.
-You are forbidden to forbid anyone else to use, share and improve
-what you give them. Help stamp out software-hoarding! */
+ In other words, you are welcome to use, share and improve this
+ program. You are forbidden to forbid anyone else to use, share and
+ improve what you give them. Help stamp out software-hoarding! */
-/* 2000-10-31: Martin Buchholz
-
- I noticed that xemacs on Irix 6.5 could not write to stderr, e.g.
- (external-debugging-output "\n")
- would produce NO output.
- temacs worked fine, so this was clearly a dumping problem.
-
- So I copied over the latest available unexelf.c from FSF Emacs,
- and installed it as unexelfsgi.c in XEmacs.
- In addition, I converted it to "Clean C", resulting in this file.
-*/
/*
* unexec.c - Convert a running program into an a.out file.
* Modified heavily since then.
*
* Synopsis:
- * unexec (new_name, old_name, data_start, bss_start, entry_address)
- * char *new_name, *old_name;
- * unsigned data_start, bss_start, entry_address;
- *
- * Takes a snapshot of the program and makes an a.out format file in the
- * file named by the string argument new_name.
- * If old_name is non-NULL, the symbol table will be taken from the given file.
- * On some machines, an existing old_name file is required.
- *
- * The boundaries within the a.out file may be adjusted with the data_start
- * and bss_start arguments. Either or both may be given as 0 for defaults.
+ * void
+ * unexec (char *new_name,
+ * char *old_name,
+ * uintptr_t data_start,
+ * uintptr_t bss_start,
+ * uintptr_t entry_address)
*
- * Data_start gives the boundary between the text segment and the data
- * segment of the program. The text segment can contain shared, read-only
- * program code and literal data, while the data segment is always unshared
- * and unprotected. Data_start gives the lowest unprotected address.
- * The value you specify may be rounded down to a suitable boundary
- * as required by the machine you are using.
+ * The basic idea is that we start with an ELF file which contains
+ * .bss (uninitialized global data) section which is normally not in
+ * the file. As we load lisp the variables, which were first set to 0,
+ * will change their values. We want to save those changed values into
+ * another ELF file, which will become a new xemacs image. To do this,
+ * we need to change several structures in the ELF file.
*
- * Bss_start indicates how much of the data segment is to be saved in the
- * a.out file and restored when the program is executed. It gives the lowest
- * unsaved address, and is rounded up to a page boundary. The default when 0
- * is given assumes that the entire data segment is to be stored, including
- * the previous data and bss as well as any additional storage allocated with
- * break (2).
+ * First of all, we need to change the programm header which tells
+ * the linker how to load stuff into memory so that data will come
+ * from the file and not from the /dev/zero. To do this, we find the
+ * segment, which is marked as loadable (type PT_LOAD) and which
+ * covers the old .bss section. We will next change the filesz and
+ * memsz for that segment to extend over the new data section.
*
- * The new file is set up to start at entry_address.
- *
- */
-
-/* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co.
- * ELF support added.
+ * Next we have to make sure that section header for the stuff which
+ * used to be uninitialized is changed to be initialized and to come
+ * from the file. To do this, we change the size and the type of the old
+ * .bss section (and all other section of the type SHT_NOBITS) to cover the
+ * new section and to be of type SHT_PROCBITS.
*
- * Basic theory: the data space of the running process needs to be
- * dumped to the output file. Normally we would just enlarge the size
- * of .data, scooting everything down. But we can't do that in ELF,
- * because there is often something between the .data space and the
- * .bss space.
+ * We also insert a new SHT_NOBITS section to keep some tools, which expect
+ * .bss happy.
*
- * In the temacs dump below, notice that the Global Offset Table
- * (.got) and the Dynamic link data (.dynamic) come between .data1 and
- * .bss. It does not work to overlap .data with these fields.
- *
- * The solution is to create a new .data segment. This segment is
- * filled with data from the current process. Since the contents of
- * various sections refer to sections by index, the new .data segment
- * is made the last in the table to avoid changing any existing index.
-
- * This is an example of how the section headers are changed. "Addr"
- * is a process virtual address. "Offset" is a file offset.
-
-raid:/nfs/raid/src/dist-18.56/src> dump -h temacs
-
-temacs:
-
- **** SECTION HEADER TABLE ****
-[No] Type Flags Addr Offset Size Name
- Link Info Adralgn Entsize
-
-[1] 1 2 0x80480d4 0xd4 0x13 .interp
- 0 0 0x1 0
-
-[2] 5 2 0x80480e8 0xe8 0x388 .hash
- 3 0 0x4 0x4
-
-[3] 11 2 0x8048470 0x470 0x7f0 .dynsym
- 4 1 0x4 0x10
-
-[4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
- 0 0 0x1 0
-
-[5] 9 2 0x8049010 0x1010 0x338 .rel.plt
- 3 7 0x4 0x8
-
-[6] 1 6 0x8049348 0x1348 0x3 .init
- 0 0 0x4 0
-
-[7] 1 6 0x804934c 0x134c 0x680 .plt
- 0 0 0x4 0x4
-
-[8] 1 6 0x80499cc 0x19cc 0x3c56f .text
- 0 0 0x4 0
-
-[9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
- 0 0 0x4 0
-
-[10] 1 2 0x8085f40 0x3df40 0x69c .rodata
- 0 0 0x4 0
-
-[11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
- 0 0 0x4 0
-
-[12] 1 3 0x8088330 0x3f330 0x20afc .data
- 0 0 0x4 0
-
-[13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
- 0 0 0x4 0
-
-[14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
- 0 0 0x4 0x4
-
-[15] 6 3 0x80a9874 0x60874 0x80 .dynamic
- 4 0 0x4 0x8
-
-[16] 8 3 0x80a98f4 0x608f4 0x449c .bss
- 0 0 0x4 0
-
-[17] 2 0 0 0x608f4 0x9b90 .symtab
- 18 371 0x4 0x10
-
-[18] 3 0 0 0x6a484 0x8526 .strtab
- 0 0 0x1 0
-
-[19] 3 0 0 0x729aa 0x93 .shstrtab
- 0 0 0x1 0
-
-[20] 1 0 0 0x72a3d 0x68b7 .comment
- 0 0 0x1 0
-
-raid:/nfs/raid/src/dist-18.56/src> dump -h xemacs
-
-xemacs:
-
- **** SECTION HEADER TABLE ****
-[No] Type Flags Addr Offset Size Name
- Link Info Adralgn Entsize
-
-[1] 1 2 0x80480d4 0xd4 0x13 .interp
- 0 0 0x1 0
-
-[2] 5 2 0x80480e8 0xe8 0x388 .hash
- 3 0 0x4 0x4
-
-[3] 11 2 0x8048470 0x470 0x7f0 .dynsym
- 4 1 0x4 0x10
-
-[4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
- 0 0 0x1 0
-
-[5] 9 2 0x8049010 0x1010 0x338 .rel.plt
- 3 7 0x4 0x8
-
-[6] 1 6 0x8049348 0x1348 0x3 .init
- 0 0 0x4 0
-
-[7] 1 6 0x804934c 0x134c 0x680 .plt
- 0 0 0x4 0x4
-
-[8] 1 6 0x80499cc 0x19cc 0x3c56f .text
- 0 0 0x4 0
-
-[9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
- 0 0 0x4 0
-
-[10] 1 2 0x8085f40 0x3df40 0x69c .rodata
- 0 0 0x4 0
-
-[11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
- 0 0 0x4 0
-
-[12] 1 3 0x8088330 0x3f330 0x20afc .data
- 0 0 0x4 0
-
-[13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
- 0 0 0x4 0
-
-[14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
- 0 0 0x4 0x4
-
-[15] 6 3 0x80a9874 0x60874 0x80 .dynamic
- 4 0 0x4 0x8
-
-[16] 8 3 0x80c6800 0x7d800 0 .bss
- 0 0 0x4 0
-
-[17] 2 0 0 0x7d800 0x9b90 .symtab
- 18 371 0x4 0x10
-
-[18] 3 0 0 0x87390 0x8526 .strtab
- 0 0 0x1 0
-
-[19] 3 0 0 0x8f8b6 0x93 .shstrtab
- 0 0 0x1 0
-
-[20] 1 0 0 0x8f949 0x68b7 .comment
- 0 0 0x1 0
-
-[21] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
- 0 0 0x4 0
-
- * This is an example of how the file header is changed. "Shoff" is
- * the section header offset within the file. Since that table is
- * after the new .data section, it is moved. "Shnum" is the number of
- * sections, which we increment.
- *
- * "Phoff" is the file offset to the program header. "Phentsize" and
- * "Shentsz" are the program and section header entries sizes respectively.
- * These can be larger than the apparent struct sizes.
-
-raid:/nfs/raid/src/dist-18.56/src> dump -f temacs
-
-temacs:
-
- **** ELF HEADER ****
-Class Data Type Machine Version
-Entry Phoff Shoff Flags Ehsize
-Phentsize Phnum Shentsz Shnum Shstrndx
-
-1 1 2 3 1
-0x80499cc 0x34 0x792f4 0 0x34
-0x20 5 0x28 21 19
-
-raid:/nfs/raid/src/dist-18.56/src> dump -f xemacs
-
-xemacs:
-
- **** ELF HEADER ****
-Class Data Type Machine Version
-Entry Phoff Shoff Flags Ehsize
-Phentsize Phnum Shentsz Shnum Shstrndx
-
-1 1 2 3 1
-0x80499cc 0x34 0x96200 0 0x34
-0x20 5 0x28 22 19
-
- * These are the program headers. "Offset" is the file offset to the
- * segment. "Vaddr" is the memory load address. "Filesz" is the
- * segment size as it appears in the file, and "Memsz" is the size in
- * memory. Below, the third segment is the code and the fourth is the
- * data: the difference between Filesz and Memsz is .bss
-
-raid:/nfs/raid/src/dist-18.56/src> dump -o temacs
-
-temacs:
- ***** PROGRAM EXECUTION HEADER *****
-Type Offset Vaddr Paddr
-Filesz Memsz Flags Align
-
-6 0x34 0x8048034 0
-0xa0 0xa0 5 0
-
-3 0xd4 0 0
-0x13 0 4 0
-
-1 0x34 0x8048034 0
-0x3f2f9 0x3f2f9 5 0x1000
-
-1 0x3f330 0x8088330 0
-0x215c4 0x25a60 7 0x1000
-
-2 0x60874 0x80a9874 0
-0x80 0 7 0
-
-raid:/nfs/raid/src/dist-18.56/src> dump -o xemacs
-
-xemacs:
- ***** PROGRAM EXECUTION HEADER *****
-Type Offset Vaddr Paddr
-Filesz Memsz Flags Align
-
-6 0x34 0x8048034 0
-0xa0 0xa0 5 0
-
-3 0xd4 0 0
-0x13 0 4 0
-
-1 0x34 0x8048034 0
-0x3f2f9 0x3f2f9 5 0x1000
-
-1 0x3f330 0x8088330 0
-0x3e4d0 0x3e4d0 7 0x1000
-
-2 0x60874 0x80a9874 0
-0x80 0 7 0
-
-
- */
-\f
-/* Modified by wtien@urbana.mcd.mot.com of Motorola Inc.
- *
- * The above mechanism does not work if the unexeced ELF file is being
- * re-layout by other applications (such as `strip'). All the applications
- * that re-layout the internal of ELF will layout all sections in ascending
- * order of their file offsets. After the re-layout, the data2 section will
- * still be the LAST section in the section header vector, but its file offset
- * is now being pushed far away down, and causes part of it not to be mapped
- * in (ie. not covered by the load segment entry in PHDR vector), therefore
- * causes the new binary to fail.
- *
- * The solution is to modify the unexec algorithm to insert the new data2
- * section header right before the new bss section header, so their file
- * offsets will be in the ascending order. Since some of the section's (all
- * sections AFTER the bss section) indexes are now changed, we also need to
- * modify some fields to make them point to the right sections. This is done
- * by macro PATCH_INDEX. All the fields that need to be patched are:
- *
- * 1. ELF header e_shstrndx field.
- * 2. section header sh_link and sh_info field.
- * 3. symbol table entry st_shndx field.
- *
- * The above example now should look like:
-
- **** SECTION HEADER TABLE ****
-[No] Type Flags Addr Offset Size Name
- Link Info Adralgn Entsize
-
-[1] 1 2 0x80480d4 0xd4 0x13 .interp
- 0 0 0x1 0
-
-[2] 5 2 0x80480e8 0xe8 0x388 .hash
- 3 0 0x4 0x4
-
-[3] 11 2 0x8048470 0x470 0x7f0 .dynsym
- 4 1 0x4 0x10
-
-[4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
- 0 0 0x1 0
-
-[5] 9 2 0x8049010 0x1010 0x338 .rel.plt
- 3 7 0x4 0x8
-
-[6] 1 6 0x8049348 0x1348 0x3 .init
- 0 0 0x4 0
-
-[7] 1 6 0x804934c 0x134c 0x680 .plt
- 0 0 0x4 0x4
-
-[8] 1 6 0x80499cc 0x19cc 0x3c56f .text
- 0 0 0x4 0
-
-[9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
- 0 0 0x4 0
-
-[10] 1 2 0x8085f40 0x3df40 0x69c .rodata
- 0 0 0x4 0
-
-[11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
- 0 0 0x4 0
-
-[12] 1 3 0x8088330 0x3f330 0x20afc .data
- 0 0 0x4 0
-
-[13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
- 0 0 0x4 0
-
-[14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
- 0 0 0x4 0x4
-
-[15] 6 3 0x80a9874 0x60874 0x80 .dynamic
- 4 0 0x4 0x8
-
-[16] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
- 0 0 0x4 0
-
-[17] 8 3 0x80c6800 0x7d800 0 .bss
- 0 0 0x4 0
-
-[18] 2 0 0 0x7d800 0x9b90 .symtab
- 19 371 0x4 0x10
-
-[19] 3 0 0 0x87390 0x8526 .strtab
- 0 0 0x1 0
-
-[20] 3 0 0 0x8f8b6 0x93 .shstrtab
- 0 0 0x1 0
-
-[21] 1 0 0 0x8f949 0x68b7 .comment
- 0 0 0x1 0
-
+ * Finally we need to patch up some references to the section
+ * indexes since we change the order and undo the relocation info to
+ * be the same as it was "before" because we actually used the data
+ * from the memory which were changed by the run-time linker.
*/
\f
#ifndef emacs
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
-#if !defined (__NetBSD__) && !defined (__OpenBSD__)
+#ifdef HAVE_ELF_H
#include <elf.h>
#endif
#include <sys/mman.h>
#include <syms.h> /* for HDRR declaration */
#endif /* __sgi */
-#if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__)
-/* Declare COFF debugging symbol table. This used to be in
- /usr/include/sym.h, but this file is no longer included in Red Hat
- 5.0 and presumably in any other glibc 2.x based distribution. */
-typedef struct {
- short magic;
- short vstamp;
- int ilineMax;
- int idnMax;
- int ipdMax;
- int isymMax;
- int ioptMax;
- int iauxMax;
- int issMax;
- int issExtMax;
- int ifdMax;
- int crfd;
- int iextMax;
- long cbLine;
- long cbLineOffset;
- long cbDnOffset;
- long cbPdOffset;
- long cbSymOffset;
- long cbOptOffset;
- long cbAuxOffset;
- long cbSsOffset;
- long cbSsExtOffset;
- long cbFdOffset;
- long cbRfdOffset;
- long cbExtOffset;
-} HDRR, *pHDRR;
-#define cbHDRR sizeof(HDRR)
-#define hdrNil ((pHDRR)0)
-#endif
-
-#ifdef __NetBSD__
-/*
- * NetBSD does not have normal-looking user-land ELF support.
- */
-# if defined __alpha__ || defined __sparc_v9__
-# define ELFSIZE 64
-# else
-# define ELFSIZE 32
-# endif
-# include <sys/exec_elf.h>
-
-# ifndef PT_LOAD
-# define PT_LOAD Elf_pt_load
-# if 0 /* was in pkgsrc patches for 20.7 */
-# define SHT_PROGBITS Elf_sht_progbits
-# endif
-# define SHT_SYMTAB Elf_sht_symtab
-# define SHT_DYNSYM Elf_sht_dynsym
-# define SHT_NULL Elf_sht_null
-# define SHT_NOBITS Elf_sht_nobits
-# define SHT_REL Elf_sht_rel
-# define SHT_RELA Elf_sht_rela
-
-# define SHN_UNDEF Elf_eshn_undefined
-# define SHN_ABS Elf_eshn_absolute
-# define SHN_COMMON Elf_eshn_common
-# endif /* !PT_LOAD */
-
-# ifdef __alpha__
-# include <sys/exec_ecoff.h>
-# define HDRR struct ecoff_symhdr
-# define pHDRR HDRR *
-# endif /* __alpha__ */
-
-#ifdef __mips__ /* was in pkgsrc patches for 20.7 */
-# define SHT_MIPS_DEBUG DT_MIPS_FLAGS
-# define HDRR struct Elf_Shdr
-#endif /* __mips__ */
-#endif /* __NetBSD__ */
-
-#ifdef __OpenBSD__
-# include <sys/exec_elf.h>
-#endif
-
#if __GNU_LIBRARY__ - 0 >= 6
# include <link.h> /* get ElfW etc */
#endif
#endif
/* Get the address of a particular section or program header entry,
- * accounting for the size of the entries.
- */
-/*
- On PPC Reference Platform running Solaris 2.5.1
- the plt section is also of type NOBI like the bss section.
- (not really stored) and therefore sections after the bss
- section start at the plt offset. The plt section is always
- the one just before the bss section.
- Thus, we modify the test from
- if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
- to
- if (NEW_SECTION_H (nn).sh_offset >=
- OLD_SECTION_H (old_bss_index-1).sh_offset)
- This is just a hack. We should put the new data section
- before the .plt section.
- And we should not have this routine at all but use
- the libelf library to read the old file and create the new
- file.
- The changed code is minimal and depends on prep set in m/prep.h
- Erik Deumens
- Quantum Theory Project
- University of Florida
- deumens@qtp.ufl.edu
- Apr 23, 1996
- */
+ * accounting for the size of the entries. */
#define OLD_SECTION_H(n) \
(*(ElfW(Shdr) *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
#define PATCH_INDEX(n) \
do { \
- if ((int) (n) >= old_bss_index) \
+ if ((int) (n) >= growme_index) \
(n)++; } while (0)
+
typedef unsigned char byte;
/* Round X up to a multiple of Y. */
static int
find_section (char *name,
- char *section_names,
+ const char *section_names,
char *file_name,
ElfW(Ehdr) *old_file_h,
ElfW(Shdr) *old_section_h,
#endif
if (!strcmp (section_names + OLD_SECTION_H (idx).sh_name,
name))
- break;
- }
- if (idx == old_file_h->e_shnum)
- {
- if (noerror)
- return -1;
- else
- fatal ("Can't find %s in %s.\n", name, file_name);
+ return idx;
}
- return idx;
+ /* If we're here, we found nothing or return did not work */
+ if ( ! noerror)
+ fatal ("Can't find %s in %s.\n", name, file_name);
+
+ return -1;
}
/* ****************************************************************
uintptr_t bss_start,
uintptr_t entry_address)
{
- int new_file, old_file, new_file_size;
+ int old_file;
- /* Pointers to the base of the image of the two files. */
+ struct stat stat_buf;
caddr_t old_base, new_base;
- /* Pointers to the file, program and section headers for the old and new
- * files.
- */
- ElfW(Ehdr) *old_file_h, *new_file_h;
- ElfW(Phdr) *old_program_h, *new_program_h;
- ElfW(Shdr) *old_section_h, *new_section_h;
-
- /* Point to the section name table in the old file */
- char *old_section_names;
-
- ElfW(Addr) old_bss_addr, new_bss_addr;
- ElfW(Word) old_bss_size, new_data2_size;
- ElfW(Off) new_data2_offset;
- ElfW(Addr) new_data2_addr;
+ ElfW(Ehdr) *old_file_h, * new_file_h;
+ ElfW(Phdr) *old_program_h, * new_program_h;
+ ElfW(Shdr) *old_section_h, * new_section_h;
+ ElfW(Shdr) * growme = NULL, * grown = NULL;
+ ElfW(Addr) old_bss_addr = 0, new_data2_addr = 0;
+ int growme_index = -1;
int n, nn;
- int old_bss_index, old_sbss_index;
- int old_data_index, new_data2_index;
- int old_mdebug_index;
- struct stat stat_buf;
-
- /* Open the old file & map it into the address space. */
+ const char *old_section_names;
+ int old_mdebug_index, old_data_index;
+ int new_bss_addr, new_data2_size, new_data2_offset, new_file, new_file_size;
- old_file = open (old_name, O_RDONLY);
-
- if (old_file < 0)
- fatal ("Can't open %s for reading: errno %d\n", old_name, errno);
+ /* Open the old file */
+ if ( (old_file = open (old_name, O_RDONLY)) < 0 )
+ fatal ("Can't open %s for reading: errno %d\n", old_name, errno);
if (fstat (old_file, &stat_buf) == -1)
- fatal ("Can't fstat (%s): errno %d\n", old_name, errno);
-
- old_base = (caddr_t) mmap ((caddr_t) 0, stat_buf.st_size,
- PROT_READ, MAP_SHARED, old_file, 0);
+ fatal ("Can't fstat (%s): errno %d\n", old_name, errno);
- if (old_base == (caddr_t) -1)
- fatal ("Can't mmap (%s): errno %d\n", old_name, errno);
-
-#ifdef DEBUG
- fprintf (stderr, "mmap (%s, %x) -> %x\n", old_name, stat_buf.st_size,
- old_base);
-#endif
+ /* map old file into the address space. */
+ if ( (old_base = (caddr_t) mmap ((caddr_t) 0, stat_buf.st_size,
+ PROT_READ, MAP_SHARED, old_file, 0)) < 0 )
+ fatal ("Can't mmap (%s): errno %d\n", old_name, errno);
- /* Get pointers to headers & section names */
-
- old_file_h = (ElfW(Ehdr) *) old_base;
+ old_file_h = (ElfW(Ehdr) *) old_base;
old_program_h = (ElfW(Phdr) *) ((byte *) old_base + old_file_h->e_phoff);
old_section_h = (ElfW(Shdr) *) ((byte *) old_base + old_file_h->e_shoff);
- old_section_names = (char *) old_base
- + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
-
- /* Find the mdebug section, if any. */
-
- old_mdebug_index = find_section (".mdebug", old_section_names,
- old_name, old_file_h, old_section_h, 1);
-
- /* Find the old .bss section. Figure out parameters of the new
- * data2 and bss sections.
- */
-
- old_bss_index = find_section (".bss", old_section_names,
- old_name, old_file_h, old_section_h, 0);
-
- old_sbss_index = find_section (".sbss", old_section_names,
- old_name, old_file_h, old_section_h, 1);
- if (old_sbss_index != -1)
- if (OLD_SECTION_H (old_sbss_index).sh_type == SHT_PROGBITS)
- old_sbss_index = -1;
-
- if (old_sbss_index == -1)
- {
- old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
- old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
- new_data2_index = old_bss_index;
- }
- else
- {
- old_bss_addr = OLD_SECTION_H (old_sbss_index).sh_addr;
- old_bss_size = OLD_SECTION_H (old_bss_index).sh_size
- + OLD_SECTION_H (old_sbss_index).sh_size;
- new_data2_index = old_sbss_index;
- }
+ old_section_names = (const char *) old_base
+ + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
+
+ /* Find a section which we will grow by looking for the SHT_NOBITS
+ * section with ALLOCATE flag and with the biggest address. */
+ for (n = 1; n < old_file_h->e_shnum; n++) {
+ ElfW(Shdr) * sh = & OLD_SECTION_H(n);
+
+ if ((sh->sh_type == SHT_NOBITS) && (sh->sh_flags & SHF_ALLOC)) {
+ if ( old_bss_addr < sh->sh_addr ) {
+ growme = sh;
+ growme_index = n;
+ new_data2_addr = old_bss_addr = sh->sh_addr;
+ }
+ }
+ }
- /* Find the old .data section. Figure out parameters of
- the new data2 and bss sections. */
+ if (growme == NULL )
+ fatal ("Can't find a section to grow\n", 0, 0);
old_data_index = find_section (".data", old_section_names,
old_name, old_file_h, old_section_h, 0);
-#if defined (emacs) || !defined (DEBUG)
new_bss_addr = (ElfW(Addr)) sbrk (0);
-#else
- new_bss_addr = old_bss_addr + old_bss_size + 0x1234;
-#endif
- new_data2_addr = old_bss_addr;
new_data2_size = new_bss_addr - old_bss_addr;
new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset +
- (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
-
-#ifdef DEBUG
- fprintf (stderr, "old_bss_index %d\n", old_bss_index);
- fprintf (stderr, "old_bss_addr %x\n", old_bss_addr);
- fprintf (stderr, "old_bss_size %x\n", old_bss_size);
- fprintf (stderr, "new_bss_addr %x\n", new_bss_addr);
- fprintf (stderr, "new_data2_addr %x\n", new_data2_addr);
- fprintf (stderr, "new_data2_size %x\n", new_data2_size);
- fprintf (stderr, "new_data2_offset %x\n", new_data2_offset);
-#endif
-
- if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
- fatal (".bss shrank when undumping???\n", 0, 0);
+ (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
- /* Set the output file to the right size and mmap it. Set
- * pointers to various interesting objects. stat_buf still has
- * old_file data.
- */
+ if ( new_bss_addr < old_bss_addr + growme->sh_size )
+ fatal (".bss shrank when undumping???\n", 0, 0);
- new_file = open (new_name, O_RDWR | O_CREAT, 0666);
- if (new_file < 0)
- fatal ("Can't creat (%s): errno %d\n", new_name, errno);
+ /* Set the output file to the right size and mmap it. */
+ if ( (new_file = open (new_name, O_RDWR | O_CREAT, 0666)) < 0 )
+ fatal ("Can't create (%s): errno %d\n", new_name, errno);
- new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
+ new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
if (ftruncate (new_file, new_file_size))
- fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
+ fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
-#ifdef UNEXEC_USE_MAP_PRIVATE
new_base = (caddr_t) mmap ((caddr_t) 0, new_file_size,
PROT_READ | PROT_WRITE,
- MAP_PRIVATE, new_file, 0);
+#ifdef UNEXEC_USE_MAP_PRIVATE
+ MAP_PRIVATE,
#else
- new_base = (caddr_t) mmap ((caddr_t) 0, new_file_size,
- PROT_READ | PROT_WRITE,
- MAP_SHARED, new_file, 0);
+ MAP_SHARED,
#endif
+ new_file, 0);
if (new_base == (caddr_t) -1)
- fatal ("Can't mmap (%s): errno %d\n", new_name, errno);
+ fatal ("Can't mmap (%s): errno %d\n", new_name, errno);
new_file_h = (ElfW(Ehdr) *) new_base;
new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
- new_section_h = (ElfW(Shdr) *)
- ((byte *) new_base + old_file_h->e_shoff + new_data2_size);
+ new_section_h = (ElfW(Shdr) *) ((byte *) new_base + old_file_h->e_shoff +
+ new_data2_size);
/* Make our new file, program and section headers as copies of the
- * originals.
- */
-
+ * originals. */
memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
memcpy (new_program_h, old_program_h,
old_file_h->e_phnum * old_file_h->e_phentsize);
PATCH_INDEX (new_file_h->e_shstrndx);
/* Fix up file header. We'll add one section. Section header is
- * further away now.
- */
-
+ * further away now. */
new_file_h->e_shoff += new_data2_size;
new_file_h->e_shnum += 1;
+ /* Fix up a new program header by extending the writable data
+ * segment so that the bss area is covered too. Find that segment by
+ * looking for one that starts before and ends after the .bss and is
+ * PT_LOADable. */
+ for (n = new_file_h->e_phnum - 1; n >= 0; n--) {
+ ElfW(Phdr) * ph = & NEW_PROGRAM_H(n);
#ifdef DEBUG
- fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff);
- fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum);
- fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff);
- fprintf (stderr, "New section count %d\n", new_file_h->e_shnum);
+ printf ("%d @ %0x + %0x against %0x + %0x",
+ n, ph->p_vaddr, ph->p_memsz,growme->sh_addr, growme->sh_size);
#endif
+ if ((ph->p_type == PT_LOAD) &&
+ (ph->p_vaddr <= growme->sh_addr) &&
+ ((ph->p_vaddr+ph->p_memsz) >= (growme->sh_addr + growme->sh_size))) {
+ /* Make sure that the size includes any padding before the
+ * old .bss section. */
+ ph->p_memsz = ph->p_filesz = new_bss_addr - ph->p_vaddr;
+#ifdef DEBUG
+ puts (" That's the one!");
+#endif
+ break;
+ }
+#ifdef DEBUG
+ putchar ('\n');
+#endif
+ }
- /* Fix up a new program header. Extend the writable data segment so
- * that the bss area is covered too. Find that segment by looking
- * for a segment that ends just before the .bss area. Make sure
- * that no segments are above the new .data2. Put a loop at the end
- * to adjust the offset and address of any segment that is above
- * data2, just in case we decide to allow this later.
- */
-
- for (n = new_file_h->e_phnum - 1; n >= 0; n--)
- {
- /* Compute maximum of all requirements for alignment of section. */
- ElfW(Word) alignment = (NEW_PROGRAM_H (n)).p_align;
- if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
- alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
-
-#ifdef __sgi
- /* According to r02kar@x4u2.desy.de (Karsten Kuenne)
- and oliva@gnu.org (Alexandre Oliva), on IRIX 5.2, we
- always get "Program segment above .bss" when dumping
- when the executable doesn't have an sbss section. */
- if (old_sbss_index != -1)
-#endif /* __sgi */
- if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz
- > (old_sbss_index == -1
- ? old_bss_addr
- : round_up (old_bss_addr, alignment)))
- fatal ("Program segment above .bss in %s\n", old_name, 0);
-
- if (NEW_PROGRAM_H (n).p_type == PT_LOAD
- && (round_up ((NEW_PROGRAM_H (n)).p_vaddr
- + (NEW_PROGRAM_H (n)).p_filesz,
- alignment)
- == round_up (old_bss_addr, alignment)))
- break;
- }
if (n < 0)
- fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
+ fatal ("Couldn't find segment which covers %s",
+ old_section_names + growme->sh_name);
+
+ /* Walk through all section headers, insert the new data2 section
+ * right before the new bss section. */
+ for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++) {
+ ElfW(Shdr) * nsec = & NEW_SECTION_H(nn);
+ ElfW(Shdr) * osec = & OLD_SECTION_H(n);
+
+ /* If this is the section we want to grow, insert the new data
+ * section before it. */
+ if ( osec == growme ) {
+ /* Steal the data section header for this data2 section but
+ * use the * 'grow' section's alignment. This * will assure
+ * that the new section * always be placed in the same spot
+ * * as the old section by any other * application. */
+ ElfW(Shdr) * od = &OLD_SECTION_H(old_data_index);
+
+ memcpy (nsec, od, new_file_h->e_shentsize);
+
+ nsec->sh_addr = new_data2_addr;
+ nsec->sh_offset = new_data2_offset;
+ nsec->sh_size = new_data2_size;
+ nsec->sh_addralign = osec->sh_addralign;
+
+ /* Copy over what we have in memory now. */
+ memcpy (nsec->sh_offset + new_base, (caddr_t) osec->sh_addr,
+ new_data2_size);
+ nn++;
+ grown = nsec++;
+ }
- /* Make sure that the size includes any padding before the old .bss
- section. */
- NEW_PROGRAM_H (n).p_filesz = new_bss_addr - NEW_PROGRAM_H (n).p_vaddr;
- NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
+ memcpy (nsec, osec, old_file_h->e_shentsize);
+
+ if ( osec == growme ) {
+ /* The new bss section's size is zero, and its file offset
+ * and virtual address should be off by NEW_DATA2_SIZE. */
+ nsec->sh_offset = grown->sh_offset + new_data2_size;
+ nsec->sh_addr = grown->sh_addr + new_data2_size;
+
+ /* Let the new bss section address alignment be the same as
+ * the section address alignment followed the old bss
+ * section, so this section will be placed in exactly the
+ * same place. */
+ nsec->sh_addralign = osec->sh_addralign;
+ nsec->sh_size = 0;
+ } else {
+ /* Any section that was originally placed AFTER the bss
+ * section should now be off by NEW_DATA2_SIZE. */
+ if ( round_up (nsec->sh_offset, growme->sh_addralign) >=
+ new_data2_offset)
+ nsec->sh_offset += new_data2_size;
+ }
-#if 0 /* Maybe allow section after data2 - does this ever happen? */
- for (n = new_file_h->e_phnum - 1; n >= 0; n--)
- {
- if (NEW_PROGRAM_H (n).p_vaddr
- && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr)
- NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size;
+ /* Any section that was originally placed after the section *
+ * header table should now be off by the size of one section
+ * header table entry. */
+ if (nsec->sh_offset > new_file_h->e_shoff)
+ nsec->sh_offset += new_file_h->e_shentsize;
- if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset)
- NEW_PROGRAM_H (n).p_offset += new_data2_size;
- }
-#endif
-
- /* Fix up section headers based on new .data2 section. Any section
- * whose offset or virtual address is after the new .data2 section
- * gets its value adjusted. .bss size becomes zero and new address
- * is set. data2 section header gets added by copying the existing
- * .data header and modifying the offset, address and size.
- */
- for (old_data_index = 1; old_data_index < (int) old_file_h->e_shnum;
- old_data_index++)
- if (!strcmp (old_section_names + OLD_SECTION_H (old_data_index).sh_name,
- ".data"))
- break;
- if (old_data_index == old_file_h->e_shnum)
- fatal ("Can't find .data in %s.\n", old_name, 0);
-
- /* Walk through all section headers, insert the new data2 section right
- before the new bss section. */
- for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++)
- {
- caddr_t src;
- /* If it is (s)bss section, insert the new data2 section before it. */
- /* new_data2_index is the index of either old_sbss or old_bss, that was
- chosen as a section for new_data2. */
- if (n == new_data2_index)
- {
- /* Steal the data section header for this data2 section. */
- memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
- new_file_h->e_shentsize);
-
- NEW_SECTION_H (nn).sh_addr = new_data2_addr;
- NEW_SECTION_H (nn).sh_offset = new_data2_offset;
- NEW_SECTION_H (nn).sh_size = new_data2_size;
- /* Use the bss section's alignment. This will assure that the
- new data2 section always be placed in the same spot as the old
- bss section by any other application. */
- NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign;
-
- /* Now copy over what we have in the memory now. */
- memcpy (NEW_SECTION_H (nn).sh_offset + new_base,
- (caddr_t) OLD_SECTION_H (n).sh_addr,
- new_data2_size);
- nn++;
- }
-
- memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
- old_file_h->e_shentsize);
-
- if (n == old_bss_index
- /* The new bss and sbss section's size is zero, and its file offset
- and virtual address should be off by NEW_DATA2_SIZE. */
- || n == old_sbss_index
- )
- {
- /* NN should be `old_s?bss_index + 1' at this point. */
- NEW_SECTION_H (nn).sh_offset =
- NEW_SECTION_H (new_data2_index).sh_offset + new_data2_size;
- NEW_SECTION_H (nn).sh_addr =
- NEW_SECTION_H (new_data2_index).sh_addr + new_data2_size;
- /* Let the new bss section address alignment be the same as the
- section address alignment followed the old bss section, so
- this section will be placed in exactly the same place. */
- NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign;
- NEW_SECTION_H (nn).sh_size = 0;
- }
- else
- {
- /* Any section that was original placed AFTER the bss
- section should now be off by NEW_DATA2_SIZE. */
-#ifdef SOLARIS_POWERPC
- /* On PPC Reference Platform running Solaris 2.5.1
- the plt section is also of type NOBI like the bss section.
- (not really stored) and therefore sections after the bss
- section start at the plt offset. The plt section is always
- the one just before the bss section.
- It would be better to put the new data section before
- the .plt section, or use libelf instead.
- Erik Deumens, deumens@qtp.ufl.edu. */
- if (NEW_SECTION_H (nn).sh_offset
- >= OLD_SECTION_H (old_bss_index-1).sh_offset)
- NEW_SECTION_H (nn).sh_offset += new_data2_size;
-#else
- if (round_up (NEW_SECTION_H (nn).sh_offset,
- OLD_SECTION_H (old_bss_index).sh_addralign)
- >= new_data2_offset)
- NEW_SECTION_H (nn).sh_offset += new_data2_size;
-#endif
- /* Any section that was originally placed after the section
- header table should now be off by the size of one section
- header table entry. */
- if (NEW_SECTION_H (nn).sh_offset > new_file_h->e_shoff)
- NEW_SECTION_H (nn).sh_offset += new_file_h->e_shentsize;
- }
/* If any section hdr refers to the section after the new .data
- section, make it refer to next one because we have inserted
- a new section in between. */
-
- PATCH_INDEX (NEW_SECTION_H (nn).sh_link);
- /* For symbol tables, info is a symbol table index,
- so don't change it. */
- if (NEW_SECTION_H (nn).sh_type != SHT_SYMTAB
- && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM)
- PATCH_INDEX (NEW_SECTION_H (nn).sh_info);
-
- if (old_sbss_index != -1)
- if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".sbss"))
- {
- NEW_SECTION_H (nn).sh_offset =
- round_up (NEW_SECTION_H (nn).sh_offset,
- NEW_SECTION_H (nn).sh_addralign);
- NEW_SECTION_H (nn).sh_type = SHT_PROGBITS;
+ * section, make it refer to next one because we have inserted a
+ * new section in between. */
+ PATCH_INDEX (nsec->sh_link);
+
+ /* For symbol tables, info is a symbol table index, so don't
+ * change it. */
+ if (nsec->sh_type != SHT_SYMTAB && nsec->sh_type != SHT_DYNSYM)
+ PATCH_INDEX (nsec->sh_info);
+
+ /* Any section which used to be NOBITS will now becomes PROGBITS
+ * if it's ALLOC-atable, unless, of cause, it's not the one we
+ * decided to grow */
+ if ( (osec->sh_type == SHT_NOBITS) && (osec->sh_flags & SHF_ALLOC) &&
+ (osec != growme ) ) {
+ nsec->sh_type = SHT_PROGBITS;
+ }
+
+ /* Now, start to copy the content of sections */
+ if ( nsec->sh_type != SHT_NULL || nsec->sh_type != SHT_NOBITS ) {
+
+ /* Write out the sections. .data and .data1 (and data2,
+ * called ".data" in the strings table) get copied from the
+ * current process instead of the old file. */
+ caddr_t src = old_base + osec->sh_offset;
+ const char * secname = old_section_names + nsec->sh_name;
+ const char * names[] = {
+ ".data",".sdata", ".lit4", ".lit8", ".sdata1", ".data1",
+ ".sbss", NULL};
+ int i;
+
+ for ( i=0; names[i] != NULL; i++ ) {
+ if ( ! strcmp (secname, names[i]) ) {
+ src = (caddr_t) osec->sh_addr;
+ break;
+ }
}
- /* Now, start to copy the content of sections. */
- if (NEW_SECTION_H (nn).sh_type == SHT_NULL
- || NEW_SECTION_H (nn).sh_type == SHT_NOBITS)
- continue;
-
- /* Write out the sections. .data and .data1 (and data2, called
- ".data" in the strings table) get copied from the current process
- instead of the old file. */
- if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data")
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
- ".sdata")
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
- ".lit4")
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
- ".lit8")
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
- ".sdata1")
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
- ".data1")
- || !strcmp (old_section_names + NEW_SECTION_H (nn).sh_name,
- ".sbss"))
- src = (caddr_t) OLD_SECTION_H (n).sh_addr;
- else
- src = old_base + OLD_SECTION_H (n).sh_offset;
-
- memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src,
- NEW_SECTION_H (nn).sh_size);
+ memcpy (nsec->sh_offset + new_base, src, nsec->sh_size);
+ }
-#ifdef __alpha__
- /* Update Alpha COFF symbol table: */
- if (strcmp (old_section_names + OLD_SECTION_H (n).sh_name, ".mdebug")
- == 0)
- {
- pHDRR symhdr = (pHDRR) (NEW_SECTION_H (nn).sh_offset + new_base);
-
- symhdr->cbLineOffset += new_data2_size;
- symhdr->cbDnOffset += new_data2_size;
- symhdr->cbPdOffset += new_data2_size;
- symhdr->cbSymOffset += new_data2_size;
- symhdr->cbOptOffset += new_data2_size;
- symhdr->cbAuxOffset += new_data2_size;
- symhdr->cbSsOffset += new_data2_size;
- symhdr->cbSsExtOffset += new_data2_size;
- symhdr->cbFdOffset += new_data2_size;
- symhdr->cbRfdOffset += new_data2_size;
- symhdr->cbExtOffset += new_data2_size;
- }
-#endif /* __alpha__ */
+ old_mdebug_index = find_section (".mdebug", old_section_names,
+ old_name, old_file_h, old_section_h, 1);
#if defined (__sony_news) && defined (_SYSTYPE_SYSV)
- if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG
- && old_mdebug_index != -1)
- {
- int diff = NEW_SECTION_H(nn).sh_offset
- - OLD_SECTION_H(old_mdebug_index).sh_offset;
- HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base);
-
- if (diff)
- {
+ if (nsec->sh_type == SHT_MIPS_DEBUG && old_mdebug_index != -1) {
+ int diff = nsec->sh_offset-OLD_SECTION_H(old_mdebug_index).sh_offset;
+ HDRR *phdr = (HDRR *)(nsec->sh_offset + new_base);
+
+ if (diff) {
phdr->cbLineOffset += diff;
phdr->cbDnOffset += diff;
phdr->cbPdOffset += diff;
phdr->cbFdOffset += diff;
phdr->cbRfdOffset += diff;
phdr->cbExtOffset += diff;
- }
- }
+ }
+ }
#endif /* __sony_news && _SYSTYPE_SYSV */
#if __sgi
- /* Adjust the HDRR offsets in .mdebug and copy the
- line data if it's in its usual 'hole' in the object.
- Makes the new file debuggable with dbx.
- patches up two problems: the absolute file offsets
- in the HDRR record of .mdebug (see /usr/include/syms.h), and
- the ld bug that gets the line table in a hole in the
- elf file rather than in the .mdebug section proper.
- David Anderson. davea@sgi.com Jan 16,1994. */
- if (n == old_mdebug_index)
- {
+ /* Adjust the HDRR offsets in .mdebug and copy the line data if
+ * it's in its usual 'hole' in the object. Makes the new file
+ * debuggable with dbx. patches up two problems: the absolute
+ * file offsets in the HDRR record of .mdebug (see
+ * /usr/include/syms.h), and the ld bug that gets the line table
+ * in a hole in the elf file rather than in the .mdebug section
+ * proper.
+ *
+ * David Anderson. davea@sgi.com Jan 16,1994 */
#define MDEBUGADJUST(__ct,__fileaddr) \
if (n_phdrr->__ct > 0) \
{ \
n_phdrr->__fileaddr += movement; \
}
- HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset);
- HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset);
+ if (n == old_mdebug_index) {
+ HDRR * o_phdrr = (HDRR *)((byte *)old_base + osec->sh_offset);
+ HDRR * n_phdrr = (HDRR *)((byte *)new_base + nsec->sh_offset);
unsigned movement = new_data2_size;
MDEBUGADJUST (idnMax, cbDnOffset);
MDEBUGADJUST (ifdMax, cbFdOffset);
MDEBUGADJUST (crfd, cbRfdOffset);
MDEBUGADJUST (iextMax, cbExtOffset);
- /* The Line Section, being possible off in a hole of the object,
- requires special handling. */
- if (n_phdrr->cbLine > 0)
- {
- if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset
- + OLD_SECTION_H (n).sh_size))
- {
- /* line data is in a hole in elf. do special copy and adjust
- for this ld mistake.
- */
+
+ /* The Line Section, being possible off in a hole of the
+ * object, requires special handling. */
+ if (n_phdrr->cbLine > 0) {
+ if (o_phdrr->cbLineOffset >
+ osec->sh_offset+ osec->sh_size){
+ /* line data is in a hole in elf. do special copy
+ * and adjust for this ld mistake. */
n_phdrr->cbLineOffset += movement;
memcpy (n_phdrr->cbLineOffset + new_base,
o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
- }
- else
- {
- /* somehow line data is in .mdebug as it is supposed to be. */
+ } else {
+ /* somehow line data is in .mdebug as it is supposed
+ * to be. */
MDEBUGADJUST (cbLine, cbLineOffset);
- }
- }
- }
+ }
+ }
+ }
#endif /* __sgi */
-
- /* If it is the symbol table, its st_shndx field needs to be patched. */
- if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
- || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
- {
- ElfW(Shdr) *spt = &NEW_SECTION_H (nn);
- unsigned int num = spt->sh_size / spt->sh_entsize;
- ElfW(Sym) * sym = (ElfW(Sym) *) (NEW_SECTION_H (nn).sh_offset +
- new_base);
- for (; num--; sym++)
- {
- if ((sym->st_shndx == SHN_UNDEF)
- || (sym->st_shndx == SHN_ABS)
- || (sym->st_shndx == SHN_COMMON))
- continue;
+ /* If it is the symbol table, its st_shndx field needs to be
+ * patched. */
+ if (nsec->sh_type == SHT_SYMTAB || nsec->sh_type == SHT_DYNSYM) {
+ unsigned int num = nsec->sh_size / nsec->sh_entsize;
+ ElfW(Sym) * sym = (ElfW(Sym) *)(nsec->sh_offset + new_base);
+ byte *symnames = ((byte *) new_base +
+ NEW_SECTION_H (nsec->sh_link).sh_offset);
+
+ for (; num--; sym++) {
+ const char * symnam = (char *) (symnames + sym->st_name);
+
+ /* Update the symbol values of _edata and _end. */
+ if (strcmp (symnam, "_end") == 0
+ || strcmp (symnam, "end") == 0
+ || strcmp (symnam, "_edata") == 0
+ || strcmp (symnam, "edata") == 0)
+ memcpy (&sym->st_value, &new_bss_addr,sizeof (new_bss_addr));
+
+
+ if ((sym->st_shndx == SHN_UNDEF) || (sym->st_shndx == SHN_ABS)
+ || (sym->st_shndx == SHN_COMMON)
+ || (sym->st_shndx >= SHN_LOPROC &&
+ sym->st_shndx <= SHN_HIPROC))
+ continue;
PATCH_INDEX (sym->st_shndx);
- }
- }
- }
-
- /* Update the symbol values of _edata and _end. */
- for (n = new_file_h->e_shnum - 1; n; n--)
- {
- byte *symnames;
- ElfW(Sym) *symp, *symendp;
-
- if (NEW_SECTION_H (n).sh_type != SHT_DYNSYM
- && NEW_SECTION_H (n).sh_type != SHT_SYMTAB)
- continue;
-
- symnames = ((byte *) new_base
- + NEW_SECTION_H (NEW_SECTION_H (n).sh_link).sh_offset);
- symp = (ElfW(Sym) *) (NEW_SECTION_H (n).sh_offset + new_base);
- symendp = (ElfW(Sym) *) ((byte *)symp + NEW_SECTION_H (n).sh_size);
-
- for (; symp < symendp; symp ++)
- if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0
- || strcmp ((char *) (symnames + symp->st_name), "end") == 0
- || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0
- || strcmp ((char *) (symnames + symp->st_name), "edata") == 0)
- memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr));
- }
+ }
+ }
+ }
/* This loop seeks out relocation sections for the data section, so
- that it can undo relocations performed by the runtime linker. */
- for (n = new_file_h->e_shnum - 1; n; n--)
- {
+ * that it can undo relocations performed by the runtime linker. */
+ for (n = new_file_h->e_shnum - 1; n; n--) {
ElfW(Shdr) section = NEW_SECTION_H (n);
- switch (section.sh_type) {
- default:
- break;
- case SHT_REL:
- case SHT_RELA:
- /* This code handles two different size structs, but there should
- be no harm in that provided that r_offset is always the first
- member. */
- nn = section.sh_info;
- if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".sdata")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".lit4")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".lit8")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".sdata1")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".data1"))
- {
- ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr -
- NEW_SECTION_H (nn).sh_offset;
- caddr_t reloc = old_base + section.sh_offset, end;
- for (end = reloc + section.sh_size; reloc < end;
- reloc += section.sh_entsize)
- {
- ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset;
+
+ if ( section.sh_type == SHT_REL || section.sh_type == SHT_RELA ) {
+ /* This code handles two different size structs, but there
+ * should be no harm in that provided that r_offset is
+ * always the first member. */
+ ElfW(Shdr) * info = & NEW_SECTION_H(section.sh_info);
+ const char * nm = old_section_names + info->sh_name;
+
+ if (!strcmp (nm, ".data") || !strcmp (nm, ".sdata")
+ || !strcmp (nm, ".lit4") || !strcmp (nm, ".lit8")
+ || !strcmp (nm, ".sdata1") || !strcmp (nm, ".data1")) {
+ ElfW(Addr) offset = info->sh_addr - info->sh_offset;
+ caddr_t end, reloc = old_base + section.sh_offset;
+
+ for (end = reloc + section.sh_size; reloc < end;
+ reloc += section.sh_entsize) {
+ ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset;
#ifdef __alpha__
- /* The Alpha ELF binutils currently have a bug that
- sometimes results in relocs that contain all
- zeroes. Work around this for now... */
- if (((ElfW(Rel) *) reloc)->r_offset == 0)
- continue;
+ /* The Alpha ELF binutils currently have a bug that
+ * sometimes results in relocs that contain all
+ * zeroes. Work around this for now... */
+ if (((ElfW(Rel) *) reloc)->r_offset == 0)
+ continue;
#endif
- memcpy (new_base + addr, old_base + addr, sizeof(ElfW(Addr)));
+ memcpy (new_base + addr, old_base + addr,
+ sizeof(ElfW(Addr)));
}
}
- break;
}
- }
+ }
#ifdef UNEXEC_USE_MAP_PRIVATE
if (lseek (new_file, 0, SEEK_SET) == -1)
- fatal ("Can't rewind (%s): errno %d\n", new_name, errno);
+ fatal ("Can't rewind (%s): errno %d\n", new_name, errno);
if (write (new_file, new_base, new_file_size) != new_file_size)
- fatal ("Can't write (%s): errno %d\n", new_name, errno);
+ fatal ("Can't write (%s): errno %d\n", new_name, errno);
#endif
/* Close the files and make the new file executable. */
-
if (close (old_file))
- fatal ("Can't close (%s): errno %d\n", old_name, errno);
+ fatal ("Can't close (%s): errno %d\n", old_name, errno);
if (close (new_file))
- fatal ("Can't close (%s): errno %d\n", new_name, errno);
+ fatal ("Can't close (%s): errno %d\n", new_name, errno);
if (stat (new_name, &stat_buf) == -1)
- fatal ("Can't stat (%s): errno %d\n", new_name, errno);
+ fatal ("Can't stat (%s): errno %d\n", new_name, errno);
n = umask (777);
umask (n);
stat_buf.st_mode |= 0111 & ~n;
if (chmod (new_name, stat_buf.st_mode) == -1)
- fatal ("Can't chmod (%s): errno %d\n", new_name, errno);
+ fatal ("Can't chmod (%s): errno %d\n", new_name, errno);
}
+2000-12-05 Martin Buchholz <martin@xemacs.org>
+
+ * XEmacs 21.2.38 is released.
+
+2000-12-01 Martin Buchholz <martin@xemacs.org>
+
+ * automated/test-harness.el (test-harness-from-buffer): Throw away
+ all warnings, even those not influenced by byte-compiler-warnings.
+
+2000-11-30 Martin Buchholz <martin@xemacs.org>
+
+ * automated/lisp-tests.el:
+ Test byte-compiler arithmetic optimizations.
+
+2000-11-27 Yoshiki Hayashi <yoshiki@xemacs.org>
+
+ * automated/case-tests.el: Add more tests.
+
+2000-11-24 Yoshiki Hayashi <yoshiki@xemacs.org>
+
+ * automated/regexp-tests.el: New file.
+
+2000-11-22 Martin Buchholz <martin@xemacs.org>
+
+ * automated/lisp-tests.el:
+ Add 64-bit-correctness format tests.
+ Don't quote the first arg to Check-Error.
+
+2000-11-14 Yoshiki Hayashi <yoshiki@xemacs.org>
+
+ * automated/case-tests.el: New file.
+
2000-11-14 Martin Buchholz <martin@xemacs.org>
* XEmacs 21.2.37 is released.
(Assert (= two (max one two two)))
(Assert (= two (max two two one)))))
+;; The byte compiler has special handling for these constructs:
+(let ((three 3) (five 5))
+ (Assert (= (+ three five 1) 9))
+ (Assert (= (+ 1 three five) 9))
+ (Assert (= (+ three five -1) 7))
+ (Assert (= (+ -1 three five) 7))
+ (Assert (= (+ three 1) 4))
+ (Assert (= (+ three -1) 2))
+ (Assert (= (+ -1 three) 2))
+ (Assert (= (+ -1 three) 2))
+ (Assert (= (- three five 1) -3))
+ (Assert (= (- 1 three five) -7))
+ (Assert (= (- three five -1) -1))
+ (Assert (= (- -1 three five) -9))
+ (Assert (= (- three 1) 2))
+ (Assert (= (- three 2 1) 0))
+ (Assert (= (- 2 three 1) -2))
+ (Assert (= (- three -1) 4))
+ (Assert (= (- three 0) 3))
+ (Assert (= (- three 0 five) -2))
+ (Assert (= (- 0 three 0 five) -8))
+ (Assert (= (- 0 three five) -8))
+ (Assert (= (* three 2) 6))
+ (Assert (= (* three -1 five) -15))
+ (Assert (= (* three 1 five) 15))
+ (Assert (= (* three 0 five) 0))
+ (Assert (= (* three 2 five) 30))
+ (Assert (= (/ three 1) 3))
+ (Assert (= (/ three -1) -3))
+ (Assert (= (/ (* five five) 2 2) 6))
+ (Assert (= (/ 64 five 2) 6)))
+
+
;;-----------------------------------------------------
;; Logical bit-twiddling operations
;;-----------------------------------------------------
;; The following 2 functions used to crash XEmacs via mapcar1().
;; We don't test the actual values of the mapcar, since they're undefined.
-(Assert
+(Assert
(let ((x (list (cons 1 1) (cons 2 2) (cons 3 3))))
(mapcar
(lambda (y)
(car y)) ; sorry, hard landing
x)))
-(Assert
+(Assert
(let ((x (list (cons 1 1) (cons 2 2) (cons 3 3))))
(mapcar
(lambda (y)
(Assert (equal (split-string ",foo,,bar," ",+") '("" "foo" "bar" "")))
(Assert (not (string-match "\\(\\.\\=\\)" ".")))
-(Assert (string= "" (let ((str "test string"))
+(Assert (string= "" (let ((str "test string"))
(if (string-match "^.*$" str)
(replace-match "\\U" t nil str)))))
(with-temp-buffer
(Assert (equal (subseq '(1 2 3) 0) '(1 2 3)))
(Assert (equal (subseq '(1 2 3 4) -3 nil) '(2 3 4)))
-(Check-Error 'wrong-type-argument (subseq 3 2))
-(Check-Error 'args-out-of-range (subseq [1 2 3] -42))
-(Check-Error 'args-out-of-range (subseq [1 2 3] 0 42))
+(Check-Error wrong-type-argument (subseq 3 2))
+(Check-Error args-out-of-range (subseq [1 2 3] -42))
+(Check-Error args-out-of-range (subseq [1 2 3] 0 42))
;;-----------------------------------------------------
;; Time-related tests
(Assert (string= (format "%01.3d" 10) "10"))
(Assert (string= (format "%1.3d" 10) "10"))
(Assert (string= (format "%3.1d" 10) " 10"))
+
+;;; Check for 64-bit cleanness on LP64 platforms.
+(Assert (= (read (format "%d" most-positive-fixnum)) most-positive-fixnum))
+(Assert (= (read (format "%ld" most-positive-fixnum)) most-positive-fixnum))
+(Assert (= (read (format "%u" most-positive-fixnum)) most-positive-fixnum))
+(Assert (= (read (format "%lu" most-positive-fixnum)) most-positive-fixnum))
+(Assert (= (read (format "%d" most-negative-fixnum)) most-negative-fixnum))
+(Assert (= (read (format "%ld" most-negative-fixnum)) most-negative-fixnum))
+
+;;; "%u" is undocumented, and Emacs Lisp has no unsigned type.
+;;; What to do if "%u" is used with a negative number?
+;;; The most reasonable thing seems to be to print an un-read-able number.
+;;; The printed value might be useful to a human, if not to Emacs Lisp.
+(Check-Error invalid-read-syntax (read (format "%u" most-negative-fixnum)))
+(Check-Error invalid-read-syntax (read (format "%u" -1)))
(princ "\nTesting Compiled Lisp\n\n")
(let (code)
(condition-case error-info
- (setq code (let ((byte-compile-warnings nil))
- (byte-compile (test-harness-read-from-buffer inbuffer))))
+ (setq code
+ ;; our lisp code is often intentionally dubious,
+ ;; so throw away _all_ the byte compiler warnings.
+ (letf (((symbol-function 'byte-compile-warn) 'ignore))
+ (byte-compile (test-harness-read-from-buffer inbuffer))))
(error
(princ (format "Unexpected error %S while byte-compiling code\n"
error-info))))
emacs_is_beta=t
emacs_major_version=21
emacs_minor_version=2
-emacs_beta_version=37
-xemacs_codename="Pan"
+emacs_beta_version=38
+xemacs_codename="Peisino\e,Ak\e(B"
infodock_major_version=4
infodock_minor_version=0
infodock_build_version=8