comparison lisp/progmodes/compile.el @ 17623:a09fd9348b0d

Support compilers that give a message each time the file being compiled changes but don't include a file name each error message. Speed up by searching for regexps one by one instead of combining. (compile-internal): Takes more optional arguments. All five regexp alists can be given as argument. Change name of variable regexp-alist to error-regexp-alist. Change some local variables directly by setq instead of rebinding by let. (compilation-shell-minor-mode): New minor mode. Similar to compilation-minor-mode, but key bindings don't collide with shell mode. (compilation-shell-minor-mode-map, compilation-shell-minor-mode): New variables. (compile-auto-highlight): Doc fix. (compilation-error-regexp-alist): Removed unnecessary line break in first regexp. Replaced \\(\\|.* on \\) by \\(.* on \\)? in regexp for Absoft FORTRAN 77 Compiler 3.1.3. Added regexp for SPARCcompiler Pascal. Divided long line in regexp for Cray C compiler error messages. Made comment fit in line at regexp for Sun Ada (VADS, Solaris). FILE-IDX may be nil, meaning an error message with no file name, so the file name must be taken from an earlier message. LINE-IDX may be a function which is called with two arguments the file name and column strings and returns an error position descriptor. (compilation-enter-directory-regexp-alist) (compilation-leave-directory-regexp-alist): New variables. (compilation-file-regexp-alist) (compilation-nomessage-regexp-alist): New variables. (grep-regexp-alist): Removed unnecessary ^ at beginning of regexp. (compilation-enter-directory-regexp) (compilation-leave-directory-regexp): Variables deleted. Replaced by compilation-enter-directory-regexp-alist and compilation-leave-directory-regexp-alist. (compilation-buffer-p): Return true also for buffer in compilation-shell-minor-mode. (compilation-next-error-locus): Split a long line. (count-regexp-groupings): Comment about this function not being needed any more. (compilation-current-file, compilation-regexps); New variables. (compilation-parse-errors): Large parts rewritten. Don't put the regexps together in one large regexp, instead match them one by one. Support the generalized subexpression indices. (compile-collect-regexps, compile-buffer-substring): New functions supporting compilation-parse-errors.
author Richard M. Stallman <rms@gnu.org>
date Sat, 03 May 1997 04:37:52 +0000
parents 52780f61eb76
children 5339baa0a334
comparison
equal deleted inserted replaced
17622:742a57e66f7d 17623:a09fd9348b0d
38 (defvar compilation-window-height nil 38 (defvar compilation-window-height nil
39 "*Number of lines in a compilation window. If nil, use Emacs default.") 39 "*Number of lines in a compilation window. If nil, use Emacs default.")
40 40
41 (defvar compile-auto-highlight nil 41 (defvar compile-auto-highlight nil
42 "*Specify how many compiler errors to highlight (and parse) initially. 42 "*Specify how many compiler errors to highlight (and parse) initially.
43 \(Highlighting applies to ean error message when the mouse is over it.) 43 \(Highlighting applies to an error message when the mouse is over it.)
44 If this is a number N, all compiler error messages in the first N lines 44 If this is a number N, all compiler error messages in the first N lines
45 are highlighted and parsed as soon as they arrive in Emacs. 45 are highlighted and parsed as soon as they arrive in Emacs.
46 If t, highlight and parse the whole compilation output as soon as it arrives. 46 If t, highlight and parse the whole compilation output as soon as it arrives.
47 If nil, don't highlight or parse any of the buffer until you try to 47 If nil, don't highlight or parse any of the buffer until you try to
48 move to the error messages. 48 move to the error messages.
138 ;; foo.adb:2:1: Unit name does not match file name 138 ;; foo.adb:2:1: Unit name does not match file name
139 ;; 139 ;;
140 ;; We'll insist that the number be followed by a colon or closing 140 ;; We'll insist that the number be followed by a colon or closing
141 ;; paren, because otherwise this matches just about anything 141 ;; paren, because otherwise this matches just about anything
142 ;; containing a number with spaces around it. 142 ;; containing a number with spaces around it.
143 ("\ 143 ("\\([a-zA-Z]?:?[^:( \t\n]+\\)[:(][ \t]*\\([0-9]+\\)\\([) \t]\\|\
144 \\([a-zA-Z]?:?[^:( \t\n]+\\)[:(][ \t]*\\([0-9]+\\)\\([) \t]\\|\
145 :\\([^0-9\n]\\|\\([0-9]+:\\)\\)\\)" 1 2 5) 144 :\\([^0-9\n]\\|\\([0-9]+:\\)\\)\\)" 1 2 5)
146 145
147 ;; Microsoft C/C++: 146 ;; Microsoft C/C++:
148 ;; keyboard.c(537) : warning C4005: 'min' : macro redefinition 147 ;; keyboard.c(537) : warning C4005: 'min' : macro redefinition
149 ;; d:\tmp\test.c(23) : error C2143: syntax error : missing ';' before 'if' 148 ;; d:\tmp\test.c(23) : error C2143: syntax error : missing ';' before 'if'
182 ;; Unknown who does this: 181 ;; Unknown who does this:
183 ;; Line 45 of "foo.c": bloofle undefined 182 ;; Line 45 of "foo.c": bloofle undefined
184 ;; Absoft FORTRAN 77 Compiler 3.1.3 183 ;; Absoft FORTRAN 77 Compiler 3.1.3
185 ;; error on line 19 of fplot.f: spelling error? 184 ;; error on line 19 of fplot.f: spelling error?
186 ;; warning on line 17 of fplot.f: data type is undefined for variable d 185 ;; warning on line 17 of fplot.f: data type is undefined for variable d
187 ("\\(\\|.* on \\)[Ll]ine[ \t]+\\([0-9]+\\)[ \t]+\ 186 ("\\(.* on \\)?[Ll]ine[ \t]+\\([0-9]+\\)[ \t]+\
188 of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2) 187 of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2)
189 188
190 ;; Apollo cc, 4.3BSD fc: 189 ;; Apollo cc, 4.3BSD fc:
191 ;; "foo.f", line 3: Error: syntax error near end of statement 190 ;; "foo.f", line 3: Error: syntax error near end of statement
192 ;; IBM RS6000: 191 ;; IBM RS6000:
212 ;; ****** Error number 140 in line 8 of file errors.c ****** 211 ;; ****** Error number 140 in line 8 of file errors.c ******
213 (".*in line \\([0-9]+\\) of file \\([^ \n]+[^. \n]\\)\\.? " 2 1) 212 (".*in line \\([0-9]+\\) of file \\([^ \n]+[^. \n]\\)\\.? " 2 1)
214 ;; IBM AIX lint is too painful to do right this way. File name 213 ;; IBM AIX lint is too painful to do right this way. File name
215 ;; prefixes entire sections rather than being on each line. 214 ;; prefixes entire sections rather than being on each line.
216 215
216 ;; SPARCcompiler Pascal:
217 ;; 20 linjer : array[1..4] of linje;
218 ;; e 18480-----------^--- Inserted ';'
219 ;; and
220 ;; E 18520 line 61 - 0 is undefined
221 ;; These messages don't contain a file name. Instead the compiler gives
222 ;; a message whenever the file being compiled is changed.
223 (" +\\([0-9]+\\) +.*\n[ew] [0-9]+-+" nil 1)
224 ("[Ew] +[0-9]+ line \\([0-9]+\\) - " nil 1)
225
217 ;; Lucid Compiler, lcc 3.x 226 ;; Lucid Compiler, lcc 3.x
218 ;; E, file.cc(35,52) Illegal operation on pointers 227 ;; E, file.cc(35,52) Illegal operation on pointers
219 ("[EW], \\([^(\n]*\\)(\\([0-9]+\\),[ \t]*\\([0-9]+\\)" 1 2 3) 228 ("[EW], \\([^(\n]*\\)(\\([0-9]+\\),[ \t]*\\([0-9]+\\)" 1 2 3)
220 229
221 ;; GNU messages with program name and optional column number. 230 ;; GNU messages with program name and optional column number.
222 ("[a-zA-Z]?:?[^0-9 \n\t:]+[^ \n\t:]*:[ \t]*\\([^ \n\t:]+\\):\ 231 ("[a-zA-Z]?:?[^0-9 \n\t:]+[^ \n\t:]*:[ \t]*\\([^ \n\t:]+\\):\
223 \\([0-9]+\\):\\(\\([0-9]+\\)[: \t]\\)?" 1 2 4) 232 \\([0-9]+\\):\\(\\([0-9]+\\)[: \t]\\)?" 1 2 4)
224 233
225 ;; Cray C compiler error messages 234 ;; Cray C compiler error messages
226 ("\\(cc\\| cft\\)-[0-9]+ c\\(c\\|f77\\): ERROR \\([^,\n]+, \\)* File = \\([^,\n]+\\), Line = \\([0-9]+\\)" 4 5) 235 ("\\(cc\\| cft\\)-[0-9]+ c\\(c\\|f77\\): ERROR \\([^,\n]+, \\)* File = \
236 \\([^,\n]+\\), Line = \\([0-9]+\\)" 4 5)
227 237
228 ;; IBM C/C++ Tools 2.01: 238 ;; IBM C/C++ Tools 2.01:
229 ;; foo.c(2:0) : informational EDC0804: Function foo is not referenced. 239 ;; foo.c(2:0) : informational EDC0804: Function foo is not referenced.
230 ;; foo.c(3:8) : warning EDC0833: Implicit return statement encountered. 240 ;; foo.c(3:8) : warning EDC0833: Implicit return statement encountered.
231 ;; foo.c(5:5) : error EDC0350: Syntax error. 241 ;; foo.c(5:5) : error EDC0350: Syntax error.
235 ;; /home3/xdhar/rcds_rc/main.a, line 361, char 6:syntax error: "," inserted 245 ;; /home3/xdhar/rcds_rc/main.a, line 361, char 6:syntax error: "," inserted
236 ("\\([^, \n\t]+\\), line \\([0-9]+\\), char \\([0-9]+\\)[:., \(-]" 1 2 3) 246 ("\\([^, \n\t]+\\), line \\([0-9]+\\), char \\([0-9]+\\)[:., \(-]" 1 2 3)
237 247
238 ;; Perl -w: 248 ;; Perl -w:
239 ;; syntax error at automake line 922, near "':'" 249 ;; syntax error at automake line 922, near "':'"
240 ("\n.* at \\([^ ]+\\) line \\([0-9]+\\)," 1 2) 250 (".* at \\([^ ]+\\) line \\([0-9]+\\)," 1 2)
241 ) 251 )
242 "Alist that specifies how to match errors in compiler output. 252 "Alist that specifies how to match errors in compiler output.
243 Each elt has the form (REGEXP FILE-IDX LINE-IDX [COLUMN-IDX FILE-FORMAT...]) 253 Each elt has the form (REGEXP FILE-IDX LINE-IDX [COLUMN-IDX FILE-FORMAT...])
244 If REGEXP matches, the FILE-IDX'th subexpression gives the file name, and 254 If REGEXP matches, the FILE-IDX'th subexpression gives the file name, and
245 the LINE-IDX'th subexpression gives the line number. If COLUMN-IDX is 255 the LINE-IDX'th subexpression gives the line number. If COLUMN-IDX is
246 given, the COLUMN-IDX'th subexpression gives the column number on that line. 256 given, the COLUMN-IDX'th subexpression gives the column number on that line.
247 If any FILE-FORMAT is given, each is a format string to produce a file name to 257 If any FILE-FORMAT is given, each is a format string to produce a file name to
248 try; %s in the string is replaced by the text matching the FILE-IDX'th 258 try; %s in the string is replaced by the text matching the FILE-IDX'th
249 subexpression.") 259 subexpression.")
250 260
261 (defvar compilation-enter-directory-regexp-alist
262 '(
263 ;; Matches lines printed by the `-w' option of GNU Make.
264 (".*: Entering directory `\\(.*\\)'$" 1)
265 )
266 "Alist specifying how to match lines that indicate a new current directory.
267 Note that the match is done at the beginning of lines.
268 Each elt has the form (REGEXP IDX).
269 If REGEXP matches, the IDX'th subexpression gives the directory name.
270
271 The default value matches lines printed by the `-w' option of GNU Make.")
272
273 (defvar compilation-leave-directory-regexp-alist
274 '(
275 ;; Matches lines printed by the `-w' option of GNU Make.
276 (".*: Leaving directory `\\(.*\\)'$" 1)
277 )
278 "Alist specifying how to match lines that indicate restoring current directory.
279 Note that the match is done at the beginning of lines.
280 Each elt has the form (REGEXP IDX).
281 If REGEXP matches, the IDX'th subexpression gives the name of the directory
282 being moved from. If IDX is nil, the last directory entered \(by a line
283 matching `compilation-enter-directory-regexp-alist'\) is assumed.
284
285 The default value matches lines printed by the `-w' option of GNU Make.")
286
287 (defvar compilation-file-regexp-alist
288 '(
289 ;; This matches entries with date time year file-name: like
290 ;; Thu May 14 10:46:12 1992 mom3.p:
291 ("\\w\\w\\w \\w\\w\\w +[0-9]+ [0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9][0-9][0-9][0-9] \\(.*\\):$" 1)
292 )
293 "Alist specifying how to match lines that indicate a new current file.
294 Note that the match is done at the beginning of lines.
295 Each elt has the form (REGEXP IDX).
296 If REGEXP matches, the IDX'th subexpression gives the file name. This is
297 used with compilers that don't indicate file name in every error message.")
298
299 ;; There is no generally useful regexp that will match non messages, but
300 ;; in special cases there might be one. The lines that are not matched by
301 ;; a regexp take much longer time than the ones that are recognized so if
302 ;; you have same regexeps here, parsing is faster.
303 (defvar compilation-nomessage-regexp-alist
304 '(
305 )
306 "Alist specifying how to match lines that have no message.
307 Note that the match is done at the beginning of lines.
308 Each elt has the form (REGEXP). This alist is by default empty, but if
309 you have some good regexps here, the parsing of messages will be faster.")
310
251 (defvar compilation-read-command t 311 (defvar compilation-read-command t
252 "If not nil, M-x compile reads the compilation command to use. 312 "If not nil, M-x compile reads the compilation command to use.
253 Otherwise, M-x compile just uses the value of `compile-command'.") 313 Otherwise, M-x compile just uses the value of `compile-command'.")
254 314
255 (defvar compilation-ask-about-save t 315 (defvar compilation-ask-about-save t
256 "If not nil, M-x compile asks which buffers to save before compiling. 316 "If not nil, M-x compile asks which buffers to save before compiling.
257 Otherwise, it saves all modified buffers without asking.") 317 Otherwise, it saves all modified buffers without asking.")
258 318
259 (defvar grep-regexp-alist 319 (defvar grep-regexp-alist
260 '(("^\\([a-zA-Z]?:?[^:( \t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]" 1 2)) 320 '(("\\([a-zA-Z]?:?[^:( \t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]" 1 2))
261 "Regexp used to match grep hits. See `compilation-error-regexp-alist'.") 321 "Regexp used to match grep hits. See `compilation-error-regexp-alist'.")
262 322
263 ;; The system null device. (Should reference NULL_DEVICE from C.) 323 ;; The system null device. (Should reference NULL_DEVICE from C.)
264 (defvar grep-null-device "/dev/null" "The system null device.") 324 (defvar grep-null-device "/dev/null" "The system null device.")
265 325
326 '(lambda () (or (file-exists-p \"makefile\") (file-exists-p \"Makefile\") 386 '(lambda () (or (file-exists-p \"makefile\") (file-exists-p \"Makefile\")
327 (progn (make-local-variable 'compile-command) 387 (progn (make-local-variable 'compile-command)
328 (setq compile-command 388 (setq compile-command
329 (concat \"make -k \" 389 (concat \"make -k \"
330 buffer-file-name))))))") 390 buffer-file-name))))))")
331
332 (defvar compilation-enter-directory-regexp
333 ".*: Entering directory `\\(.*\\)'$"
334 "Regular expression matching lines that indicate a new current directory.
335 This must contain one \\(, \\) pair around the directory name.
336
337 The default value matches lines printed by the `-w' option of GNU Make.")
338
339 (defvar compilation-leave-directory-regexp
340 ".*: Leaving directory `\\(.*\\)'$"
341 "Regular expression matching lines that indicate restoring current directory.
342 This may contain one \\(, \\) pair around the name of the directory
343 being moved from. If it does not, the last directory entered \(by a
344 line matching `compilation-enter-directory-regexp'\) is assumed.
345
346 The default value matches lines printed by the `-w' option of GNU Make.")
347 391
348 (defvar compilation-directory-stack nil 392 (defvar compilation-directory-stack nil
349 "Stack of previous directories for `compilation-leave-directory-regexp'. 393 "Stack of previous directories for `compilation-leave-directory-regexp'.
350 The head element is the directory the compilation was started in.") 394 The head element is the directory the compilation was started in.")
351 395
371 (list (nth 1 item) 'font-lock-warning-face nil t) 415 (list (nth 1 item) 'font-lock-warning-face nil t)
372 (list (nth 2 item) 'font-lock-variable-name-face nil t))) 416 (list (nth 2 item) 'font-lock-variable-name-face nil t)))
373 compilation-error-regexp-alist) 417 compilation-error-regexp-alist)
374 (list 418 (list
375 ;; 419 ;;
376 ;; Compiler output lines. Recognise `make[n]:' lines too. 420 ;; Compiler output lines. Recognize `make[n]:' lines too.
377 '("^\\([A-Za-z_0-9/\.+-]+\\)\\(\\[\\([0-9]+\\)\\]\\)?[ \t]*:" 421 '("^\\([A-Za-z_0-9/\.+-]+\\)\\(\\[\\([0-9]+\\)\\]\\)?[ \t]*:"
378 (1 font-lock-function-name-face) (3 font-lock-comment-face nil t))) 422 (1 font-lock-function-name-face) (3 font-lock-comment-face nil t)))
379 )) 423 ))
380 424
381 ;;;###autoload 425 ;;;###autoload
462 grep-find-command nil nil 'grep-find-history))) 506 grep-find-command nil nil 'grep-find-history)))
463 (let ((grep-null-device nil)) ; see grep 507 (let ((grep-null-device nil)) ; see grep
464 (grep command-args))) 508 (grep command-args)))
465 509
466 (defun compile-internal (command error-message 510 (defun compile-internal (command error-message
467 &optional name-of-mode parser regexp-alist 511 &optional name-of-mode parser
468 name-function) 512 error-regexp-alist name-function
513 enter-regexp-alist leave-regexp-alist
514 file-regexp-alist nomessage-regexp-alist)
469 "Run compilation command COMMAND (low level interface). 515 "Run compilation command COMMAND (low level interface).
470 ERROR-MESSAGE is a string to print if the user asks to see another error 516 ERROR-MESSAGE is a string to print if the user asks to see another error
471 and there are no more errors. Third argument NAME-OF-MODE is the name 517 and there are no more errors. The rest of the arguments, 3-10 are optional.
472 to display as the major mode in the compilation buffer. 518 For them nil means use the default.
473 519 NAME-OF-MODE is the name to display as the major mode in the compilation
474 Fourth arg PARSER is the error parser function (nil means the default). Fifth 520 buffer. PARSER is the error parser function. ERROR-REGEXP-ALIST is the error
475 arg REGEXP-ALIST is the error message regexp alist to use (nil means the 521 message regexp alist to use. NAME-FUNCTION is a function called to name the
476 default). Sixth arg NAME-FUNCTION is a function called to name the buffer (nil 522 buffer. ENTER-REGEXP-ALIST is the enter directory message regexp alist to use.
477 means the default). The defaults for these variables are the global values of 523 LEAVE-REGEXP-ALIST is the leave directory message regexp alist to use.
478 \`compilation-parse-errors-function', `compilation-error-regexp-alist', and 524 FILE-REGEXP-ALIST is the change current file message regexp alist to use.
479 \`compilation-buffer-name-function', respectively. 525 NOMESSAGE-REGEXP-ALIST is the nomessage regexp alist to use.
526 The defaults for these variables are the global values of
527 \`compilation-parse-errors-function', `compilation-error-regexp-alist',
528 \`compilation-buffer-name-function', `compilation-enter-directory-regexp-alist',
529 \`compilation-leave-directory-regexp-alist', `compilation-file-regexp-alist',
530 \ and `compilation-nomessage-regexp-alist', respectively.
531 For arg 7-10 a value `t' means an empty alist.
480 532
481 Returns the compilation buffer created." 533 Returns the compilation buffer created."
482 (let (outbuf) 534 (let (outbuf)
483 (save-excursion 535 (save-excursion
484 (or name-of-mode 536 (or name-of-mode
506 (buffer-name)) 558 (buffer-name))
507 ))) 559 )))
508 ;; In case the compilation buffer is current, make sure we get the global 560 ;; In case the compilation buffer is current, make sure we get the global
509 ;; values of compilation-error-regexp-alist, etc. 561 ;; values of compilation-error-regexp-alist, etc.
510 (kill-all-local-variables)) 562 (kill-all-local-variables))
511 (let ((regexp-alist (or regexp-alist compilation-error-regexp-alist)) 563 (or error-regexp-alist
512 (parser (or parser compilation-parse-errors-function)) 564 (setq error-regexp-alist compilation-error-regexp-alist))
513 (thisdir default-directory) 565 (or enter-regexp-alist
566 (setq enter-regexp-alist compilation-enter-directory-regexp-alist))
567 (or leave-regexp-alist
568 (setq leave-regexp-alist compilation-leave-directory-regexp-alist))
569 (or file-regexp-alist
570 (setq file-regexp-alist compilation-file-regexp-alist))
571 (or nomessage-regexp-alist
572 (setq nomessage-regexp-alist compilation-nomessage-regexp-alist))
573 (or parser (setq parser compilation-parse-errors-function))
574 (let ((thisdir default-directory)
514 outwin) 575 outwin)
515 (save-excursion 576 (save-excursion
516 ;; Clear out the compilation buffer and make it writable. 577 ;; Clear out the compilation buffer and make it writable.
517 ;; Change its default-directory to the directory where the compilation 578 ;; Change its default-directory to the directory where the compilation
518 ;; will happen, and insert a `cd' command to indicate this. 579 ;; will happen, and insert a `cd' command to indicate this.
534 (set-buffer outbuf) 595 (set-buffer outbuf)
535 (compilation-mode) 596 (compilation-mode)
536 ;; (setq buffer-read-only t) ;;; Non-ergonomic. 597 ;; (setq buffer-read-only t) ;;; Non-ergonomic.
537 (set (make-local-variable 'compilation-parse-errors-function) parser) 598 (set (make-local-variable 'compilation-parse-errors-function) parser)
538 (set (make-local-variable 'compilation-error-message) error-message) 599 (set (make-local-variable 'compilation-error-message) error-message)
539 (set (make-local-variable 'compilation-error-regexp-alist) regexp-alist) 600 (set (make-local-variable 'compilation-error-regexp-alist)
601 error-regexp-alist)
602 (set (make-local-variable 'compilation-enter-directory-regexp-alist)
603 enter-regexp-alist)
604 (set (make-local-variable 'compilation-leave-directory-regexp-alist)
605 leave-regexp-alist)
606 (set (make-local-variable 'compilation-file-regexp-alist)
607 file-regexp-alist)
608 (set (make-local-variable 'compilation-nomessage-regexp-alist)
609 nomessage-regexp-alist)
540 (setq default-directory thisdir 610 (setq default-directory thisdir
541 compilation-directory-stack (list default-directory)) 611 compilation-directory-stack (list default-directory))
542 (set-window-start outwin (point-min)) 612 (set-window-start outwin (point-min))
543 (setq mode-name name-of-mode) 613 (setq mode-name name-of-mode)
544 (or (eq outwin (selected-window)) 614 (or (eq outwin (selected-window))
610 (define-key map "\M-{" 'compilation-previous-file) 680 (define-key map "\M-{" 'compilation-previous-file)
611 (define-key map "\M-}" 'compilation-next-file) 681 (define-key map "\M-}" 'compilation-next-file)
612 map) 682 map)
613 "Keymap for `compilation-minor-mode'.") 683 "Keymap for `compilation-minor-mode'.")
614 684
685 (defvar compilation-shell-minor-mode-map
686 (let ((map (make-sparse-keymap)))
687 (define-key map [mouse-2] 'compile-mouse-goto-error)
688 (define-key map "\M-\C-m" 'compile-goto-error)
689 (define-key map "\M-\C-n" 'compilation-next-error)
690 (define-key map "\M-\C-p" 'compilation-previous-error)
691 (define-key map "\M-{" 'compilation-previous-file)
692 (define-key map "\M-}" 'compilation-next-file)
693 ;; Set up the menu-bar
694 (define-key map [menu-bar errors-menu]
695 (cons "Errors" (make-sparse-keymap "Errors")))
696 (define-key map [menu-bar errors-menu stop-subjob]
697 '("Stop" . comint-interrupt-subjob))
698 (define-key map [menu-bar errors-menu compilation-mode-separator2]
699 '("----" . nil))
700 (define-key map [menu-bar errors-menu compilation-mode-first-error]
701 '("First Error" . first-error))
702 (define-key map [menu-bar errors-menu compilation-mode-previous-error]
703 '("Previous Error" . previous-error))
704 (define-key map [menu-bar errors-menu compilation-mode-next-error]
705 '("Next Error" . next-error))
706 map)
707 "Keymap for `compilation-shell-minor-mode'.")
708
615 (defvar compilation-mode-map 709 (defvar compilation-mode-map
616 (let ((map (cons 'keymap compilation-minor-mode-map))) 710 (let ((map (cons 'keymap compilation-minor-mode-map)))
617 (define-key map " " 'scroll-up) 711 (define-key map " " 'scroll-up)
618 (define-key map "\^?" 'scroll-down) 712 (define-key map "\^?" 'scroll-down)
619 ;; Set up the menu-bar 713 ;; Set up the menu-bar
667 (set (make-local-variable 'compilation-error-list) nil) 761 (set (make-local-variable 'compilation-error-list) nil)
668 (set (make-local-variable 'compilation-old-error-list) nil) 762 (set (make-local-variable 'compilation-old-error-list) nil)
669 (set (make-local-variable 'compilation-parsing-end) 1) 763 (set (make-local-variable 'compilation-parsing-end) 1)
670 (set (make-local-variable 'compilation-directory-stack) nil) 764 (set (make-local-variable 'compilation-directory-stack) nil)
671 (setq compilation-last-buffer (current-buffer))) 765 (setq compilation-last-buffer (current-buffer)))
766
767 (defvar compilation-shell-minor-mode nil
768 "Non-nil when in compilation-shell-minor-mode.
769 In this minor mode, all the error-parsing commands of the
770 Compilation major mode are available but bound to keys that don't
771 collide with Shell mode.")
772 (make-variable-buffer-local 'compilation-shell-minor-mode)
773
774 (or (assq 'compilation-shell-minor-mode minor-mode-alist)
775 (setq minor-mode-alist
776 (cons '(compilation-shell-minor-mode " Shell-Compile")
777 minor-mode-alist)))
778 (or (assq 'compilation-shell-minor-mode minor-mode-map-alist)
779 (setq minor-mode-map-alist (cons (cons 'compilation-shell-minor-mode
780 compilation-shell-minor-mode-map)
781 minor-mode-map-alist)))
672 782
673 (defvar compilation-minor-mode nil 783 (defvar compilation-minor-mode nil
674 "Non-nil when in compilation-minor-mode. 784 "Non-nil when in compilation-minor-mode.
675 In this minor mode, all the error-parsing commands of the 785 In this minor mode, all the error-parsing commands of the
676 Compilation major mode are available.") 786 Compilation major mode are available.")
785 errors)) 895 errors))
786 896
787 (defsubst compilation-buffer-p (buffer) 897 (defsubst compilation-buffer-p (buffer)
788 (save-excursion 898 (save-excursion
789 (set-buffer buffer) 899 (set-buffer buffer)
790 (or compilation-minor-mode (eq major-mode 'compilation-mode)))) 900 (or compilation-shell-minor-mode compilation-minor-mode
901 (eq major-mode 'compilation-mode))))
791 902
792 (defun compilation-next-error (n) 903 (defun compilation-next-error (n)
793 "Move point to the next error in the compilation buffer. 904 "Move point to the next error in the compilation buffer.
794 Does NOT find the source line like \\[next-error]." 905 Does NOT find the source line like \\[next-error]."
795 (interactive "p") 906 (interactive "p")
977 (or (compilation-buffer-p (current-buffer)) 1088 (or (compilation-buffer-p (current-buffer))
978 (error "Not in a compilation buffer.")) 1089 (error "Not in a compilation buffer."))
979 (setq compilation-last-buffer (current-buffer)) 1090 (setq compilation-last-buffer (current-buffer))
980 ;; `compile-reinitialize-errors' needs to see the complete filename 1091 ;; `compile-reinitialize-errors' needs to see the complete filename
981 ;; on the line where they clicked the mouse. Since it only looks 1092 ;; on the line where they clicked the mouse. Since it only looks
982 ;; upto point, moving point to eol makes sure the filename is 1093 ;; up to point, moving point to eol makes sure the filename is
983 ;; visible to `compile-reinitialize-errors'. 1094 ;; visible to `compile-reinitialize-errors'.
984 (end-of-line) 1095 (end-of-line)
985 (compile-reinitialize-errors nil (point)) 1096 (compile-reinitialize-errors nil (point))
986 1097
987 ;; Move to bol; the marker for the error on this line will point there. 1098 ;; Move to bol; the marker for the error on this line will point there.
1260 1371
1261 (if compilation-skip-to-next-location 1372 (if compilation-skip-to-next-location
1262 ;; Skip over multiple error messages for the same source location, 1373 ;; Skip over multiple error messages for the same source location,
1263 ;; so the next C-x ` won't go to an error in the same place. 1374 ;; so the next C-x ` won't go to an error in the same place.
1264 (while (and compilation-error-list 1375 (while (and compilation-error-list
1265 (equal (cdr (car compilation-error-list)) (cdr next-error))) 1376 (equal (cdr (car compilation-error-list))
1377 (cdr next-error)))
1266 (setq compilation-error-list (cdr compilation-error-list)))) 1378 (setq compilation-error-list (cdr compilation-error-list))))
1267 1379
1268 ;; We now have a marker for the position of the error source code. 1380 ;; We now have a marker for the position of the error source code.
1269 ;; NEXT-ERROR is a cons (ERROR . SOURCE) of two markers. 1381 ;; NEXT-ERROR is a cons (ERROR . SOURCE) of two markers.
1270 next-error)) 1382 next-error))
1359 (let ((inhibit-read-only t)) 1471 (let ((inhibit-read-only t))
1360 (remove-text-properties (point-min) (point-max) '(mouse-face highlight))) 1472 (remove-text-properties (point-min) (point-max) '(mouse-face highlight)))
1361 ) 1473 )
1362 1474
1363 1475
1476 ;; This function is not needed any more by compilation mode.
1477 ;; Does anyone else need it or can it be deleted?
1364 (defun count-regexp-groupings (regexp) 1478 (defun count-regexp-groupings (regexp)
1365 "Return the number of \\( ... \\) groupings in REGEXP (a string)." 1479 "Return the number of \\( ... \\) groupings in REGEXP (a string)."
1366 (let ((groupings 0) 1480 (let ((groupings 0)
1367 (len (length regexp)) 1481 (len (length regexp))
1368 (i 0) 1482 (i 0)
1384 ;; We found the end of a grouping, 1498 ;; We found the end of a grouping,
1385 ;; so bump our counter. 1499 ;; so bump our counter.
1386 (setq groupings (1+ groupings)))))))) 1500 (setq groupings (1+ groupings))))))))
1387 groupings)) 1501 groupings))
1388 1502
1503 (defvar compilation-current-file nil
1504 "Used by compilation-parse-errors to store filename for file being compiled")
1505
1506 ;; This variable is not used as a global variable. It's defined here just to
1507 ;; shut up the byte compiler. It's bound and used by compilation-parse-errors
1508 ;; and set by compile-collect-regexps.
1509 (defvar compilation-regexps nil)
1510
1389 (defun compilation-parse-errors (limit-search find-at-least) 1511 (defun compilation-parse-errors (limit-search find-at-least)
1390 "Parse the current buffer as grep, cc or lint error messages. 1512 "Parse the current buffer as grep, cc, lint or other error messages.
1391 See variable `compilation-parse-errors-function' for the interface it uses." 1513 See variable `compilation-parse-errors-function' for the interface it uses."
1392 (setq compilation-error-list nil) 1514 (setq compilation-error-list nil)
1393 (message "Parsing error messages...") 1515 (message "Parsing error messages...")
1394 (let (text-buffer orig orig-expanded parent-expanded 1516 (if (null compilation-error-regexp-alist)
1395 regexp enter-group leave-group error-group 1517 (error "compilation-error-regexp-alist is empty!"))
1396 alist subexpr error-regexp-groups 1518 (let* ((compilation-regexps nil) ; Variable set by compile-collect-regexps.
1397 (found-desired nil) 1519 (found-desired nil)
1398 (compilation-num-errors-found 0)) 1520 (compilation-num-errors-found 0)
1521 ;; Set up now the expanded, abbreviated directory variables
1522 ;; that compile-abbreviate-directory will need, so we can
1523 ;; compute them just once here.
1524 (orig (abbreviate-file-name default-directory))
1525 (orig-expanded (abbreviate-file-name
1526 (file-truename default-directory)))
1527 (parent-expanded (abbreviate-file-name
1528 (expand-file-name "../" orig-expanded))))
1529
1530 ;; Make a list of all the regexps. Each element has the form
1531 ;; (REGEXP TYPE IDX1 IDX2 ...)
1532 ;; where TYPE is one of leave, enter, file, error or nomessage.
1533 (compile-collect-regexps 'leave compilation-leave-directory-regexp-alist)
1534 (compile-collect-regexps 'enter compilation-enter-directory-regexp-alist)
1535 (compile-collect-regexps 'file compilation-file-regexp-alist)
1536 (compile-collect-regexps 'nomessage compilation-nomessage-regexp-alist)
1537 (compile-collect-regexps 'error compilation-error-regexp-alist)
1399 1538
1400 ;; Don't reparse messages already seen at last parse. 1539 ;; Don't reparse messages already seen at last parse.
1401 (goto-char compilation-parsing-end) 1540 (goto-char compilation-parsing-end)
1402 ;; Don't parse the first two lines as error messages.
1403 ;; This matters for grep.
1404 (if (bobp) 1541 (if (bobp)
1405 (progn 1542 (progn
1406 (forward-line 2) 1543 (setq compilation-current-file nil) ; No current file at start.
1407 ;; Move back so point is before the newline. 1544 ;; Don't parse the first two lines as error messages.
1408 ;; This matters because some error regexps use \n instead of ^ 1545 ;; This matters for grep.
1409 ;; to be faster. 1546 (forward-line 2)))
1410 (forward-char -1))) 1547
1411 1548 ;; Parse messages.
1412 ;; Compile all the regexps we want to search for into one. 1549 (while (not (or found-desired (eobp)))
1413 (setq regexp (concat "\\(" compilation-enter-directory-regexp "\\)\\|" 1550 (let ((this compilation-regexps) (prev nil) (alist nil) type)
1414 "\\(" compilation-leave-directory-regexp "\\)\\|" 1551 ;; Go through the regular expressions. If a match is found,
1415 "\\(" (mapconcat (function 1552 ;; variable alist is set to the corresponding alist and the
1416 (lambda (elt) 1553 ;; matching regexp is moved to the front of compilation-regexps
1417 (concat "\\(" (car elt) "\\)"))) 1554 ;; to make it match faster next time.
1418 compilation-error-regexp-alist 1555 (while (and this (null alist))
1419 "\\|") "\\)")) 1556 (if (not (looking-at (car (car this))))
1420 1557 (progn (setq prev this) ; No match, go to next.
1421 ;; Find out how many \(...\) groupings are in each of the regexps, and set 1558 (setq this (cdr this)))
1422 ;; *-GROUP to the grouping containing each constituent regexp (whose 1559 (setq alist (cdr (car this))) ; Got a match.
1423 ;; subgroups will come immediately thereafter) of the big regexp we have 1560 ;;; (if prev ; If not the first regexp,
1424 ;; just constructed. 1561 ;;; (progn ; move it to the front.
1425 (setq enter-group 1 1562 ;;; (setcdr prev (cdr this))
1426 leave-group (+ enter-group 1563 ;;; (setcdr this compilation-regexps)
1427 (count-regexp-groupings 1564 ;;; (setq compilation-regexps this)))
1428 compilation-enter-directory-regexp) 1565 ))
1429 1) 1566 (if (and alist ; Seen a match and not to
1430 error-group (+ leave-group 1567 (not (eq (setq type (car alist)) 'nomessage))) ; be ignored.
1431 (count-regexp-groupings 1568 (let* ((end-of-match (match-end 0))
1432 compilation-leave-directory-regexp) 1569 (filename
1433 1)) 1570 (compile-buffer-substring (car (setq alist (cdr alist)))))
1434 1571 stack)
1435 ;; Compile an alist (IDX FILE LINE [COL]), where IDX is the number of 1572 (if (eq type 'error) ; error message
1436 ;; the subexpression for an entire error-regexp, and FILE and LINE (and 1573 (let* ((linenum (if (numberp (car (setq alist (cdr alist))))
1437 ;; possibly COL) are the numbers for the subexpressions giving the file 1574 (string-to-int
1438 ;; name and line number (and possibly column number). 1575 (compile-buffer-substring (car alist)))
1439 (setq alist (or compilation-error-regexp-alist 1576 ;; (car alist) is not a number, must be a
1440 (error "compilation-error-regexp-alist is empty!")) 1577 ;; function that is called below to return
1441 subexpr (1+ error-group)) 1578 ;; an error position descriptor.
1442 (while alist 1579 (car alist)))
1443 (setq error-regexp-groups 1580 ;; Convert to integer later if linenum not a function.
1444 (cons (list subexpr 1581 (column (compile-buffer-substring
1445 (+ subexpr (nth 1 (car alist))) 1582 (car (setq alist (cdr alist)))))
1446 (+ subexpr (nth 2 (car alist))) 1583 this-error)
1447 (and (nth 3 (car alist)) 1584
1448 (+ subexpr (nth 3 (car alist))))) 1585 ;; Check that we have a file name.
1449 error-regexp-groups)) 1586 (or filename
1450 (setq subexpr (+ subexpr 1 (count-regexp-groupings (car (car alist))))) 1587 ;; No file name in message, we must have seen it before
1451 (setq alist (cdr alist))) 1588 (setq filename compilation-current-file)
1452 1589 (error "\
1453 ;; Set up now the expanded, abbreviated directory variables 1590 An error message with no file name and no file name has been seen earlier."))
1454 ;; that compile-abbreviate-directory will need, so we can 1591
1455 ;; compute them just once here. 1592 ;; Check for a comint-file-name-prefix and prepend it if
1456 (setq orig (abbreviate-file-name default-directory) 1593 ;; appropriate. (This is very useful for
1457 orig-expanded (abbreviate-file-name 1594 ;; compilation-minor-mode in an rlogin-mode buffer.)
1458 (file-truename default-directory)) 1595 (and (boundp 'comint-file-name-prefix)
1459 parent-expanded (abbreviate-file-name 1596 ;; If file name is relative, default-directory will
1460 (expand-file-name "../" orig-expanded))) 1597 ;; already contain the comint-file-name-prefix (done
1461 1598 ;; by compile-abbreviate-directory).
1462 (while (and (not found-desired) 1599 (file-name-absolute-p filename)
1463 ;; Instead of using re-search-forward, 1600 (setq filename
1464 ;; we use this loop which tries only at each line. 1601 (concat comint-file-name-prefix filename)))
1465 (progn 1602
1466 (while (and (not (eobp)) 1603 ;; Some compilers (e.g. Sun's java compiler, reportedly)
1467 (not (looking-at regexp))) 1604 ;; produce bogus file names like "./bar//foo.c" for file
1468 (forward-line 1)) 1605 ;; "bar/foo.c"; expand-file-name will collapse these into
1469 (not (eobp)))) 1606 ;; "/foo.c" and fail to find the appropriate file. So we
1470 1607 ;; look for doubled slashes in the file name and fix them
1471 ;; Move to the end of the match we just found. 1608 ;; up in the buffer.
1472 (goto-char (match-end 0)) 1609 (setq filename (command-line-normalize-file-name filename))
1473 1610
1474 ;; Figure out which constituent regexp matched. 1611 (setq filename
1475 (cond ((match-beginning enter-group) 1612 (cons filename (cons default-directory (cdr alist))))
1476 ;; The match was the enter-directory regexp. 1613
1477 (let ((dir 1614 ;; Locate the erring file and line.
1478 (file-name-as-directory 1615 ;; Make this-error a new elt for compilation-error-list,
1479 (expand-file-name 1616 ;; giving a marker for the current compilation buffer
1480 (buffer-substring (match-beginning (+ enter-group 1)) 1617 ;; location, and the file and line number of the error.
1481 (match-end (+ enter-group 1))))))) 1618 ;; Save, as the start of the error, the beginning of the
1482 ;; The directory name in the "entering" message 1619 ;; line containing the match.
1483 ;; is a truename. Try to convert it to a form 1620 (if (setq this-error
1484 ;; like what the user typed in. 1621 (if (numberp linenum)
1485 (setq dir 1622 (list (point-marker) filename linenum
1486 (compile-abbreviate-directory dir orig orig-expanded 1623 (and column (string-to-int column)))
1487 parent-expanded)) 1624 ;; If linenum is not a number then it must be
1488 (setq compilation-directory-stack 1625 ;; a function returning an error position
1489 (cons dir compilation-directory-stack)) 1626 ;; descriptor or nil (meaning no position).
1490 (and (file-directory-p dir) 1627 (save-excursion
1491 (setq default-directory dir))) 1628 (funcall linenum filename column))))
1492 1629
1493 (and limit-search (>= (point) limit-search) 1630 ;; We have an error position descriptor.
1494 ;; The user wanted a specific error, and we're past it. 1631 ;; If we have found as many new errors as the user
1495 ;; We do this check here (and in the leave-group case) 1632 ;; wants, or if we are past the buffer position he
1496 ;; rather than at the end of the loop because if the last 1633 ;; indicated, then we continue to parse until we have
1497 ;; thing seen is an error message, we must carefully 1634 ;; seen all consecutive errors in the same file. This
1498 ;; discard the last error when it is the first in a new 1635 ;; means that all the errors of a source file will be
1499 ;; file (see below in the error-group case). 1636 ;; seen in one parsing run, so that the error positions
1500 (setq found-desired t))) 1637 ;; will be recorded as markers in the source file
1501 1638 ;; buffer that will move when the buffer is changed.
1502 ((match-beginning leave-group) 1639 (if (and (or (and find-at-least
1503 ;; The match was the leave-directory regexp. 1640 (>= compilation-num-errors-found
1504 (let ((beg (match-beginning (+ leave-group 1)))
1505 (stack compilation-directory-stack))
1506 (if beg
1507 (let ((dir
1508 (file-name-as-directory
1509 (expand-file-name
1510 (buffer-substring beg
1511 (match-end (+ leave-group
1512 1)))))))
1513 ;; The directory name in the "leaving" message
1514 ;; is a truename. Try to convert it to a form
1515 ;; like what the user typed in.
1516 (setq dir
1517 (compile-abbreviate-directory dir orig orig-expanded
1518 parent-expanded))
1519 (while (and stack
1520 (not (string-equal (car stack) dir)))
1521 (setq stack (cdr stack)))))
1522 (setq compilation-directory-stack (cdr stack))
1523 (setq stack (car compilation-directory-stack))
1524 (if stack
1525 (setq default-directory stack))
1526 )
1527
1528 (and limit-search (>= (point) limit-search)
1529 ;; The user wanted a specific error, and we're past it.
1530 ;; We do this check here (and in the enter-group case)
1531 ;; rather than at the end of the loop because if the last
1532 ;; thing seen is an error message, we must carefully
1533 ;; discard the last error when it is the first in a new
1534 ;; file (see below in the error-group case).
1535 (setq found-desired t)))
1536
1537 ((match-beginning error-group)
1538 ;; The match was the composite error regexp.
1539 ;; Find out which individual regexp matched.
1540 (setq alist error-regexp-groups)
1541 (while (and alist
1542 (null (match-beginning (car (car alist)))))
1543 (setq alist (cdr alist)))
1544 (if alist
1545 (setq alist (car alist))
1546 (error "compilation-parse-errors: impossible regexp match!"))
1547
1548 ;; Extract the file name and line number from the error message.
1549 (let ((beginning-of-match (match-beginning 0)) ;looking-at nukes
1550 (filename (buffer-substring (match-beginning (nth 1 alist))
1551 (match-end (nth 1 alist))))
1552 (linenum (string-to-int
1553 (buffer-substring
1554 (match-beginning (nth 2 alist))
1555 (match-end (nth 2 alist)))))
1556 (column (and (nth 3 alist)
1557 (match-beginning (nth 3 alist))
1558 (string-to-int
1559 (buffer-substring
1560 (match-beginning (nth 3 alist))
1561 (match-end (nth 3 alist)))))))
1562
1563 ;; Check for a comint-file-name-prefix and prepend it if
1564 ;; appropriate. (This is very useful for
1565 ;; compilation-minor-mode in an rlogin-mode buffer.)
1566 (and (boundp 'comint-file-name-prefix)
1567 ;; If the file name is relative, default-directory will
1568 ;; already contain the comint-file-name-prefix (done by
1569 ;; compile-abbreviate-directory).
1570 (file-name-absolute-p filename)
1571 (setq filename (concat comint-file-name-prefix filename)))
1572
1573 ;; Some compilers (e.g. Sun's java compiler, reportedly)
1574 ;; produce bogus file names like "./bar//foo.c" for the file
1575 ;; "bar/foo.c"; expand-file-name will collapse these into
1576 ;; "/foo.c" and fail to find the appropriate file. So we look
1577 ;; for doubled slashes in the file name and fix them up in the
1578 ;; buffer.
1579 (setq filename (command-line-normalize-file-name filename))
1580 (setq filename (cons filename (cons default-directory
1581 (nthcdr 4 alist))))
1582
1583
1584 ;; Locate the erring file and line.
1585 ;; Cons a new elt onto compilation-error-list,
1586 ;; giving a marker for the current compilation buffer
1587 ;; location, and the file and line number of the error.
1588 (save-excursion
1589 ;; Save as the start of the error the beginning of the
1590 ;; line containing the match unless the match starts at a
1591 ;; newline, in which case the beginning of the next line.
1592 (goto-char beginning-of-match)
1593 (forward-line (if (eolp) 1 0))
1594 (let ((this (cons (point-marker)
1595 (list filename linenum column))))
1596 ;; Don't add the same source line more than once.
1597 (if (and compilation-skip-to-next-location
1598 (equal (cdr this)
1599 (cdr (car compilation-error-list))))
1600 nil
1601 (setq compilation-error-list
1602 (cons this
1603 compilation-error-list))
1604 (setq compilation-num-errors-found
1605 (1+ compilation-num-errors-found)))))
1606 (and (or (and find-at-least (> compilation-num-errors-found
1607 find-at-least)) 1641 find-at-least))
1608 (and limit-search (>= (point) limit-search))) 1642 (and limit-search
1609 ;; We have found as many new errors as the user wants, 1643 (>= end-of-match limit-search)))
1610 ;; or past the buffer position he indicated. We 1644 compilation-error-list ;At least one previous.
1611 ;; continue to parse until we have seen all the 1645 (not (equal ; Same filename?
1612 ;; consecutive errors in the same file, so the error 1646 (car (cdr (car compilation-error-list)))
1613 ;; positions will be recorded as markers in this buffer 1647 (car (cdr this-error)))))
1614 ;; that might change. 1648 ;; We are past the limits and the last error
1615 (cdr compilation-error-list) ; Must check at least two. 1649 ;; parsed, didn't belong to the same source file
1616 (not (equal (car (cdr (nth 0 compilation-error-list))) 1650 ;; as the earlier ones i.e. we have seen all the
1617 (car (cdr (nth 1 compilation-error-list))))) 1651 ;; errors belonging to the earlier file. We don't
1618 (progn 1652 ;; add the error just parsed so that the next
1619 ;; Discard the error just parsed, so that the next 1653 ;; parsing run can get it and the following errors
1620 ;; parsing run can get it and the following errors in 1654 ;; in the same file all at once.
1621 ;; the same file all at once. If we didn't do this, we 1655 (setq found-desired t)
1622 ;; would have the same problem we are trying to avoid 1656
1623 ;; with the test above, just delayed until the next run! 1657 (goto-char end-of-match) ; Prepare for next message.
1624 (setq compilation-error-list 1658 ;; Don't add the same source line more than once.
1625 (cdr compilation-error-list)) 1659 (and (not (and
1626 (goto-char beginning-of-match) 1660 compilation-error-list
1627 (setq found-desired t))) 1661 (equal (cdr (car compilation-error-list))
1628 ) 1662 (cdr this-error))))
1629 ) 1663 (setq compilation-error-list
1630 (t 1664 (cons this-error compilation-error-list)
1631 (error "compilation-parse-errors: known groups didn't match!"))) 1665 compilation-num-errors-found
1632 1666 (1+ compilation-num-errors-found))))))
1633 (message "Parsing error messages...%d (%.0f%% of buffer)" 1667
1668 ;; Not an error message.
1669 (if (eq type `file) ; Change current file.
1670 (and filename (setq compilation-current-file filename))
1671 ;; Enter or leave directory.
1672 (setq stack compilation-directory-stack)
1673 (and filename
1674 (file-directory-p
1675 (setq filename
1676 ;; The directory name in the message
1677 ;; is a truename. Try to convert it to a form
1678 ;; like what the user typed in.
1679 (compile-abbreviate-directory
1680 (file-name-as-directory
1681 (expand-file-name filename))
1682 orig orig-expanded parent-expanded)))
1683 (if (eq type 'leave)
1684 (while (and stack
1685 (not (string-equal (car stack)
1686 filename)))
1687 (setq stack (cdr stack)))
1688 (setq compilation-directory-stack
1689 (cons filename compilation-directory-stack)
1690 default-directory filename)))
1691 (and (eq type 'leave
1692 stack
1693 (setq compilation-directory-stack (cdr stack))
1694 (setq stack (car compilation-directory-stack))
1695 (setq default-directory stack)))
1696 (goto-char end-of-match) ; Prepare to look at next message.
1697 (and limit-search (>= end-of-match limit-search)
1698 ;; The user wanted a specific error, and we're past it.
1699 ;; We do this check here rather than at the end of the
1700 ;; loop because if the last thing seen is an error
1701 ;; message, we must carefully discard the last error
1702 ;; when it is the first in a new file (see above in
1703 ;; the error-message case)
1704 (setq found-desired t))))
1705
1706 ;; Go to before the last character in the message so that we will
1707 ;; see the next line also when the message ended at end of line.
1708 ;; When we ignore the last error message above, this will
1709 ;; cancel the effect of forward-line below so that point
1710 ;; doesn't move.
1711 (forward-char -1)
1712
1713 ;; Is this message necessary any more? Parsing is now so fast
1714 ;; that you might not need to know how it proceeds.
1715 (message
1716 "Parsing error messages...%d found. %.0f%% of buffer seen."
1634 compilation-num-errors-found 1717 compilation-num-errors-found
1635 ;; Use floating-point because (* 100 (point)) frequently 1718 ;; Use floating-point because (* 100 (point)) frequently
1636 ;; exceeds the range of Emacs Lisp integers. 1719 ;; exceeds the range of Emacs Lisp integers.
1637 (/ (* 100.0 (point)) (point-max))) 1720 (/ (* 100.0 (point)) (point-max)))
1638 1721 ))
1639 (and limit-search (>= (point) limit-search) 1722
1640 ;; The user wanted a specific error, and we're past it. 1723 (forward-line 1))) ; End of while loop. Look at next line.
1641 (setq found-desired t))) 1724
1642 (setq compilation-parsing-end (if found-desired 1725 (setq compilation-parsing-end (point))
1643 (point) 1726 (setq compilation-error-list (nreverse compilation-error-list))
1644 ;; We have searched the whole buffer. 1727 ;;; (message "Parsing error messages...done. %d found. %.0f%% of buffer seen."
1645 (point-max)))) 1728 ;;; compilation-num-errors-found
1646 (setq compilation-error-list (nreverse compilation-error-list)) 1729 ;;; (/ (* 100.0 (point)) (point-max)))
1647 (message "Parsing error messages...done")) 1730 (message "Parsing error messages...done.")))
1731
1732 (defun compile-collect-regexps (type this)
1733 ;; Add elements to variable compilation-regexps that is bound in
1734 ;; compilation-parse-errors.
1735 (and (not (eq this t))
1736 (while this
1737 (setq compilation-regexps
1738 (cons (cons (car (car this)) (cons type (cdr (car this))))
1739 compilation-regexps))
1740 (setq this (cdr this)))))
1741
1742 (defun compile-buffer-substring (index)
1743 ;; Get substring matched by INDEXth subexpression.
1744 (if index
1745 (let ((beg (match-beginning index)))
1746 (if beg (buffer-substring beg (match-end index))))))
1648 1747
1649 ;; If directory DIR is a subdir of ORIG or of ORIG's parent, 1748 ;; If directory DIR is a subdir of ORIG or of ORIG's parent,
1650 ;; return a relative name for it starting from ORIG or its parent. 1749 ;; return a relative name for it starting from ORIG or its parent.
1651 ;; ORIG-EXPANDED is an expanded version of ORIG. 1750 ;; ORIG-EXPANDED is an expanded version of ORIG.
1652 ;; PARENT-EXPANDED is an expanded version of ORIG's parent. 1751 ;; PARENT-EXPANDED is an expanded version of ORIG's parent.