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

Jö Fahlke's avatar
Jö Fahlke committed
164 165 166 167 168 169 170
    (cmake
     "^CMake \\(?:Error\\|\\(Warning\\)\\) at \\(.*\\):\\([1-9][0-9]*\\) ([^)]+):$"
     2 3 nil (1))
    (cmake-info
     "^  \\(?: \\*\\)?\\(.*\\):\\([1-9][0-9]*\\) ([^)]+)$"
     1 2 nil 0)

Stefan Monnier's avatar
Stefan Monnier committed
171 172 173 174
    (comma
     "^\"\\([^,\" \n\t]+\\)\", line \\([0-9]+\\)\
\\(?:[(. pos]+\\([0-9]+\\))?\\)?[:.,; (-]\\( warning:\\|[-0-9 ]*(W)\\)?" 1 2 3 (4))

175 176
    (cucumber
     "\\(?:^cucumber\\(?: -p [^[:space:]]+\\)?\\|#\\)\
177
\\(?: \\)\\([^(].*\\):\\([1-9][0-9]*\\)" 1 2)
178

179 180 181 182 183 184 185 186 187
    (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))

188 189 190 191 192 193 194
    (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
195
    (epc
196
     "^Error [0-9]+ at (\\([0-9]+\\):\\([^)\n]+\\))" 2 1)
Stefan Monnier's avatar
Stefan Monnier committed
197

198 199 200
    (ftnchek
     "\\(^Warning .*\\)? line[ \n]\\([0-9]+\\)[ \n]\\(?:col \\([0-9]+\\)[ \n]\\)?file \\([^ :;\n]+\\)"
     4 2 3 (1))
201

Stefan Monnier's avatar
Stefan Monnier committed
202 203 204 205 206 207 208 209
    (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
210
    ;; fixme: should be `mips'
Stefan Monnier's avatar
Stefan Monnier committed
211
    (irix
212 213
     "^[-[: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
214 215 216 217 218 219

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

    (jikes-file
     "^\\(?:Found\\|Issued\\) .* compiling \"\\(.+\\)\":$" 1 nil nil 0)
220 221 222 223 224 225


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

Stefan Monnier's avatar
Stefan Monnier committed
228 229 230 231 232
    (jikes-line
     "^ *\\([0-9]+\\)\\.[ \t]+.*\n +\\(<-*>\n\\*\\*\\* \\(?:Error\\|Warnin\\(g\\)\\)\\)"
     nil 1 nil 2 0
     (2 (compilation-face '(3))))

233 234
    (gcc-include
     "^\\(?:In file included \\|                 \\|\t\\)from \
Andreas Schwab's avatar
Andreas Schwab committed
235 236 237
\\([0-9]*[^0-9\n]\\(?:[^\n :]\\| [^-/\n]\\|:[^ \n]\\)*?\\):\
\\([0-9]+\\)\\(?::\\([0-9]+\\)\\)?\\(?:\\(:\\)\\|\\(,\\|$\\)\\)?"
     1 2 3 (4 . 5))
238

239
    (ruby-Test::Unit
240
     "^[\t ]*\\[\\([^(].*\\):\\([1-9][0-9]*\\)\\(\\]\\)?:in " 1 2)
241

Stefan Monnier's avatar
Stefan Monnier committed
242
    (gnu
243 244 245 246 247 248 249 250 251 252 253 254 255
     ;; 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.

256 257 258 259
     ;; 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
260 261 262 263

     ;; 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
264
     ;; followed by a -, or a colon followed by a space.
265
     ;;
266
     ;; The "in \\|from " exception was added to handle messages from Ruby.
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 298 299 300 301 302 303 304
     ,(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]")))
305
     1 (2 . 4) (3 . 5) (6 . 7))
Stefan Monnier's avatar
Stefan Monnier committed
306 307 308 309 310 311

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

    (makepp
Daniel Pfeiffer's avatar
Daniel Pfeiffer committed
312
     "^makepp\\(?:\\(?:: warning\\(:\\).*?\\|\\(: Scanning\\|: [LR]e?l?oading makefile\\|: Imported\\|log:.*?\\) \\|: .*?\\)\
313
`\\(\\(\\S +?\\)\\(?::\\([0-9]+\\)\\)?\\)['(]\\)"
Stefan Monnier's avatar
Stefan Monnier committed
314
     4 5 nil (1 . 2) 3
315 316 317 318 319 320 321 322 323
     (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
324

Stefan Monnier's avatar
Stefan Monnier committed
325
    ;; Should be lint-1, lint-2 (SysV lint)
Stefan Monnier's avatar
Stefan Monnier committed
326 327 328 329 330 331
    (mips-1
     " (\\([0-9]+\\)) in \\([^ \n]+\\)" 2 1)
    (mips-2
     " in \\([^()\n ]+\\)(\\([0-9]+\\))$" 1 2)

    (msft
332 333 334 335 336
     ;; 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
337

338 339 340
    (omake
     ;; "omake -P" reports "file foo changed"
     ;; (useful if you do "cvs up" and want to see what has changed)
341 342 343 344 345 346
     "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)))
347

Stefan Monnier's avatar
Stefan Monnier committed
348
    (oracle
349 350 351
     "^\\(?:Semantic error\\|Error\\|PCC-[0-9]+:\\).* line \\([0-9]+\\)\
\\(?:\\(?:,\\| at\\)? column \\([0-9]+\\)\\)?\
\\(?:,\\| in\\| of\\)? file \\(.*?\\):?$"
Stefan Monnier's avatar
Stefan Monnier committed
352
     3 1 2)
353

354 355 356
    ;; "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
357
    (perl
358 359
     " at \\([^ \n]+\\) line \\([0-9]+\\)\\(?:[,.]\\|$\\| \
during global destruction\\.$\\)" 1 2)
Stefan Monnier's avatar
Stefan Monnier committed
360

361 362 363 364
    (php
     "\\(?:Parse\\|Fatal\\) error: \\(.*\\) in \\(.*\\) on line \\([0-9]+\\)"
     2 3 nil nil)

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

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

389
    (watcom
390
     "^[ \t]*\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)): ?\
Chong Yidong's avatar
Chong Yidong committed
391 392
\\(?:\\(Error! E[0-9]+\\)\\|\\(Warning! W[0-9]+\\)\\):"
     1 2 nil (4))
393

Stefan Monnier's avatar
Stefan Monnier committed
394 395
    (4bsd
     "\\(?:^\\|::  \\|\\S ( \\)\\(/[^ \n\t()]+\\)(\\([0-9]+\\))\
396 397 398
\\(?:: \\(warning:\\)?\\|$\\| ),\\)" 1 2 nil (3))

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

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

    ;; 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)
510
    (guile-line "^ *\\([0-9]+\\): *\\([0-9]+\\)" nil 1 2)
511
    )
Stefan Monnier's avatar
Stefan Monnier committed
512 513 514 515
  "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
516
  "Alist that specifies how to match errors in compiler output.
517
On GNU and Unix, any string is a valid filename, so these
Stefan Monnier's avatar
Stefan Monnier committed
518 519 520 521 522 523
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
524
`etc/compilation.txt' (linked below if you are customizing this).
Stefan Monnier's avatar
Stefan Monnier committed
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540

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
541 542
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
543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559

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.

560 561
Additional HIGHLIGHTs take the shape (SUBMATCH FACE), where
SUBMATCH is the number of a submatch and FACE is an expression
562 563 564 565
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
566 567
  :type '(repeat (choice (symbol :tag "Predefined symbol")
			 (sexp :tag "Error specification")))
Stefan Monnier's avatar
Stefan Monnier committed
568
  :link `(file-link :tag "example file"
569
		    ,(expand-file-name "compilation.txt" data-directory))
Stefan Monnier's avatar
Stefan Monnier committed
570
  :group 'compilation)
Richard M. Stallman's avatar
Richard M. Stallman committed
571

572
;;;###autoload(put 'compilation-directory 'safe-local-variable 'stringp)
573 574 575
(defvar compilation-directory nil
  "Directory to restore to when doing `recompile'.")

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

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

612 613 614 615 616 617 618
(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.")

619
(defcustom compilation-error-screen-columns t
620
  "If non-nil, column numbers in error messages are screen columns.
621 622 623 624
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
625 626 627 628
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."
629 630 631 632
  :type 'boolean
  :group 'compilation
  :version "20.4")

633
(defcustom compilation-read-command t
634
  "Non-nil means \\[compile] reads the compilation command to use.
635 636 637 638 639 640
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."
641 642
  :type 'boolean
  :group 'compilation)
643

644
;;;###autoload
645
(defcustom compilation-ask-about-save t
646
  "Non-nil means \\[compile] asks which buffers to save before compiling.
647 648 649
Otherwise, it saves all modified buffers without asking."
  :type 'boolean
  :group 'compilation)
650

651 652 653 654 655 656 657 658 659 660 661 662
(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)
663 664
  :group 'compilation
  :version "24.1")
665

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

675
;;;###autoload
676
(defcustom compile-command (purecopy "make -k ")
677
  "Last shell command used to do a compilation; default for next compilation.
Richard M. Stallman's avatar
Richard M. Stallman committed
678 679 680 681

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:

682
    (add-hook \\='c-mode-hook
683 684 685
       (lambda ()
	 (unless (or (file-exists-p \"makefile\")
		     (file-exists-p \"Makefile\"))
686
	   (set (make-local-variable \\='compile-command)
687
		(concat \"make -k \"
688 689 690
			(if buffer-file-name
			  (shell-quote-argument
			    (file-name-sans-extension buffer-file-name))))))))"
691 692
  :type 'string
  :group 'compilation)
693
;;;###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
694

695
;;;###autoload
696
(defcustom compilation-disable-input nil
697
  "If non-nil, send end-of-file as compilation process input.
698
This only affects platforms that support asynchronous processes (see
699
`start-process'); synchronous compilation processes never accept input."
700 701 702 703
  :type 'boolean
  :group 'compilation
  :version "22.1")

Stefan Monnier's avatar
Stefan Monnier committed
704 705
;; 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
706
;; key.  This holds the tree seen from root, for storing new nodes.
Stefan Monnier's avatar
Stefan Monnier committed
707 708 709
(defvar compilation-locs ())

(defvar compilation-debug nil
710
  "Set this to t before creating a *compilation* buffer.
Stefan Monnier's avatar
Stefan Monnier committed
711 712
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
713

714 715
(defvar compilation-exit-message-function nil "\
If non-nil, called when a compilation process dies to return a status message.
716 717 718
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.")
719

720 721
(defcustom compilation-environment nil
  "List of environment variables for compilation to inherit.
722 723
Each element should be a string of the form ENVVARNAME=VALUE.
This list is temporarily prepended to `process-environment' prior to
724 725 726 727 728
starting the compilation process."
  :type '(repeat (string :tag "ENVVARNAME=VALUE"))
  :options '(("LANG=C"))
  :group 'compilation
  :version "24.1")
729

730 731 732
;; History of compile commands.
(defvar compile-history nil)

733
(defface compilation-error
734
  '((t :inherit error))
735
  "Face used to highlight compiler errors."
736
  :group 'compilation
737 738
  :version "22.1")

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

745
(defface compilation-info
746
  '((t :inherit success))
747
  "Face used to highlight compiler information."
748
  :group 'compilation
749
  :version "22.1")
Stefan Monnier's avatar
Stefan Monnier committed
750

751 752 753 754 755 756 757 758 759 760
;; 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
761
  :version "24.3")
762 763 764 765 766

(defface compilation-mode-line-run
  '((t :inherit compilation-warning))
  "Face for Compilation mode's \"running\" mode line indicator."
  :group 'compilation
767
  :version "24.3")
768 769 770 771 772 773 774 775 776

(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
777
  :version "24.3")
778

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

(defface compilation-column-number
786
  '((t :inherit font-lock-doc-face))
787
  "Face for displaying column numbers in compiler messages."
788
  :group 'compilation
789 790
  :version "22.1")

791
(defcustom compilation-message-face 'underline
Stefan Monnier's avatar
Stefan Monnier committed
792 793 794
  "Face name to use for whole messages.
Faces `compilation-error-face', `compilation-warning-face',
`compilation-info-face', `compilation-line-face' and
795 796 797 798
`compilation-column-face' get prepended to this, when applicable."
  :type 'face
  :group 'compilation
  :version "22.1")
Stefan Monnier's avatar
Stefan Monnier committed
799

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

803
(defvar compilation-warning-face 'compilation-warning
Stefan Monnier's avatar
Stefan Monnier committed
804 805
  "Face name to use for file name in warning messages.")

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

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

812
(defvar compilation-column-face 'compilation-column-number
813
  "Face name to use for column numbers in compiler messages.")
Stefan Monnier's avatar
Stefan Monnier committed
814 815 816

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

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

822 823
;; Used for compatibility with the old compile.el.
(defvar compilation-parse-errors-function nil)
824 825
(make-obsolete-variable 'compilation-parse-errors-function
			'compilation-error-regexp-alist "24.1")
826

827
(defcustom compilation-auto-jump-to-first-error nil
828
  "If non-nil, automatically jump to the first error during compilation."
829 830 831
  :type 'boolean
  :group 'compilation
  :version "23.1")
832 833 834 835 836

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

837 838 839
;; (defvar compilation-buffer-modtime nil
;;   "The buffer modification time, for buffers not associated with files.")
;; (make-variable-buffer-local 'compilation-buffer-modtime)
840 841

(defvar compilation-skip-to-next-location t
842
  "If non-nil, skip multiple error messages for the same source location.")
843 844 845 846 847 848 849

(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."
850 851 852
  :type '(choice (const :tag "Skip warnings and info" 2)
		 (const :tag "Skip info" 1)
		 (const :tag "No skip" 0))
853 854 855
  :group 'compilation
  :version "22.1")

856 857 858 859 860 861 862 863 864 865
(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"
866
           (pcase compilation-skip-threshold
867 868 869 870
             (0 "Nothing")
             (1 "Info messages")
             (2 "Warnings and info"))))

871 872 873 874 875 876 877 878 879
(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
880 881 882 883 884
(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))

885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
;;   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.

901
;; (cl-defstruct (compilation--loc
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 943 944 945 946 947 948 949
;;             (: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.

950
(cl-defstruct (compilation--message
951 952 953 954 955 956 957
            (:constructor nil)
            (:copier nil)
            ;; (:type list)                ;Old representation.
            (:constructor compilation--make-message (loc type end-loc))
            (:conc-name compilation--message->))
  loc type end-loc)

958 959 960
(defvar compilation--previous-directory-cache nil
  "A pair (POS . RES) caching the result of previous directory search.
Basically, this pair says that calling
961
   (previous-single-property-change POS \\='compilation-directory)
962 963
returned RES, i.e. there is no change of `compilation-directory' between
POS and RES.")
964
(make-variable-buffer-local 'compilation--previous-directory-cache)
965

966
(defun compilation--flush-directory-cache (start _end)
967 968 969 970
  (cond
   ((or (not compilation--previous-directory-cache)
        (<= (car compilation--previous-directory-cache) start)))
   ((or (not (cdr compilation--previous-directory-cache))
971
	(null (marker-buffer (cdr compilation--previous-directory-cache)))
972 973 974 975
        (<= (cdr compilation--previous-directory-cache) start))
    (set-marker (car compilation--previous-directory-cache) start))
   (t (setq compilation--previous-directory-cache nil))))

976
(defun compilation--previous-directory (pos)
977
  "Like (previous-single-property-change POS \\='compilation-directory), but faster."
978 979 980
  ;; 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.