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

3
;; Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
Glenn Morris's avatar
Glenn Morris committed
4
;;   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
5
;;   Free Software Foundation, Inc.
Eric S. Raymond's avatar
Eric S. Raymond committed
6

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

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

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

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

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

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

32
;; This mode uses some complex data-structures:
Stefan Monnier's avatar
Stefan Monnier committed
33

34
;;   LOC (or location) is a list of (COLUMN LINE FILE-STRUCTURE)
Stefan Monnier's avatar
Stefan Monnier committed
35 36 37 38 39

;; 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
40 41
;; (COLUMN LINE FILE-STRUCTURE MARKER TIMESTAMP . VISITED)
;; for all LOCs pertaining to that file.
Stefan Monnier's avatar
Stefan Monnier committed
42 43 44
;; 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.
45 46 47
;; TIMESTAMP is necessary because of "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.
Stefan Monnier's avatar
Stefan Monnier committed
48

49 50
;;   FILE-STRUCTURE is a list of
;;   ((FILENAME . DIRECTORY) FORMATS (LINE LOC ...) ...)
Stefan Monnier's avatar
Stefan Monnier committed
51 52 53 54 55 56 57 58 59 60 61

;; 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.

62
;;   MESSAGE is a list of (LOC TYPE END-LOC)
Stefan Monnier's avatar
Stefan Monnier committed
63 64 65

;; 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
Juanma Barranquero's avatar
Juanma Barranquero committed
66
;; other end, if the parsed message contained a range.  If the end of the
Stefan Monnier's avatar
Stefan Monnier committed
67 68 69 70
;; range didn't specify a COLUMN, it defaults to -1, meaning end of line.
;; These are the value of the `message' text-properties in the compilation
;; buffer.

71 72
;;; Code:

Stefan Monnier's avatar
Stefan Monnier committed
73
(eval-when-compile (require 'cl))
Jan Djärv's avatar
Jan Djärv committed
74
(require 'tool-bar)
75
(require 'comint)
Stefan Monnier's avatar
Stefan Monnier committed
76

77 78 79 80 81 82
(defvar font-lock-extra-managed-props)
(defvar font-lock-keywords)
(defvar font-lock-maximum-size)
(defvar font-lock-support-mode)


83 84 85 86 87 88
(defgroup compilation nil
  "Run compiler as inferior of Emacs, parse error messages."
  :group 'tools
  :group 'processes)


Roland McGrath's avatar
Roland McGrath committed
89
;;;###autoload
90
(defcustom compilation-mode-hook nil
91
  "List of hook functions run by `compilation-mode' (see `run-mode-hooks')."
92 93
  :type 'hook
  :group 'compilation)
Roland McGrath's avatar
Roland McGrath committed
94

95 96 97 98 99 100 101 102 103 104 105
;;;###autoload
(defcustom compilation-start-hook nil
  "List of hook functions run by `compilation-start' on the compilation process.
\(See `run-hook-with-args').
If you use \"omake -P\" and do not want \\[save-buffers-kill-terminal] to ask whether you want
the compilation to be killed, you can use this hook:
  (add-hook 'compilation-start-hook
    (lambda (process) (set-process-query-on-exit-flag process nil)) nil t)"
  :type 'hook
  :group 'compilation)

Roland McGrath's avatar
Roland McGrath committed
106
;;;###autoload
107
(defcustom compilation-window-height nil
108
  "Number of lines in a compilation window.  If nil, use Emacs default."
109 110 111
  :type '(choice (const :tag "Default" nil)
		 integer)
  :group 'compilation)
Roland McGrath's avatar
Roland McGrath committed
112

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

116 117 118 119 120
(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.")

121 122 123
;;;###autoload
(defvar compilation-process-setup-function nil
  "*Function to call to customize the compilation process.
Stefan Monnier's avatar
Stefan Monnier committed
124
This function is called immediately before the compilation process is
125
started.  It can be used to set any variables or functions that are used
126 127
while processing the output of the compilation process.  The function
is called with variables `compilation-buffer' and `compilation-window'
Stefan Monnier's avatar
Stefan Monnier committed
128
bound to the compilation buffer and window, respectively.")
129

Jim Blandy's avatar
Jim Blandy committed
130
;;;###autoload
Roland McGrath's avatar
Roland McGrath committed
131
(defvar compilation-buffer-name-function nil
Richard M. Stallman's avatar
Richard M. Stallman committed
132 133 134
  "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.
135
If nil, compute the name with `(concat \"*\" (downcase major-mode) \"*\")'.")
Richard M. Stallman's avatar
Richard M. Stallman committed
136

Jim Blandy's avatar
Jim Blandy committed
137
;;;###autoload
Roland McGrath's avatar
Roland McGrath committed
138
(defvar compilation-finish-function nil
139
  "Function to call when a compilation process finishes.
Roland McGrath's avatar
Roland McGrath committed
140
It is called with two arguments: the compilation buffer, and a string
141
describing how the process finished.")
142 143

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

147 148
;;;###autoload
(defvar compilation-finish-functions nil
149
  "Functions to call when a compilation process finishes.
150 151 152
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
153 154 155 156 157 158
(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
159 160
(defvar compilation-error "error"
  "Stem of message to print when no matches are found.")
Richard M. Stallman's avatar
Richard M. Stallman committed
161

162
(defvar compilation-arguments nil
Stefan Monnier's avatar
Stefan Monnier committed
163
  "Arguments that were given to `compilation-start'.")
164

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

Stefan Monnier's avatar
Stefan Monnier committed
167 168 169 170
(defconst compilation-error-regexp-alist-alist
  '((absoft
     "^\\(?:[Ee]rror on \\|[Ww]arning on\\( \\)\\)?[Ll]ine[ \t]+\\([0-9]+\\)[ \t]+\
of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
171

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

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

Stefan Monnier's avatar
Stefan Monnier committed
178 179 180
    (ant
     "^[ \t]*\\[[^] \n]+\\][ \t]*\\([^: \n]+\\):\\([0-9]+\\):\\(?:\\([0-9]+\\):[0-9]+:[0-9]+:\\)?\
\\( warning\\)?" 1 2 3 (4))
181

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

Stefan Monnier's avatar
Stefan Monnier committed
185 186 187 188 189 190
    (borland
     "^\\(?:Error\\|Warnin\\(g\\)\\) \\(?:[FEW][0-9]+ \\)?\
\\([a-zA-Z]?:?[^:( \t\n]+\\)\
 \\([0-9]+\\)\\(?:[) \t]\\|:[^0-9\n]\\)" 2 3 nil (1))

    (caml
191 192 193
     "^ *File \\(\"?\\)\\([^,\" \n\t<>]+\\)\\1, lines? \\([0-9]+\\)-?\\([0-9]+\\)?\\(?:$\\|,\
\\(?: characters? \\([0-9]+\\)-?\\([0-9]+\\)?:\\)?\\([ \n]Warning:\\)?\\)"
     2 (3 . 4) (5 . 6) (7))
Stefan Monnier's avatar
Stefan Monnier committed
194 195 196 197 198

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

199 200 201 202 203 204 205
    (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
206
    (epc
207
     "^Error [0-9]+ at (\\([0-9]+\\):\\([^)\n]+\\))" 2 1)
Stefan Monnier's avatar
Stefan Monnier committed
208

209 210 211
    (ftnchek
     "\\(^Warning .*\\)? line[ \n]\\([0-9]+\\)[ \n]\\(?:col \\([0-9]+\\)[ \n]\\)?file \\([^ :;\n]+\\)"
     4 2 3 (1))
212

Stefan Monnier's avatar
Stefan Monnier committed
213 214 215 216 217 218 219 220
    (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
221
    ;; fixme: should be `mips'
Stefan Monnier's avatar
Stefan Monnier committed
222
    (irix
223 224
     "^[-[: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
225 226 227 228 229 230 231 232 233 234 235 236

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

    (jikes-file
     "^\\(?:Found\\|Issued\\) .* compiling \"\\(.+\\)\":$" 1 nil nil 0)
    (jikes-line
     "^ *\\([0-9]+\\)\\.[ \t]+.*\n +\\(<-*>\n\\*\\*\\* \\(?:Error\\|Warnin\\(g\\)\\)\\)"
     nil 1 nil 2 0
     (2 (compilation-face '(3))))

    (gnu
237 238 239 240 241 242 243 244 245 246 247 248 249
     ;; 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.

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

     ;; 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
     ;; followed by a -.
Stefan Monnier's avatar
Stefan Monnier committed
259
     "^\\(?:[[:alpha:]][-[:alnum:].]+: ?\\)?\
260
\\([0-9]*[^0-9\n]\\(?:[^\n ]\\| [^-/\n]\\)*?\\): ?\
261
\\([0-9]+\\)\\(?:\\([.:]\\)\\([0-9]+\\)\\)?\
Chong Yidong's avatar
Chong Yidong committed
262
\\(?:-\\([0-9]+\\)?\\(?:\\.\\([0-9]+\\)\\)?\\)?:\
Stefan Monnier's avatar
Stefan Monnier committed
263
\\(?: *\\(\\(?:Future\\|Runtime\\)?[Ww]arning\\|W:\\)\\|\
264
 *\\([Ii]nfo\\(?:\\>\\|rmationa?l?\\)\\|I:\\|instantiated from\\|[Nn]ote\\)\\|\
265
\[0-9]?\\(?:[^0-9\n]\\|$\\)\\|[0-9][0-9][0-9]\\)"
Stefan Monnier's avatar
Stefan Monnier committed
266 267
     1 (2 . 5) (4 . 6) (7 . 8))

268 269 270 271 272 273
    ;; The `gnu' style above can incorrectly match gcc's "In file
    ;; included from" message, so we process that first. -- cyd
    (gcc-include
     "^\\(?:In file included\\|                \\) from \
\\(.+\\):\\([0-9]+\\)\\(?:\\(:\\)\\|\\(,\\)\\)?" 1 2 nil (3 . 4))

Stefan Monnier's avatar
Stefan Monnier committed
274 275 276 277 278
    (lcc
     "^\\(?:E\\|\\(W\\)\\), \\([^(\n]+\\)(\\([0-9]+\\),[ \t]*\\([0-9]+\\)"
     2 3 4 (1))

    (makepp
Daniel Pfeiffer's avatar
Daniel Pfeiffer committed
279
     "^makepp\\(?:\\(?:: warning\\(:\\).*?\\|\\(: Scanning\\|: [LR]e?l?oading makefile\\|: Imported\\|log:.*?\\) \\|: .*?\\)\
280
`\\(\\(\\S +?\\)\\(?::\\([0-9]+\\)\\)?\\)['(]\\)"
Stefan Monnier's avatar
Stefan Monnier committed
281
     4 5 nil (1 . 2) 3
282
     ("`\\(\\(\\S +?\\)\\(?::\\([0-9]+\\)\\)?\\)['(]" nil nil
Stefan Monnier's avatar
Stefan Monnier committed
283 284
      (2 compilation-info-face)
      (3 compilation-line-face nil t)
Daniel Pfeiffer's avatar
Daniel Pfeiffer committed
285
      (1 (compilation-error-properties 2 3 nil nil nil 0 nil)
Stefan Monnier's avatar
Stefan Monnier committed
286 287
	 append)))

288 289 290 291
    ;; This regexp is pathologically slow on long lines (Bug#3441).
    ;; (maven
    ;;  ;; Maven is a popular build tool for Java.  Maven is Free Software.
    ;;  "\\(.*?\\):\\[\\([0-9]+\\),\\([0-9]+\\)\\]" 1 2 3)
292

Stefan Monnier's avatar
Stefan Monnier committed
293
    ;; Should be lint-1, lint-2 (SysV lint)
Stefan Monnier's avatar
Stefan Monnier committed
294 295 296 297 298 299
    (mips-1
     " (\\([0-9]+\\)) in \\([^ \n]+\\)" 2 1)
    (mips-2
     " in \\([^()\n ]+\\)(\\([0-9]+\\))$" 1 2)

    (msft
300 301 302 303 304
     ;; 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
305

306 307 308 309 310
    (omake
     ;; "omake -P" reports "file foo changed"
     ;; (useful if you do "cvs up" and want to see what has changed)
     "omake: file \\(.*\\) changed" 1)

Stefan Monnier's avatar
Stefan Monnier committed
311
    (oracle
312 313 314
     "^\\(?:Semantic error\\|Error\\|PCC-[0-9]+:\\).* line \\([0-9]+\\)\
\\(?:\\(?:,\\| at\\)? column \\([0-9]+\\)\\)?\
\\(?:,\\| in\\| of\\)? file \\(.*?\\):?$"
Stefan Monnier's avatar
Stefan Monnier committed
315
     3 1 2)
316

317 318 319
    ;; "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
320
    (perl
321 322
     " at \\([^ \n]+\\) line \\([0-9]+\\)\\(?:[,.]\\|$\\| \
during global destruction\\.$\\)" 1 2)
Stefan Monnier's avatar
Stefan Monnier committed
323

324 325 326 327
    (php
     "\\(?:Parse\\|Fatal\\) error: \\(.*\\) in \\(.*\\) on line \\([0-9]+\\)"
     2 3 nil nil)

Stefan Monnier's avatar
Stefan Monnier committed
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
    (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
345
     ": \\(?:ERROR\\|WARNIN\\(G\\)\\|REMAR\\(K\\)\\) \\(?:[[:alnum:] ]+, \\)?\
Stefan Monnier's avatar
Stefan Monnier committed
346 347 348 349 350 351
File = \\(.+\\), Line = \\([0-9]+\\)\\(?:, Column = \\([0-9]+\\)\\)?"
     3 4 5 (1 . 2))

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

352
    (watcom
353
     "^[ \t]*\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)): ?\
Chong Yidong's avatar
Chong Yidong committed
354 355
\\(?:\\(Error! E[0-9]+\\)\\|\\(Warning! W[0-9]+\\)\\):"
     1 2 nil (4))
356

Stefan Monnier's avatar
Stefan Monnier committed
357 358
    (4bsd
     "\\(?:^\\|::  \\|\\S ( \\)\\(/[^ \n\t()]+\\)(\\([0-9]+\\))\
359 360 361
\\(?:: \\(warning:\\)?\\|$\\| ),\\)" 1 2 nil (3))

    (gcov-file
362
     "^ *-: *\\(0\\):Source:\\(.+\\)$"
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
     2 1 nil 0 nil
     (1 compilation-line-face prepend) (2 compilation-info-face prepend))
    (gcov-header
     "^ *-: *\\(0\\):\\(?:Object\\|Graph\\|Data\\|Runs\\|Programs\\):.+$"
     nil 1 nil 0 nil
     (1 compilation-line-face prepend))
    ;; 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
     (0 'default t)
     (1 compilation-line-face prepend))
379
    (gcov-called-line
380
     "^ *\\([0-9]+\\): *\\([0-9]+\\):.*$"
381
     nil 2 nil 0 nil
382 383 384
     (0 'default t)
     (1 compilation-info-face prepend) (2 compilation-line-face prepend))
    (gcov-never-called
385
     "^ *\\(#####\\): *\\([0-9]+\\):.*$"
386 387 388
     nil 2 nil 2 nil
     (0 'default t)
     (1 compilation-error-face prepend) (2 compilation-line-face prepend))
389

390
    (perl--Pod::Checker
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
     ;; 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))
408
    (perl--Test
409 410 411 412 413 414
     ;; 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)
415
    (perl--Test2
416 417 418 419 420 421 422 423 424 425
     ;; Or when comparing got/want values,
     ;; # Test 2 got: "xx" (t-compilation-perl-2.t at line 10)
     ;;
     ;; And under Test::Harness they're preceded by progress stuff with
     ;; \r and "NOK",
     ;; ... NOK 1# Test 1 got: "1234" (t/foo.t at line 46)
     ;;
     "^\\(.*NOK.*\\)?# Test [0-9]+ got:.* (\\([^ \t\r\n]+\\) at line \
\\([0-9]+\\))"
     2 3)
426
    (perl--Test::Harness
427 428 429 430 431 432 433 434 435 436
     ;; 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)
437
    (weblint
438 439 440 441 442 443 444 445 446 447 448 449 450
     ;; 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)
451
    )
Stefan Monnier's avatar
Stefan Monnier committed
452 453 454 455
  "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
456
  "Alist that specifies how to match errors in compiler output.
457
On GNU and Unix, any string is a valid filename, so these
Stefan Monnier's avatar
Stefan Monnier committed
458 459 460 461 462 463
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
464
`etc/compilation.txt' (linked below if you are customizing this).
Stefan Monnier's avatar
Stefan Monnier committed
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480

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
481 482
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
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506

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.

Additional HIGHLIGHTs as described under `font-lock-keywords' can
be added."
  :type `(set :menu-tag "Pick"
	      ,@(mapcar (lambda (elt)
			  (list 'const (car elt)))
			compilation-error-regexp-alist-alist))
  :link `(file-link :tag "example file"
507
		    ,(expand-file-name "compilation.txt" data-directory))
Stefan Monnier's avatar
Stefan Monnier committed
508
  :group 'compilation)
Richard M. Stallman's avatar
Richard M. Stallman committed
509

510
;;;###autoload(put 'compilation-directory 'safe-local-variable 'stringp)
511 512 513
(defvar compilation-directory nil
  "Directory to restore to when doing `recompile'.")

Stefan Monnier's avatar
Stefan Monnier committed
514 515 516
(defvar compilation-directory-matcher
  '("\\(?:Entering\\|Leavin\\(g\\)\\) directory `\\(.+\\)'$" (2 . 1))
  "A list for tracking when directories are entered or left.
517
If nil, do not track directories, e.g. if all file names are absolute.  The
Stefan Monnier's avatar
Stefan Monnier committed
518 519 520 521 522 523 524 525 526 527 528 529 530 531
first element is the REGEXP matching these messages.  It can match any number
of variants, e.g. different languages.  The remaining elements are all of the
form (DIR .  LEAVE).  If for any one of these the DIR'th subexpression
matches, that is a directory name.  If LEAVE is nil or the corresponding
LEAVE'th subexpression doesn't match, this message is about going into another
directory.  If it does match anything, this message is about going back to the
directory we were in before the last entering message.  If you change this,
you may also want to change `compilation-page-delimiter'.")

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

(defvar compilation-mode-font-lock-keywords
532
   '(;; configure output lines.
Stefan Monnier's avatar
Stefan Monnier committed
533 534
     ("^[Cc]hecking \\(?:[Ff]or \\|[Ii]f \\|[Ww]hether \\(?:to \\)?\\)?\\(.+\\)\\.\\.\\. *\\(?:(cached) *\\)?\\(\\(yes\\(?: .+\\)?\\)\\|no\\|\\(.*\\)\\)$"
      (1 font-lock-variable-name-face)
535
      (2 (compilation-face '(4 . 3))))
Stefan Monnier's avatar
Stefan Monnier committed
536
     ;; Command output lines.  Recognize `make[n]:' lines too.
Stefan Monnier's avatar
Stefan Monnier committed
537
     ("^\\([[:alnum:]_/.+-]+\\)\\(\\[\\([0-9]+\\)\\]\\)?[ \t]*:"
Stefan Monnier's avatar
Stefan Monnier committed
538 539
      (1 font-lock-function-name-face) (3 compilation-line-face nil t))
     (" --?o\\(?:utfile\\|utput\\)?[= ]?\\(\\S +\\)" . 1)
540 541
     ("^Compilation \\(finished\\).*"
      (0 '(face nil message nil help-echo nil mouse-face nil) t)
542
      (1 compilation-info-face))
543
     ("^Compilation \\(exited abnormally\\|interrupt\\|killed\\|terminated\\|segmentation fault\\)\\(?:.*with code \\([0-9]+\\)\\)?.*"
544
      (0 '(face nil message nil help-echo nil mouse-face nil) t)
545 546
      (1 compilation-error-face)
      (2 compilation-error-face nil t)))
Stefan Monnier's avatar
Stefan Monnier committed
547 548
   "Additional things to highlight in Compilation mode.
This gets tacked on the end of the generated expressions.")
549

550 551 552 553 554 555 556
(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.")

557
(defcustom compilation-error-screen-columns t
558
  "If non-nil, column numbers in error messages are screen columns.
559 560 561 562 563 564 565 566 567
Otherwise they are interpreted as character positions, with
each character occupying one column.
The default is to use screen columns, which requires that the compilation
program and Emacs agree about the display width of the characters,
especially the TAB character."
  :type 'boolean
  :group 'compilation
  :version "20.4")

568
(defcustom compilation-read-command t
569
  "Non-nil means \\[compile] reads the compilation command to use.
570 571 572 573 574 575
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."
576 577
  :type 'boolean
  :group 'compilation)
578

579
;;;###autoload
580
(defcustom compilation-ask-about-save t
581
  "Non-nil means \\[compile] asks which buffers to save before compiling.
582 583 584
Otherwise, it saves all modified buffers without asking."
  :type 'boolean
  :group 'compilation)
585

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

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

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:

602 603 604 605
    (add-hook 'c-mode-hook
       (lambda ()
	 (unless (or (file-exists-p \"makefile\")
		     (file-exists-p \"Makefile\"))
606 607
	   (set (make-local-variable 'compile-command)
		(concat \"make -k \"
Stefan Monnier's avatar
Stefan Monnier committed
608
			(file-name-sans-extension buffer-file-name))))))"
609 610
  :type 'string
  :group 'compilation)
611
;;;###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
612

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

Stefan Monnier's avatar
Stefan Monnier committed
622 623
;; 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
624
;; key.  This holds the tree seen from root, for storing new nodes.
Stefan Monnier's avatar
Stefan Monnier committed
625 626 627
(defvar compilation-locs ())

(defvar compilation-debug nil
Stefan Monnier's avatar
Stefan Monnier committed
628
  "*Set this to t before creating a *compilation* buffer.
Stefan Monnier's avatar
Stefan Monnier committed
629 630
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
631

632 633
(defvar compilation-exit-message-function nil "\
If non-nil, called when a compilation process dies to return a status message.
634 635 636
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.")
637

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

644 645 646
;; History of compile commands.
(defvar compile-history nil)

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

653
(defface compilation-warning
654 655
  '((((class color) (min-colors 16)) (:foreground "Orange" :weight bold))
    (((class color)) (:foreground "cyan" :weight bold))
Stefan Monnier's avatar
Stefan Monnier committed
656 657
    (t (:weight bold)))
  "Face used to highlight compiler warnings."
658
  :group 'compilation
659
  :version "22.1")
Stefan Monnier's avatar
Stefan Monnier committed
660

661
(defface compilation-info
662
  '((((class color) (min-colors 16) (background light))
663
     (:foreground "Green3" :weight bold))
664 665
    (((class color) (min-colors 88) (background dark))
     (:foreground "Green1" :weight bold))
666
    (((class color) (min-colors 16) (background dark))
667 668
     (:foreground "Green" :weight bold))
    (((class color)) (:foreground "green" :weight bold))
Stefan Monnier's avatar
Stefan Monnier committed
669
    (t (:weight bold)))
670
  "Face used to highlight compiler information."
671
  :group 'compilation
672
  :version "22.1")
Stefan Monnier's avatar
Stefan Monnier committed
673

674
(defface compilation-line-number
675
  '((t :inherit font-lock-variable-name-face))
676
  "Face for displaying line numbers in compiler messages."
677
  :group 'compilation
678 679 680
  :version "22.1")

(defface compilation-column-number
681
  '((t :inherit font-lock-type-face))
682
  "Face for displaying column numbers in compiler messages."
683
  :group 'compilation
684 685
  :version "22.1")

686
(defcustom compilation-message-face 'underline
Stefan Monnier's avatar
Stefan Monnier committed
687 688 689
  "Face name to use for whole messages.
Faces `compilation-error-face', `compilation-warning-face',
`compilation-info-face', `compilation-line-face' and
690 691 692 693
`compilation-column-face' get prepended to this, when applicable."
  :type 'face
  :group 'compilation
  :version "22.1")
Stefan Monnier's avatar
Stefan Monnier committed
694

695
(defvar compilation-error-face 'compilation-error
Stefan Monnier's avatar
Stefan Monnier committed
696 697
  "Face name to use for file name in error messages.")

698
(defvar compilation-warning-face 'compilation-warning
Stefan Monnier's avatar
Stefan Monnier committed
699 700
  "Face name to use for file name in warning messages.")

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

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

707
(defvar compilation-column-face 'compilation-column-number
708
  "Face name to use for column numbers in compiler messages.")
Stefan Monnier's avatar
Stefan Monnier committed
709 710 711

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

(defvar compilation-leave-directory-face 'font-lock-type-face
715
  "Face name to use for leaving directory messages.")
Stefan Monnier's avatar
Stefan Monnier committed
716 717 718



719
;; Used for compatibility with the old compile.el.
720
(defvaralias 'compilation-last-buffer 'next-error-last-buffer)
Stefan Monnier's avatar
Stefan Monnier committed
721
(defvar compilation-parsing-end (make-marker))
722 723 724 725
(defvar compilation-parse-errors-function nil)
(defvar compilation-error-list nil)
(defvar compilation-old-error-list nil)

726
(defcustom compilation-auto-jump-to-first-error nil
727
  "If non-nil, automatically jump to the first error during compilation."
728 729 730
  :type 'boolean
  :group 'compilation
  :version "23.1")
731 732 733 734 735

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

736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760

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

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

(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
761 762 763 764 765
(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))

766 767 768 769
;; Internal function for calculating the text properties of a directory
;; change message.  The directory property is important, because it is
;; the stack of nested enter-messages.  Relative filenames on the following
;; lines are relative to the top of the stack.
Stefan Monnier's avatar
Stefan Monnier committed
770 771 772 773 774 775 776 777 778 779 780 781 782 783
(defun compilation-directory-properties (idx leave)
  (if leave (setq leave (match-end leave)))
  ;; find previous stack, and push onto it, or if `leave' pop it
  (let ((dir (previous-single-property-change (point) 'directory)))
    (setq dir (if dir (or (get-text-property (1- dir) 'directory)
			  (get-text-property dir 'directory))))
    `(face ,(if leave
		compilation-leave-directory-face
	      compilation-enter-directory-face)
      directory ,(if leave
		     (or (cdr dir)
			 '(nil))	; nil only isn't a property-change
		   (cons (match-string-no-properties idx) dir))
      mouse-face highlight
Stefan Monnier's avatar
Stefan Monnier committed
784
      keymap compilation-button-map
785
      help-echo "mouse-2: visit destination directory")))
Stefan Monnier's avatar
Stefan Monnier committed
786

Juanma Barranquero's avatar
Juanma Barranquero committed
787
;; Data type `reverse-ordered-alist' retriever.  This function retrieves the
Stefan Monnier's avatar
Stefan Monnier committed
788 789 790 791
;; KEY element from the ALIST, creating it in the right position if not already
;; present. ALIST structure is
;; '(ANCHOR (KEY1 ...) (KEY2 ...)... (KEYn ALIST ...))
;; ANCHOR is ignored, but necessary so that elements can be inserted.  KEY1
Juanma Barranquero's avatar
Juanma Barranquero committed
792
;; may be nil.  The other KEYs are ordered backwards so that growing line
Stefan Monnier's avatar
Stefan Monnier committed
793 794
;; numbers can be inserted in front and searching can abort after half the
;; list on average.
Stefan Monnier's avatar
Stefan Monnier committed
795
(eval-when-compile		    ;Don't keep it at runtime if not needed.
Stefan Monnier's avatar
Stefan Monnier committed
796 797 798 799 800 801 802 803 804 805
(defmacro compilation-assq (key alist)
  `(let* ((l1 ,alist)
	  (l2 (cdr l1)))
     (car (if (if (null ,key)
		  (if l2 (null (caar l2)))
		(while (if l2 (if (caar l2) (< ,key (caar l2)) t))
		  (setq l1 l2
			l2 (cdr l1)))
		(if l2 (eq ,key (caar l2))))
	      l2
Stefan Monnier's avatar
Stefan Monnier committed
806
	    (setcdr l1 (cons (list ,key) l2)))))))
Stefan Monnier's avatar
Stefan Monnier committed
807

808 809 810
(defun compilation-auto-jump (buffer pos)
  (with-current-buffer buffer
    (goto-char pos)
811 812
    (let ((win (get-buffer-window buffer 0)))
      (if win (set-window-point win pos)))
Juri Linkov's avatar
Juri Linkov committed
813 814
    (if compilation-auto-jump-to-first-error
	(compile-goto-error))))
Stefan Monnier's avatar
Stefan Monnier committed
815 816 817 818

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

Stefan Monnier's avatar
Stefan Monnier committed
820
(defun compilation-error-properties (file line end-line col end-col type fmt)
821 822
  (unless (< (next-single-property-change (match-beginning 0)
                                          'directory nil (point))
Stefan Monnier's avatar
Stefan Monnier committed
823 824 825 826 827 828 829 830 831 832
	     (point))
    (if file
	(if (functionp file)
	    (setq file (funcall file))
	  (let (dir)
	    (setq file (match-string-no-properties file))
	    (unless (file-name-absolute-p file)
	      (setq dir (previous-single-property-change (point) 'directory)
		    dir (if dir (or (get-text-property (1- dir) 'directory)
				    (get-text-property dir 'directory)))))
833
	    (setq file (cons file (car dir)))))
Stefan Monnier's avatar
Stefan Monnier committed
834
      ;; This message didn't mention one, get it from previous
835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850
      (let ((prev-pos
	     ;; Find the previous message.
	     (previous-single-property-change (point) 'message)))
	(if prev-pos
	    ;; Get the file structure that belongs to it.
	    (let* ((prev
		    (or (get-text-property (1- prev-pos) 'message)
			(get-text-property prev-pos 'message)))
		   (prev-struct
		    (car (nth 2 (car prev)))))
	      ;; Construct FILE . DIR from that.
	      (if prev-struct
		  (setq file (cons (car prev-struct)
				   (cadr prev-struct))))))
	(unless file
	  (setq file '("*unknown*")))))
Stefan Monnier's avatar
Stefan Monnier committed
851 852 853 854 855 856 857 858
    ;; All of these fields are optional, get them only if we have an index, and
    ;; it matched some part of the message.
    (and line
	 (setq line (match-string-no-properties line))
	 (setq line (string-to-number line)))
    (and end-line
	 (setq end-line (match-string-no-properties end-line))
	 (setq end-line (string-to-number end-line)))
859 860 861 862 863 864 865 866 867 868 869
    (if col
        (if (functionp col)
            (setq col (funcall col))
          (and
           (setq col (match-string-no-properties col))
           (setq col (- (string-to-number col) compilation-first-column)))))
    (if (and end-col (functionp end-col))
        (setq end-col (funcall end-col))
      (if (and end-col (setq end-col (match-string-no-properties end-col)))
          (setq end-col (- (string-to-number end-col) compilation-first-column -1))
        (if end-line (setq end-col -1))))
870
    (if (consp type)			; not a static type, check what it is.
Stefan Monnier's avatar
Stefan Monnier committed
871 872 873
	(setq type (or (and (car type) (match-end (car type)) 1)
		       (and (cdr type) (match-end (cdr type)) 0)
		       2)))
874 875 876 877 878 879 880

    (when (and compilation-auto-jump-to-next
               (>= type compilation-skip-threshold))
      (kill-local-variable 'compilation-auto-jump-to-next)
      (run-with-timer 0 nil 'compilation-auto-jump
                      (current-buffer) (match-beginning 0)))

881 882
    (compilation-internal-error-properties file line end-line col end-col type fmt)))

883 884 885 886 887
(defun compilation-move-to-column (col screen)
  "Go to column COL on the current line.
If SCREEN is non-nil, columns are screen columns, otherwise, they are
just char-counts."
  (if screen
888
      (move-to-column (max col 0))
889 890
    (goto-char (min (+ (line-beginning-position) col) (line-end-position)))))

891
(defun compilation-internal-error-properties (file line end-line col end-col type fmts)
892 893
  "Get the meta-info that will be added as text-properties.
LINE, END-LINE, COL, END-COL are integers or nil.
894 895 896 897
TYPE can be 0, 1, or 2, meaning error, warning, or just info.
FILE should be (FILENAME) or (RELATIVE-FILENAME . DIRNAME) or nil.
FMTS is a list of format specs for transforming the file name.
 (See `compilation-error-regexp-alist'.)"
898
  (unless file (setq file '("*unknown*")))
899 900 901 902
  (let* ((file-struct (compilation-get-file-structure file fmts))
	 ;; Get first already existing marker (if any has one, all have one).
	 ;; Do this first, as the compilation-assq`s may create new nodes.
	 (marker-line (car (cddr file-struct)))	; a line structure
903 904 905 906
	 (marker (nth 3 (cadr marker-line)))	; its marker
	 (compilation-error-screen-columns compilation-error-screen-columns)
	 end-marker loc end-loc)
    (if (not (and marker (marker-buffer marker)))
907
	(setq marker nil)		; no valid marker for this file
908 909
      (setq loc (or line 1))		; normalize no linenumber to line 1
      (catch 'marker			; find nearest loc, at least one exists
910
	(dolist (x (nthcdr 3 file-struct))	; loop over remaining lines
911
	  (if (> (car x) loc)		; still bigger
912
	      (setq marker-line x)
913 914
	    (if (> (- (or (car marker-line) 1) loc)
		   (- loc (car x)))	; current line is nearer
915 916 917
		(setq marker-line x))
	    (throw 'marker t))))
      (setq marker (nth 3 (cadr marker-line))
918
	    marker-line (or (car marker-line) 1))
919
      (with-current-buffer (marker-buffer marker)
920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938
	(save-excursion
	  (save-restriction
	    (widen)
	    (goto-char (marker-position marker))
	    (when (or end-col end-line)
	      (beginning-of-line (- (or end-line line) marker-line -1))
	      (if (or (null end-col) (< end-col 0))
		  (end-of-line)
		(compilation-move-to-column
		 end-col compilation-error-screen-columns))
	      (setq end-marker (list (point-marker))))
	    (beginning-of-line (if end-line
				   (- line end-line -1)
				 (- loc marker-line -1)))
	    (if col
		(compilation-move-to-column
		 col compilation-error-screen-columns)
	      (forward-to-indentation 0))
	    (setq marker (list (point-marker)))))))
939

940
    (setq loc (compilation-assq line (cdr file-struct)))
941
    (if end-line
942
	(setq end-loc (compilation-assq end-line (cdr file-struct))
943 944 945 946 947
	      end-loc (compilation-assq end-col end-loc))
      (if end-col			; use same line element
	  (setq end-loc (compilation-assq end-col loc))))
    (setq loc (compilation-assq col loc))
    ;; If they are new, make the loc(s) reference the file they point to.
948
    (or (cdr loc) (setcdr loc `(,line ,file-struct ,@marker)))
949
    (if end-loc
950 951
	(or (cdr end-loc)
	    (setcdr end-loc `(,(or end-line line) ,file-struct ,@end-marker))))
952 953 954 955 956 957 958 959 960 961 962 963 964 965

    ;; Must start with face
    `(face ,compilation-message-face
	   message (,loc ,type ,end-loc)
	   ,@(if compilation-debug
		 `(debug (,(assoc (with-no-warnings matcher) font-lock-keywords)
			  ,@(match-data))))
	   help-echo ,(if col
			  "mouse-2: visit this file, line and column"
			(if line
			    "mouse-2: visit this file and line"
			  "mouse-2: visit this file"))
	   keymap compilation-button-map
	   mouse-face highlight)))
Stefan Monnier's avatar
Stefan Monnier committed
966

Simon Marshall's avatar
Simon Marshall committed
967 968
(defun compilation-mode-font-lock-keywords ()
  "Return expressions to highlight in Compilation mode."
969 970 971 972 973 974