From 0e69443dde4eafd767fc8a7f10ae566dd5050954 Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Wed, 21 Nov 2012 07:17:28 -0500 Subject: Auto-commit of generated files. --- autogen/configure | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/autogen/configure b/autogen/configure index 67e1039d54c..ce683a5fa29 100755 --- a/autogen/configure +++ b/autogen/configure @@ -2036,8 +2036,9 @@ Optional Features: enable compile time checks for the Lisp_Object data type. This is useful for development for catching certain types of bugs. - --enable-profiling build emacs with profiling support. This might not - work on all platforms + --enable-profiling build emacs with low-level, gprof profiling support. + Mainly useful for debugging Emacs itself. May not + work on all platforms. Stops profiler.el working. --enable-autodepend automatically generate dependencies to .h-files. Requires GNU Make and Gcc. Enabled if GNU Make and Gcc is found -- cgit v1.2.1 From 365fc14aa4c5033422481d9145cba015821df052 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Wed, 21 Nov 2012 09:14:42 -0500 Subject: * doc/lispref/debugging.texi (Profiling): Make it more clear that --enable-profiling is about profiling the C code. --- doc/lispref/ChangeLog | 5 +++++ doc/lispref/debugging.texi | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index b5bbd8ef93f..40bd3c2cbbe 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,8 @@ +2012-11-21 Stefan Monnier + + * debugging.texi (Profiling): Make it more clear + that --enable-profiling is about profiling the C code. + 2012-11-21 Glenn Morris * debugging.texi (Profiling): Mention --enable-profiling (if !tex). diff --git a/doc/lispref/debugging.texi b/doc/lispref/debugging.texi index 3439a8ae152..6e4f6628637 100644 --- a/doc/lispref/debugging.texi +++ b/doc/lispref/debugging.texi @@ -866,7 +866,7 @@ You can check the speed of individual Emacs Lisp forms using the @c Not worth putting in the printed manual. @ifnottex @cindex --enable-profiling option of configure -For low-level profiling of Emacs itself, you can build it using the +To profile Emacs at the level of its C code, you can build it using the @option{--enable-profiling} option of @command{configure}. When Emacs exits, it generates a file @file{gmon.out} that you can examine using the @command{gprof} utility. This feature is mainly useful for -- cgit v1.2.1 From cb5867b1f8af39ffd70767fc06fd364bca67e968 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Wed, 21 Nov 2012 21:28:14 +0200 Subject: Fix bug #12930 with vertical-motion through a display string. src/indent.c (Fvertical_motion): If the starting position is covered by a display string, return to one position before that, to avoid overshooting it inside move_it_to. --- src/ChangeLog | 6 ++++++ src/indent.c | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/ChangeLog b/src/ChangeLog index f7cb0fe850f..f760adf313f 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2012-11-21 Eli Zaretskii + + * indent.c (Fvertical_motion): If the starting position is covered + by a display string, return to one position before that, to avoid + overshooting it inside move_it_to. (Bug#12930) + 2012-11-20 Daniel Colascione * w32fns.c (Fx_file_dialog): diff --git a/src/indent.c b/src/indent.c index bbc944d2518..33322287c9d 100644 --- a/src/indent.c +++ b/src/indent.c @@ -2057,7 +2057,13 @@ whether or not it is currently displayed in some window. */) comment said this is "so we don't move too far" (2005-01-19 checkin by kfs). But this does nothing useful that I can tell, and it causes Bug#2694 . -- cyd */ - move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS); + /* When the position we started from is covered by a display + string, move_it_to will overshoot it, while vertical-motion + wants to put the cursor _before_ the display string. So in + that case, we move to buffer position before the display + string, and avoid overshooting. */ + move_it_to (&it, disp_string_at_start_p ? PT - 1 : PT, + -1, -1, -1, MOVE_TO_POS); /* IT may move too far if truncate-lines is on and PT lies beyond the right margin. IT may also move too far if the -- cgit v1.2.1 From b03aabdac594c3c6fd587ad4927bc4187fa12c2d Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Wed, 21 Nov 2012 20:41:03 +0000 Subject: Fix bugs in the CC Mode state cache. Enhance a debugging mechanism. --- lisp/ChangeLog | 17 +++++++++++++++ lisp/progmodes/cc-engine.el | 53 ++++++++++++++++++++++++++++++++++++--------- lisp/progmodes/cc-mode.el | 7 ++++-- 3 files changed, 65 insertions(+), 12 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 8502cd477e9..e60e9b49043 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,20 @@ +2012-11-21 Alan Mackenzie + + Fix bugs in the state cache. Enhance a debugging mechanism. + * progmodes/cc-engine.el (c-parse-state-get-strategy): Don't use + "brace at column zero" strategy for C++. + (c-append-lower-brace-pair-to-state-cache): Repair algorithm. + (c-parse-state-point): New variable. + (c-record-parse-state-state): Record old parse state with + `copy-tree'. Record previous value of point. + (c-debug-parse-state-double-cons): New debugging function. + (c-debug-parse-state): Call the above new function. + (c-toggle-parse-state-debug): Output a confirmatory message. + + * progmodes/cc-mode.el (c-before-change, c-after-change): Call + c-invalidate-state-cache from `c-before-change' instead of + `c-after-change'. + 2012-11-20 Daniel Colascione * term/w32-win.el (cygwin-convert-path-from-windows): Accomodate diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 2aa04cb2b0b..10355451480 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -2561,8 +2561,11 @@ comment at the start of cc-engine.el for more info." start-point cache-pos))) ;; Might we be better off starting from the top level, two defuns back, - ;; instead? - (when (> how-far c-state-cache-too-far) + ;; instead? This heuristic no longer works well in C++, where + ;; declarations inside namespace brace blocks are frequently placed at + ;; column zero. + (when (and (not (c-major-mode-is 'c++-mode)) + (> how-far c-state-cache-too-far)) (setq BOD-pos (c-get-fallback-scan-pos here)) ; somewhat EXPENSIVE!!! (if (< (- here BOD-pos) how-far) (setq strategy 'BOD @@ -2649,17 +2652,20 @@ comment at the start of cc-engine.el for more info." ;; If we're essentially repeating a fruitless search, just give up. (unless (and c-state-brace-pair-desert (eq cache-pos (car c-state-brace-pair-desert)) + (or (null (car c-state-brace-pair-desert)) + (> from (car c-state-brace-pair-desert))) (<= from (cdr c-state-brace-pair-desert))) - ;; DESERT-LIM. Only search what we absolutely need to, + ;; DESERT-LIM. Avoid repeated searching through the cached desert. (let ((desert-lim (and c-state-brace-pair-desert (eq cache-pos (car c-state-brace-pair-desert)) + (>= from (cdr c-state-brace-pair-desert)) (cdr c-state-brace-pair-desert))) ;; CACHE-LIM. This limit will be necessary when an opening ;; paren at `cache-pos' has just had its matching close paren - ;; inserted. `cache-pos' continues to be a search bound, even - ;; though the algorithm below would skip over the new paren - ;; pair. + ;; inserted into the buffer. `cache-pos' continues to be a + ;; search bound, even though the algorithm below would skip + ;; over the new paren pair. (cache-lim (and cache-pos (< cache-pos from) cache-pos))) (narrow-to-region (cond @@ -3342,12 +3348,18 @@ comment at the start of cc-engine.el for more info." (fset 'c-real-parse-state (symbol-function 'c-parse-state))) (cc-bytecomp-defun c-real-parse-state) +(defvar c-parse-state-point nil) (defvar c-parse-state-state nil) (defun c-record-parse-state-state () + (setq c-parse-state-point (point)) (setq c-parse-state-state (mapcar (lambda (arg) - (cons arg (symbol-value arg))) + (let ((val (symbol-value arg))) + (cons arg + (if (consp val) + (copy-tree val) + val)))) '(c-state-cache c-state-cache-good-pos c-state-nonlit-pos-cache @@ -3360,7 +3372,8 @@ comment at the start of cc-engine.el for more info." c-state-point-min-lit-start c-state-min-scan-pos c-state-old-cpp-beg - c-state-old-cpp-end)))) + c-state-old-cpp-end + c-parse-state-point)))) (defun c-replay-parse-state-state () (message (concat "(setq " @@ -3370,6 +3383,16 @@ comment at the start of cc-engine.el for more info." c-parse-state-state " ") ")"))) +(defun c-debug-parse-state-double-cons (state) + (let (state-car conses-not-ok) + (while state + (setq state-car (car state) + state (cdr state)) + (if (and (consp state-car) + (consp (car state))) + (setq conses-not-ok t))) + conses-not-ok)) + (defun c-debug-parse-state () (let ((here (point)) (res1 (c-real-parse-state)) res2) (let ((c-state-cache nil) @@ -3402,8 +3425,16 @@ comment at the start of cc-engine.el for more info." here res1 res2) (message "Old state:") (c-replay-parse-state-state)) + + (when (c-debug-parse-state-double-cons res1) + (message "c-parse-state INVALIDITY at %s: %s" + here res1) + (message "Old state:") + (c-replay-parse-state-state)) + (c-record-parse-state-state) - res1)) + res2 ; res1 correct a cascading series of errors ASAP + )) (defun c-toggle-parse-state-debug (&optional arg) (interactive "P") @@ -3411,7 +3442,9 @@ comment at the start of cc-engine.el for more info." (fset 'c-parse-state (symbol-function (if c-debug-parse-state 'c-debug-parse-state 'c-real-parse-state))) - (c-keep-region-active)) + (c-keep-region-active) + (message "c-debug-parse-state %sabled" + (if c-debug-parse-state "en" "dis"))) (when c-debug-parse-state (c-toggle-parse-state-debug 1)) diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 50eaebe4dec..91866278e28 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -1034,7 +1034,10 @@ Note that the style variables are always made local to the buffer." (mapc (lambda (fn) (funcall fn beg end)) c-get-state-before-change-functions)) - )))) + ))) + ;; The following must be done here rather than in `c-after-change' because + ;; newly inserted parens would foul up the invalidation algorithm. + (c-invalidate-state-cache beg)) (defvar c-in-after-change-fontification nil) (make-variable-buffer-local 'c-in-after-change-fontification) @@ -1082,7 +1085,7 @@ Note that the style variables are always made local to the buffer." (c-trim-found-types beg end old-len) ; maybe we don't need all of these. (c-invalidate-sws-region-after beg end) - (c-invalidate-state-cache beg) + ;; (c-invalidate-state-cache beg) ; moved to `c-before-change'. (c-invalidate-find-decl-cache beg) (when c-recognize-<>-arglists -- cgit v1.2.1 From dc310ed0ab37f1176971061362bffc982926bd25 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Wed, 21 Nov 2012 20:47:09 +0000 Subject: Bump CC Mode's version number to 5.32.4. --- lisp/ChangeLog | 2 ++ lisp/progmodes/cc-defs.el | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index e60e9b49043..e0f67188227 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,5 +1,7 @@ 2012-11-21 Alan Mackenzie + * progmodes/cc-defs.el (c-version): Bump to 5.32.4. + Fix bugs in the state cache. Enhance a debugging mechanism. * progmodes/cc-engine.el (c-parse-state-get-strategy): Don't use "brace at column zero" strategy for C++. diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el index 0dc596a472b..17bd2760baa 100644 --- a/lisp/progmodes/cc-defs.el +++ b/lisp/progmodes/cc-defs.el @@ -93,7 +93,7 @@ ;;; Variables also used at compile time. -(defconst c-version "5.32.3" +(defconst c-version "5.32.4" "CC Mode version number.") (defconst c-version-sym (intern c-version)) -- cgit v1.2.1 From cc4c01bd96b929e5b19bcb77eebd40e12930ef06 Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Fri, 23 Nov 2012 09:28:37 +0200 Subject: * lisp/wdired.el: Revert 2012-10-17 change partly and replace it with Patch by Christopher Schmidt . (wdired-finish-edit): Add marks for new file names to `wdired-old-marks'. Restore marks using `dired-mark-remembered' after `revert-buffer'. (wdired-do-renames): Remove calls to `dired-remove-file', `dired-add-file', `dired-add-entry'. Fixes: debbugs:11795 --- lisp/ChangeLog | 10 ++++++++++ lisp/wdired.el | 30 +++++++++++++++--------------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index e0f67188227..6222c9d0237 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,13 @@ +2012-11-23 Juri Linkov + + * wdired.el: Revert 2012-10-17 change partly and replace it with + Patch by Christopher Schmidt . + (wdired-finish-edit): Add marks for new file names to + `wdired-old-marks'. Restore marks using `dired-mark-remembered' + after `revert-buffer'. + (wdired-do-renames): Remove calls to `dired-remove-file', + `dired-add-file', `dired-add-entry'. (Bug#11795) + 2012-11-21 Alan Mackenzie * progmodes/cc-defs.el (c-version): Bump to 5.32.4. diff --git a/lisp/wdired.el b/lisp/wdired.el index 9851b2046d9..5183b5639c3 100644 --- a/lisp/wdired.el +++ b/lisp/wdired.el @@ -399,6 +399,15 @@ non-nil means return old filename." (setq changes t) (if (not file-new) ;empty filename! (push file-old files-deleted) + (when wdired-keep-marker-rename + (let ((mark (cond ((integerp wdired-keep-marker-rename) + wdired-keep-marker-rename) + (wdired-keep-marker-rename + (cdr (assoc file-old wdired-old-marks))) + (t nil)))) + (when mark + (push (cons (substitute-in-file-name file-new) mark) + wdired-old-marks)))) (push (cons file-old (substitute-in-file-name file-new)) files-renamed)))) (forward-line -1))) @@ -416,7 +425,9 @@ non-nil means return old filename." (= (length files-renamed) 1)) (setq dired-directory (cdr (car files-renamed)))) ;; Re-sort the buffer. - (revert-buffer)) + (revert-buffer) + (let ((inhibit-read-only t)) + (dired-mark-remembered wdired-old-marks))) (let ((inhibit-read-only t)) (remove-text-properties (point-min) (point-max) '(old-name nil end-name nil old-link nil @@ -430,8 +441,6 @@ non-nil means return old filename." (set-buffer-modified-p nil) (setq buffer-undo-list nil)) -(declare-function dired-add-entry "dired-aux" (filename &optional marker-char relative)) - (defun wdired-do-renames (renames) "Perform RENAMES in parallel." (let ((residue ()) @@ -473,8 +482,7 @@ non-nil means return old filename." (push (cons tmp file-new) residue)))) (t (setq progress t) - (let* ((file-ori (car rename)) - (old-mark (cdr (assoc file-ori wdired-old-marks)))) + (let ((file-ori (car rename))) (if wdired-use-interactive-rename (wdired-search-and-rename file-ori file-new) ;; If dired-rename-file autoloads dired-aux while @@ -485,20 +493,12 @@ non-nil means return old filename." (condition-case err (let ((dired-backup-overwrite nil)) (dired-rename-file file-ori file-new - overwrite) - (dired-remove-file file-ori) - (dired-add-file - file-new - (cond ((integerp wdired-keep-marker-rename) - wdired-keep-marker-rename) - (wdired-keep-marker-rename old-mark) - (t nil)))) + overwrite)) (error (setq errors (1+ errors)) (dired-log (concat "Rename `" file-ori "' to `" file-new "' failed:\n%s\n") - err) - (dired-add-entry file-ori old-mark))))))))) + err))))))))) errors)) -- cgit v1.2.1 From 8654a41b44c8fe925af2b10378faa09909699240 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 23 Nov 2012 09:54:33 +0200 Subject: Fix pgx in .gdbinit when CHECK_LISP_OBJECT_TYPE is defined. src/.gdbinit (pgx): If the glyph's object is a string, display the pointer to string data, rather than the value of the string object itself (which barfs under CHECK_LISP_OBJECT_TYPE). --- src/.gdbinit | 3 ++- src/ChangeLog | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/.gdbinit b/src/.gdbinit index 952d7392a4c..98ae247b8c5 100644 --- a/src/.gdbinit +++ b/src/.gdbinit @@ -495,7 +495,8 @@ define pgx end xgettype ($g.object) if ($type == Lisp_String) - printf " str=%x[%d]", $g.object, $g.charpos + xgetptr $g.object + printf " str=0x%x[%d]", ((struct Lisp_String *)$ptr)->data, $g.charpos else printf " pos=%d", $g.charpos end diff --git a/src/ChangeLog b/src/ChangeLog index f760adf313f..7460e2c5704 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2012-11-23 Eli Zaretskii + + * .gdbinit (pgx): If the glyph's object is a string, display the + pointer to string data, rather than the value of the string object + itself (which barfs under CHECK_LISP_OBJECT_TYPE). + 2012-11-21 Eli Zaretskii * indent.c (Fvertical_motion): If the starting position is covered -- cgit v1.2.1 From bccffa83747ae14e9a45779be7e8e570f8d70be5 Mon Sep 17 00:00:00 2001 From: Chong Yidong Date: Fri, 23 Nov 2012 15:56:27 +0800 Subject: * faces.el (color-defined-p): Doc fix. Fixes: debbugs:12853 --- lisp/ChangeLog | 4 ++++ lisp/faces.el | 36 ++++++++++++++++++++++++++---------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 6222c9d0237..a020790e4fd 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,7 @@ +2012-11-23 Chong Yidong + + * faces.el (color-defined-p): Doc fix (Bug#12853). + 2012-11-23 Juri Linkov * wdired.el: Revert 2012-10-17 change partly and replace it with diff --git a/lisp/faces.el b/lisp/faces.el index 9e0ca962499..71e8a17f6ef 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -926,13 +926,25 @@ of the default face. Value is FACE." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun read-face-name (prompt &optional default multiple) - "Read a face, defaulting to the face or faces on the char after point. -If it has the property `read-face-name', that overrides the `face' property. -PROMPT should be a string that describes what the caller will do with the face; -it should not end in a space. + "Read a face, defaulting to the face or faces at point. +If the text at point has the property `read-face-name', that +overrides the `face' property for determining the default. + +PROMPT should be a string that describes what the caller will do +with the face; it should not end in a space. + + +This function uses `completing-read-multiple' with \",\" as the +separator character, i.e. + + + + + The optional argument DEFAULT provides the value to display in the minibuffer prompt that is returned if the user just types RET unless DEFAULT is a string (in which case nil is returned). + If MULTIPLE is non-nil, return a list of faces (possibly only one). Otherwise, return a single face." (let ((faceprop (or (get-char-property (point) 'read-face-name) @@ -1689,12 +1701,16 @@ If FRAME is nil, that stands for the selected frame." (declare-function xw-color-defined-p "xfns.c" (color &optional frame)) (defun color-defined-p (color &optional frame) - "Return non-nil if color COLOR is supported on frame FRAME. -If FRAME is omitted or nil, use the selected frame. -If COLOR is the symbol `unspecified' or one of the strings -\"unspecified-fg\" or \"unspecified-bg\", the value is nil." - (if (member color '(unspecified "unspecified-bg" "unspecified-fg")) - nil + "Return non-nil if COLOR is supported on frame FRAME. +COLOR should be a string naming a color (e.g. \"white\"), or a +string specifying a color's RGB components (e.g. \"#ff12ec\"), or +the symbol `unspecified'. + +This function returns nil if COLOR is the symbol `unspecified', +or one of the strings \"unspecified-fg\" or \"unspecified-bg\". + +If FRAME is omitted or nil, use the selected frame." + (unless (member color '(unspecified "unspecified-bg" "unspecified-fg")) (if (member (framep (or frame (selected-frame))) '(x w32 ns)) (xw-color-defined-p color frame) (numberp (tty-color-translate color frame))))) -- cgit v1.2.1 From 61a2a12285951942d007929973f8bdd59f82ea53 Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Fri, 23 Nov 2012 09:59:43 +0200 Subject: * lisp/dired.el (dired-mark): Add optional arg `interactive'. Check for `use-region-p' if `interactive' is non-nil. (dired-unmark, dired-flag-file-deletion): Add optional arg `interactive'. Call `dired-mark' with the arg `interactive'. Fixes: debbugs:10624 --- lisp/ChangeLog | 8 ++++++++ lisp/dired.el | 18 +++++++++--------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index a020790e4fd..eed11358baf 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -2,6 +2,14 @@ * faces.el (color-defined-p): Doc fix (Bug#12853). +2012-11-23 Juri Linkov + + * dired.el (dired-mark): Add optional arg `interactive'. + Check for `use-region-p' if `interactive' is non-nil. + (dired-unmark, dired-flag-file-deletion): Add optional arg + `interactive'. Call `dired-mark' with the arg `interactive'. + (Bug#10624) + 2012-11-23 Juri Linkov * wdired.el: Revert 2012-10-17 change partly and replace it with diff --git a/lisp/dired.el b/lisp/dired.el index 5f7ee48a810..b62b4d1ad08 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -3109,7 +3109,7 @@ argument or confirmation)." (insert dired-marker-char))) (forward-line 1)))) -(defun dired-mark (arg) +(defun dired-mark (arg &optional interactive) "Mark the file at point in the Dired buffer. If the region is active, mark all files in the region. Otherwise, with a prefix arg, mark files on the next ARG lines. @@ -3119,10 +3119,10 @@ If on a subdir headerline, mark all its files except `.' and `..'. Use \\[dired-unmark-all-files] to remove all marks and \\[dired-unmark] on a subdir to remove the marks in this subdir." - (interactive "P") + (interactive (list current-prefix-arg t)) (cond ;; Mark files in the active region. - ((and transient-mark-mode mark-active) + ((and interactive (use-region-p)) (save-excursion (let ((beg (region-beginning)) (end (region-end))) @@ -3139,7 +3139,7 @@ this subdir." (prefix-numeric-value arg) (function (lambda () (delete-char 1) (insert dired-marker-char)))))))) -(defun dired-unmark (arg) +(defun dired-unmark (arg &optional interactive) "Unmark the file at point in the Dired buffer. If the region is active, unmark all files in the region. Otherwise, with a prefix arg, unmark files on the next ARG lines. @@ -3147,11 +3147,11 @@ Otherwise, with a prefix arg, unmark files on the next ARG lines. If looking at a subdir, unmark all its files except `.' and `..'. If the region is active in Transient Mark mode, unmark all files in the active region." - (interactive "P") + (interactive (list current-prefix-arg t)) (let ((dired-marker-char ?\040)) - (dired-mark arg))) + (dired-mark arg interactive))) -(defun dired-flag-file-deletion (arg) +(defun dired-flag-file-deletion (arg &optional interactive) "In Dired, flag the current line's file for deletion. If the region is active, flag all files in the region. Otherwise, with a prefix arg, flag files on the next ARG lines. @@ -3159,9 +3159,9 @@ Otherwise, with a prefix arg, flag files on the next ARG lines. If on a subdir headerline, flag all its files except `.' and `..'. If the region is active in Transient Mark mode, flag all files in the active region." - (interactive "P") + (interactive (list current-prefix-arg t)) (let ((dired-marker-char dired-del-marker)) - (dired-mark arg))) + (dired-mark arg interactive))) (defun dired-unmark-backward (arg) "In Dired, move up lines and remove marks or deletion flags there. -- cgit v1.2.1 From 24becea4a7839adcea1bafd28604b204ff5cb7d6 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 23 Nov 2012 10:27:05 +0200 Subject: Fix cursor display when several display strings follow each other. src/xdisp.c (set_cursor_from_row): Skip step 2 only if point is not between bpos_covered and bpos_max. This fixes cursor display when several display strings follow each other. --- src/ChangeLog | 4 ++++ src/xdisp.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ChangeLog b/src/ChangeLog index 7460e2c5704..88fbf7a99f2 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,9 @@ 2012-11-23 Eli Zaretskii + * xdisp.c (set_cursor_from_row): Skip step 2 only if point is not + between bpos_covered and bpos_max. This fixes cursor display when + several display strings follow each other. + * .gdbinit (pgx): If the glyph's object is a string, display the pointer to string data, rather than the value of the string object itself (which barfs under CHECK_LISP_OBJECT_TYPE). diff --git a/src/xdisp.c b/src/xdisp.c index 85fe9a00f60..4bb744a2f9d 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -14232,7 +14232,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, GLYPH_BEFORE and GLYPH_AFTER. */ if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end) && BUFFERP (glyph->object) && glyph->charpos == pt_old) - && bpos_covered < pt_old) + && !(bpos_max < pt_old && pt_old <= bpos_covered)) { /* An empty line has a single glyph whose OBJECT is zero and whose CHARPOS is the position of a newline on that line. -- cgit v1.2.1 From 90d99fdf02ce6494b7e004936e467da6edd2bf73 Mon Sep 17 00:00:00 2001 From: Chong Yidong Date: Fri, 23 Nov 2012 16:32:43 +0800 Subject: * modes.texi (%-Constructs): Fix statement about mode construct padding. Fixes: debbugs:12866 --- doc/lispref/ChangeLog | 5 +++++ doc/lispref/modes.texi | 15 ++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index 40bd3c2cbbe..23da5634889 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,8 @@ +2012-11-23 Chong Yidong + + * modes.texi (%-Constructs): Fix statement about mode construct + padding (Bug#12866). + 2012-11-21 Stefan Monnier * debugging.texi (Profiling): Make it more clear diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index 0634cddff84..55d838d111e 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -2086,11 +2086,16 @@ specifies addition of text properties. @subsection @code{%}-Constructs in the Mode Line Strings used as mode line constructs can use certain -@code{%}-constructs to substitute various kinds of data. Here is a -list of the defined @code{%}-constructs, and what they mean. In any -construct except @samp{%%}, you can add a decimal integer after the -@samp{%} to specify a minimum field width. If the width is less, the -field is padded with spaces to the right. +@code{%}-constructs to substitute various kinds of data. The +following is a list of the defined @code{%}-constructs, and what they +mean. + + In any construct except @samp{%%}, you can add a decimal integer +after the @samp{%} to specify a minimum field width. If the width is +less, the field is padded to that width. Purely numeric constructs +(@samp{c}, @samp{i}, @samp{I}, and @samp{l}) are padded by inserting +spaces to the left, and others are padded by inserting spaces to the +right. @table @code @item %b -- cgit v1.2.1 From 0d4bb04f1a82acacdcfffa0bb1a42393365608db Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Fri, 23 Nov 2012 15:39:07 +0100 Subject: Correct and reword recent changes to window.texi. * windows.texi (Basic Windows): Fix typo. (Windows and Frames): Fix example. Move description of window-in-direction here. (Recombining Windows): Fix example. (Buffers and Windows): Fix description of replace-buffer-in-windows. (Switching Buffers): Reword. (Display Action Functions): Minor adjustments. (Choosing Window Options): Minor fixes. (Window History): Minor rewording. (Dedicated Windows): Correct and reword part describing how dedicatedness affects functions removing buffers or windows. * buffers.texi (The Buffer List): Fix description of bury-buffer. --- doc/lispref/ChangeLog | 17 +++ doc/lispref/buffers.texi | 20 ++-- doc/lispref/windows.texi | 267 ++++++++++++++++++++++++----------------------- 3 files changed, 165 insertions(+), 139 deletions(-) diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index 23da5634889..adb52dc7f2b 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,20 @@ +2012-11-23 Martin Rudalics + + * windows.texi (Basic Windows): Fix typo. + (Windows and Frames): Fix example. Move description of + window-in-direction here. + (Recombining Windows): Fix example. + (Buffers and Windows): Fix description of + replace-buffer-in-windows. + (Switching Buffers): Reword. + (Display Action Functions): Minor adjustments. + (Choosing Window Options): Minor fixes. + (Window History): Minor rewording. + (Dedicated Windows): Correct and reword part describing how + dedicatedness affects functions removing buffers or windows. + * buffers.texi (The Buffer List): Fix description of + bury-buffer. + 2012-11-23 Chong Yidong * modes.texi (%-Constructs): Fix statement about mode construct diff --git a/doc/lispref/buffers.texi b/doc/lispref/buffers.texi index 4a556895de7..6462788b34e 100644 --- a/doc/lispref/buffers.texi +++ b/doc/lispref/buffers.texi @@ -886,7 +886,7 @@ This buffer therefore becomes the least desirable candidate for @code{other-buffer} to return. The argument can be either a buffer itself or the name of one. -This functions operates on each frame's @code{buffer-list} parameter as +This function operates on each frame's @code{buffer-list} parameter as well as the fundamental buffer list; therefore, the buffer that you bury will come last in the value of @code{(buffer-list @var{frame})} and in the value of @code{(buffer-list)}. In addition, it also puts the buffer @@ -896,15 +896,15 @@ History}) provided it is shown in that window. If @var{buffer-or-name} is @code{nil} or omitted, this means to bury the current buffer. In addition, if the current buffer is displayed in the selected window, this makes sure that the window is either deleted or -another buffer is shown in it. More precisely, if the window is -dedicated (@pxref{Dedicated Windows}) and there are other windows on its -frame, the window is deleted. If the window is both dedicated and the -only window on its frame's terminal, the function specified by -@code{frame-auto-hide-function} (@pxref{Quitting Windows}) will deal -with the window. If the window is not dedicated to its buffer, it calls -@code{switch-to-prev-buffer} (@pxref{Window History}) to show another -buffer in that window. If @var{buffer-or-name} is displayed in some -other window, it remains displayed there. +another buffer is shown in it. More precisely, if the selected window +is dedicated (@pxref{Dedicated Windows}) and there are other windows on +its frame, the window is deleted. If it is the only window on its frame +and that frame is not the only frame on its terminal, the frame is +``dismissed'' by calling the function specified by +@code{frame-auto-hide-function} (@pxref{Quitting Windows}). Otherwise, +it calls @code{switch-to-prev-buffer} (@pxref{Window History}) to show +another buffer in that window. If @var{buffer-or-name} is displayed in +some other window, it remains displayed there. To replace a buffer in all the windows that display it, use @code{replace-buffer-in-windows}, @xref{Buffers and Windows}. diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 46b31ef0d9f..224c4736c92 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -51,9 +51,9 @@ is displayed in windows. @section Basic Concepts of Emacs Windows @cindex window -A @dfn{window} is a area of the screen that is used to display a -buffer (@pxref{Buffers}). In Emacs Lisp, windows are represented by a -special Lisp object type. +A @dfn{window} is an area of the screen that is used to display a buffer +(@pxref{Buffers}). In Emacs Lisp, windows are represented by a special +Lisp object type. @cindex multiple windows Windows are grouped into frames (@pxref{Frames}). Each frame @@ -247,12 +247,12 @@ following example: @end smallexample @noindent -The root window of this frame is an internal window, @code{W1}. Its +The root window of this frame is an internal window, @var{W1}. Its child windows form a horizontal combination, consisting of the live -window @code{W2} and the internal window @code{W3}. The child windows -of @code{W3} form a vertical combination, consisting of the live -windows @code{W4} and @code{W5}. Hence, the live windows in this -window tree are @code{W2} @code{W4}, and @code{W5}. +window @var{W2} and the internal window @var{W3}. The child windows +of @var{W3} form a vertical combination, consisting of the live +windows @var{W4} and @var{W5}. Hence, the live windows in this +window tree are @var{W2} @var{W4}, and @var{W5}. The following functions can be used to retrieve a child window of an internal window, and the siblings of a child window. @@ -308,8 +308,8 @@ The functions @code{window-next-sibling} and and previous window, respectively, in the cyclic ordering of windows (@pxref{Cyclic Window Ordering}). - You can use the following functions to find the first live window on -a frame, and to retrieve the entire window tree of a frame: + You can use the following functions to find the first live window on a +frame and the window nearest to a given window. @defun frame-first-window &optional frame-or-window This function returns the live window at the upper left corner of the @@ -318,9 +318,32 @@ frame specified by @var{frame-or-window}. The argument to the selected frame. If @var{frame-or-window} specifies a window, this function returns the first window on that window's frame. Under the assumption that the frame from our canonical example is selected -@code{(frame-first-window)} returns @code{W2}. +@code{(frame-first-window)} returns @var{W2}. @end defun +@cindex window in direction +@defun window-in-direction direction &optional window ignore +This function returns the nearest live window in direction +@var{direction} as seen from the position of @code{window-point} in +window @var{window}. The argument @var{direction} must be one of +@code{above}, @code{below}, @code{left} or @code{right}. The optional +argument @var{window} must denote a live window and defaults to the +selected one. + +This function does not return a window whose @code{no-other-window} +parameter is non-@code{nil} (@pxref{Window Parameters}). If the nearest +window's @code{no-other-window} parameter is non-@code{nil}, this +function tries to find another window in the indicated direction whose +@code{no-other-window} parameter is @code{nil}. If the optional +argument @var{ignore} is non-@code{nil}, a window may be returned even +if its @code{no-other-window} parameter is non-@code{nil}. + +If it doesn't find a suitable window, this function returns @code{nil}. +@end defun + +The following function allows to retrieve the entire window tree of a +frame: + @defun window-tree &optional frame This function returns a list representing the window tree for frame @var{frame}. If @var{frame} is omitted or @code{nil}, it defaults to @@ -925,9 +948,9 @@ are the opposite of what they are in those other functions. @node Recombining Windows @section Recombining Windows -When deleting the last sibling of a window @code{W}, its parent window -is deleted too, with @code{W} replacing it in the window tree. This -means that @code{W} must be recombined with its parent's siblings to +When deleting the last sibling of a window @var{W}, its parent window +is deleted too, with @var{W} replacing it in the window tree. This +means that @var{W} must be recombined with its parent's siblings to form a new window combination (@pxref{Windows and Frames}). In some occasions, deleting a live window may even entail the deletion of two internal windows. @@ -952,20 +975,20 @@ internal windows. @end smallexample @noindent -Deleting @code{W5} in this configuration normally causes the deletion of -@code{W3} and @code{W4}. The remaining live windows @code{W2}, -@code{W6} and @code{W7} are recombined to form a new horizontal -combination with parent @code{W1}. +Deleting @var{W5} in this configuration normally causes the deletion of +@var{W3} and @var{W4}. The remaining live windows @var{W2}, +@var{W6} and @var{W7} are recombined to form a new horizontal +combination with parent @var{W1}. Sometimes, however, it makes sense to not delete a parent window like -@code{W4}. In particular, a parent window should not be removed when it +@var{W4}. In particular, a parent window should not be removed when it was used to preserve a combination embedded in a combination of the same type. Such embeddings make sense to assure that when you split a window and subsequently delete the new window, Emacs reestablishes the layout of the associated frame as it existed before the splitting. - Consider a scenario starting with two live windows @code{W2} and -@code{W3} and their parent @code{W1}. + Consider a scenario starting with two live windows @var{W2} and +@var{W3} and their parent @var{W1}. @smallexample @group @@ -988,7 +1011,7 @@ of the associated frame as it existed before the splitting. @end smallexample @noindent -Split @code{W2} to make a new window @code{W4} as follows. +Split @var{W2} to make a new window @var{W4} as follows. @smallexample @group @@ -1013,8 +1036,8 @@ Split @code{W2} to make a new window @code{W4} as follows. @noindent Now, when enlarging a window vertically, Emacs tries to obtain the corresponding space from its lower sibling, provided such a window -exists. In our scenario, enlarging @code{W4} will steal space from -@code{W3}. +exists. In our scenario, enlarging @var{W4} will steal space from +@var{W3}. @smallexample @group @@ -1037,8 +1060,8 @@ exists. In our scenario, enlarging @code{W4} will steal space from @end smallexample @noindent -Deleting @code{W4} will now give its entire space to @code{W2}, -including the space earlier stolen from @code{W3}. +Deleting @var{W4} will now give its entire space to @var{W2}, +including the space earlier stolen from @var{W3}. @smallexample @group @@ -1061,12 +1084,12 @@ including the space earlier stolen from @code{W3}. @end smallexample @noindent -This can be counterintutive, in particular if @code{W4} were used for +This can be counterintutive, in particular if @var{W4} were used for displaying a buffer only temporarily (@pxref{Temporary Displays}), and you want to continue working with the initial layout. The behavior can be fixed by making a new parent window when splitting -@code{W2}. The variable described next allows to do that. +@var{W2}. The variable described next allows to do that. @defopt window-combination-limit This variable controls whether splitting a window shall make a new @@ -1108,7 +1131,7 @@ internal window. This affects how the window tree is rearranged when the child windows are deleted (see below). @end defopt - If @code{window-combination-limit} is @code{t}, splitting @code{W2} in + If @code{window-combination-limit} is @code{t}, splitting @var{W2} in the initial configuration of our scenario would have produced this: @smallexample @@ -1132,12 +1155,12 @@ the initial configuration of our scenario would have produced this: @end smallexample @noindent -A new internal window @code{W5} has been created; its children are -@code{W2} and the new live window @code{W4}. Now, @code{W2} is the only -sibling of @code{W4}, so enlarging @code{W4} will try to shrink -@code{W2}, leaving @code{W3} unaffected. Observe that @code{W5} +A new internal window @var{W5} has been created; its children are +@var{W2} and the new live window @var{W4}. Now, @var{W2} is the only +sibling of @var{W4}, so enlarging @var{W4} will try to shrink +@var{W2}, leaving @var{W3} unaffected. Observe that @var{W5} represents a vertical combination of two windows embedded in the -vertical combination @code{W1}. +vertical combination @var{W1}. @cindex window combination limit @defun set-window-combination-limit window limit @@ -1162,9 +1185,9 @@ windows of @var{window} are never automatically recombined with its siblings. If, in the configuration shown at the beginning of this section, the -combination limit of @code{W4} (the parent window of @code{W6} and -@code{W7}) is @code{t}, deleting @code{W5} will not implicitly delete -@code{W4} too. +combination limit of @var{W4} (the parent window of @var{W6} and +@var{W7}) is @code{t}, deleting @var{W5} will not implicitly delete +@var{W4} too. @end defun Alternatively, the problems sketched above can be avoided by always @@ -1215,7 +1238,7 @@ the following frame layout. @noindent If @code{window-combination-resize} is @code{nil}, splitting window -@code{W3} leaves the size of @code{W2} unchanged: +@var{W3} leaves the size of @var{W2} unchanged: @smallexample @group @@ -1238,7 +1261,7 @@ If @code{window-combination-resize} is @code{nil}, splitting window @end smallexample @noindent -If @code{window-combination-resize} is @code{t}, splitting @code{W3} +If @code{window-combination-resize} is @code{t}, splitting @var{W3} instead leaves all three live windows with approximately the same height: @@ -1263,7 +1286,7 @@ height: @end smallexample @noindent -Deleting any of the live windows @code{W2}, @code{W3} or @code{W4} will +Deleting any of the live windows @var{W2}, @var{W3} or @var{W4} will distribute its space proportionally among the two remaining live windows. @@ -1510,25 +1533,6 @@ windows to search, and have the same meanings as in @code{next-window}. @end defun -@cindex window in direction -@defun window-in-direction direction &optional window ignore -This function returns the nearest window in direction @var{direction} as -seen from the position of @code{window-point} in window @var{window}. -The argument @var{direction} must be one of @code{above}, @code{below}, -@code{left} or @code{right}. The optional argument @var{window} must -denote a live window and defaults to the selected one. - -This function does not return a window whose @code{no-other-window} -parameter is non-@code{nil}. If the nearest window's -@code{no-other-window} parameter is non-@code{nil}, this function tries -to find another window in the indicated direction whose -@code{no-other-window} parameter is @code{nil}. If the optional -argument @var{ignore} is non-@code{nil}, a window may be returned even -if its @code{no-other-window} parameter is non-@code{nil}. - -If it doesn't find a suitable window, this function returns @code{nil}. -@end defun - @node Buffers and Windows @section Buffers and Windows @@ -1631,28 +1635,30 @@ behave exactly like in @code{get-buffer-window}. @deffn Command replace-buffer-in-windows &optional buffer-or-name This command replaces @var{buffer-or-name} with some other buffer, in -all windows displaying it. @var{buffer-or-name} should be a buffer, -or the name of an existing buffer; if omitted or @code{nil}, it -defaults to the current buffer. +all windows displaying it. @var{buffer-or-name} should be a buffer, or +the name of an existing buffer; if omitted or @code{nil}, it defaults to +the current buffer. The replacement buffer in each window is chosen via @code{switch-to-prev-buffer} (@pxref{Window History}). Any dedicated -window displaying @var{buffer-or-name} is deleted (@pxref{Dedicated -Windows}), unless it is the only window on its frame---if it is the -only window, and that frame is not the only frame on its terminal, the -frame is ``dismissed'' by calling the function specified by -@code{frame-auto-hide-function} (@pxref{Quitting Windows}). If the -dedicated window is the only window on the only frame on its terminal, -the buffer is replaced anyway. +window displaying @var{buffer-or-name} is deleted if possible +(@pxref{Dedicated Windows}). If such a window is the only window on its +frame and there are other frames on the same terminal, the frame is +deleted as well. If the dedicated window is the only window on the only +frame on its terminal, the buffer is replaced anyway. @end deffn + @node Switching Buffers @section Switching to a Buffer in a Window @cindex switching to a buffer @cindex displaying a buffer - This section describes high-level functions for switching to a -specified buffer in some window. +This section describes high-level functions for switching to a specified +buffer in some window. In general, ``switching to a buffer'' means to +(1) show the buffer in some window, (2) make that window the selected +window (and its frame the selected frame), and (3) make the buffer the +current buffer. Do @emph{not} use these functions to make a buffer temporarily current just so a Lisp program can access or modify it. They have @@ -1664,9 +1670,9 @@ to make a buffer current to modify it in Lisp, use @deffn Command switch-to-buffer buffer-or-name &optional norecord force-same-window This command attempts to display @var{buffer-or-name} in the selected -window, and makes it the current buffer. It is often used -interactively (as the binding of @kbd{C-x b}), as well as in Lisp -programs. The return value is the buffer switched to. +window and make it the current buffer. It is often used interactively +(as the binding of @kbd{C-x b}), as well as in Lisp programs. The +return value is the buffer switched to. If @var{buffer-or-name} is @code{nil}, it defaults to the buffer returned by @code{other-buffer} (@pxref{The Buffer List}). If @@ -1690,9 +1696,8 @@ normally tries to display the buffer in some other window, by invoking instead. @end deffn -By default, @code{switch-to-buffer} sets @code{window-point} of the -window used to the buffer's position of @code{point}. This behavior can -be tuned using the following option. +By default, @code{switch-to-buffer} shows the buffer at its position of +@code{point}. This behavior can be tuned using the following option. @defopt switch-to-buffer-preserve-window-point If this variable is @code{nil}, @code{switch-to-buffer} displays the @@ -1710,13 +1715,13 @@ selected window or never appeared in it before, or if buffer. @end defopt -The next two functions are similar to @code{switch-to-buffer}, except -for the described features. +The next two commands are similar to @code{switch-to-buffer}, except for +the described features. @deffn Command switch-to-buffer-other-window buffer-or-name &optional norecord -This function makes the buffer specified by @var{buffer-or-name} -current and displays it in some window other than the selected window. -It uses the function @code{pop-to-buffer} internally (see below). +This function displays the buffer specified by @var{buffer-or-name} in +some window other than the selected window. It uses the function +@code{pop-to-buffer} internally (see below). If the selected window already displays the specified buffer, it continues to do so, but another window is nonetheless found to display @@ -1727,9 +1732,9 @@ meanings as in @code{switch-to-buffer}. @end deffn @deffn Command switch-to-buffer-other-frame buffer-or-name &optional norecord -This function makes the buffer specified by @var{buffer-or-name} -current and displays it, usually in a new frame. It uses the function -@code{pop-to-buffer} (see below). +This function displays the buffer specified by @var{buffer-or-name} in a +new frame. It uses the function @code{pop-to-buffer} internally (see +below). If the specified buffer is already displayed in another window, in any frame on the current terminal, this switches to that window instead of @@ -1987,8 +1992,8 @@ of the window; its return value is ignored. @end itemize This function can fail if no window splitting can be performed for some -reason (e.g. if there is just one frame and it has an -@code{unsplittable} frame parameter; @pxref{Buffer Parameters}). +reason (e.g. if the selected frame has an @code{unsplittable} frame +parameter; @pxref{Buffer Parameters}). @end defun @defun display-buffer-below-selected buffer alist @@ -2035,14 +2040,15 @@ example. @noindent Evaluating the form above will cause @code{display-buffer} to proceed as -follows: If `*foo*' already appears on a visible or iconified frame, it -will reuse its window. Otherwise, it will try to pop up a new window -or, if that is impossible, a new frame. If all these steps fail, it -will proceed using whatever @code{display-buffer-base-action} and +follows: If a buffer called *foo* already appears on a visible or +iconified frame, it will reuse its window. Otherwise, it will try to +pop up a new window or, if that is impossible, a new frame and show the +buffer there. If all these steps fail, it will proceed using whatever +@code{display-buffer-base-action} and @code{display-buffer-fallback-action} prescribe. Furthermore, @code{display-buffer} will try to adjust a reused window -(provided `*foo*' was put by @code{display-buffer} there before) or a +(provided *foo* was put by @code{display-buffer} there before) or a popped-up window as follows: If the window is part of a vertical combination, it will set its height to ten lines. Note that if, instead of the number ``10'', we specified the function @@ -2077,10 +2083,10 @@ and @code{split-width-threshold} (@pxref{Choosing Window Options}). @end example @noindent -Evaluating this form will cause @code{display-buffer} to first try -reusing a window showing @code{*foo*} on the selected frame. -If no such window exists, it will try to split the selected window or, -if that is impossible, use the window below the selected window. +This form will have @code{display-buffer} first try reusing a window +that shows *foo* on the selected frame. If there's no such window, it +will try to split the selected window or, if that is impossible, use the +window below the selected window. If there's no window below the selected one, or the window below the selected one is dedicated to its buffer, @code{display-buffer} will @@ -2119,8 +2125,8 @@ make a new window for displaying a buffer. It is used by the the window (@pxref{Display Action Functions}). The default value is @code{split-window-sensibly}, which is documented -below. The value must be a function that takes one argument, a -window, and return either a new window (which is used to display the +below. The value must be a function that takes one argument, a window, +and return either a new window (which will be used to display the desired buffer) or @code{nil} (which means the splitting failed). @end defopt @@ -2198,15 +2204,15 @@ Parameters}), which is used by the default function in @defopt same-window-buffer-names A list of buffer names for buffers that should be displayed in the selected window. If a buffer's name is in this list, -@code{display-buffer} handles the buffer by switching to it in the -selected window. +@code{display-buffer} handles the buffer by showing it in the selected +window. @end defopt @defopt same-window-regexps A list of regular expressions that specify buffers that should be displayed in the selected window. If the buffer's name matches any of the regular expressions in this list, @code{display-buffer} handles the -buffer by switching to it in the selected window. +buffer by showing it in the selected window. @end defopt @defun same-window-p buffer-name @@ -2219,22 +2225,23 @@ put it in the selected window. @section Window History @cindex window history -Each window remembers the buffers it has previously displayed, and the order -in which these buffers were removed from it. This history is used, -for example, by @code{replace-buffer-in-windows} (@pxref{Buffers and -Windows}). This list is automatically maintained by Emacs, but you can -use the following functions to explicitly inspect or alter it: +Each window remembers in a list the buffers it has previously displayed, +and the order in which these buffers were removed from it. This history +is used, for example, by @code{replace-buffer-in-windows} +(@pxref{Buffers and Windows}). The list is automatically maintained by +Emacs, but you can use the following functions to explicitly inspect or +alter it: @defun window-prev-buffers &optional window This function returns a list specifying the previous contents of -@var{window}, which should be a live window and defaults to the -selected window. +@var{window}. The optional argument @var{window} should be a live +window and defaults to the selected one. Each list element has the form @code{(@var{buffer} @var{window-start} @var{window-pos})}, where @var{buffer} is a buffer previously shown in the window, @var{window-start} is the window start position when that buffer was last shown, and @var{window-pos} is the point position when -that buffer was last shown. +that buffer was last shown in @var{window}. The list is ordered so that earlier elements correspond to more recently-shown buffers, and the first element usually corresponds to the @@ -2331,29 +2338,31 @@ Functions for displaying a buffer can be told to not use specific windows by marking these windows as @dfn{dedicated} to their buffers. @code{display-buffer} (@pxref{Choosing Window}) never uses a dedicated window for displaying another buffer in it. @code{get-lru-window} and -@code{get-largest-window} (@pxref{Selecting Windows}) do not consider -dedicated windows as candidates when their @var{dedicated} argument is -non-@code{nil}. The behavior of @code{set-window-buffer} +@code{get-largest-window} (@pxref{Cyclic Window Ordering}) do not +consider dedicated windows as candidates when their @var{dedicated} +argument is non-@code{nil}. The behavior of @code{set-window-buffer} (@pxref{Buffers and Windows}) with respect to dedicated windows is slightly different, see below. -When @code{delete-windows-on} (@pxref{Deleting Windows}) wants to -delete a dedicated window and that window is the only window on its -frame, it deletes the window's frame too, provided there are other -frames left. @code{replace-buffer-in-windows} (@pxref{Switching -Buffers}) tries to delete all dedicated windows showing its buffer -argument. When such a window is the only window on its frame, that -frame is deleted, provided there are other frames left. If there are -no more frames left, some other buffer is displayed in the window, and -the window is marked as non-dedicated. - -When you kill a buffer (@pxref{Killing Buffers}) displayed in a -dedicated window, any such window usually gets deleted too, since -@code{kill-buffer} calls @code{replace-buffer-in-windows} for cleaning -up windows. Burying a buffer (@pxref{The Buffer List}) deletes the -selected window if it is dedicated to that buffer. If, however, that -window is the only window on its frame, @code{bury-buffer} displays -another buffer in it and iconifies the frame. + Functions supposed to remove a buffer from a window or a window from +a frame can behave specially when a window they operate on is dedicated. +We will distinguish three basic cases, namely where (1) the window is +not the only window on its frame, (2) the window is the only window on +its frame but there are other frames on the same terminal left, and (3) +the window is the only window on the only frame on the same terminal. + + In particular, @code{delete-windows-on} (@pxref{Deleting Windows}) +handles case (2) by deleting the associated frame and case (3) by +showing another buffer in that frame's only window. The function +@code{replace-buffer-in-windows} (@pxref{Buffers and Windows}) which is +called when a buffer gets killed, deletes the window in case (1) and +behaves like @code{delete-windows-on} otherwise. + + When @code{bury-buffer} (@pxref{The Buffer List}) operates on the +selected window (which shows the buffer that shall be buried), it +handles case (2) by calling @code{frame-auto-hide-function} +(@pxref{Quitting Windows}) to deal with the selected frame. The other +two cases are handled as with @code{replace-buffer-in-windows}. @defun window-dedicated-p &optional window This function returns non-@code{nil} if @var{window} is dedicated to its -- cgit v1.2.1 From 977f932513ce1d8ee73eafb73e39d51774021fab Mon Sep 17 00:00:00 2001 From: Wolfgang Jenkner Date: Fri, 23 Nov 2012 18:41:01 +0100 Subject: lisp/image-mode.el (image-transform-check-size): Use assertions only for images of type imagemagick. Otherwise no error, image-transform-fit-to-{width,height} is silently ignored, as before. Doc fix. --- lisp/ChangeLog | 8 ++++++++ lisp/image-mode.el | 10 ++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index eed11358baf..be04ad733f0 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,11 @@ +2012-11-23 Wolfgang Jenkner + + * image-mode.el (image-transform-check-size): Use assertions only + for images of type imagemagick. + + Otherwise no error, image-transform-fit-to-{width,height} is + silently ignored, as before. Doc fix. + 2012-11-23 Chong Yidong * faces.el (color-defined-p): Doc fix (Bug#12853). diff --git a/lisp/image-mode.el b/lisp/image-mode.el index 4ac62fbb6fc..0e91567a29a 100644 --- a/lisp/image-mode.el +++ b/lisp/image-mode.el @@ -746,8 +746,14 @@ close to a multiple of 90, see `image-transform-right-angle-fudge'." h))))) (defun image-transform-check-size () - "Check that the image exactly fits the width/height of the window." - (unless (numberp image-transform-resize) + "Check that the image exactly fits the width/height of the window. + +Do this for an image of type `imagemagick' to make sure that the +elisp code matches the way ImageMagick computes the bounding box +of a rotated image." + (when (and (not (numberp image-transform-resize)) + (boundp 'image-type) + (eq image-type 'imagemagick)) (let ((size (image-display-size (image-get-display-property) t))) (cond ((eq image-transform-resize 'fit-width) (cl-assert (= (car size) -- cgit v1.2.1 From 002c019c34eeb1cad4ce8f5ae721b1cdf22f0946 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Fri, 23 Nov 2012 16:49:13 -0500 Subject: * lisp/emacs-lisp/bytecomp.el (byte-compile-file): Setup default value for lexical-binding. Fixes: debbugs:12938 --- lisp/ChangeLog | 13 +++++++++---- lisp/emacs-lisp/bytecomp.el | 3 +++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index be04ad733f0..431f45c3695 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,8 @@ +2012-11-23 Stefan Monnier + + * emacs-lisp/bytecomp.el (byte-compile-file): Setup default value for + lexical-binding (bug#12938). + 2012-11-23 Wolfgang Jenkner * image-mode.el (image-transform-check-size): Use assertions only @@ -43,14 +48,14 @@ (c-debug-parse-state): Call the above new function. (c-toggle-parse-state-debug): Output a confirmatory message. - * progmodes/cc-mode.el (c-before-change, c-after-change): Call - c-invalidate-state-cache from `c-before-change' instead of + * progmodes/cc-mode.el (c-before-change, c-after-change): + Call c-invalidate-state-cache from `c-before-change' instead of `c-after-change'. 2012-11-20 Daniel Colascione - * term/w32-win.el (cygwin-convert-path-from-windows): Accomodate - rename of cygwin_convert_path* to cygwin_convert_file_name*. + * term/w32-win.el (cygwin-convert-path-from-windows): + Accomodate rename of cygwin_convert_path* to cygwin_convert_file_name*. This change is a backport from trunk. 2012-11-20 Eli Zaretskii diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 7534ce5eaca..df6a79d5196 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -1745,6 +1745,9 @@ The value is non-nil if there were no errors, nil if errors." ;; There may be a file local variable setting (bug#10419). (setq buffer-read-only nil filename buffer-file-name)) + ;; Don't inherit lexical-binding from caller (bug#12938). + (unless (local-variable-p 'lexical-binding) + (setq-local lexical-binding nil)) ;; Set the default directory, in case an eval-when-compile uses it. (setq default-directory (file-name-directory filename))) ;; Check if the file's local variables explicitly specify not to -- cgit v1.2.1 From 6d4e8f62e93b575a1da2cd2b4abeb9dce56e1e52 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 23 Nov 2012 14:20:31 -0800 Subject: Fix a race condition with glib (Bug#8855). This is a backport from the trunk, consisting of: 2012-11-17 Eli Zaretskii * nt/inc/sys/wait.h: New file, with prototype of waitpid and definitions of macros it needs. * nt/inc/ms-w32.h (wait): Don't define, 'wait' is not used anymore. (sys_wait): Remove prototype. * nt/config.nt (HAVE_SYS_WAIT_H): Define to 1. * src/w32proc.c (create_child): Don't clip the PID of the child process to fit into an Emacs integer, as this is no longer a restriction. (waitpid): Rename from sys_wait. Emulate a Posix 'waitpid' by reaping only the process specified by PID argument, if that is positive. Use PID instead of dead_child to know which process to reap. Wait for the child to die only if WNOHANG is not in OPTIONS. (sys_select): Don't set dead_child. * src/sysdep.c (wait_for_termination_1): Remove the WINDOWSNT portion, as it is no longer needed. * src/process.c (waitpid, WUNTRACED) [!WNOHANG]: Remove definitions, no longer needed. (record_child_status_change): Remove the setting of record_at_most_one_child for the !WNOHANG case. 2012-11-03 Paul Eggert Fix a race condition that causes Emacs to mess up glib (Bug#8855). This is a backport from the trunk. The symptom is a diagnostic "GLib-WARNING **: In call to g_spawn_sync(), exit status of a child process was requested but SIGCHLD action was set to SIG_IGN and ECHILD was received by waitpid(), so exit status can't be returned." The diagnostic is partly wrong, as the SIGCHLD action is not set to SIG_IGN. The real bug is a race condition between Emacs and glib: Emacs does a waitpid (-1, ...) and reaps glib's subprocess by mistake, so that glib can't find it. Work around the bug by invoking waitpid only on subprocesses that Emacs itself creates. * src/process.c (create_process, record_child_status_change): Don't use special value -1 in pid field, as the caller now must know the pid rather than having the callee infer it. The inference was sometimes incorrect anyway, due to another race. (create_process): Set new 'alive' member if child is created. (process_status_retrieved): New function. (record_child_status_change): Use it. Accept negative 1st argument, which means to wait for the processes that Emacs already knows about. Move special-case code for DOS_NT (which lacks WNOHANG) here, from caller. Keep track of processes that have already been waited for, by testing and clearing new 'alive' member. (CAN_HANDLE_MULTIPLE_CHILDREN): Remove, as record_child_status_change now does this internally. (handle_child_signal): Let record_child_status_change do all the work, since we do not want to reap all exited child processes, only the child processes that Emacs itself created. * src/process.h (Lisp_Process): New boolean member 'alive'. --- nt/ChangeLog | 13 ++++ nt/config.nt | 2 +- nt/inc/ms-w32.h | 3 - nt/inc/sys/wait.h | 33 ++++++++++ src/ChangeLog | 57 ++++++++++++++++ src/process.c | 191 +++++++++++++++++++++++++----------------------------- src/process.h | 3 + src/sysdep.c | 7 +- src/w32proc.c | 127 +++++++++++++++++++++++++----------- 9 files changed, 287 insertions(+), 149 deletions(-) create mode 100644 nt/inc/sys/wait.h diff --git a/nt/ChangeLog b/nt/ChangeLog index f11f1fc5fc5..b4537de0d4f 100644 --- a/nt/ChangeLog +++ b/nt/ChangeLog @@ -1,3 +1,16 @@ +2012-11-23 Paul Eggert + + Fix a race condition with glib (Bug#8855). + This is a backport from the trunk, consisting of: + + 2012-11-17 Eli Zaretskii + + * inc/sys/wait.h: New file, with prototype of waitpid and + definitions of macros it needs. + * inc/ms-w32.h (wait): Don't define, 'wait' is not used anymore. + (sys_wait): Remove prototype. + * config.nt (HAVE_SYS_WAIT_H): Define to 1. + 2012-11-20 Eli Zaretskii * nmake.defs: Use !if, not !ifdef. See diff --git a/nt/config.nt b/nt/config.nt index ed1cddf1e12..7e82283b41a 100644 --- a/nt/config.nt +++ b/nt/config.nt @@ -963,7 +963,7 @@ along with GNU Emacs. If not, see . */ #undef HAVE_SYS_VLIMIT_H /* Define to 1 if you have that is POSIX.1 compatible. */ -#undef HAVE_SYS_WAIT_H +#define HAVE_SYS_WAIT_H 1 /* Define to 1 if you have the header file. */ #undef HAVE_TERM_H diff --git a/nt/inc/ms-w32.h b/nt/inc/ms-w32.h index dd2ae781cb8..a9a3049f9b0 100644 --- a/nt/inc/ms-w32.h +++ b/nt/inc/ms-w32.h @@ -185,15 +185,12 @@ extern char *getenv (); /* Subprocess calls that are emulated. */ #define spawnve sys_spawnve -#define wait sys_wait #define kill sys_kill #define signal sys_signal /* Internal signals. */ #define emacs_raise(sig) emacs_abort() -extern int sys_wait (int *); - /* termcap.c calls that are emulated. */ #define tputs sys_tputs #define tgetstr sys_tgetstr diff --git a/nt/inc/sys/wait.h b/nt/inc/sys/wait.h new file mode 100644 index 00000000000..8d890c9e175 --- /dev/null +++ b/nt/inc/sys/wait.h @@ -0,0 +1,33 @@ +/* A limited emulation of sys/wait.h on Posix systems. + +Copyright (C) 2012 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs 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 3 of the License, 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. + +You should have received a copy of the GNU General Public License +along with GNU Emacs. If not, see . */ + +#ifndef INC_SYS_WAIT_H_ +#define INC_SYS_WAIT_H_ + +#define WNOHANG 1 +#define WUNTRACED 2 +#define WSTOPPED 2 /* same as WUNTRACED */ +#define WEXITED 4 +#define WCONTINUED 8 + +/* The various WIF* macros are defined in src/syswait.h. */ + +extern pid_t waitpid (pid_t, int *, int); + +#endif /* INC_SYS_WAIT_H_ */ diff --git a/src/ChangeLog b/src/ChangeLog index 88fbf7a99f2..655eb1595c0 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,60 @@ +2012-11-23 Paul Eggert + + Fix a race condition with glib (Bug#8855). + This is a backport from the trunk, consisting of: + + 2012-11-17 Eli Zaretskii + + * w32proc.c (create_child): Don't clip the PID of the child + process to fit into an Emacs integer, as this is no longer a + restriction. + (waitpid): Rename from sys_wait. Emulate a Posix 'waitpid' by + reaping only the process specified by PID argument, if that is + positive. Use PID instead of dead_child to know which process to + reap. Wait for the child to die only if WNOHANG is not in + OPTIONS. + (sys_select): Don't set dead_child. + + * sysdep.c (wait_for_termination_1): Remove the WINDOWSNT portion, + as it is no longer needed. + + * process.c (waitpid, WUNTRACED) [!WNOHANG]: Remove definitions, + no longer needed. + (record_child_status_change): Remove the setting of + record_at_most_one_child for the !WNOHANG case. + + 2012-11-03 Paul Eggert + + Fix a race condition that causes Emacs to mess up glib (Bug#8855). + This is a backport from the trunk. + The symptom is a diagnostic "GLib-WARNING **: In call to + g_spawn_sync(), exit status of a child process was requested but + SIGCHLD action was set to SIG_IGN and ECHILD was received by + waitpid(), so exit status can't be returned." The diagnostic + is partly wrong, as the SIGCHLD action is not set to SIG_IGN. + The real bug is a race condition between Emacs and glib: Emacs + does a waitpid (-1, ...) and reaps glib's subprocess by mistake, + so that glib can't find it. Work around the bug by invoking + waitpid only on subprocesses that Emacs itself creates. + * process.c (create_process, record_child_status_change): + Don't use special value -1 in pid field, as the caller now must + know the pid rather than having the callee infer it. The + inference was sometimes incorrect anyway, due to another race. + (create_process): Set new 'alive' member if child is created. + (process_status_retrieved): New function. + (record_child_status_change): Use it. + Accept negative 1st argument, which means to wait for the + processes that Emacs already knows about. Move special-case code + for DOS_NT (which lacks WNOHANG) here, from caller. Keep track of + processes that have already been waited for, by testing and + clearing new 'alive' member. + (CAN_HANDLE_MULTIPLE_CHILDREN): Remove, as record_child_status_change + now does this internally. + (handle_child_signal): Let record_child_status_change do all + the work, since we do not want to reap all exited child processes, + only the child processes that Emacs itself created. + * process.h (Lisp_Process): New boolean member 'alive'. + 2012-11-23 Eli Zaretskii * xdisp.c (set_cursor_from_row): Skip step 2 only if point is not diff --git a/src/process.c b/src/process.c index 77e99ead01f..c095d13293b 100644 --- a/src/process.c +++ b/src/process.c @@ -130,14 +130,6 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, EMACS_TIME *, void *); #endif -#ifndef WNOHANG -# undef waitpid -# define waitpid(pid, status, options) wait (status) -#endif -#ifndef WUNTRACED -# define WUNTRACED 0 -#endif - /* Work around GCC 4.7.0 bug with strict overflow checking; see . These lines can be removed once the GCC bug is fixed. */ @@ -795,9 +787,8 @@ get_process (register Lisp_Object name) #ifdef SIGCHLD /* Fdelete_process promises to immediately forget about the process, but in reality, Emacs needs to remember those processes until they have been - treated by the SIGCHLD handler; otherwise this handler would consider the - process as being synchronous and say that the synchronous process is - dead. */ + treated by the SIGCHLD handler and waitpid has been invoked on them; + otherwise they might fill up the kernel's process table. */ static Lisp_Object deleted_pid_list; #endif @@ -1704,16 +1695,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) if (inchannel > max_process_desc) max_process_desc = inchannel; - /* Until we store the proper pid, enable the SIGCHLD handler - to recognize an unknown pid as standing for this process. - It is very important not to let this `marker' value stay - in the table after this function has returned; if it does - it might cause call-process to hang and subsequent asynchronous - processes to get their return values scrambled. */ - XPROCESS (process)->pid = -1; - - /* This must be called after the above line because it may signal an - error. */ + /* This may signal an error. */ setup_process_coding_systems (process); encoded_current_dir = ENCODE_FILE (current_dir); @@ -1880,6 +1862,8 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) #endif XPROCESS (process)->pid = pid; + if (0 <= pid) + XPROCESS (process)->alive = 1; /* Stop blocking signals in the parent. */ #ifdef SIGCHLD @@ -6273,9 +6257,35 @@ process has been transmitted to the serial port. */) return process; } -/* On receipt of a signal that a child status has changed, loop asking - about children with changed statuses until the system says there - are no more. +/* If the status of the process DESIRED has changed, return true and + set *STATUS to its exit status; otherwise, return false. + If HAVE is nonnegative, assume that HAVE = waitpid (HAVE, STATUS, ...) + has already been invoked, and do not invoke waitpid again. */ + +static bool +process_status_retrieved (pid_t desired, pid_t have, int *status) +{ + if (have < 0) + { + /* Invoke waitpid only with a known process ID; do not invoke + waitpid with a nonpositive argument. Otherwise, Emacs might + reap an unwanted process by mistake. For example, invoking + waitpid (-1, ...) can mess up glib by reaping glib's subprocesses, + so that another thread running glib won't find them. */ + do + have = waitpid (desired, status, WNOHANG | WUNTRACED); + while (have < 0 && errno == EINTR); + } + + return have == desired; +} + +/* If PID is nonnegative, the child process PID with wait status W has + changed its status; record this and return true. + + If PID is negative, ignore W, and look for known child processes + of Emacs whose status have changed. For each one found, record its new + status. All we do is change the status; we do not run sentinels or print notifications. That is saved for the next time keyboard input is @@ -6298,13 +6308,15 @@ process has been transmitted to the serial port. */) ** Malloc WARNING: This should never call malloc either directly or indirectly; if it does, that is a bug */ -/* Record the changed status of the child process PID with wait status W. */ void record_child_status_change (pid_t pid, int w) { #ifdef SIGCHLD - Lisp_Object proc; - struct Lisp_Process *p; + + /* On POSIXish hosts, record at most one child only if we already + know one child that has exited. */ + bool record_at_most_one_child = 0 <= pid; + Lisp_Object tail; /* Find the process that signaled us, and record its status. */ @@ -6312,68 +6324,69 @@ record_child_status_change (pid_t pid, int w) /* The process can have been deleted by Fdelete_process. */ for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail)) { + bool all_pids_are_fixnums + = (MOST_NEGATIVE_FIXNUM <= TYPE_MINIMUM (pid_t) + && TYPE_MAXIMUM (pid_t) <= MOST_POSITIVE_FIXNUM); Lisp_Object xpid = XCAR (tail); - if ((INTEGERP (xpid) && pid == XINT (xpid)) - || (FLOATP (xpid) && pid == XFLOAT_DATA (xpid))) + if (all_pids_are_fixnums ? INTEGERP (xpid) : NUMBERP (xpid)) { - XSETCAR (tail, Qnil); - return; + pid_t deleted_pid; + if (INTEGERP (xpid)) + deleted_pid = XINT (xpid); + else + deleted_pid = XFLOAT_DATA (xpid); + if (process_status_retrieved (deleted_pid, pid, &w)) + { + XSETCAR (tail, Qnil); + if (record_at_most_one_child) + return; + } } } /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */ - p = 0; for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) { - proc = XCDR (XCAR (tail)); - p = XPROCESS (proc); - if (EQ (p->type, Qreal) && p->pid == pid) - break; - p = 0; - } - - /* Look for an asynchronous process whose pid hasn't been filled - in yet. */ - if (! p) - for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) - { - proc = XCDR (XCAR (tail)); - p = XPROCESS (proc); - if (p->pid == -1) - break; - p = 0; - } + Lisp_Object proc = XCDR (XCAR (tail)); + struct Lisp_Process *p = XPROCESS (proc); + if (p->alive && process_status_retrieved (p->pid, pid, &w)) + { + /* Change the status of the process that was found. */ + p->tick = ++process_tick; + p->raw_status = w; + p->raw_status_new = 1; - /* Change the status of the process that was found. */ - if (p) - { - int clear_desc_flag = 0; + /* If process has terminated, stop waiting for its output. */ + if (WIFSIGNALED (w) || WIFEXITED (w)) + { + int clear_desc_flag = 0; + p->alive = 0; + if (p->infd >= 0) + clear_desc_flag = 1; - p->tick = ++process_tick; - p->raw_status = w; - p->raw_status_new = 1; + /* clear_desc_flag avoids a compiler bug in Microsoft C. */ + if (clear_desc_flag) + { + FD_CLR (p->infd, &input_wait_mask); + FD_CLR (p->infd, &non_keyboard_wait_mask); + } + } - /* If process has terminated, stop waiting for its output. */ - if ((WIFSIGNALED (w) || WIFEXITED (w)) - && p->infd >= 0) - clear_desc_flag = 1; + /* Tell wait_reading_process_output that it needs to wake up and + look around. */ + if (input_available_clear_time) + *input_available_clear_time = make_emacs_time (0, 0); - /* We use clear_desc_flag to avoid a compiler bug in Microsoft C. */ - if (clear_desc_flag) - { - FD_CLR (p->infd, &input_wait_mask); - FD_CLR (p->infd, &non_keyboard_wait_mask); + if (record_at_most_one_child) + return; } - - /* Tell wait_reading_process_output that it needs to wake up and - look around. */ - if (input_available_clear_time) - *input_available_clear_time = make_emacs_time (0, 0); } - /* There was no asynchronous process found for that pid: we have - a synchronous process. */ - else + + if (0 <= pid) { + /* The caller successfully waited for a pid but no asynchronous + process was found for it, so this is a synchronous process. */ + synch_process_alive = 0; /* Report the status of the synchronous process. */ @@ -6392,38 +6405,10 @@ record_child_status_change (pid_t pid, int w) #ifdef SIGCHLD -/* On some systems, the SIGCHLD handler must return right away. If - any more processes want to signal us, we will get another signal. - Otherwise, loop around to use up all the processes that have - something to tell us. */ -#if (defined WINDOWSNT \ - || (defined USG && !defined GNU_LINUX \ - && !(defined HPUX && defined WNOHANG))) -enum { CAN_HANDLE_MULTIPLE_CHILDREN = 0 }; -#else -enum { CAN_HANDLE_MULTIPLE_CHILDREN = 1 }; -#endif - static void handle_child_signal (int sig) { - do - { - pid_t pid; - int status; - - do - pid = waitpid (-1, &status, WNOHANG | WUNTRACED); - while (pid < 0 && errno == EINTR); - - /* PID == 0 means no processes found, PID == -1 means a real failure. - Either way, we have done all our job. */ - if (pid <= 0) - break; - - record_child_status_change (pid, status); - } - while (CAN_HANDLE_MULTIPLE_CHILDREN); + record_child_status_change (-1, 0); } static void diff --git a/src/process.h b/src/process.h index ce3d2e702cc..74d1a124060 100644 --- a/src/process.h +++ b/src/process.h @@ -142,6 +142,9 @@ struct Lisp_Process /* Flag to set coding-system of the process buffer from the coding_system used to decode process output. */ unsigned int inherit_coding_system_flag : 1; + /* Whether the process is alive, i.e., can be waited for. Running + processes can be waited for, but exited and fake processes cannot. */ + unsigned int alive : 1; /* Record the process status in the raw form in which it comes from `wait'. This is to avoid consing in a signal handler. The `raw_status_new' flag indicates that `raw_status' contains a new status that still diff --git a/src/sysdep.c b/src/sysdep.c index 63eac5d9e09..bb81353847b 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -289,10 +289,6 @@ wait_for_termination_1 (pid_t pid, int interruptible) { while (1) { -#ifdef WINDOWSNT - wait (0); - break; -#else /* not WINDOWSNT */ int status; int wait_result = waitpid (pid, &status, 0); if (wait_result < 0) @@ -306,7 +302,8 @@ wait_for_termination_1 (pid_t pid, int interruptible) break; } -#endif /* not WINDOWSNT */ + /* Note: the MS-Windows emulation of waitpid calls QUIT + internally. */ if (interruptible) QUIT; } diff --git a/src/w32proc.c b/src/w32proc.c index e3c54fe5460..b4f2099f06a 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -783,7 +783,6 @@ alarm (int seconds) /* Child process management list. */ int child_proc_count = 0; child_process child_procs[ MAX_CHILDREN ]; -child_process *dead_child = NULL; static DWORD WINAPI reader_thread (void *arg); @@ -1036,9 +1035,6 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app, if (cp->pid < 0) cp->pid = -cp->pid; - /* pid must fit in a Lisp_Int */ - cp->pid = cp->pid & INTMASK; - *pPid = cp->pid; return TRUE; @@ -1114,55 +1110,110 @@ reap_subprocess (child_process *cp) delete_child (cp); } -/* Wait for any of our existing child processes to die - When it does, close its handle - Return the pid and fill in the status if non-NULL. */ +/* Wait for a child process specified by PID, or for any of our + existing child processes (if PID is nonpositive) to die. When it + does, close its handle. Return the pid of the process that died + and fill in STATUS if non-NULL. */ -int -sys_wait (int *status) +pid_t +waitpid (pid_t pid, int *status, int options) { DWORD active, retval; int nh; - int pid; child_process *cp, *cps[MAX_CHILDREN]; HANDLE wait_hnd[MAX_CHILDREN]; + DWORD timeout_ms; + int dont_wait = (options & WNOHANG) != 0; nh = 0; - if (dead_child != NULL) + /* According to Posix: + + PID = -1 means status is requested for any child process. + + PID > 0 means status is requested for a single child process + whose pid is PID. + + PID = 0 means status is requested for any child process whose + process group ID is equal to that of the calling process. But + since Windows has only a limited support for process groups (only + for console processes and only for the purposes of passing + Ctrl-BREAK signal to them), and since we have no documented way + of determining whether a given process belongs to our group, we + treat 0 as -1. + + PID < -1 means status is requested for any child process whose + process group ID is equal to the absolute value of PID. Again, + since we don't support process groups, we treat that as -1. */ + if (pid > 0) { - /* We want to wait for a specific child */ - wait_hnd[nh] = dead_child->procinfo.hProcess; - cps[nh] = dead_child; - if (!wait_hnd[nh]) emacs_abort (); - nh++; - active = 0; - goto get_result; + int our_child = 0; + + /* We are requested to wait for a specific child. */ + for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) + { + /* Some child_procs might be sockets; ignore them. Also + ignore subprocesses whose output is not yet completely + read. */ + if (CHILD_ACTIVE (cp) + && cp->procinfo.hProcess + && cp->pid == pid) + { + our_child = 1; + break; + } + } + if (our_child) + { + if (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0) + { + wait_hnd[nh] = cp->procinfo.hProcess; + cps[nh] = cp; + nh++; + } + else if (dont_wait) + { + /* PID specifies our subprocess, but its status is not + yet available. */ + return 0; + } + } + if (nh == 0) + { + /* No such child process, or nothing to wait for, so fail. */ + errno = ECHILD; + return -1; + } } else { for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) - /* some child_procs might be sockets; ignore them */ - if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess - && (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0)) - { - wait_hnd[nh] = cp->procinfo.hProcess; - cps[nh] = cp; - nh++; - } + { + if (CHILD_ACTIVE (cp) + && cp->procinfo.hProcess + && (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0)) + { + wait_hnd[nh] = cp->procinfo.hProcess; + cps[nh] = cp; + nh++; + } + } + if (nh == 0) + { + /* Nothing to wait on, so fail. */ + errno = ECHILD; + return -1; + } } - if (nh == 0) - { - /* Nothing to wait on, so fail */ - errno = ECHILD; - return -1; - } + if (dont_wait) + timeout_ms = 0; + else + timeout_ms = 1000; /* check for quit about once a second. */ do { - /* Check for quit about once a second. */ QUIT; - active = WaitForMultipleObjects (nh, wait_hnd, FALSE, 1000); + active = WaitForMultipleObjects (nh, wait_hnd, FALSE, timeout_ms); } while (active == WAIT_TIMEOUT); if (active == WAIT_FAILED) @@ -1192,8 +1243,10 @@ get_result: } if (retval == STILL_ACTIVE) { - /* Should never happen */ + /* Should never happen. */ DebPrint (("Wait.WaitForMultipleObjects returned an active process\n")); + if (pid > 0 && dont_wait) + return 0; errno = EINVAL; return -1; } @@ -1207,6 +1260,8 @@ get_result: else retval <<= 8; + if (pid > 0 && active != 0) + emacs_abort (); cp = cps[active]; pid = cp->pid; #ifdef FULL_DEBUG @@ -1995,9 +2050,7 @@ count_children: DebPrint (("select calling SIGCHLD handler for pid %d\n", cp->pid)); #endif - dead_child = cp; sig_handlers[SIGCHLD] (SIGCHLD); - dead_child = NULL; } } else if (fdindex[active] == -1) -- cgit v1.2.1