compile.el 97.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
;;   FILE-STRUCTURE is a list of
50
;;   ((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
    (cucumber
     "\\(?:^cucumber\\(?: -p [^[:space:]]+\\)?\\|#\\)\
\\(?: \\)\\([^\(].*\\):\\([1-9][0-9]*\\)" 1 2)

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

213 214 215
    (ftnchek
     "\\(^Warning .*\\)? line[ \n]\\([0-9]+\\)[ \n]\\(?:col \\([0-9]+\\)[ \n]\\)?file \\([^ :;\n]+\\)"
     4 2 3 (1))
216

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

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

240 241 242 243
    (gcc-include
     "^\\(?:In file included \\|                 \\|\t\\)from \
\\(.+\\):\\([0-9]+\\)\\(?:\\(:\\)\\|\\(,\\|$\\)\\)?" 1 2 nil (3 . 4))

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

258 259 260 261
     ;; 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
262 263 264 265 266

     ;; 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 -.
267
     "^\\(?:[[:alpha:]][-[:alnum:].]+: ?\\|[ \t]+\\(?:in \\|from \\)\\)?\
268
\\([0-9]*[^0-9\n]\\(?:[^\n ]\\| [^-/\n]\\)*?\\): ?\
269
\\([0-9]+\\)\\(?:\\([.:]\\)\\([0-9]+\\)\\)?\
Chong Yidong's avatar
Chong Yidong committed
270
\\(?:-\\([0-9]+\\)?\\(?:\\.\\([0-9]+\\)\\)?\\)?:\
Stefan Monnier's avatar
Stefan Monnier committed
271
\\(?: *\\(\\(?:Future\\|Runtime\\)?[Ww]arning\\|W:\\)\\|\
272
 *\\([Ii]nfo\\(?:\\>\\|rmationa?l?\\)\\|I:\\|instantiated from\\|[Nn]ote\\)\\|\
273
\[0-9]?\\(?:[^0-9\n]\\|$\\)\\|[0-9][0-9][0-9]\\)"
Stefan Monnier's avatar
Stefan Monnier committed
274 275 276 277 278 279 280
     1 (2 . 5) (4 . 6) (7 . 8))

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

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

290 291 292 293
    ;; 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)
294

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

    (msft
302 303 304 305 306
     ;; 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
307

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

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

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

330 331 332
    (ruby-Test::Unit
     "[\t ]*\\[\\([^\(].*\\):\\([1-9][0-9]*\\)\\(\\]\\)?:$" 1 2)

Stefan Monnier's avatar
Stefan Monnier committed
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
    (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
350
     ": \\(?:ERROR\\|WARNIN\\(G\\)\\|REMAR\\(K\\)\\) \\(?:[[:alnum:] ]+, \\)?\
Stefan Monnier's avatar
Stefan Monnier committed
351 352 353 354 355 356
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)

357
    (watcom
358
     "^[ \t]*\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)): ?\
Chong Yidong's avatar
Chong Yidong committed
359 360
\\(?:\\(Error! E[0-9]+\\)\\|\\(Warning! W[0-9]+\\)\\):"
     1 2 nil (4))
361

Stefan Monnier's avatar
Stefan Monnier committed
362 363
    (4bsd
     "\\(?:^\\|::  \\|\\S ( \\)\\(/[^ \n\t()]+\\)(\\([0-9]+\\))\
364 365 366
\\(?:: \\(warning:\\)?\\|$\\| ),\\)" 1 2 nil (3))

    (gcov-file
367
     "^ *-: *\\(0\\):Source:\\(.+\\)$"
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
     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))
384
    (gcov-called-line
385
     "^ *\\([0-9]+\\): *\\([0-9]+\\):.*$"
386
     nil 2 nil 0 nil
387 388 389
     (0 'default t)
     (1 compilation-info-face prepend) (2 compilation-line-face prepend))
    (gcov-never-called
390
     "^ *\\(#####\\): *\\([0-9]+\\):.*$"
391 392 393
     nil 2 nil 2 nil
     (0 'default t)
     (1 compilation-error-face prepend) (2 compilation-line-face prepend))
394

395
    (perl--Pod::Checker
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
     ;; 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))
413
    (perl--Test
414 415 416 417 418 419
     ;; 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)
420
    (perl--Test2
421 422 423 424 425 426 427 428 429 430
     ;; 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)
431
    (perl--Test::Harness
432 433 434 435 436 437 438 439 440 441
     ;; 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)
442
    (weblint
443 444 445 446 447 448 449 450 451 452 453 454 455
     ;; 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)
456
    )
Stefan Monnier's avatar
Stefan Monnier committed
457 458 459 460
  "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
461
  "Alist that specifies how to match errors in compiler output.
462
On GNU and Unix, any string is a valid filename, so these
Stefan Monnier's avatar
Stefan Monnier committed
463 464 465 466 467 468
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
469
`etc/compilation.txt' (linked below if you are customizing this).
Stefan Monnier's avatar
Stefan Monnier committed
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485

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
486 487
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
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511

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"
512
		    ,(expand-file-name "compilation.txt" data-directory))
Stefan Monnier's avatar
Stefan Monnier committed
513
  :group 'compilation)
Richard M. Stallman's avatar
Richard M. Stallman committed
514

515
;;;###autoload(put 'compilation-directory 'safe-local-variable 'stringp)
516 517 518
(defvar compilation-directory nil
  "Directory to restore to when doing `recompile'.")

Stefan Monnier's avatar
Stefan Monnier committed
519 520 521
(defvar compilation-directory-matcher
  '("\\(?:Entering\\|Leavin\\(g\\)\\) directory `\\(.+\\)'$" (2 . 1))
  "A list for tracking when directories are entered or left.
522
If nil, do not track directories, e.g. if all file names are absolute.  The
Stefan Monnier's avatar
Stefan Monnier committed
523 524 525 526 527 528 529 530 531 532 533 534 535 536
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
537
   '(;; configure output lines.
Stefan Monnier's avatar
Stefan Monnier committed
538 539
     ("^[Cc]hecking \\(?:[Ff]or \\|[Ii]f \\|[Ww]hether \\(?:to \\)?\\)?\\(.+\\)\\.\\.\\. *\\(?:(cached) *\\)?\\(\\(yes\\(?: .+\\)?\\)\\|no\\|\\(.*\\)\\)$"
      (1 font-lock-variable-name-face)
540
      (2 (compilation-face '(4 . 3))))
Stefan Monnier's avatar
Stefan Monnier committed
541
     ;; Command output lines.  Recognize `make[n]:' lines too.
Stefan Monnier's avatar
Stefan Monnier committed
542
     ("^\\([[:alnum:]_/.+-]+\\)\\(\\[\\([0-9]+\\)\\]\\)?[ \t]*:"
Stefan Monnier's avatar
Stefan Monnier committed
543 544
      (1 font-lock-function-name-face) (3 compilation-line-face nil t))
     (" --?o\\(?:utfile\\|utput\\)?[= ]?\\(\\S +\\)" . 1)
545 546
     ("^Compilation \\(finished\\).*"
      (0 '(face nil message nil help-echo nil mouse-face nil) t)
547
      (1 compilation-info-face))
548
     ("^Compilation \\(exited abnormally\\|interrupt\\|killed\\|terminated\\|segmentation fault\\)\\(?:.*with code \\([0-9]+\\)\\)?.*"
549
      (0 '(face nil message nil help-echo nil mouse-face nil) t)
550 551
      (1 compilation-error-face)
      (2 compilation-error-face nil t)))
Stefan Monnier's avatar
Stefan Monnier committed
552 553
   "Additional things to highlight in Compilation mode.
This gets tacked on the end of the generated expressions.")
554

555 556 557 558 559 560 561
(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.")

562
(defcustom compilation-error-screen-columns t
563
  "If non-nil, column numbers in error messages are screen columns.
564 565 566 567 568 569 570 571 572
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")

573
(defcustom compilation-read-command t
574
  "Non-nil means \\[compile] reads the compilation command to use.
575 576 577 578 579 580
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."
581 582
  :type 'boolean
  :group 'compilation)
583

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

591 592 593 594 595 596 597 598 599 600 601 602
(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)
603 604
  :group 'compilation
  :version "24.1")
605

Roland McGrath's avatar
Roland McGrath committed
606
;;;###autoload
607
(defcustom compilation-search-path '(nil)
608
  "List of directories to search for source files named in error messages.
Roland McGrath's avatar
Roland McGrath committed
609
Elements should be directory names, not file names of directories.
610
The value nil as an element means to try the default directory."
611 612 613
  :type '(repeat (choice (const :tag "Default" nil)
			 (string :tag "Directory")))
  :group 'compilation)
Richard M. Stallman's avatar
Richard M. Stallman committed
614

615
;;;###autoload
616
(defcustom compile-command (purecopy "make -k ")
617
  "Last shell command used to do a compilation; default for next compilation.
Richard M. Stallman's avatar
Richard M. Stallman committed
618 619 620 621

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:

622 623 624 625
    (add-hook 'c-mode-hook
       (lambda ()
	 (unless (or (file-exists-p \"makefile\")
		     (file-exists-p \"Makefile\"))
626 627
	   (set (make-local-variable 'compile-command)
		(concat \"make -k \"
Stefan Monnier's avatar
Stefan Monnier committed
628
			(file-name-sans-extension buffer-file-name))))))"
629 630
  :type 'string
  :group 'compilation)
631
;;;###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
632

633
;;;###autoload
634
(defcustom compilation-disable-input nil
635
  "If non-nil, send end-of-file as compilation process input.
636
This only affects platforms that support asynchronous processes (see
637
`start-process'); synchronous compilation processes never accept input."
638 639 640 641
  :type 'boolean
  :group 'compilation
  :version "22.1")

Stefan Monnier's avatar
Stefan Monnier committed
642 643
;; 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
644
;; key.  This holds the tree seen from root, for storing new nodes.
Stefan Monnier's avatar
Stefan Monnier committed
645 646 647
(defvar compilation-locs ())

(defvar compilation-debug nil
Stefan Monnier's avatar
Stefan Monnier committed
648
  "*Set this to t before creating a *compilation* buffer.
Stefan Monnier's avatar
Stefan Monnier committed
649 650
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
651

652 653
(defvar compilation-exit-message-function nil "\
If non-nil, called when a compilation process dies to return a status message.
654 655 656
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.")
657

658 659 660 661 662 663
(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.")

664 665 666
;; History of compile commands.
(defvar compile-history nil)

667 668 669
(defface compilation-error
  '((t :inherit font-lock-warning-face))
  "Face used to highlight compiler errors."
670
  :group 'compilation
671 672
  :version "22.1")

673
(defface compilation-warning
674 675
  '((((class color) (min-colors 16)) (:foreground "Orange" :weight bold))
    (((class color)) (:foreground "cyan" :weight bold))
Stefan Monnier's avatar
Stefan Monnier committed
676 677
    (t (:weight bold)))
  "Face used to highlight compiler warnings."
678
  :group 'compilation
679
  :version "22.1")
Stefan Monnier's avatar
Stefan Monnier committed
680

681
(defface compilation-info
682
  '((((class color) (min-colors 16) (background light))
683
     (:foreground "Green3" :weight bold))
684 685
    (((class color) (min-colors 88) (background dark))
     (:foreground "Green1" :weight bold))
686
    (((class color) (min-colors 16) (background dark))
687 688
     (:foreground "Green" :weight bold))
    (((class color)) (:foreground "green" :weight bold))
Stefan Monnier's avatar
Stefan Monnier committed
689
    (t (:weight bold)))
690
  "Face used to highlight compiler information."
691
  :group 'compilation
692
  :version "22.1")
Stefan Monnier's avatar
Stefan Monnier committed
693

694
(defface compilation-line-number
695
  '((t :inherit font-lock-variable-name-face))
696
  "Face for displaying line numbers in compiler messages."
697
  :group 'compilation
698 699 700
  :version "22.1")

(defface compilation-column-number
701
  '((t :inherit font-lock-type-face))
702
  "Face for displaying column numbers in compiler messages."
703
  :group 'compilation
704 705
  :version "22.1")

706
(defcustom compilation-message-face 'underline
Stefan Monnier's avatar
Stefan Monnier committed
707 708 709
  "Face name to use for whole messages.
Faces `compilation-error-face', `compilation-warning-face',
`compilation-info-face', `compilation-line-face' and
710 711 712 713
`compilation-column-face' get prepended to this, when applicable."
  :type 'face
  :group 'compilation
  :version "22.1")
Stefan Monnier's avatar
Stefan Monnier committed
714

715
(defvar compilation-error-face 'compilation-error
Stefan Monnier's avatar
Stefan Monnier committed
716 717
  "Face name to use for file name in error messages.")

718
(defvar compilation-warning-face 'compilation-warning
Stefan Monnier's avatar
Stefan Monnier committed
719 720
  "Face name to use for file name in warning messages.")

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

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

727
(defvar compilation-column-face 'compilation-column-number
728
  "Face name to use for column numbers in compiler messages.")
Stefan Monnier's avatar
Stefan Monnier committed
729 730 731

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

(defvar compilation-leave-directory-face 'font-lock-type-face
735
  "Face name to use for leaving directory messages.")
Stefan Monnier's avatar
Stefan Monnier committed
736 737 738



739
;; Used for compatibility with the old compile.el.
740
(defvaralias 'compilation-last-buffer 'next-error-last-buffer)
Stefan Monnier's avatar
Stefan Monnier committed
741
(defvar compilation-parsing-end (make-marker))
742 743 744 745
(defvar compilation-parse-errors-function nil)
(defvar compilation-error-list nil)
(defvar compilation-old-error-list nil)

746
(defcustom compilation-auto-jump-to-first-error nil
747
  "If non-nil, automatically jump to the first error during compilation."
748 749 750
  :type 'boolean
  :group 'compilation
  :version "23.1")
751 752 753 754 755

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

756
(defvar compilation-buffer-modtime nil
757
  "The buffer modification time, for buffers not associated with files.")
758
(make-variable-buffer-local 'compilation-buffer-modtime)
759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783

(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
784 785 786 787 788
(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))

789 790 791 792
;; 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
793 794 795 796 797 798 799 800 801 802 803 804 805 806
(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
807
      keymap compilation-button-map
808
      help-echo "mouse-2: visit destination directory")))
Stefan Monnier's avatar
Stefan Monnier committed
809

Juanma Barranquero's avatar
Juanma Barranquero committed
810
;; Data type `reverse-ordered-alist' retriever.  This function retrieves the
Stefan Monnier's avatar
Stefan Monnier committed
811 812 813 814
;; 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
815
;; may be nil.  The other KEYs are ordered backwards so that growing line
Stefan Monnier's avatar
Stefan Monnier committed
816 817
;; numbers can be inserted in front and searching can abort after half the
;; list on average.
Stefan Monnier's avatar
Stefan Monnier committed
818
(eval-when-compile		    ;Don't keep it at runtime if not needed.
Stefan Monnier's avatar
Stefan Monnier committed
819 820 821 822 823 824 825 826 827 828
(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
829
	    (setcdr l1 (cons (list ,key) l2)))))))
Stefan Monnier's avatar
Stefan Monnier committed
830

831 832 833
(defun compilation-auto-jump (buffer pos)
  (with-current-buffer buffer
    (goto-char pos)
834 835
    (let ((win (get-buffer-window buffer 0)))
      (if win (set-window-point win pos)))
Juri Linkov's avatar
Juri Linkov committed
836 837
    (if compilation-auto-jump-to-first-error
	(compile-goto-error))))
Stefan Monnier's avatar
Stefan Monnier committed
838 839 840 841

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

Stefan Monnier's avatar
Stefan Monnier committed
843
(defun compilation-error-properties (file line end-line col end-col type fmt)
844 845
  (unless (< (next-single-property-change (match-beginning 0)
                                          'directory nil (point))
Stefan Monnier's avatar
Stefan Monnier committed
846 847 848 849 850 851 852 853 854 855
	     (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)))))
856
	    (setq file (cons file (car dir)))))
Stefan Monnier's avatar
Stefan Monnier committed
857
      ;; This message didn't mention one, get it from previous
858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873
      (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
874 875 876 877 878 879 880 881
    ;; 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)))
882 883 884 885 886 887 888 889 890 891 892
    (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))))
893
    (if (consp type)			; not a static type, check what it is.
Stefan Monnier's avatar
Stefan Monnier committed
894 895 896
	(setq type (or (and (car type) (match-end (car type)) 1)
		       (and (cdr type) (match-end (cdr type)) 0)
		       2)))
897 898 899 900 901 902 903

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

904 905
    (compilation-internal-error-properties file line end-line col end-col type fmt)))

906 907 908 909 910
(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
911
      (move-to-column (max col 0))
912 913
    (goto-char (min (+ (line-beginning-position) col) (line-end-position)))))

914
(defun compilation-internal-error-properties (file line end-line col end-col type fmts)
915 916
  "Get the meta-info that will be added as text-properties.
LINE, END-LINE, COL, END-COL are integers or nil.
917 918 919 920
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'.)"
921
  (unless file (setq file '("*unknown*")))
922 923 924 925
  (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
926 927 928 929
	 (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)))
930
	(setq marker nil)		; no valid marker for this file
931 932
      (setq loc (or line 1))		; normalize no linenumber to line 1
      (catch 'marker			; find nearest loc, at least one exists
933
	(dolist (x (nthcdr 3 file-struct))	; loop over remaining lines
934
	  (if (> (car x) loc)		; still bigger
935
	      (setq marker-line x)
936 937
	    (if (> (- (or (car marker-line) 1) loc)
		   (- loc (car x)))	; current line is nearer
938 939 940
		(setq marker-line x))
	    (throw 'marker t))))
      (setq marker (nth 3 (cadr marker-line))
941
	    marker-line (or (car marker-line) 1))
942
      (with-current-buffer (marker-buffer marker)
943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961
	(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)))))))
962

963
    (setq loc (compilation-assq line (cdr file-struct)))
964
    (if end-line
965
	(setq end-loc (compilation-assq end-line (cdr file-struct))