compile.el 122 KB
Newer Older
1
;;; compile.el --- run compiler as inferior of Emacs, parse error messages  -*- lexical-binding:t -*-
Eric S. Raymond's avatar
Eric S. Raymond committed
2

Paul Eggert's avatar
Paul Eggert committed
3
;; Copyright (C) 1985-1987, 1993-1999, 2001-2016 Free Software
4
;; 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>
8
;; Maintainer: emacs-devel@gnu.org
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:

33
(eval-when-compile (require 'cl-lib))
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'."
46 47
  :type 'hook
  :group 'compilation)
Roland McGrath's avatar
Roland McGrath committed
48

49 50
;;;###autoload
(defcustom compilation-start-hook nil
51 52
  "Hook run after starting a new compilation process.
The hook is run with one argument, the new process."
53 54 55
  :type 'hook
  :group 'compilation)

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

64 65 66 67
(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
68 69 70 71
its end.

If Emacs lacks asynchronous process support, this hook is run
after `call-process' inserts the grep output into the buffer.")
72 73

(defvar compilation-filter-start nil
74 75
  "Position of the start of the text inserted by `compilation-filter'.
This is bound before running `compilation-filter-hook'.")
76

Stefan Monnier's avatar
Stefan Monnier committed
77
(defvar compilation-first-column 1
78
  "This is how compilers number the first column, usually 1 or 0.
Glenn Morris's avatar
Glenn Morris committed
79 80 81
If this is buffer-local in the destination buffer, Emacs obeys
that value, otherwise it uses the value in the *compilation*
buffer.  This enables a major-mode to specify its own value.")
Richard M. Stallman's avatar
Richard M. Stallman committed
82

83 84 85 86 87
(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.")

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

Jim Blandy's avatar
Jim Blandy committed
95
;;;###autoload
Roland McGrath's avatar
Roland McGrath committed
96
(defvar compilation-buffer-name-function nil
Richard M. Stallman's avatar
Richard M. Stallman committed
97 98 99
  "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.
100
If nil, compute the name with `(concat \"*\" (downcase major-mode) \"*\")'.")
Richard M. Stallman's avatar
Richard M. Stallman committed
101

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

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

112 113
;;;###autoload
(defvar compilation-finish-functions nil
114
  "Functions to call when a compilation process finishes.
115 116 117
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
118 119 120 121 122 123
(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
124 125
(defvar compilation-error "error"
  "Stem of message to print when no matches are found.")
Richard M. Stallman's avatar
Richard M. Stallman committed
126

127
(defvar compilation-arguments nil
Stefan Monnier's avatar
Stefan Monnier committed
128
  "Arguments that were given to `compilation-start'.")
129

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

132 133
;; If you make any changes to `compilation-error-regexp-alist-alist',
;; be sure to run the ERT test in test/automated/compile-tests.el.
134
;; emacs -batch -l compile-tests.el -f ert-run-tests-batch-and-exit
135

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

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

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

Stefan Monnier's avatar
Stefan Monnier committed
147
    (ant
148
     "^[ \t]*\\[[^] \n]+\\][ \t]*\\(\\(?:[A-Za-z]:\\\\\\)?[^: \n]+\\):\\([0-9]+\\):\\(?:\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\):\\)?\
Chong Yidong's avatar
Chong Yidong committed
149
\\( warning\\)?" 1 (2 . 4) (3 . 5) (6))
150

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

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

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

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

168 169
    (cucumber
     "\\(?:^cucumber\\(?: -p [^[:space:]]+\\)?\\|#\\)\
170
\\(?: \\)\\([^(].*\\):\\([1-9][0-9]*\\)" 1 2)
171

172 173 174 175 176 177 178 179 180
    (msft
     ;; Must be before edg-1, so that MSVC's longer messages are
     ;; considered before EDG.
     ;; 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))

181 182 183 184 185 186 187
    (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
188
    (epc
189
     "^Error [0-9]+ at (\\([0-9]+\\):\\([^)\n]+\\))" 2 1)
Stefan Monnier's avatar
Stefan Monnier committed
190

191 192 193
    (ftnchek
     "\\(^Warning .*\\)? line[ \n]\\([0-9]+\\)[ \n]\\(?:col \\([0-9]+\\)[ \n]\\)?file \\([^ :;\n]+\\)"
     4 2 3 (1))
194

Stefan Monnier's avatar
Stefan Monnier committed
195 196 197 198 199 200 201 202
    (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
203
    ;; fixme: should be `mips'
Stefan Monnier's avatar
Stefan Monnier committed
204
    (irix
205 206
     "^[-[: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
207 208 209 210 211 212

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

    (jikes-file
     "^\\(?:Found\\|Issued\\) .* compiling \"\\(.+\\)\":$" 1 nil nil 0)
213 214 215 216 217 218


    ;; 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.
219
     "\\(\\[WARNING\\] *\\)?\\([^ \n]\\(?:[^\n :]\\| [^-/\n]\\|:[^ \n]\\)*?\\):\\[\\([0-9]+\\),\\([0-9]+\\)\\] " 2 3 4 (1))
220

Stefan Monnier's avatar
Stefan Monnier committed
221 222 223 224 225
    (jikes-line
     "^ *\\([0-9]+\\)\\.[ \t]+.*\n +\\(<-*>\n\\*\\*\\* \\(?:Error\\|Warnin\\(g\\)\\)\\)"
     nil 1 nil 2 0
     (2 (compilation-face '(3))))

226 227
    (gcc-include
     "^\\(?:In file included \\|                 \\|\t\\)from \
Andreas Schwab's avatar
Andreas Schwab committed
228 229 230
\\([0-9]*[^0-9\n]\\(?:[^\n :]\\| [^-/\n]\\|:[^ \n]\\)*?\\):\
\\([0-9]+\\)\\(?::\\([0-9]+\\)\\)?\\(?:\\(:\\)\\|\\(,\\|$\\)\\)?"
     1 2 3 (4 . 5))
231

232
    (ruby-Test::Unit
233
     "^[\t ]*\\[\\([^(].*\\):\\([1-9][0-9]*\\)\\(\\]\\)?:in " 1 2)
234

Stefan Monnier's avatar
Stefan Monnier committed
235
    (gnu
236 237 238 239 240 241 242 243 244 245 246 247 248
     ;; 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.

249 250 251 252
     ;; 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
253 254 255 256

     ;; 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
257
     ;; followed by a -, or a colon followed by a space.
258
     ;;
259
     ;; The "in \\|from " exception was added to handle messages from Ruby.
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
     ,(rx
       bol
       (? (| (regexp "[[:alpha:]][-[:alnum:].]+: ?")
             (regexp "[ \t]+\\(?:in \\|from\\)")))
       (group-n 1 (: (regexp "[0-9]*[^0-9\n]")
                     (*? (| (regexp "[^\n :]")
                            (regexp " [^-/\n]")
                            (regexp ":[^ \n]")))))
       (regexp ": ?")
       (group-n 2 (regexp "[0-9]+"))
       (? (| (: "-"
                (group-n 4 (regexp "[0-9]+"))
                (? "." (group-n 5 (regexp "[0-9]+"))))
             (: (in ".:")
                (group-n 3 (regexp "[0-9]+"))
                (? "-"
                   (? (group-n 4 (regexp "[0-9]+")) ".")
                   (group-n 5 (regexp "[0-9]+"))))))
       ":"
       (| (: (* " ")
             (group-n 6 (| "FutureWarning"
                           "RuntimeWarning"
                           "Warning"
                           "warning"
                           "W:")))
          (: (* " ")
             (group-n 7 (| (regexp "[Ii]nfo\\(?:\\>\\|rmationa?l?\\)")
                           "I:"
                           (: "[ skipping " (+ ".") " ]")
                           "instantiated from"
                           "required from"
                           (regexp "[Nn]ote"))))
          (: (* " ")
             (regexp "[Ee]rror"))
          (: (regexp "[0-9]?")
             (| (regexp "[^0-9\n]")
                eol))
          (regexp "[0-9][0-9][0-9]")))
298
     1 (2 . 4) (3 . 5) (6 . 7))
Stefan Monnier's avatar
Stefan Monnier committed
299 300 301 302 303 304

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

    (makepp
Daniel Pfeiffer's avatar
Daniel Pfeiffer committed
305
     "^makepp\\(?:\\(?:: warning\\(:\\).*?\\|\\(: Scanning\\|: [LR]e?l?oading makefile\\|: Imported\\|log:.*?\\) \\|: .*?\\)\
306
`\\(\\(\\S +?\\)\\(?::\\([0-9]+\\)\\)?\\)['(]\\)"
Stefan Monnier's avatar
Stefan Monnier committed
307
     4 5 nil (1 . 2) 3
308 309 310 311 312 313 314 315 316
     (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
317

Stefan Monnier's avatar
Stefan Monnier committed
318
    ;; Should be lint-1, lint-2 (SysV lint)
Stefan Monnier's avatar
Stefan Monnier committed
319 320 321 322 323 324
    (mips-1
     " (\\([0-9]+\\)) in \\([^ \n]+\\)" 2 1)
    (mips-2
     " in \\([^()\n ]+\\)(\\([0-9]+\\))$" 1 2)

    (msft
325 326 327 328 329
     ;; 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
330

331 332 333
    (omake
     ;; "omake -P" reports "file foo changed"
     ;; (useful if you do "cvs up" and want to see what has changed)
334 335 336 337 338 339
     "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)))
340

Stefan Monnier's avatar
Stefan Monnier committed
341
    (oracle
342 343 344
     "^\\(?:Semantic error\\|Error\\|PCC-[0-9]+:\\).* line \\([0-9]+\\)\
\\(?:\\(?:,\\| at\\)? column \\([0-9]+\\)\\)?\
\\(?:,\\| in\\| of\\)? file \\(.*?\\):?$"
Stefan Monnier's avatar
Stefan Monnier committed
345
     3 1 2)
346

347 348 349
    ;; "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
350
    (perl
351 352
     " at \\([^ \n]+\\) line \\([0-9]+\\)\\(?:[,.]\\|$\\| \
during global destruction\\.$\\)" 1 2)
Stefan Monnier's avatar
Stefan Monnier committed
353

354 355 356 357
    (php
     "\\(?:Parse\\|Fatal\\) error: \\(.*\\) in \\(.*\\) on line \\([0-9]+\\)"
     2 3 nil nil)

Stefan Monnier's avatar
Stefan Monnier committed
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
    (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
375
     ": \\(?:ERROR\\|WARNIN\\(G\\)\\|REMAR\\(K\\)\\) \\(?:[[:alnum:] ]+, \\)?\
Stefan Monnier's avatar
Stefan Monnier committed
376 377 378 379
File = \\(.+\\), Line = \\([0-9]+\\)\\(?:, Column = \\([0-9]+\\)\\)?"
     3 4 5 (1 . 2))

    (sun-ada
380
     "^\\([^, \n\t]+\\), line \\([0-9]+\\), char \\([0-9]+\\)[:., (-]" 1 2 3)
Stefan Monnier's avatar
Stefan Monnier committed
381

382
    (watcom
383
     "^[ \t]*\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)): ?\
Chong Yidong's avatar
Chong Yidong committed
384 385
\\(?:\\(Error! E[0-9]+\\)\\|\\(Warning! W[0-9]+\\)\\):"
     1 2 nil (4))
386

Stefan Monnier's avatar
Stefan Monnier committed
387 388
    (4bsd
     "\\(?:^\\|::  \\|\\S ( \\)\\(/[^ \n\t()]+\\)(\\([0-9]+\\))\
389 390 391
\\(?:: \\(warning:\\)?\\|$\\| ),\\)" 1 2 nil (3))

    (gcov-file
392
     "^ *-: *\\(0\\):Source:\\(.+\\)$"
393
     2 1 nil 0 nil)
394 395
    (gcov-header
     "^ *-: *\\(0\\):\\(?:Object\\|Graph\\|Data\\|Runs\\|Programs\\):.+$"
396
     nil 1 nil 0 nil)
397 398 399 400 401 402 403 404
    ;; 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
405 406
     (0 'default)
     (1 compilation-line-face))
407
    (gcov-called-line
408
     "^ *\\([0-9]+\\): *\\([0-9]+\\):.*$"
409
     nil 2 nil 0 nil
410 411
     (0 'default)
     (1 compilation-info-face) (2 compilation-line-face))
412
    (gcov-never-called
413
     "^ *\\(#####\\): *\\([0-9]+\\):.*$"
414
     nil 2 nil 2 nil
415 416
     (0 'default)
     (1 compilation-error-face) (2 compilation-line-face))
417

418
    (perl--Pod::Checker
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
     ;; 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))
436
    (perl--Test
437 438 439 440 441 442
     ;; 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)
443
    (perl--Test2
444
     ;; Or when comparing got/want values, with a "fail #n" if repeated
445
     ;; # Test 2 got: "xx" (t-compilation-perl-2.t at line 10)
446
     ;; # Test 3 got: "xx" (t-compilation-perl-2.t at line 10 fail #2)
447 448 449 450 451 452
     ;;
     ;; 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 \
453
\\([0-9]+\\)\\( fail #[0-9]+\\)?)"
454
     2 3)
455
    (perl--Test::Harness
456 457 458 459 460 461 462 463 464 465
     ;; 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)
466
    (weblint
467 468 469 470 471 472 473 474 475 476 477 478 479
     ;; 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)
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502

    ;; Guile compilation yields file-headers in the following format:
    ;;
    ;;   In sourcefile.scm:
    ;;
    ;; We need to catch those, but we also need to be aware that Emacs
    ;; byte-compilation yields compiler headers in similar form of
    ;; those:
    ;;
    ;;   In toplevel form:
    ;;   In end of data:
    ;;
    ;; We want to catch the Guile file-headers but not the Emacs
    ;; byte-compilation headers, because that will cause next-error
    ;; and prev-error to break, because the files "toplevel form" and
    ;; "end of data" does not exist.
    ;;
    ;; To differentiate between these two cases, we require that the
    ;; file-match must always contain an extension.
    ;;
    ;; We should also only treat this as "info", not "error", because
    ;; we do not know what lines will follow.
    (guile-file "^In \\(.+\\..+\\):\n" 1 nil nil 0)
503
    (guile-line "^ *\\([0-9]+\\): *\\([0-9]+\\)" nil 1 2)
504
    )
Stefan Monnier's avatar
Stefan Monnier committed
505 506 507 508
  "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
509
  "Alist that specifies how to match errors in compiler output.
510
On GNU and Unix, any string is a valid filename, so these
Stefan Monnier's avatar
Stefan Monnier committed
511 512 513 514 515 516
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
517
`etc/compilation.txt' (linked below if you are customizing this).
Stefan Monnier's avatar
Stefan Monnier committed
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533

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
534 535
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
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552

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.

553 554
Additional HIGHLIGHTs take the shape (SUBMATCH FACE), where
SUBMATCH is the number of a submatch and FACE is an expression
555 556 557 558
which evaluates to a face name (a symbol or string).
Alternatively, FACE can evaluate to a property list of the
form (face FACE PROP1 VAL1 PROP2 VAL2 ...), in which case all the
listed text properties PROP# are given values VAL# as well."
Glenn Morris's avatar
Glenn Morris committed
559 560
  :type '(repeat (choice (symbol :tag "Predefined symbol")
			 (sexp :tag "Error specification")))
Stefan Monnier's avatar
Stefan Monnier committed
561
  :link `(file-link :tag "example file"
562
		    ,(expand-file-name "compilation.txt" data-directory))
Stefan Monnier's avatar
Stefan Monnier committed
563
  :group 'compilation)
Richard M. Stallman's avatar
Richard M. Stallman committed
564

565
;;;###autoload(put 'compilation-directory 'safe-local-variable 'stringp)
566 567 568
(defvar compilation-directory nil
  "Directory to restore to when doing `recompile'.")

Stefan Monnier's avatar
Stefan Monnier committed
569
(defvar compilation-directory-matcher
570
  '("\\(?:Entering\\|Leavin\\(g\\)\\) directory [`']\\(.+\\)'$" (2 . 1))
Stefan Monnier's avatar
Stefan Monnier committed
571
  "A list for tracking when directories are entered or left.
572
If nil, do not track directories, e.g. if all file names are absolute.  The
Stefan Monnier's avatar
Stefan Monnier committed
573 574 575 576 577 578 579 580 581 582
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
583
  "^\\(?:\f\\|.*\\(?:Entering\\|Leaving\\) directory [`'].+'\n\\)+"
Stefan Monnier's avatar
Stefan Monnier committed
584 585 586
  "Value of `page-delimiter' in Compilation mode.")

(defvar compilation-mode-font-lock-keywords
587
   '(;; configure output lines.
Stefan Monnier's avatar
Stefan Monnier committed
588 589
     ("^[Cc]hecking \\(?:[Ff]or \\|[Ii]f \\|[Ww]hether \\(?:to \\)?\\)?\\(.+\\)\\.\\.\\. *\\(?:(cached) *\\)?\\(\\(yes\\(?: .+\\)?\\)\\|no\\|\\(.*\\)\\)$"
      (1 font-lock-variable-name-face)
590
      (2 (compilation-face '(4 . 3))))
Stefan Monnier's avatar
Stefan Monnier committed
591
     ;; Command output lines.  Recognize `make[n]:' lines too.
Stefan Monnier's avatar
Stefan Monnier committed
592
     ("^\\([[:alnum:]_/.+-]+\\)\\(\\[\\([0-9]+\\)\\]\\)?[ \t]*:"
Stefan Monnier's avatar
Stefan Monnier committed
593
      (1 font-lock-function-name-face) (3 compilation-line-face nil t))
594
     (" --?o\\(?:utfile\\|utput\\)?[= ]\\(\\S +\\)" . 1)
595
     ("^Compilation \\(finished\\).*"
596
      (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t)
597
      (1 compilation-info-face))
598
     ("^Compilation \\(exited abnormally\\|interrupt\\|killed\\|terminated\\|segmentation fault\\)\\(?:.*with code \\([0-9]+\\)\\)?.*"
599
      (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t)
600 601
      (1 compilation-error-face)
      (2 compilation-error-face nil t)))
Stefan Monnier's avatar
Stefan Monnier committed
602 603
   "Additional things to highlight in Compilation mode.
This gets tacked on the end of the generated expressions.")
604

605 606 607 608 609 610 611
(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.")

612
(defcustom compilation-error-screen-columns t
613
  "If non-nil, column numbers in error messages are screen columns.
614 615 616 617
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,
Glenn Morris's avatar
Glenn Morris committed
618 619 620 621
especially the TAB character.
If this is buffer-local in the destination buffer, Emacs obeys
that value, otherwise it uses the value in the *compilation*
buffer.  This enables a major-mode to specify its own value."
622 623 624 625
  :type 'boolean
  :group 'compilation
  :version "20.4")

626
(defcustom compilation-read-command t
627
  "Non-nil means \\[compile] reads the compilation command to use.
628 629 630 631 632 633
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."
634 635
  :type 'boolean
  :group 'compilation)
636

637
;;;###autoload
638
(defcustom compilation-ask-about-save t
639
  "Non-nil means \\[compile] asks which buffers to save before compiling.
640 641 642
Otherwise, it saves all modified buffers without asking."
  :type 'boolean
  :group 'compilation)
643

644 645 646 647 648 649 650 651 652 653 654 655
(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)
656 657
  :group 'compilation
  :version "24.1")
658

Roland McGrath's avatar
Roland McGrath committed
659
;;;###autoload
660
(defcustom compilation-search-path '(nil)
661
  "List of directories to search for source files named in error messages.
Roland McGrath's avatar
Roland McGrath committed
662
Elements should be directory names, not file names of directories.
663
The value nil as an element means to try the default directory."
664 665 666
  :type '(repeat (choice (const :tag "Default" nil)
			 (string :tag "Directory")))
  :group 'compilation)
Richard M. Stallman's avatar
Richard M. Stallman committed
667

668
;;;###autoload
669
(defcustom compile-command (purecopy "make -k ")
670
  "Last shell command used to do a compilation; default for next compilation.
Richard M. Stallman's avatar
Richard M. Stallman committed
671 672 673 674

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:

675
    (add-hook \\='c-mode-hook
676 677 678
       (lambda ()
	 (unless (or (file-exists-p \"makefile\")
		     (file-exists-p \"Makefile\"))
679
	   (set (make-local-variable \\='compile-command)
680
		(concat \"make -k \"
681 682 683
			(if buffer-file-name
			  (shell-quote-argument
			    (file-name-sans-extension buffer-file-name))))))))"
684 685
  :type 'string
  :group 'compilation)
686
;;;###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
687

688
;;;###autoload
689
(defcustom compilation-disable-input nil
690
  "If non-nil, send end-of-file as compilation process input.
691
This only affects platforms that support asynchronous processes (see
692
`start-process'); synchronous compilation processes never accept input."
693 694 695 696
  :type 'boolean
  :group 'compilation
  :version "22.1")

Stefan Monnier's avatar
Stefan Monnier committed
697 698
;; 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
699
;; key.  This holds the tree seen from root, for storing new nodes.
Stefan Monnier's avatar
Stefan Monnier committed
700 701 702
(defvar compilation-locs ())

(defvar compilation-debug nil
703
  "Set this to t before creating a *compilation* buffer.
Stefan Monnier's avatar
Stefan Monnier committed
704 705
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
706

707 708
(defvar compilation-exit-message-function nil "\
If non-nil, called when a compilation process dies to return a status message.
709 710 711
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.")
712

713 714
(defcustom compilation-environment nil
  "List of environment variables for compilation to inherit.
715 716
Each element should be a string of the form ENVVARNAME=VALUE.
This list is temporarily prepended to `process-environment' prior to
717 718 719 720 721
starting the compilation process."
  :type '(repeat (string :tag "ENVVARNAME=VALUE"))
  :options '(("LANG=C"))
  :group 'compilation
  :version "24.1")
722

723 724 725
;; History of compile commands.
(defvar compile-history nil)

726
(defface compilation-error
727
  '((t :inherit error))
728
  "Face used to highlight compiler errors."
729
  :group 'compilation
730 731
  :version "22.1")

732
(defface compilation-warning
733
  '((t :inherit warning))
Stefan Monnier's avatar
Stefan Monnier committed
734
  "Face used to highlight compiler warnings."
735
  :group 'compilation
736
  :version "22.1")
Stefan Monnier's avatar
Stefan Monnier committed
737

738
(defface compilation-info
739
  '((t :inherit success))
740
  "Face used to highlight compiler information."
741
  :group 'compilation
742
  :version "22.1")
Stefan Monnier's avatar
Stefan Monnier committed
743

744 745 746 747 748 749 750 751 752 753
;; The next three faces must be able to stand out against the
;; `mode-line' and `mode-line-inactive' faces.

(defface compilation-mode-line-fail
  '((default :inherit compilation-error)
    (((class color) (min-colors 16)) (:foreground "Red1" :weight bold))
    (((class color) (min-colors 8)) (:foreground "red"))
    (t (:inverse-video t :weight bold)))
  "Face for Compilation mode's \"error\" mode line indicator."
  :group 'compilation
754
  :version "24.3")
755 756 757 758 759

(defface compilation-mode-line-run
  '((t :inherit compilation-warning))
  "Face for Compilation mode's \"running\" mode line indicator."
  :group 'compilation
760
  :version "24.3")
761 762 763 764 765 766 767 768 769

(defface compilation-mode-line-exit
  '((default :inherit compilation-info)
    (((class color) (min-colors 16))
     (:foreground "ForestGreen" :weight bold))
    (((class color)) (:foreground "green" :weight bold))
    (t (:weight bold)))
  "Face for Compilation mode's \"exit\" mode line indicator."
  :group 'compilation
770
  :version "24.3")
771

772
(defface compilation-line-number
773
  '((t :inherit font-lock-keyword-face))
774
  "Face for displaying line numbers in compiler messages."
775
  :group 'compilation
776 777 778
  :version "22.1")

(defface compilation-column-number
779
  '((t :inherit font-lock-doc-face))
780
  "Face for displaying column numbers in compiler messages."
781
  :group 'compilation
782 783
  :version "22.1")

784
(defcustom compilation-message-face 'underline
Stefan Monnier's avatar
Stefan Monnier committed
785 786 787
  "Face name to use for whole messages.
Faces `compilation-error-face', `compilation-warning-face',
`compilation-info-face', `compilation-line-face' and
788 789 790 791
`compilation-column-face' get prepended to this, when applicable."
  :type 'face
  :group 'compilation
  :version "22.1")
Stefan Monnier's avatar
Stefan Monnier committed
792

793
(defvar compilation-error-face 'compilation-error
Stefan Monnier's avatar
Stefan Monnier committed
794 795
  "Face name to use for file name in error messages.")

796
(defvar compilation-warning-face 'compilation-warning
Stefan Monnier's avatar
Stefan Monnier committed
797 798
  "Face name to use for file name in warning messages.")

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

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

805
(defvar compilation-column-face 'compilation-column-number
806
  "Face name to use for column numbers in compiler messages.")
Stefan Monnier's avatar
Stefan Monnier committed
807 808 809

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

812
(defvar compilation-leave-directory-face 'font-lock-builtin-face
813
  "Face name to use for leaving directory messages.")
Stefan Monnier's avatar
Stefan Monnier committed
814

815 816
;; Used for compatibility with the old compile.el.
(defvar compilation-parse-errors-function nil)
817 818
(make-obsolete-variable 'compilation-parse-errors-function
			'compilation-error-regexp-alist "24.1")
819

820
(defcustom compilation-auto-jump-to-first-error nil
821
  "If non-nil, automatically jump to the first error during compilation."
822 823 824
  :type 'boolean
  :group 'compilation
  :version "23.1")
825 826 827 828 829

(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)

830 831 832
;; (defvar compilation-buffer-modtime nil
;;   "The buffer modification time, for buffers not associated with files.")
;; (make-variable-buffer-local 'compilation-buffer-modtime)
833 834

(defvar compilation-skip-to-next-location t
835
  "If non-nil, skip multiple error messages for the same source location.")
836 837 838 839 840 841 842

(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."
843 844 845
  :type '(choice (const :tag "Skip warnings and info" 2)
		 (const :tag "Skip info" 1)
		 (const :tag "No skip" 0))
846 847 848
  :group 'compilation
  :version "22.1")

849 850 851 852 853 854 855 856 857 858
(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"
859
           (pcase compilation-skip-threshold
860 861 862 863
             (0 "Nothing")
             (1 "Info messages")
             (2 "Warnings and info"))))

864 865 866 867 868 869 870 871 872
(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
873 874 875 876 877
(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))

878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
;;   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.

894
;; (cl-defstruct (compilation--loc
895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942
;;             (: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