commit 319a2a742759e5a6738a554918e2030bed6f8188 (HEAD, refs/remotes/origin/master) Author: Filipp Gunbin Date: Wed Apr 1 03:01:23 2020 +0300 javac support in compilation-parse-errors rules * etc/compilation.txt: Add doc and example. * lisp/progmodes/compile.el (compilation-error-regexp-alist-alist): Add javac rule. (compilation-parse-errors): Fix file/line/col test, so that lambda/closure (which are valid values) don't match. * test/lisp/progmodes/compile-tests.el (compile-tests--test-regexps-data, compile-test-error-regexps): Add test. diff --git a/etc/compilation.txt b/etc/compilation.txt index ebce6a14d0..8f7e290678 100644 --- a/etc/compilation.txt +++ b/etc/compilation.txt @@ -237,6 +237,20 @@ Register 6 contains wrong type ==1332== by 0x8008621: main (vtest.c:180) +* javac Java compiler + +symbol: javac + +Should also work when compiling Java with Gradle. We use the position +of "^" in the third line as column number because no explicit value is +present. + +Test.java:5: error: ';' expected + foo foo + ^ +1 error + + * IBM jikes symbols: jikes-file jikes-line diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index e5878b28f9..a76a3c44a3 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -265,6 +265,20 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1)) (java "^\\(?:[ \t]+at \\|==[0-9]+== +\\(?:at\\|b\\(y\\)\\)\\).+(\\([^()\n]+\\):\\([0-9]+\\))$" 2 3 nil (1)) + (javac + ,(concat + ;; line1 + "^\\(\\(?:[A-Za-z]:\\)?[^:\n]+\\):" ;file + "\\([0-9]+\\): " ;line + "\\(warning: \\)?.*\n" ;type (optional) and message + ;; line2: source line containing error + ".*\n" + ;; line3: single "^" under error position in line2 + " *\\^$") + 1 2 + ,(lambda () (1- (current-column))) + (3)) + (jikes-file "^\\(?:Found\\|Issued\\) .* compiling \"\\(.+\\)\":$" 1 nil nil 0) @@ -1466,9 +1480,15 @@ to `compilation-error-regexp-alist' if RULES is nil." nil) ;; Not anchored or anchored but already allows empty spaces. (t (setq pat (concat "^\\(?: \\)?" (substring pat 1))))) - (if (consp file) (setq fmt (cdr file) file (car file))) - (if (consp line) (setq end-line (cdr line) line (car line))) - (if (consp col) (setq end-col (cdr col) col (car col))) + (if (and (consp file) (not (functionp file))) + (setq fmt (cdr file) + file (car file))) + (if (and (consp line) (not (functionp line))) + (setq end-line (cdr line) + line (car line))) + (if (and (consp col) (not (functionp col))) + (setq end-col (cdr col) + col (car col))) (unless (or (null (nth 5 item)) (integerp (nth 5 item))) (error "HYPERLINK should be an integer: %s" (nth 5 item))) diff --git a/test/lisp/progmodes/compile-tests.el b/test/lisp/progmodes/compile-tests.el index 75962566f1..cd736497e6 100644 --- a/test/lisp/progmodes/compile-tests.el +++ b/test/lisp/progmodes/compile-tests.el @@ -176,6 +176,9 @@ 13 nil 217 "../src/Lib/System.cpp") ("==1332== by 0x8008621: main (vtest.c:180)" 13 nil 180 "vtest.c") + ;; javac + ("/src/Test.java:5: ';' expected\n foo foo\n ^\n" 1 15 5 "/src/Test.java" 2) + ("e:\\src\\Test.java:7: warning: ';' expected\n foo foo\n ^\n" 1 10 7 "e:\\src\\Test.java" 1) ;; jikes-file jikes-line ("Found 2 semantic errors compiling \"../javax/swing/BorderFactory.java\":" 1 nil nil "../javax/swing/BorderFactory.java") @@ -431,8 +434,8 @@ The test data is in `compile-tests--test-regexps-data'." (compilation-num-warnings-found 0) (compilation-num-infos-found 0)) (mapc #'compile--test-error-line compile-tests--test-regexps-data) - (should (eq compilation-num-errors-found 93)) - (should (eq compilation-num-warnings-found 36)) + (should (eq compilation-num-errors-found 94)) + (should (eq compilation-num-warnings-found 37)) (should (eq compilation-num-infos-found 26))))) (ert-deftest compile-test-grep-regexps () commit cddf85d256dda8db1fad50e8e766fd7694361b8f Author: Stefan Monnier Date: Tue Mar 31 19:45:22 2020 -0400 Remove `all_buffers` and the associated `next` field of buffers * src/alloc.c (enum mem_type): Remove MEM_TYPE_BUFFER. (allocate_buffer): Allocate like any other pseudovector. Don't register on `all_buffers` any more. (live_buffer_holding, live_buffer_p): Delete functions. (mark_maybe_object, valid_lisp_object_p): Don't pay attention to MEM_TYPE_BUFFER any more. (garbage_collect): Only compact the live buffers. (mark_buffer): Mark the undo_list of dead buffers here. (mark_object): Buffers are normal pseudovectors now. (sweep_buffers): Don't do the actual sweep here, just cleanup the markers and only for live buffers. * src/buffer.c (all_buffers): Remove variable. (Fkill_buffer): Don't check indirect dead buffers. Set the undo_list before we remove ourselves from the list of live buffers. (Fbuffer_swap_text, Fset_buffer_multibyte): Don't check indirect dead buffers. (init_buffer_once): Don't set `all_buffers`. (init_buffer): Don't map new memory for dead buffers. * src/buffer.h (struct buffer): Remove `next` field. (FOR_EACH_BUFFER): Remove macro. * src/pdumper.c (dump_buffer): Don't dump the `next` field. diff --git a/src/alloc.c b/src/alloc.c index eed73bcdc4..cc9ba8dbf5 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -432,7 +432,6 @@ inline static void set_interval_marked (INTERVAL i); enum mem_type { MEM_TYPE_NON_LISP, - MEM_TYPE_BUFFER, MEM_TYPE_CONS, MEM_TYPE_STRING, MEM_TYPE_SYMBOL, @@ -3331,12 +3330,10 @@ allocate_pseudovector (int memlen, int lisplen, struct buffer * allocate_buffer (void) { - struct buffer *b = lisp_malloc (sizeof *b, false, MEM_TYPE_BUFFER); - + struct buffer *b + = ALLOCATE_PSEUDOVECTOR (struct buffer, cursor_in_non_selected_windows_, + PVEC_BUFFER); BUFFER_PVEC_INIT (b); - /* Put B on the chain of all buffers including killed ones. */ - b->next = all_buffers; - all_buffers = b; /* Note that the rest fields of B are not initialized. */ return b; } @@ -4596,40 +4593,6 @@ live_vector_p (struct mem_node *m, void *p) return !NILP (live_vector_holding (m, p)); } -/* If P is a pointer into a valid buffer object, return the buffer. - Otherwise, return nil. M is a pointer to the mem_block for P. - If IGNORE_KILLED is non-zero, treat killed buffers as invalid. */ - -static Lisp_Object -live_buffer_holding (struct mem_node *m, void *p, bool ignore_killed) -{ - /* P must point into the block, and the buffer must not - have been killed unless ALL-BUFFERS is true. */ - if (m->type == MEM_TYPE_BUFFER) - { - struct buffer *b = m->start; - char *cb = m->start; - char *cp = p; - ptrdiff_t offset = cp - cb; - if (0 <= offset && offset < sizeof *b - && !(ignore_killed && NILP (b->name_))) - { - Lisp_Object obj; - XSETBUFFER (obj, b); - return obj; - } - } - return Qnil; -} - -/* If P is a pointer into a live (valid and not killed) buffer object, - return non-zero. */ -static bool -live_buffer_p (struct mem_node *m, void *p) -{ - return !NILP (live_buffer_holding (m, p, true)); -} - /* Mark OBJ if we can prove it's a Lisp_Object. */ static void @@ -4684,8 +4647,7 @@ mark_maybe_object (Lisp_Object obj) break; case Lisp_Vectorlike: - mark_p = (EQ (obj, live_vector_holding (m, po)) - || EQ (obj, live_buffer_holding (m, po, false))); + mark_p = (EQ (obj, live_vector_holding (m, po))); break; default: @@ -4754,10 +4716,6 @@ mark_maybe_pointer (void *p) /* Nothing to do; not a pointer to Lisp memory. */ break; - case MEM_TYPE_BUFFER: - obj = live_buffer_holding (m, p, false); - break; - case MEM_TYPE_CONS: obj = live_cons_holding (m, p); break; @@ -5157,9 +5115,6 @@ valid_lisp_object_p (Lisp_Object obj) case MEM_TYPE_SPARE: return 0; - case MEM_TYPE_BUFFER: - return live_buffer_p (m, p) ? 1 : 2; - case MEM_TYPE_CONS: return live_cons_p (m, p); @@ -5976,7 +5931,7 @@ maybe_garbage_collect (void) void garbage_collect (void) { - struct buffer *nextb; + Lisp_Object tail, buffer; char stack_top_variable; bool message_p; ptrdiff_t count = SPECPDL_INDEX (); @@ -5992,8 +5947,8 @@ garbage_collect (void) /* Don't keep undo information around forever. Do this early on, so it is no problem if the user quits. */ - FOR_EACH_BUFFER (nextb) - compact_buffer (nextb); + FOR_EACH_LIVE_BUFFER (tail, buffer) + compact_buffer (XBUFFER (buffer)); byte_ct tot_before = (profiler_memory_running ? total_bytes_of_live_objects () @@ -6083,8 +6038,9 @@ garbage_collect (void) compact_font_caches (); - FOR_EACH_BUFFER (nextb) + FOR_EACH_LIVE_BUFFER (tail, buffer) { + struct buffer *nextb = XBUFFER (buffer); if (!EQ (BVAR (nextb, undo_list), Qt)) bset_undo_list (nextb, compact_undo_list (BVAR (nextb, undo_list))); /* Now that we have stripped the elements that need not be @@ -6349,7 +6305,12 @@ mark_buffer (struct buffer *buffer) /* For now, we just don't mark the undo_list. It's done later in a special way just before the sweep phase, and after stripping - some of its elements that are not needed any more. */ + some of its elements that are not needed any more. + Note: this later processing is only done for live buffers, so + for dead buffers, the undo_list should be nil (set by Fkill_buffer), + but just to be on the safe side, we mark it here. */ + if (!BUFFER_LIVE_P (buffer)) + mark_object (BVAR (buffer, undo_list)); mark_overlay (buffer->overlays_before); mark_overlay (buffer->overlays_after); @@ -6613,23 +6574,12 @@ mark_object (Lisp_Object arg) = PSEUDOVECTOR_TYPE (ptr); if (pvectype != PVEC_SUBR && - pvectype != PVEC_BUFFER && !main_thread_p (po)) CHECK_LIVE (live_vector_p); switch (pvectype) { case PVEC_BUFFER: -#if GC_CHECK_MARKED_OBJECTS - { - struct buffer *b; - FOR_EACH_BUFFER (b) - if (b == po) - break; - if (b == NULL) - emacs_abort (); - } -#endif /* GC_CHECK_MARKED_OBJECTS */ mark_buffer ((struct buffer *) ptr); break; @@ -7108,25 +7058,17 @@ NO_INLINE /* For better stack traces */ static void sweep_buffers (void) { - struct buffer *buffer, **bprev = &all_buffers; + Lisp_Object tail, buf; gcstat.total_buffers = 0; - for (buffer = all_buffers; buffer; buffer = *bprev) - if (!vectorlike_marked_p (&buffer->header)) - { - *bprev = buffer->next; - lisp_free (buffer); - } - else - { - if (!pdumper_object_p (buffer)) - XUNMARK_VECTOR (buffer); - /* Do not use buffer_(set|get)_intervals here. */ - buffer->text->intervals = balance_intervals (buffer->text->intervals); - unchain_dead_markers (buffer); - gcstat.total_buffers++; - bprev = &buffer->next; - } + FOR_EACH_LIVE_BUFFER (tail, buf) + { + struct buffer *buffer = XBUFFER (buf); + /* Do not use buffer_(set|get)_intervals here. */ + buffer->text->intervals = balance_intervals (buffer->text->intervals); + unchain_dead_markers (buffer); + gcstat.total_buffers++; + } } /* Sweep: find all structures not marked, and free them. */ diff --git a/src/buffer.c b/src/buffer.c index 4e121ca4ca..d8842a6d77 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -51,11 +51,6 @@ along with GNU Emacs. If not, see . */ #include "w32heap.h" /* for mmap_* */ #endif -/* First buffer in chain of all buffers (in reverse order of creation). - Threaded through ->header.next.buffer. */ - -struct buffer *all_buffers; - /* This structure holds the default values of the buffer-local variables defined with DEFVAR_PER_BUFFER, that have special slots in each buffer. The default value occupies the same slot in this structure @@ -1786,15 +1781,11 @@ cleaning up all windows currently displaying the buffer to be killed. */) ask questions or their hooks get errors. */ if (!b->base_buffer && b->indirections > 0) { - struct buffer *other; + Lisp_Object tail, other; - FOR_EACH_BUFFER (other) - if (other->base_buffer == b) - { - Lisp_Object buf; - XSETBUFFER (buf, other); - Fkill_buffer (buf); - } + FOR_EACH_LIVE_BUFFER (tail, other) + if (XBUFFER (other)->base_buffer == b) + Fkill_buffer (other); /* Exit if we now have killed the base buffer (Bug#11665). */ if (!BUFFER_LIVE_P (b)) @@ -1849,6 +1840,9 @@ cleaning up all windows currently displaying the buffer to be killed. */) tem = Vinhibit_quit; Vinhibit_quit = Qt; + /* Once the buffer is removed from Vbuffer_alist, its undo_list field is + not traced by the GC in the same way. So set it to nil early. */ + bset_undo_list (b, Qnil); /* Remove the buffer from the list of all buffers. */ Vbuffer_alist = Fdelq (Frassq (buffer, Vbuffer_alist), Vbuffer_alist); /* If replace_buffer_in_windows didn't do its job fix that now. */ @@ -1963,7 +1957,6 @@ cleaning up all windows currently displaying the buffer to be killed. */) } bset_width_table (b, Qnil); unblock_input (); - bset_undo_list (b, Qnil); /* Run buffer-list-update-hook. */ if (!NILP (Vrun_hooks) && !b->inhibit_buffer_hooks) @@ -2351,10 +2344,10 @@ results, see Info node `(elisp)Swapping Text'. */) error ("Cannot swap indirect buffers's text"); { /* This is probably harder to make work. */ - struct buffer *other; - FOR_EACH_BUFFER (other) - if (other->base_buffer == other_buffer - || other->base_buffer == current_buffer) + Lisp_Object tail, other; + FOR_EACH_LIVE_BUFFER (tail, other) + if (XBUFFER (other)->base_buffer == other_buffer + || XBUFFER (other)->base_buffer == current_buffer) error ("One of the buffers to swap has indirect buffers"); } @@ -2502,7 +2495,7 @@ current buffer is cleared. */) (Lisp_Object flag) { struct Lisp_Marker *tail, *markers; - struct buffer *other; + Lisp_Object btail, other; ptrdiff_t begv, zv; bool narrowed = (BEG != BEGV || Z != ZV); bool modified_p = !NILP (Fbuffer_modified_p (Qnil)); @@ -2755,13 +2748,16 @@ current buffer is cleared. */) /* Copy this buffer's new multibyte status into all of its indirect buffers. */ - FOR_EACH_BUFFER (other) - if (other->base_buffer == current_buffer && BUFFER_LIVE_P (other)) - { - BVAR (other, enable_multibyte_characters) - = BVAR (current_buffer, enable_multibyte_characters); - other->prevent_redisplay_optimizations_p = 1; - } + FOR_EACH_LIVE_BUFFER (btail, other) + { + struct buffer *o = XBUFFER (other); + if (o->base_buffer == current_buffer && BUFFER_LIVE_P (o)) + { + BVAR (o, enable_multibyte_characters) + = BVAR (current_buffer, enable_multibyte_characters); + o->prevent_redisplay_optimizations_p = true; + } + } /* Restore the modifiedness of the buffer. */ if (!modified_p && !NILP (Fbuffer_modified_p (Qnil))) @@ -5327,8 +5323,6 @@ init_buffer_once (void) Vbuffer_alist = Qnil; current_buffer = 0; pdumper_remember_lv_ptr_raw (¤t_buffer, Lisp_Vectorlike); - all_buffers = 0; - pdumper_remember_lv_ptr_raw (&all_buffers, Lisp_Vectorlike); QSFundamental = build_pure_c_string ("Fundamental"); @@ -5359,7 +5353,7 @@ init_buffer (void) #ifdef USE_MMAP_FOR_BUFFERS if (dumped_with_unexec_p ()) { - struct buffer *b; + Lisp_Object tail, buffer; #ifndef WINDOWSNT /* These must be reset in the dumped Emacs, to avoid stale @@ -5381,8 +5375,9 @@ init_buffer (void) " *code-conversion-work*". They are created by init_buffer_once and init_window_once (which are not called in the dumped Emacs), and by the first call to coding.c routines. */ - FOR_EACH_BUFFER (b) + FOR_EACH_LIVE_BUFFER (tail, buffer) { + struct buffer *b = XBUFFER (buffer); b->text->beg = NULL; enlarge_buffer_text (b, 0); } diff --git a/src/buffer.h b/src/buffer.h index 31f497ea40..abb1294d03 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -570,9 +570,6 @@ struct buffer In an indirect buffer, this is the own_text field of another buffer. */ struct buffer_text *text; - /* Next buffer, in chain of all buffers, including killed ones. */ - struct buffer *next; - /* Char position of point in buffer. */ ptrdiff_t pt; @@ -1104,15 +1101,6 @@ BUFFER_CHECK_INDIRECTION (struct buffer *b) } } -/* Chain of all buffers, including killed ones. */ - -extern struct buffer *all_buffers; - -/* Used to iterate over the chain above. */ - -#define FOR_EACH_BUFFER(b) \ - for ((b) = all_buffers; (b); (b) = (b)->next) - /* This structure holds the default values of the buffer-local variables that have special slots in each buffer. The default value occupies the same slot in this structure diff --git a/src/pdumper.c b/src/pdumper.c index e52163cdae..b5861950c9 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -2845,8 +2845,6 @@ dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer) ctx->obj_offset + dump_offsetof (struct buffer, text), base_offset + dump_offsetof (struct buffer, own_text)); - dump_field_lv_rawptr (ctx, out, buffer, &buffer->next, - Lisp_Vectorlike, WEIGHT_NORMAL); DUMP_FIELD_COPY (out, buffer, pt); DUMP_FIELD_COPY (out, buffer, pt_byte); DUMP_FIELD_COPY (out, buffer, begv); commit a477a7b86ba7c59a90b18283cc86769c27de6c7c Author: Noam Postavsky Date: Tue Mar 24 05:39:03 2020 -0400 Don't lose point during fileloop replace (Bug#38867) Suggested by Eric Michael Timmons . * lisp/fileloop.el (fileloop-initialize-replace): Save the match-beginning position in a variable instead of the buffer's point. The point may be changed by the time perform-replace is called, e.g., due to switch-to-buffer-preserve-window-point. diff --git a/lisp/fileloop.el b/lisp/fileloop.el index 543963feaf..8f4911638e 100644 --- a/lisp/fileloop.el +++ b/lisp/fileloop.el @@ -200,18 +200,22 @@ the default setting of `case-fold-search'. DELIMITED if non-nil means replace only word-delimited matches." ;; FIXME: Not sure how the delimited-flag interacts with the regexp-flag in ;; `perform-replace', so I just try to mimic the old code. - (fileloop-initialize - files - (lambda () - (let ((case-fold-search - (if (memql case-fold '(nil t)) case-fold case-fold-search))) - (if (re-search-forward from nil t) - ;; When we find a match, move back - ;; to the beginning of it so perform-replace - ;; will see it. - (goto-char (match-beginning 0))))) - (lambda () - (perform-replace from to t t delimited nil multi-query-replace-map)))) + (let ((mstart (make-hash-table :test 'eq))) + (fileloop-initialize + files + (lambda () + (let ((case-fold-search + (if (memql case-fold '(nil t)) case-fold case-fold-search))) + (when (re-search-forward from nil t) + ;; When we find a match, save its beginning for + ;; `perform-replace' (we used to just set point, but this + ;; is unreliable in the face of + ;; `switch-to-buffer-preserve-window-point'). + (puthash (current-buffer) (match-beginning 0) mstart)))) + (lambda () + (perform-replace from to t t delimited nil multi-query-replace-map + (gethash (current-buffer) mstart (point-min)) + (point-max)))))) (provide 'fileloop) ;;; fileloop.el ends here commit 05cab7ad06efabae18ee94e3b609ea10ae2f60be Author: Stefan Monnier Date: Tue Mar 31 12:11:26 2020 -0400 * lisp/dired.el (dired-readin): Improve comment diff --git a/lisp/dired.el b/lisp/dired.el index d58c37be2f..62e232b79f 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -1226,10 +1226,10 @@ wildcards, erases the buffer, and builds the subdir-alist anew ;; We used to bind `inhibit-modification-hooks' to try and speed up ;; execution, in particular, to prevent the font-lock hook from running ;; until the directory is all read in. - ;; I strongly suspect that this was only useful in Emacs<21, because - ;; jit-lock made it a non-issue. - ;; Nevertheless, I used `combine-change-calls' which provides the - ;; same performance advantages, just in case. + ;; It's not clear why font-lock would be a significant issue + ;; here, but I used `combine-change-calls' which should provide the + ;; same performance advantages without the problem of breaking + ;; users of after/before-change-functions. (combine-change-calls (point-min) (point-max) (let ((inhibit-read-only t) ;; Don't make undo entries for readin.