compile.el 114 KB
Newer Older
1
;;; compile.el --- run compiler as inferior of Emacs, parse error messages
Eric S. Raymond's avatar
Eric S. Raymond committed
2

3
;; Copyright (C) 1985-1987, 1993-1999, 2001-2011
4
;;   Free Software Foundation, Inc.
Eric S. Raymond's avatar
Eric S. Raymond committed
5

Stefan Monnier's avatar
Stefan Monnier committed
6 7
;; Authors: Roland McGrath <roland@gnu.org>,
;;	    Daniel Pfeiffer <occitan@esperanto.org>
Eric S. Raymond's avatar
Eric S. Raymond committed
8
;; Maintainer: FSF
Eric S. Raymond's avatar
Eric S. Raymond committed
9
;; Keywords: tools, processes
Eric S. Raymond's avatar
Eric S. Raymond committed
10

Richard M. Stallman's avatar
Richard M. Stallman committed
11 12
;; This file is part of GNU Emacs.

13
;; GNU Emacs is free software: you can redistribute it and/or modify
Roland McGrath's avatar
Roland McGrath committed
14
;; it under the terms of the GNU General Public License as published by
15 16
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
Roland McGrath's avatar
Roland McGrath committed
17

Richard M. Stallman's avatar
Richard M. Stallman committed
18
;; GNU Emacs is distributed in the hope that it will be useful,
Roland McGrath's avatar
Roland McGrath committed
19 20 21 22 23
;; 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
24
;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
Richard M. Stallman's avatar
Richard M. Stallman committed
25

Eric S. Raymond's avatar
Eric S. Raymond committed
26 27
;;; Commentary:

Stefan Monnier's avatar
Stefan Monnier committed
28 29
;; This package provides the compile facilities documented in the Emacs user's
;; manual.
Eric S. Raymond's avatar
Eric S. Raymond committed
30

31 32
;;; Code:

Stefan Monnier's avatar
Stefan Monnier committed
33
(eval-when-compile (require 'cl))
Jan Djärv's avatar
Jan Djärv committed
34
(require 'tool-bar)
35
(require 'comint)
Stefan Monnier's avatar
Stefan Monnier committed
36

37 38 39 40 41 42
(defgroup compilation nil
  "Run compiler as inferior of Emacs, parse error messages."
  :group 'tools
  :group 'processes)


Roland McGrath's avatar
Roland McGrath committed
43
;;;###autoload
44
(defcustom compilation-mode-hook nil
45
  "List of hook functions run by `compilation-mode' (see `run-mode-hooks')."
46 47
  :type 'hook
  :group 'compilation)
Roland McGrath's avatar
Roland McGrath committed
48

49 50 51 52 53 54 55 56 57 58 59
;;;###autoload
(defcustom compilation-start-hook nil
  "List of hook functions run by `compilation-start' on the compilation process.
\(See `run-hook-with-args').
If you use \"omake -P\" and do not want \\[save-buffers-kill-terminal] to ask whether you want
the compilation to be killed, you can use this hook:
  (add-hook 'compilation-start-hook
    (lambda (process) (set-process-query-on-exit-flag process nil)) nil t)"
  :type 'hook
  :group 'compilation)

Roland McGrath's avatar
Roland McGrath committed
60
;;;###autoload
61
(defcustom compilation-window-height nil
62
  "Number of lines in a compilation window.  If nil, use Emacs default."
63 64 65
  :type '(choice (const :tag "Default" nil)
		 integer)
  :group 'compilation)
Roland McGrath's avatar
Roland McGrath committed
66

67 68 69 70 71 72 73 74 75 76
(defvar compilation-filter-hook nil
  "Hook run after `compilation-filter' has inserted a string into the buffer.
It is called with the variable `compilation-filter-start' bound
to the position of the start of the inserted text, and point at
its end.")

(defvar compilation-filter-start nil
  "Start of the text inserted by `compilation-filter'.
This is bound to a buffer position before running `compilation-filter-hook'.")

Stefan Monnier's avatar
Stefan Monnier committed
77 78
(defvar compilation-first-column 1
  "*This is how compilers number the first column, usually 1 or 0.")
Richard M. Stallman's avatar
Richard M. Stallman committed
79

80 81 82 83 84
(defvar compilation-parse-errors-filename-function nil
  "Function to call to post-process filenames while parsing error messages.
It takes one arg FILENAME which is the name of a file as found
in the compilation output, and should return a transformed file name.")

85 86 87
;;;###autoload
(defvar compilation-process-setup-function nil
  "*Function to call to customize the compilation process.
Stefan Monnier's avatar
Stefan Monnier committed
88
This function is called immediately before the compilation process is
89
started.  It can be used to set any variables or functions that are used
90
while processing the output of the compilation process.")
91

Jim Blandy's avatar
Jim Blandy committed
92
;;;###autoload
Roland McGrath's avatar
Roland McGrath committed
93
(defvar compilation-buffer-name-function nil
Richard M. Stallman's avatar
Richard M. Stallman committed
94 95 96
  "Function to compute the name of a compilation buffer.
The function receives one argument, the name of the major mode of the
compilation buffer.  It should return a string.
97
If nil, compute the name with `(concat \"*\" (downcase major-mode) \"*\")'.")
Richard M. Stallman's avatar
Richard M. Stallman committed
98

Jim Blandy's avatar
Jim Blandy committed
99
;;;###autoload
Roland McGrath's avatar
Roland McGrath committed
100
(defvar compilation-finish-function nil
101
  "Function to call when a compilation process finishes.
Roland McGrath's avatar
Roland McGrath committed
102
It is called with two arguments: the compilation buffer, and a string
103
describing how the process finished.")
104 105

(make-obsolete-variable 'compilation-finish-function
106
  "use `compilation-finish-functions', but it works a little differently."
107
  "22.1")
Richard M. Stallman's avatar
Richard M. Stallman committed
108

109 110
;;;###autoload
(defvar compilation-finish-functions nil
111
  "Functions to call when a compilation process finishes.
112 113 114
Each function is called with two arguments: the compilation buffer,
and a string describing how the process finished.")

Roland McGrath's avatar
Roland McGrath committed
115 116 117 118 119 120
(defvar compilation-in-progress nil
  "List of compilation processes now running.")
(or (assq 'compilation-in-progress minor-mode-alist)
    (setq minor-mode-alist (cons '(compilation-in-progress " Compiling")
				 minor-mode-alist)))

Stefan Monnier's avatar
Stefan Monnier committed
121 122
(defvar compilation-error "error"
  "Stem of message to print when no matches are found.")
Richard M. Stallman's avatar
Richard M. Stallman committed
123

124
(defvar compilation-arguments nil
Stefan Monnier's avatar
Stefan Monnier committed
125
  "Arguments that were given to `compilation-start'.")
126

Richard M. Stallman's avatar
Richard M. Stallman committed
127
(defvar compilation-num-errors-found)
Roland McGrath's avatar
Roland McGrath committed
128

129 130 131
;; If you make any changes to `compilation-error-regexp-alist-alist',
;; be sure to run the ERT test in test/automated/compile-tests.el.

132
(defvar compilation-error-regexp-alist-alist
Stefan Monnier's avatar
Stefan Monnier committed
133 134 135
  '((absoft
     "^\\(?:[Ee]rror on \\|[Ww]arning on\\( \\)\\)?[Ll]ine[ \t]+\\([0-9]+\\)[ \t]+\
of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
136

Stefan Monnier's avatar
Stefan Monnier committed
137 138
    (ada
     "\\(warning: .*\\)? at \\([^ \n]+\\):\\([0-9]+\\)$" 2 3 nil (1))
Karl Heuer's avatar
Karl Heuer committed
139

Stefan Monnier's avatar
Stefan Monnier committed
140 141
    (aix
     " in line \\([0-9]+\\) of file \\([^ \n]+[^. \n]\\)\\.? " 2 1)
142

Stefan Monnier's avatar
Stefan Monnier committed
143
    (ant
144 145
     "^[ \t]*\\[[^] \n]+\\][ \t]*\\([^: \n]+\\):\\([0-9]+\\):\\(?:\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\):\\)?\
\\( warning\\)?" 1 (2 . 4) (3 . 5) (4))
146

Stefan Monnier's avatar
Stefan Monnier committed
147 148
    (bash
     "^\\([^: \n\t]+\\): line \\([0-9]+\\):" 1 2)
149

Stefan Monnier's avatar
Stefan Monnier committed
150 151 152 153 154 155
    (borland
     "^\\(?:Error\\|Warnin\\(g\\)\\) \\(?:[FEW][0-9]+ \\)?\
\\([a-zA-Z]?:?[^:( \t\n]+\\)\
 \\([0-9]+\\)\\(?:[) \t]\\|:[^0-9\n]\\)" 2 3 nil (1))

    (caml
156 157 158
     "^ *File \\(\"?\\)\\([^,\" \n\t<>]+\\)\\1, lines? \\([0-9]+\\)-?\\([0-9]+\\)?\\(?:$\\|,\
\\(?: characters? \\([0-9]+\\)-?\\([0-9]+\\)?:\\)?\\([ \n]Warning:\\)?\\)"
     2 (3 . 4) (5 . 6) (7))
Stefan Monnier's avatar
Stefan Monnier committed
159 160 161 162 163

    (comma
     "^\"\\([^,\" \n\t]+\\)\", line \\([0-9]+\\)\
\\(?:[(. pos]+\\([0-9]+\\))?\\)?[:.,; (-]\\( warning:\\|[-0-9 ]*(W)\\)?" 1 2 3 (4))

164 165 166 167
    (cucumber
     "\\(?:^cucumber\\(?: -p [^[:space:]]+\\)?\\|#\\)\
\\(?: \\)\\([^\(].*\\):\\([1-9][0-9]*\\)" 1 2)

168 169 170 171 172 173 174
    (edg-1
     "^\\([^ \n]+\\)(\\([0-9]+\\)): \\(?:error\\|warnin\\(g\\)\\|remar\\(k\\)\\)"
     1 2 nil (3 . 4))
    (edg-2
     "at line \\([0-9]+\\) of \"\\([^ \n]+\\)\"$"
     2 1 nil 0)

Stefan Monnier's avatar
Stefan Monnier committed
175
    (epc
176
     "^Error [0-9]+ at (\\([0-9]+\\):\\([^)\n]+\\))" 2 1)
Stefan Monnier's avatar
Stefan Monnier committed
177

178 179 180
    (ftnchek
     "\\(^Warning .*\\)? line[ \n]\\([0-9]+\\)[ \n]\\(?:col \\([0-9]+\\)[ \n]\\)?file \\([^ :;\n]+\\)"
     4 2 3 (1))
181

Stefan Monnier's avatar
Stefan Monnier committed
182 183 184 185 186 187 188 189
    (iar
     "^\"\\(.*\\)\",\\([0-9]+\\)\\s-+\\(?:Error\\|Warnin\\(g\\)\\)\\[[0-9]+\\]:"
     1 2 nil (3))

    (ibm
     "^\\([^( \n\t]+\\)(\\([0-9]+\\):\\([0-9]+\\)) :\
 \\(?:warnin\\(g\\)\\|informationa\\(l\\)\\)?" 1 2 3 (4 . 5))

Stefan Monnier's avatar
Stefan Monnier committed
190
    ;; fixme: should be `mips'
Stefan Monnier's avatar
Stefan Monnier committed
191
    (irix
192 193
     "^[-[:alnum:]_/ ]+: \\(?:\\(?:[sS]evere\\|[eE]rror\\|[wW]arnin\\(g\\)\\|[iI]nf\\(o\\)\\)[0-9 ]*: \\)?\
\\([^,\" \n\t]+\\)\\(?:, line\\|:\\) \\([0-9]+\\):" 3 4 nil (1 . 2))
Stefan Monnier's avatar
Stefan Monnier committed
194 195 196 197 198 199

    (java
     "^\\(?:[ \t]+at \\|==[0-9]+== +\\(?:at\\|b\\(y\\)\\)\\).+(\\([^()\n]+\\):\\([0-9]+\\))$" 2 3 nil (1))

    (jikes-file
     "^\\(?:Found\\|Issued\\) .* compiling \"\\(.+\\)\":$" 1 nil nil 0)
200 201 202 203 204 205 206 207


    ;; This used to be pathologically slow on long lines (Bug#3441),
    ;; due to matching filenames via \\(.*?\\).  This might be faster.
    (maven
     ;; Maven is a popular free software build tool for Java.
     "\\([0-9]*[^0-9\n]\\(?:[^\n :]\\| [^-/\n]\\|:[^ \n]\\)*?\\):\\[\\([0-9]+\\),\\([0-9]+\\)\\] " 1 2 3)

Stefan Monnier's avatar
Stefan Monnier committed
208 209 210 211 212
    (jikes-line
     "^ *\\([0-9]+\\)\\.[ \t]+.*\n +\\(<-*>\n\\*\\*\\* \\(?:Error\\|Warnin\\(g\\)\\)\\)"
     nil 1 nil 2 0
     (2 (compilation-face '(3))))

213 214
    (gcc-include
     "^\\(?:In file included \\|                 \\|\t\\)from \
Andreas Schwab's avatar
Andreas Schwab committed
215 216 217
\\([0-9]*[^0-9\n]\\(?:[^\n :]\\| [^-/\n]\\|:[^ \n]\\)*?\\):\
\\([0-9]+\\)\\(?::\\([0-9]+\\)\\)?\\(?:\\(:\\)\\|\\(,\\|$\\)\\)?"
     1 2 3 (4 . 5))
218

219 220 221
    (ruby-Test::Unit
     "^[\t ]*\\[\\([^\(].*\\):\\([1-9][0-9]*\\)\\(\\]\\)?:in " 1 2)

Stefan Monnier's avatar
Stefan Monnier committed
222
    (gnu
223 224 225 226 227 228 229 230 231 232 233 234 235
     ;; The first line matches the program name for

     ;;     PROGRAM:SOURCE-FILE-NAME:LINENO: MESSAGE

     ;; format, which is used for non-interactive programs other than
     ;; compilers (e.g. the "jade:" entry in compilation.txt).

     ;; This first line makes things ambiguous with output such as
     ;; "foo:344:50:blabla" since the "foo" part can match this first
     ;; line (in which case the file name as "344").  To avoid this,
     ;; the second line disallows filenames exclusively composed of
     ;; digits.

236 237 238 239
     ;; Similarly, we get lots of false positives with messages including
     ;; times of the form "HH:MM:SS" where MM is taken as a line number, so
     ;; the last line tries to rule out message where the info after the
     ;; line number starts with "SS".  --Stef
240 241 242 243

     ;; The core of the regexp is the one with *?.  It says that a file name
     ;; can be composed of any non-newline char, but it also rules out some
     ;; valid but unlikely cases, such as a trailing space or a space
244 245 246
     ;; followed by a -, or a colon followed by a space.

     ;; The "in \\|from " exception was added to handle messages from Ruby.
247
     "^\\(?:[[:alpha:]][-[:alnum:].]+: ?\\|[ \t]+\\(?:in \\|from \\)\\)?\
248
\\([0-9]*[^0-9\n]\\(?:[^\n :]\\| [^-/\n]\\|:[^ \n]\\)*?\\): ?\
249
\\([0-9]+\\)\\(?:[.:]\\([0-9]+\\)\\)?\
Chong Yidong's avatar
Chong Yidong committed
250
\\(?:-\\([0-9]+\\)?\\(?:\\.\\([0-9]+\\)\\)?\\)?:\
Stefan Monnier's avatar
Stefan Monnier committed
251
\\(?: *\\(\\(?:Future\\|Runtime\\)?[Ww]arning\\|W:\\)\\|\
252
 *\\([Ii]nfo\\(?:\\>\\|rmationa?l?\\)\\|I:\\|instantiated from\\|[Nn]ote\\)\\|\
253
\[0-9]?\\(?:[^0-9\n]\\|$\\)\\|[0-9][0-9][0-9]\\)"
254
     1 (2 . 4) (3 . 5) (6 . 7))
Stefan Monnier's avatar
Stefan Monnier committed
255 256 257 258 259 260

    (lcc
     "^\\(?:E\\|\\(W\\)\\), \\([^(\n]+\\)(\\([0-9]+\\),[ \t]*\\([0-9]+\\)"
     2 3 4 (1))

    (makepp
Daniel Pfeiffer's avatar
Daniel Pfeiffer committed
261
     "^makepp\\(?:\\(?:: warning\\(:\\).*?\\|\\(: Scanning\\|: [LR]e?l?oading makefile\\|: Imported\\|log:.*?\\) \\|: .*?\\)\
262
`\\(\\(\\S +?\\)\\(?::\\([0-9]+\\)\\)?\\)['(]\\)"
Stefan Monnier's avatar
Stefan Monnier committed
263
     4 5 nil (1 . 2) 3
264 265 266 267 268 269 270 271 272
     (0 (progn (save-match-data
                 (compilation-parse-errors
                  (match-end 0) (line-end-position)
                  `("`\\(\\(\\S +?\\)\\(?::\\([0-9]+\\)\\)?\\)['(]"
                    2 3 nil
                    ,(cond ((match-end 1) 1) ((match-end 2) 0) (t 2))
                    1)))
               (end-of-line)
               nil)))
Stefan Monnier's avatar
Stefan Monnier committed
273

Stefan Monnier's avatar
Stefan Monnier committed
274
    ;; Should be lint-1, lint-2 (SysV lint)
Stefan Monnier's avatar
Stefan Monnier committed
275 276 277 278 279 280
    (mips-1
     " (\\([0-9]+\\)) in \\([^ \n]+\\)" 2 1)
    (mips-2
     " in \\([^()\n ]+\\)(\\([0-9]+\\))$" 1 2)

    (msft
281 282 283 284 285
     ;; The message may be a "warning", "error", or "fatal error" with
     ;; an error code, or "see declaration of" without an error code.
     "^ *\\([0-9]+>\\)?\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)) \
: \\(?:see declaration\\|\\(?:warnin\\(g\\)\\|[a-z ]+\\) C[0-9]+:\\)"
     2 3 nil (4))
Stefan Monnier's avatar
Stefan Monnier committed
286

287 288 289
    (omake
     ;; "omake -P" reports "file foo changed"
     ;; (useful if you do "cvs up" and want to see what has changed)
290 291 292 293 294 295
     "omake: file \\(.*\\) changed" 1 nil nil nil nil
     ;; FIXME-omake: This tries to prevent reusing pre-existing markers
     ;; for subsequent messages, since those messages's line numbers
     ;; are about another version of the file.
     (0 (progn (compilation--flush-file-structure (match-string 1))
               nil)))
296

Stefan Monnier's avatar
Stefan Monnier committed
297
    (oracle
298 299 300
     "^\\(?:Semantic error\\|Error\\|PCC-[0-9]+:\\).* line \\([0-9]+\\)\
\\(?:\\(?:,\\| at\\)? column \\([0-9]+\\)\\)?\
\\(?:,\\| in\\| of\\)? file \\(.*?\\):?$"
Stefan Monnier's avatar
Stefan Monnier committed
301
     3 1 2)
302

303 304 305
    ;; "during global destruction": This comes out under "use
    ;; warnings" in recent perl when breaking circular references
    ;; during program or thread exit.
Stefan Monnier's avatar
Stefan Monnier committed
306
    (perl
307 308
     " at \\([^ \n]+\\) line \\([0-9]+\\)\\(?:[,.]\\|$\\| \
during global destruction\\.$\\)" 1 2)
Stefan Monnier's avatar
Stefan Monnier committed
309

310 311 312 313
    (php
     "\\(?:Parse\\|Fatal\\) error: \\(.*\\) in \\(.*\\) on line \\([0-9]+\\)"
     2 3 nil nil)

Stefan Monnier's avatar
Stefan Monnier committed
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
    (rxp
     "^\\(?:Error\\|Warnin\\(g\\)\\):.*\n.* line \\([0-9]+\\) char\
 \\([0-9]+\\) of file://\\(.+\\)"
     4 2 3 (1))

    (sparc-pascal-file
     "^\\w\\w\\w \\w\\w\\w +[0-3]?[0-9] +[0-2][0-9]:[0-5][0-9]:[0-5][0-9]\
 [12][09][0-9][0-9] +\\(.*\\):$"
     1 nil nil 0)
    (sparc-pascal-line
     "^\\(\\(?:E\\|\\(w\\)\\) +[0-9]+\\) line \\([0-9]+\\) -  "
     nil 3 nil (2) nil (1 (compilation-face '(2))))
    (sparc-pascal-example
     "^ +\\([0-9]+\\) +.*\n\\(\\(?:e\\|\\(w\\)\\) [0-9]+\\)-+"
     nil 1 nil (3) nil (2 (compilation-face '(3))))

    (sun
Stefan Monnier's avatar
Stefan Monnier committed
331
     ": \\(?:ERROR\\|WARNIN\\(G\\)\\|REMAR\\(K\\)\\) \\(?:[[:alnum:] ]+, \\)?\
Stefan Monnier's avatar
Stefan Monnier committed
332 333 334 335 336 337
File = \\(.+\\), Line = \\([0-9]+\\)\\(?:, Column = \\([0-9]+\\)\\)?"
     3 4 5 (1 . 2))

    (sun-ada
     "^\\([^, \n\t]+\\), line \\([0-9]+\\), char \\([0-9]+\\)[:., \(-]" 1 2 3)

338
    (watcom
339
     "^[ \t]*\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)): ?\
Chong Yidong's avatar
Chong Yidong committed
340 341
\\(?:\\(Error! E[0-9]+\\)\\|\\(Warning! W[0-9]+\\)\\):"
     1 2 nil (4))
342

Stefan Monnier's avatar
Stefan Monnier committed
343 344
    (4bsd
     "\\(?:^\\|::  \\|\\S ( \\)\\(/[^ \n\t()]+\\)(\\([0-9]+\\))\
345 346 347
\\(?:: \\(warning:\\)?\\|$\\| ),\\)" 1 2 nil (3))

    (gcov-file
348
     "^ *-: *\\(0\\):Source:\\(.+\\)$"
349
     2 1 nil 0 nil)
350 351
    (gcov-header
     "^ *-: *\\(0\\):\\(?:Object\\|Graph\\|Data\\|Runs\\|Programs\\):.+$"
352
     nil 1 nil 0 nil)
353 354 355 356 357 358 359 360
    ;; Underlines over all lines of gcov output are too uncomfortable to read.
    ;; However, hyperlinks embedded in the lines are useful.
    ;; So I put default face on the lines; and then put
    ;; compilation-*-face by manually to eliminate the underlines.
    ;; The hyperlinks are still effective.
    (gcov-nomark
     "^ *-: *\\([1-9]\\|[0-9]\\{2,\\}\\):.*$"
     nil 1 nil 0 nil
361 362
     (0 'default)
     (1 compilation-line-face))
363
    (gcov-called-line
364
     "^ *\\([0-9]+\\): *\\([0-9]+\\):.*$"
365
     nil 2 nil 0 nil
366 367
     (0 'default)
     (1 compilation-info-face) (2 compilation-line-face))
368
    (gcov-never-called
369
     "^ *\\(#####\\): *\\([0-9]+\\):.*$"
370
     nil 2 nil 2 nil
371 372
     (0 'default)
     (1 compilation-error-face) (2 compilation-line-face))
373

374
    (perl--Pod::Checker
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
     ;; podchecker error messages, per Pod::Checker.
     ;; The style is from the Pod::Checker::poderror() function, eg.
     ;; *** ERROR: Spurious text after =cut at line 193 in file foo.pm
     ;;
     ;; Plus end_pod() can give "at line EOF" instead of a
     ;; number, so for that match "on line N" which is the
     ;; originating spot, eg.
     ;; *** ERROR: =over on line 37 without closing =back at line EOF in file bar.pm
     ;;
     ;; Plus command() can give both "on line N" and "at line N";
     ;; the latter is desired and is matched because the .* is
     ;; greedy.
     ;; *** ERROR: =over on line 1 without closing =back (at head1) at line 3 in file x.pod
     ;;
     "^\\*\\*\\* \\(?:ERROR\\|\\(WARNING\\)\\).* \\(?:at\\|on\\) line \
\\([0-9]+\\) \\(?:.* \\)?in file \\([^ \t\n]+\\)"
     3 2 nil (1))
392
    (perl--Test
393 394 395 396 397 398
     ;; perl Test module error messages.
     ;; Style per the ok() function "$context", eg.
     ;; # Failed test 1 in foo.t at line 6
     ;;
     "^# Failed test [0-9]+ in \\([^ \t\r\n]+\\) at line \\([0-9]+\\)"
     1 2)
399
    (perl--Test2
400 401 402 403 404 405 406 407 408 409
     ;; Or when comparing got/want values,
     ;; # Test 2 got: "xx" (t-compilation-perl-2.t at line 10)
     ;;
     ;; And under Test::Harness they're preceded by progress stuff with
     ;; \r and "NOK",
     ;; ... NOK 1# Test 1 got: "1234" (t/foo.t at line 46)
     ;;
     "^\\(.*NOK.*\\)?# Test [0-9]+ got:.* (\\([^ \t\r\n]+\\) at line \
\\([0-9]+\\))"
     2 3)
410
    (perl--Test::Harness
411 412 413 414 415 416 417 418 419 420
     ;; perl Test::Harness output, eg.
     ;; NOK 1# Test 1 got: "1234" (t/foo.t at line 46)
     ;;
     ;; Test::Harness is slightly designed for tty output, since
     ;; it prints CRs to overwrite progress messages, but if you
     ;; run it in with M-x compile this pattern can at least step
     ;; through the failures.
     ;;
     "^.*NOK.* \\([^ \t\r\n]+\\) at line \\([0-9]+\\)"
     1 2)
421
    (weblint
422 423 424 425 426 427 428 429 430 431 432 433 434
     ;; The style comes from HTML::Lint::Error::as_string(), eg.
     ;; index.html (13:1) Unknown element <fdjsk>
     ;;
     ;; The pattern only matches filenames without spaces, since that
     ;; should be usual and should help reduce the chance of a false
     ;; match of a message from some unrelated program.
     ;;
     ;; This message style is quite close to the "ibm" entry which is
     ;; for IBM C, though that ibm bit doesn't put a space after the
     ;; filename.
     ;;
     "^\\([^ \t\r\n(]+\\) (\\([0-9]+\\):\\([0-9]+\\)) "
     1 2 3)
435
    )
Stefan Monnier's avatar
Stefan Monnier committed
436 437 438 439
  "Alist of values for `compilation-error-regexp-alist'.")

(defcustom compilation-error-regexp-alist
  (mapcar 'car compilation-error-regexp-alist-alist)
Richard M. Stallman's avatar
Richard M. Stallman committed
440
  "Alist that specifies how to match errors in compiler output.
441
On GNU and Unix, any string is a valid filename, so these
Stefan Monnier's avatar
Stefan Monnier committed
442 443 444 445 446 447
matchers must make some common sense assumptions, which catch
normal cases.  A shorter list will be lighter on resource usage.

Instead of an alist element, you can use a symbol, which is
looked up in `compilation-error-regexp-alist-alist'.  You can see
the predefined symbols and their effects in the file
Stefan Monnier's avatar
Stefan Monnier committed
448
`etc/compilation.txt' (linked below if you are customizing this).
Stefan Monnier's avatar
Stefan Monnier committed
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464

Each elt has the form (REGEXP FILE [LINE COLUMN TYPE HYPERLINK
HIGHLIGHT...]).  If REGEXP matches, the FILE'th subexpression
gives the file name, and the LINE'th subexpression gives the line
number.  The COLUMN'th subexpression gives the column number on
that line.

If FILE, LINE or COLUMN are nil or that index didn't match, that
information is not present on the matched line.  In that case the
file name is assumed to be the same as the previous one in the
buffer, line number defaults to 1 and column defaults to
beginning of line's indentation.

FILE can also have the form (FILE FORMAT...), where the FORMATs
\(e.g. \"%s.c\") will be applied in turn to the recognized file
name, until a file of that name is found.  Or FILE can also be a
465 466
function that returns (FILENAME) or (RELATIVE-FILENAME . DIRNAME).
In the former case, FILENAME may be relative or absolute.
Stefan Monnier's avatar
Stefan Monnier committed
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483

LINE can also be of the form (LINE . END-LINE) meaning a range
of lines.  COLUMN can also be of the form (COLUMN . END-COLUMN)
meaning a range of columns starting on LINE and ending on
END-LINE, if that matched.

TYPE is 2 or nil for a real error or 1 for warning or 0 for info.
TYPE can also be of the form (WARNING . INFO).  In that case this
will be equivalent to 1 if the WARNING'th subexpression matched
or else equivalent to 0 if the INFO'th subexpression matched.
See `compilation-error-face', `compilation-warning-face',
`compilation-info-face' and `compilation-skip-threshold'.

What matched the HYPERLINK'th subexpression has `mouse-face' and
`compilation-message-face' applied.  If this is nil, the text
matched by the whole REGEXP becomes the hyperlink.

484 485 486
Additional HIGHLIGHTs take the shape (SUBMATCH FACE), where SUBMATCH is
the number of a submatch that should be highlighted when it matches,
and FACE is an expression returning the face to use for that submatch.."
Glenn Morris's avatar
Glenn Morris committed
487 488
  :type '(repeat (choice (symbol :tag "Predefined symbol")
			 (sexp :tag "Error specification")))
Stefan Monnier's avatar
Stefan Monnier committed
489
  :link `(file-link :tag "example file"
490
		    ,(expand-file-name "compilation.txt" data-directory))
Stefan Monnier's avatar
Stefan Monnier committed
491
  :group 'compilation)
Richard M. Stallman's avatar
Richard M. Stallman committed
492

493
;;;###autoload(put 'compilation-directory 'safe-local-variable 'stringp)
494 495 496
(defvar compilation-directory nil
  "Directory to restore to when doing `recompile'.")

Stefan Monnier's avatar
Stefan Monnier committed
497 498 499
(defvar compilation-directory-matcher
  '("\\(?:Entering\\|Leavin\\(g\\)\\) directory `\\(.+\\)'$" (2 . 1))
  "A list for tracking when directories are entered or left.
500
If nil, do not track directories, e.g. if all file names are absolute.  The
Stefan Monnier's avatar
Stefan Monnier committed
501 502 503 504 505 506 507 508 509 510 511 512 513 514
first element is the REGEXP matching these messages.  It can match any number
of variants, e.g. different languages.  The remaining elements are all of the
form (DIR .  LEAVE).  If for any one of these the DIR'th subexpression
matches, that is a directory name.  If LEAVE is nil or the corresponding
LEAVE'th subexpression doesn't match, this message is about going into another
directory.  If it does match anything, this message is about going back to the
directory we were in before the last entering message.  If you change this,
you may also want to change `compilation-page-delimiter'.")

(defvar compilation-page-delimiter
  "^\\(?:\f\\|.*\\(?:Entering\\|Leaving\\) directory `.+'\n\\)+"
  "Value of `page-delimiter' in Compilation mode.")

(defvar compilation-mode-font-lock-keywords
515
   '(;; configure output lines.
Stefan Monnier's avatar
Stefan Monnier committed
516 517
     ("^[Cc]hecking \\(?:[Ff]or \\|[Ii]f \\|[Ww]hether \\(?:to \\)?\\)?\\(.+\\)\\.\\.\\. *\\(?:(cached) *\\)?\\(\\(yes\\(?: .+\\)?\\)\\|no\\|\\(.*\\)\\)$"
      (1 font-lock-variable-name-face)
518
      (2 (compilation-face '(4 . 3))))
Stefan Monnier's avatar
Stefan Monnier committed
519
     ;; Command output lines.  Recognize `make[n]:' lines too.
Stefan Monnier's avatar
Stefan Monnier committed
520
     ("^\\([[:alnum:]_/.+-]+\\)\\(\\[\\([0-9]+\\)\\]\\)?[ \t]*:"
Stefan Monnier's avatar
Stefan Monnier committed
521
      (1 font-lock-function-name-face) (3 compilation-line-face nil t))
522
     (" -\\(?:o[= ]?\\|-\\(?:outfile\\|output\\)[= ]\\)\\(\\S +\\)" . 1)
523
     ("^Compilation \\(finished\\).*"
524
      (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t)
525
      (1 compilation-info-face))
526
     ("^Compilation \\(exited abnormally\\|interrupt\\|killed\\|terminated\\|segmentation fault\\)\\(?:.*with code \\([0-9]+\\)\\)?.*"
527
      (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t)
528 529
      (1 compilation-error-face)
      (2 compilation-error-face nil t)))
Stefan Monnier's avatar
Stefan Monnier committed
530 531
   "Additional things to highlight in Compilation mode.
This gets tacked on the end of the generated expressions.")
532

533 534 535 536 537 538 539
(defvar compilation-highlight-regexp t
  "Regexp matching part of visited source lines to highlight temporarily.
Highlight entire line if t; don't highlight source lines if nil.")

(defvar compilation-highlight-overlay nil
  "Overlay used to temporarily highlight compilation matches.")

540
(defcustom compilation-error-screen-columns t
541
  "If non-nil, column numbers in error messages are screen columns.
542 543 544 545 546 547 548 549 550
Otherwise they are interpreted as character positions, with
each character occupying one column.
The default is to use screen columns, which requires that the compilation
program and Emacs agree about the display width of the characters,
especially the TAB character."
  :type 'boolean
  :group 'compilation
  :version "20.4")

551
(defcustom compilation-read-command t
552
  "Non-nil means \\[compile] reads the compilation command to use.
553 554 555 556 557 558
Otherwise, \\[compile] just uses the value of `compile-command'.

Note that changing this to nil may be a security risk, because a
file might define a malicious `compile-command' as a file local
variable, and you might not notice.  Therefore, `compile-command'
is considered unsafe if this variable is nil."
559 560
  :type 'boolean
  :group 'compilation)
561

562
;;;###autoload
563
(defcustom compilation-ask-about-save t
564
  "Non-nil means \\[compile] asks which buffers to save before compiling.
565 566 567
Otherwise, it saves all modified buffers without asking."
  :type 'boolean
  :group 'compilation)
568

569 570 571 572 573 574 575 576 577 578 579 580
(defcustom compilation-save-buffers-predicate nil
  "The second argument (PRED) passed to `save-some-buffers' before compiling.
E.g., one can set this to
  (lambda ()
    (string-prefix-p my-compilation-root (file-truename (buffer-file-name))))
to limit saving to files located under `my-compilation-root'.
Note, that, in general, `compilation-directory' cannot be used instead
of `my-compilation-root' here."
  :type '(choice
          (const :tag "Default (save all file-visiting buffers)" nil)
          (const :tag "Save all buffers" t)
          function)
581 582
  :group 'compilation
  :version "24.1")
583

Roland McGrath's avatar
Roland McGrath committed
584
;;;###autoload
585
(defcustom compilation-search-path '(nil)
586
  "List of directories to search for source files named in error messages.
Roland McGrath's avatar
Roland McGrath committed
587
Elements should be directory names, not file names of directories.
588
The value nil as an element means to try the default directory."
589 590 591
  :type '(repeat (choice (const :tag "Default" nil)
			 (string :tag "Directory")))
  :group 'compilation)
Richard M. Stallman's avatar
Richard M. Stallman committed
592

593
;;;###autoload
594
(defcustom compile-command (purecopy "make -k ")
595
  "Last shell command used to do a compilation; default for next compilation.
Richard M. Stallman's avatar
Richard M. Stallman committed
596 597 598 599

Sometimes it is useful for files to supply local values for this variable.
You might also use mode hooks to specify it in certain modes, like this:

600 601 602 603
    (add-hook 'c-mode-hook
       (lambda ()
	 (unless (or (file-exists-p \"makefile\")
		     (file-exists-p \"Makefile\"))
604 605
	   (set (make-local-variable 'compile-command)
		(concat \"make -k \"
Stefan Monnier's avatar
Stefan Monnier committed
606
			(file-name-sans-extension buffer-file-name))))))"
607 608
  :type 'string
  :group 'compilation)
609
;;;###autoload(put 'compile-command 'safe-local-variable (lambda (a) (and (stringp a) (or (not (boundp 'compilation-read-command)) compilation-read-command))))
Richard M. Stallman's avatar
Richard M. Stallman committed
610

611
;;;###autoload
612
(defcustom compilation-disable-input nil
613
  "If non-nil, send end-of-file as compilation process input.
614
This only affects platforms that support asynchronous processes (see
615
`start-process'); synchronous compilation processes never accept input."
616 617 618 619
  :type 'boolean
  :group 'compilation
  :version "22.1")

Stefan Monnier's avatar
Stefan Monnier committed
620 621
;; A weak per-compilation-buffer hash indexed by (FILENAME . DIRECTORY).  Each
;; value is a FILE-STRUCTURE as described above, with the car eq to the hash
Juanma Barranquero's avatar
Juanma Barranquero committed
622
;; key.  This holds the tree seen from root, for storing new nodes.
Stefan Monnier's avatar
Stefan Monnier committed
623 624 625
(defvar compilation-locs ())

(defvar compilation-debug nil
Stefan Monnier's avatar
Stefan Monnier committed
626
  "*Set this to t before creating a *compilation* buffer.
Stefan Monnier's avatar
Stefan Monnier committed
627 628
Then every error line will have a debug text property with the matcher that
fit this line and the match data.  Use `describe-text-properties'.")
Roland McGrath's avatar
Roland McGrath committed
629

630 631
(defvar compilation-exit-message-function nil "\
If non-nil, called when a compilation process dies to return a status message.
632 633 634
This should be a function of three arguments: process status, exit status,
and exit message; it returns a cons (MESSAGE . MODELINE) of the strings to
write into the compilation buffer, and to put in its mode line.")
635

636 637 638 639 640 641
(defvar compilation-environment nil
  "*List of environment variables for compilation to inherit.
Each element should be a string of the form ENVVARNAME=VALUE.
This list is temporarily prepended to `process-environment' prior to
starting the compilation process.")

642 643 644
;; History of compile commands.
(defvar compile-history nil)

645 646 647
(defface compilation-error
  '((t :inherit font-lock-warning-face))
  "Face used to highlight compiler errors."
648
  :group 'compilation
649 650
  :version "22.1")

651
(defface compilation-warning
652
  '((t :inherit font-lock-variable-name-face))
Stefan Monnier's avatar
Stefan Monnier committed
653
  "Face used to highlight compiler warnings."
654
  :group 'compilation
655
  :version "22.1")
Stefan Monnier's avatar
Stefan Monnier committed
656

657
(defface compilation-info
658
  '((t :inherit font-lock-type-face))
659
  "Face used to highlight compiler information."
660
  :group 'compilation
661
  :version "22.1")
Stefan Monnier's avatar
Stefan Monnier committed
662

663
(defface compilation-line-number
664
  '((t :inherit font-lock-keyword-face))
665
  "Face for displaying line numbers in compiler messages."
666
  :group 'compilation
667 668 669
  :version "22.1")

(defface compilation-column-number
670
  '((t :inherit font-lock-doc-face))
671
  "Face for displaying column numbers in compiler messages."
672
  :group 'compilation
673 674
  :version "22.1")

675
(defcustom compilation-message-face 'underline
Stefan Monnier's avatar
Stefan Monnier committed
676 677 678
  "Face name to use for whole messages.
Faces `compilation-error-face', `compilation-warning-face',
`compilation-info-face', `compilation-line-face' and
679 680 681 682
`compilation-column-face' get prepended to this, when applicable."
  :type 'face
  :group 'compilation
  :version "22.1")
Stefan Monnier's avatar
Stefan Monnier committed
683

684
(defvar compilation-error-face 'compilation-error
Stefan Monnier's avatar
Stefan Monnier committed
685 686
  "Face name to use for file name in error messages.")

687
(defvar compilation-warning-face 'compilation-warning
Stefan Monnier's avatar
Stefan Monnier committed
688 689
  "Face name to use for file name in warning messages.")

690
(defvar compilation-info-face 'compilation-info
Stefan Monnier's avatar
Stefan Monnier committed
691 692
  "Face name to use for file name in informational messages.")

693
(defvar compilation-line-face 'compilation-line-number
694
  "Face name to use for line numbers in compiler messages.")
Stefan Monnier's avatar
Stefan Monnier committed
695

696
(defvar compilation-column-face 'compilation-column-number
697
  "Face name to use for column numbers in compiler messages.")
Stefan Monnier's avatar
Stefan Monnier committed
698 699 700

;; same faces as dired uses
(defvar compilation-enter-directory-face 'font-lock-function-name-face
701
  "Face name to use for entering directory messages.")
Stefan Monnier's avatar
Stefan Monnier committed
702

703
(defvar compilation-leave-directory-face 'font-lock-builtin-face
704
  "Face name to use for leaving directory messages.")
Stefan Monnier's avatar
Stefan Monnier committed
705 706 707



708 709
;; Used for compatibility with the old compile.el.
(defvar compilation-parse-errors-function nil)
710 711
(make-obsolete 'compilation-parse-errors-function
               'compilation-error-regexp-alist "24.1")
712

713
(defcustom compilation-auto-jump-to-first-error nil
714
  "If non-nil, automatically jump to the first error during compilation."
715 716 717
  :type 'boolean
  :group 'compilation
  :version "23.1")
718 719 720 721 722

(defvar compilation-auto-jump-to-next nil
  "If non-nil, automatically jump to the next error encountered.")
(make-variable-buffer-local 'compilation-auto-jump-to-next)

723 724 725
;; (defvar compilation-buffer-modtime nil
;;   "The buffer modification time, for buffers not associated with files.")
;; (make-variable-buffer-local 'compilation-buffer-modtime)
726 727 728 729 730 731 732 733 734 735

(defvar compilation-skip-to-next-location t
  "*If non-nil, skip multiple error messages for the same source location.")

(defcustom compilation-skip-threshold 1
  "Compilation motion commands skip less important messages.
The value can be either 2 -- skip anything less than error, 1 --
skip anything less than warning or 0 -- don't skip any messages.
Note that all messages not positively identified as warning or
info, are considered errors."
736 737 738
  :type '(choice (const :tag "Skip warnings and info" 2)
		 (const :tag "Skip info" 1)
		 (const :tag "No skip" 0))
739 740 741
  :group 'compilation
  :version "22.1")

742 743 744 745 746 747 748 749 750 751 752 753 754 755 756
(defun compilation-set-skip-threshold (level)
  "Switch the `compilation-skip-threshold' level."
  (interactive
   (list
    (mod (if current-prefix-arg
             (prefix-numeric-value current-prefix-arg)
           (1+ compilation-skip-threshold))
         3)))
  (setq compilation-skip-threshold level)
  (message "Skipping %s"
           (case compilation-skip-threshold
             (0 "Nothing")
             (1 "Info messages")
             (2 "Warnings and info"))))

757 758 759 760 761 762 763 764 765
(defcustom compilation-skip-visited nil
  "Compilation motion commands skip visited messages if this is t.
Visited messages are ones for which the file, line and column have been jumped
to from the current content in the current compilation buffer, even if it was
from a different message."
  :type 'boolean
  :group 'compilation
  :version "22.1")

Stefan Monnier's avatar
Stefan Monnier committed
766 767 768 769 770
(defun compilation-face (type)
  (or (and (car type) (match-end (car type)) compilation-warning-face)
      (and (cdr type) (match-end (cdr type)) compilation-info-face)
      compilation-error-face))

771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
;;   LOC (or location) is a list of (COLUMN LINE FILE-STRUCTURE nil nil)

;; COLUMN and LINE are numbers parsed from an error message.  COLUMN and maybe
;; LINE will be nil for a message that doesn't contain them.  Then the
;; location refers to a indented beginning of line or beginning of file.
;; Once any location in some file has been jumped to, the list is extended to
;; (COLUMN LINE FILE-STRUCTURE MARKER TIMESTAMP . VISITED)
;; for all LOCs pertaining to that file.
;; MARKER initially points to LINE and COLUMN in a buffer visiting that file.
;; Being a marker it sticks to some text, when the buffer grows or shrinks
;; before that point.  VISITED is t if we have jumped there, else nil.
;; FIXME-omake: TIMESTAMP was used to try and handle "incremental compilation":
;; `omake -P' polls filesystem for changes and recompiles when a file is
;; modified using the same *compilation* buffer. this necessitates
;; re-parsing markers.

;; (defstruct (compilation--loc
;;             (:constructor nil)
;;             (:copier nil)
;;             (:constructor compilation--make-loc
;;                           (file-struct line col marker))
;;             (:conc-name compilation--loc->))
;;   col line file-struct marker timestamp visited)

;; FIXME: We don't use a defstruct because of compilation-assq which looks up
;; and creates part of the LOC (only the first cons cell containing the COL).

(defmacro compilation--make-cdrloc (line file-struct marker)
  `(list ,line ,file-struct ,marker nil))
(defmacro compilation--loc->col (loc) `(car ,loc))
(defmacro compilation--loc->line (loc) `(cadr ,loc))
(defmacro compilation--loc->file-struct (loc) `(nth 2 ,loc))
(defmacro compilation--loc->marker (loc) `(nth 3 ,loc))
;; (defmacro compilation--loc->timestamp (loc) `(nth 4 ,loc))
(defmacro compilation--loc->visited (loc) `(nthcdr 5 ,loc))

;;   FILE-STRUCTURE is a list of
;;   ((FILENAME DIRECTORY) FORMATS (LINE LOC ...) ...)

;; FILENAME is a string parsed from an error message.  DIRECTORY is a string
;; obtained by following directory change messages.  DIRECTORY will be nil for
;; an absolute filename.  FORMATS is a list of formats to apply to FILENAME if
;; a file of that name can't be found.
;; The rest of the list is an alist of elements with LINE as key.  The keys
;; are either nil or line numbers.  If present, nil comes first, followed by
;; the numbers in decreasing order.  The LOCs for each line are again an alist
;; ordered the same way.  Note that the whole file structure is referenced in
;; every LOC.

(defmacro compilation--make-file-struct (file-spec formats &optional loc-tree)
  `(cons ,file-spec (cons ,formats ,loc-tree)))
(defmacro compilation--file-struct->file-spec (fs) `(car ,fs))
(defmacro compilation--file-struct->formats (fs) `(cadr ,fs))
;; The FORMATS field plays the role of ANCHOR in the loc-tree.
(defmacro compilation--file-struct->loc-tree (fs) `(cdr ,fs))

;;   MESSAGE is a list of (LOC TYPE END-LOC)

;; TYPE is 0 for info or 1 for warning if the message matcher identified it as
;; such, 2 otherwise (for a real error).  END-LOC is a LOC pointing to the
;; other end, if the parsed message contained a range.  If the end of the
;; range didn't specify a COLUMN, it defaults to -1, meaning end of line.
;; These are the value of the `compilation-message' text-properties in the
;; compilation buffer.

(defstruct (compilation--message
            (:constructor nil)
            (:copier nil)
            ;; (:type list)                ;Old representation.
            (:constructor compilation--make-message (loc type end-loc))
            (:conc-name compilation--message->))
  loc type end-loc)

844 845 846 847 848 849
(defvar compilation--previous-directory-cache nil
  "A pair (POS . RES) caching the result of previous directory search.
Basically, this pair says that calling
   (previous-single-property-change POS 'compilation-directory)
returned RES, i.e. there is no change of `compilation-directory' between
POS and RES.")
850
(make-variable-buffer-local 'compilation--previous-directory-cache)
851

852
(defun compilation--flush-directory-cache (start _end)
853 854 855 856
  (cond
   ((or (not compilation--previous-directory-cache)
        (<= (car compilation--previous-directory-cache) start)))
   ((or (not (cdr compilation--previous-directory-cache))
857
	(null (marker-buffer (cdr compilation--previous-directory-cache)))
858 859 860 861
        (<= (cdr compilation--previous-directory-cache) start))
    (set-marker (car compilation--previous-directory-cache) start))
   (t (setq compilation--previous-directory-cache nil))))

862 863 864 865 866
(defun compilation--previous-directory (pos)
  "Like (previous-single-property-change POS 'compilation-directory), but faster."
  ;; This avoids an N² behavior when there's no/few compilation-directory
  ;; entries, in which case each call to previous-single-property-change
  ;; ends up having to walk very far back to find the last change.
867 868
  (if (and compilation--previous-directory-cache
           (< pos (car compilation--previous-directory-cache))
869 870
           (or (null (cdr compilation--previous-directory-cache))
               (< (cdr compilation--previous-directory-cache) pos)))
871 872
      ;; No need to call previous-single-property-change.
      (cdr compilation--previous-directory-cache)
873

874 875 876 877 878
    (let* ((cache (and compilation--previous-directory-cache
                       (<= (car compilation--previous-directory-cache) pos)
                       (car compilation--previous-directory-cache)))
           (prev
            (previous-single-property-change
879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901
             pos 'compilation-directory nil cache))
           (res
            (cond
             ((null cache)
              (setq compilation--previous-directory-cache
                    (cons (copy-marker pos) (if prev (copy-marker prev))))
              prev)
             ((and prev (= prev cache))
              (if cache
                  (set-marker (car compilation--previous-directory-cache) pos)
                (setq compilation--previous-directory-cache
                      (cons (copy-marker pos) nil)))
              (cdr compilation--previous-directory-cache))
             (t
              (if cache
                  (progn
                    (set-marker cache pos)
                    (setcdr compilation--previous-directory-cache
                            (copy-marker prev)))
                (setq compilation--previous-directory-cache
                      (cons (copy-marker pos) (if prev (copy-marker prev)))))
              prev))))
      (if (markerp res) (marker-position res) res))))
902

903
;; Internal function for calculating the text properties of a directory
904 905
;; change message.  The compilation-directory property is important, because it
;; is the stack of nested enter-messages.  Relative filenames on the following
906
;; lines are relative to the top of the stack.
Stefan Monnier's avatar
Stefan Monnier committed
907 908 909
(defun compilation-directory-properties (idx leave)
  (if leave (setq leave (match-end leave)))
  ;; find previous stack, and push onto it, or if `leave' pop it
910
  (let ((dir (compilation--previous-directory (match-beginning 0))))
911 912
    (setq dir (if dir (or (get-text-property (1- dir) 'compilation-directory)
			  (get-text-property dir 'compilation-directory))))
913 914 915
    `(font-lock-face ,(if leave
                          compilation-leave-directory-face
                        compilation-enter-directory-face)
916 917 918 919
      compilation-directory ,(if leave
                                 (or (cdr dir)
                                     '(nil)) ; nil only isn't a property-change
                               (cons (match-string-no-properties idx) dir))
920 921 922
      ;; Place a `compilation-message' everywhere we change text-properties
      ;; so compilation--remove-properties can know what to remove.
      compilation-message ,(compilation--make-message nil 0 nil)
Stefan Monnier's avatar
Stefan Monnier committed
923
      mouse-face highlight
Stefan Monnier's avatar
Stefan Monnier committed
924
      keymap compilation-button-map
925
      help-echo "mouse-2: visit destination directory")))
Stefan Monnier's avatar
Stefan Monnier committed
926

Juanma Barranquero's avatar
Juanma Barranquero committed
927
;; Data type `reverse-ordered-alist' retriever.  This function retrieves the
Stefan Monnier's avatar
Stefan Monnier committed
928 929 930 931
;; KEY element from the ALIST, creating it in the right position if not already
;; present. ALIST structure is
;; '(ANCHOR (KEY1 ...) (KEY2 ...)... (KEYn ALIST ...))
;; ANCHOR is ignored, but necessary so that elements can be inserted.  KEY1
Juanma Barranquero's avatar
Juanma Barranquero committed
932
;; may be nil.  The other KEYs are ordered backwards so that growing line
Stefan Monnier's avatar
Stefan Monnier committed
933 934
;; numbers can be inserted in front and searching can abort after half the
;; list on average.
Stefan Monnier's avatar
Stefan Monnier committed
935
(eval-when-compile		    ;Don't keep it at runtime if not needed.
Stefan Monnier's avatar
Stefan Monnier committed
936 937 938 939 940 941 942 943 944 945
(defmacro compilation-assq (key alist)
  `(let* ((l1 ,alist)
	  (l2 (cdr l1)))
     (car (if (if (null ,key)
		  (if l2 (null (caar l2)))
		(while (if l2 (if (caar l2) (< ,key (caar l2)) t))
		  (setq l1 l2
			l2 (cdr l1)))
		(if l2 (eq ,key (caar l2))))
	      l2
Stefan Monnier's avatar
Stefan Monnier committed
946
	    (setcdr l1 (cons (list ,key) l2)))))))
Stefan Monnier's avatar
Stefan Monnier committed
947

948 949 950
(defun compilation-auto-jump (buffer pos)
  (with-current-buffer buffer
    (goto-char pos)
951 952
    (let ((win (get-buffer-window buffer 0)))
      (if win (set-window-point win pos)))
Juri Linkov's avatar
Juri Linkov committed
953 954
    (if compilation-auto-jump-to-first-error
	(compile-goto-error))))
Stefan Monnier's avatar
Stefan Monnier committed
955 956 957 958

;; This function is the central driver, called when font-locking to gather
;; all information needed to later jump to corresponding source code.
;; Return a property list with all meta information on this error location.
959

Stefan Monnier's avatar
Stefan Monnier committed
960
(defun compilation-error-properties (file line end-line col end-col type fmt)
961 962
  (unless (text-property-not-all (match-beginning 0) (point)
                                 'compilation-message nil)
Stefan Monnier's avatar
Stefan Monnier committed
963
    (if file
964 965 966 967
        (when (stringp
               (setq file (if (functionp file) (funcall file)
                            (match-string-no-properties file))))
	  (let ((dir
Stefan Monnier's avatar
Stefan Monnier committed
968
	    (unless (file-name-absolute-p file)
969 970
                   (let ((pos (compilation--previous-directory
                               (match-beginning 0))))
971 972 973
                     (when pos
                       (or (get-text-property (1- pos) 'compilation-directory)
                           (get-text-property pos 'compilation-directory)))))))
974
	    (setq file (cons file (car dir)))))
Stefan Monnier's avatar
Stefan Monnier committed
975
      ;; This message didn't mention one, get it from previous