]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/make-mode.el
(etags-tags-completion-table): Use progress reporter.
[gnu-emacs] / lisp / progmodes / make-mode.el
index b2d50413fb41b5763c851e0ff3bd02a65a7a84f2..99138444f7ccca46377cf0c368b320586729f7af 100644 (file)
@@ -1,6 +1,6 @@
 ;;; make-mode.el --- makefile editing commands for Emacs
 
 ;;; make-mode.el --- makefile editing commands for Emacs
 
-;; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+;; Copyright (C) 1992,94,99,2000,2001, 2002, 2003  Free Software Foundation, Inc.
 
 ;; Author: Thomas Neumann <tom@smart.bo.open.de>
 ;;     Eric S. Raymond <esr@snark.thyrsus.com>
 
 ;; Author: Thomas Neumann <tom@smart.bo.open.de>
 ;;     Eric S. Raymond <esr@snark.thyrsus.com>
@@ -8,11 +8,6 @@
 ;; Adapted-By: ESR
 ;; Keywords: unix, tools
 
 ;; Adapted-By: ESR
 ;; Keywords: unix, tools
 
-;; RMS:
-;; This needs work.
-;; Also, the doc strings need fixing: the first line doesn't stand alone,
-;; and other usage is not high quality.  Symbol names don't have `...'.
-
 ;; This file is part of GNU Emacs.
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; This file is part of GNU Emacs.
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
@@ -63,6 +58,7 @@
 ;;
 ;; To Do:
 ;;
 ;;
 ;; To Do:
 ;;
+;; * Add missing doc strings, improve terse doc strings.
 ;; * Eliminate electric stuff entirely.
 ;; * It might be nice to highlight targets differently depending on
 ;;   whether they are up-to-date or not.  Not sure how this would
 ;; * Eliminate electric stuff entirely.
 ;; * It might be nice to highlight targets differently depending on
 ;;   whether they are up-to-date or not.  Not sure how this would
 
 ;;; Code:
 
 
 ;;; Code:
 
-(provide 'make-mode)
-
 ;; Sadly we need this for a macro.
 (eval-when-compile
 ;; Sadly we need this for a macro.
 (eval-when-compile
-  (require 'imenu))
+  (require 'imenu)
+  (require 'dabbrev)
+  (require 'add-log))
 
 ;;; ------------------------------------------------------------
 ;;; Configurable stuff
 
 ;;; ------------------------------------------------------------
 ;;; Configurable stuff
      (t (:reverse-video t)))
   "Face to use for highlighting leading spaces in Font-Lock mode."
   :group 'faces
      (t (:reverse-video t)))
   "Face to use for highlighting leading spaces in Font-Lock mode."
   :group 'faces
-  :group 'makemode)
+  :group 'makefile)
 
 (defcustom makefile-browser-buffer-name "*Macros and Targets*"
 
 (defcustom makefile-browser-buffer-name "*Macros and Targets*"
-  "Name of the macro- and target browser buffer."
+  "*Name of the macro- and target browser buffer."
   :type 'string
   :group 'makefile)
 
 (defcustom makefile-target-colon ":"
   :type 'string
   :group 'makefile)
 
 (defcustom makefile-target-colon ":"
-  "String to append to all target names inserted by `makefile-insert-target'.
+  "*String to append to all target names inserted by `makefile-insert-target'.
 \":\" or \"::\" are common values."
   :type 'string
   :group 'makefile)
 
 (defcustom makefile-macro-assign " = "
 \":\" or \"::\" are common values."
   :type 'string
   :group 'makefile)
 
 (defcustom makefile-macro-assign " = "
-  "String to append to all macro names inserted by `makefile-insert-macro'.
+  "*String to append to all macro names inserted by `makefile-insert-macro'.
 The normal value should be \" = \", since this is what
 standard make expects.  However, newer makes such as dmake
 allow a larger variety of different macro assignments, so you
 The normal value should be \" = \", since this is what
 standard make expects.  However, newer makes such as dmake
 allow a larger variety of different macro assignments, so you
@@ -131,32 +127,32 @@ might prefer to use \" += \" or \" := \" ."
   :group 'makefile)
 
 (defcustom makefile-electric-keys nil
   :group 'makefile)
 
 (defcustom makefile-electric-keys nil
-  "If non-nil, Makefile mode should install electric keybindings.
+  "*If non-nil, Makefile mode should install electric keybindings.
 Default is nil."
   :type 'boolean
   :group 'makefile)
 
 (defcustom makefile-use-curly-braces-for-macros-p nil
 Default is nil."
   :type 'boolean
   :group 'makefile)
 
 (defcustom makefile-use-curly-braces-for-macros-p nil
-  "Controls the style of generated macro references.
+  "*Controls the style of generated macro references.
 Non-nil means macro references should use curly braces, like `${this}'.
 nil means use parentheses, like `$(this)'."
   :type 'boolean
   :group 'makefile)
 
 (defcustom makefile-tab-after-target-colon t
 Non-nil means macro references should use curly braces, like `${this}'.
 nil means use parentheses, like `$(this)'."
   :type 'boolean
   :group 'makefile)
 
 (defcustom makefile-tab-after-target-colon t
-  "If non-nil, insert a TAB after a target colon.
+  "*If non-nil, insert a TAB after a target colon.
 Otherwise, a space is inserted.
 The default is t."
   :type 'boolean
   :group 'makefile)
 
 (defcustom makefile-browser-leftmost-column 10
 Otherwise, a space is inserted.
 The default is t."
   :type 'boolean
   :group 'makefile)
 
 (defcustom makefile-browser-leftmost-column 10
-  "Number of blanks to the left of the browser selection mark."
+  "*Number of blanks to the left of the browser selection mark."
   :type 'integer
   :group 'makefile)
 
 (defcustom makefile-browser-cursor-column 10
   :type 'integer
   :group 'makefile)
 
 (defcustom makefile-browser-cursor-column 10
-  "Column the cursor goes to when it moves up or down in the Makefile browser."
+  "*Column the cursor goes to when it moves up or down in the Makefile browser."
   :type 'integer
   :group 'makefile)
 
   :type 'integer
   :group 'makefile)
 
@@ -166,34 +162,34 @@ The default is t."
   :group 'makefile)
 
 (defcustom makefile-backslash-align t
   :group 'makefile)
 
 (defcustom makefile-backslash-align t
-  "If non-nil, `makefile-backslash-region' will align backslashes."
+  "*If non-nil, `makefile-backslash-region' will align backslashes."
   :type 'boolean
   :group 'makefile)
 
 (defcustom makefile-browser-selected-mark "+  "
   :type 'boolean
   :group 'makefile)
 
 (defcustom makefile-browser-selected-mark "+  "
-  "String used to mark selected entries in the Makefile browser."
+  "*String used to mark selected entries in the Makefile browser."
   :type 'string
   :group 'makefile)
 
 (defcustom makefile-browser-unselected-mark "   "
   :type 'string
   :group 'makefile)
 
 (defcustom makefile-browser-unselected-mark "   "
-  "String used to mark unselected entries in the Makefile browser."
+  "*String used to mark unselected entries in the Makefile browser."
   :type 'string
   :group 'makefile)
 
 (defcustom makefile-browser-auto-advance-after-selection-p t
   :type 'string
   :group 'makefile)
 
 (defcustom makefile-browser-auto-advance-after-selection-p t
-  "If non-nil, cursor will move after item is selected in Makefile browser."
+  "*If non-nil, cursor will move after item is selected in Makefile browser."
   :type 'boolean
   :group 'makefile)
 
 (defcustom makefile-pickup-everything-picks-up-filenames-p nil
   :type 'boolean
   :group 'makefile)
 
 (defcustom makefile-pickup-everything-picks-up-filenames-p nil
-  "If non-nil, `makefile-pickup-everything' picks up filenames as targets.
+  "*If non-nil, `makefile-pickup-everything' picks up filenames as targets.
 This means it calls `makefile-pickup-filenames-as-targets'.
 Otherwise filenames are omitted."
   :type 'boolean
   :group 'makefile)
 
 This means it calls `makefile-pickup-filenames-as-targets'.
 Otherwise filenames are omitted."
   :type 'boolean
   :group 'makefile)
 
-(defcustom makefile-cleanup-continuations-p t
-  "If non-nil, automatically clean up continuation lines when saving.
+(defcustom makefile-cleanup-continuations nil
+  "*If non-nil, automatically clean up continuation lines when saving.
 A line is cleaned up by removing all whitespace following a trailing
 backslash.  This is done silently.
 IMPORTANT: Please note that enabling this option causes Makefile mode
 A line is cleaned up by removing all whitespace following a trailing
 backslash.  This is done silently.
 IMPORTANT: Please note that enabling this option causes Makefile mode
@@ -202,7 +198,7 @@ to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems necessary\"."
   :group 'makefile)
 
 (defcustom makefile-mode-hook nil
   :group 'makefile)
 
 (defcustom makefile-mode-hook nil
-  "Normal hook run by `makefile-mode'."
+  "*Normal hook run by `makefile-mode'."
   :type 'hook
   :group 'makefile)
 
   :type 'hook
   :group 'makefile)
 
@@ -210,7 +206,7 @@ to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems necessary\"."
 
 ;;
 ;; Special targets for DMake, Sun's make ...
 
 ;;
 ;; Special targets for DMake, Sun's make ...
-;; 
+;;
 (defcustom makefile-special-targets-list
   '(("DEFAULT")      ("DONE")        ("ERROR")        ("EXPORT")
     ("FAILED")       ("GROUPEPILOG") ("GROUPPROLOG")  ("IGNORE")
 (defcustom makefile-special-targets-list
   '(("DEFAULT")      ("DONE")        ("ERROR")        ("EXPORT")
     ("FAILED")       ("GROUPEPILOG") ("GROUPPROLOG")  ("IGNORE")
@@ -220,15 +216,15 @@ to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems necessary\"."
     ("SCCS_GET")     ("SILENT")      ("SOURCE")       ("SUFFIXES")
     ("WAIT")         ("c.o")         ("C.o")          ("m.o")
     ("el.elc")       ("y.c")         ("s.o"))
     ("SCCS_GET")     ("SILENT")      ("SOURCE")       ("SUFFIXES")
     ("WAIT")         ("c.o")         ("C.o")          ("m.o")
     ("el.elc")       ("y.c")         ("s.o"))
-  "List of special targets.
+  "*List of special targets.
 You will be offered to complete on one of those in the minibuffer whenever
 You will be offered to complete on one of those in the minibuffer whenever
-you enter a \".\" at the beginning of a line in makefile-mode."
+you enter a \".\" at the beginning of a line in `makefile-mode'."
   :type '(repeat (list string))
   :group 'makefile)
 
 (defcustom makefile-runtime-macros-list
   '(("@") ("&") (">") ("<") ("*") ("^") ("+") ("?") ("%") ("$"))
   :type '(repeat (list string))
   :group 'makefile)
 
 (defcustom makefile-runtime-macros-list
   '(("@") ("&") (">") ("<") ("*") ("^") ("+") ("?") ("%") ("$"))
-  "List of macros that are resolved by make at runtime.
+  "*List of macros that are resolved by make at runtime.
 If you insert a macro reference using `makefile-insert-macro-ref', the name
 of the macro is checked against this list.  If it can be found its name will
 not be enclosed in { } or ( )."
 If you insert a macro reference using `makefile-insert-macro-ref', the name
 of the macro is checked against this list.  If it can be found its name will
 not be enclosed in { } or ( )."
@@ -246,7 +242,7 @@ not be enclosed in { } or ( )."
 ;; that if you change this regexp you might have to fix the imenu
 ;; index in makefile-imenu-generic-expression.
 (defconst makefile-macroassign-regex
 ;; that if you change this regexp you might have to fix the imenu
 ;; index in makefile-imenu-generic-expression.
 (defconst makefile-macroassign-regex
-  "^ *\\([^ \n\t][^:#= \t\n]*\\)[ \t]*[*:+]?:?="
+  "^ *\\([^ \n\t][^:#= \t\n]*\\)[ \t]*[*:+]?[:?]?="
   "Regex used to find macro assignment lines in a makefile.")
 
 (defconst makefile-ignored-files-in-pickup-regex
   "Regex used to find macro assignment lines in a makefile.")
 
 (defconst makefile-ignored-files-in-pickup-regex
@@ -260,19 +256,34 @@ not be enclosed in { } or ( )."
 
 (defconst makefile-font-lock-keywords
   (list
 
 (defconst makefile-font-lock-keywords
   (list
+
    ;; Do macro assignments.  These get the "variable-name" face rather
    ;; arbitrarily.
    (list makefile-macroassign-regex 1 'font-lock-variable-name-face)
    ;; Do macro assignments.  These get the "variable-name" face rather
    ;; arbitrarily.
    (list makefile-macroassign-regex 1 'font-lock-variable-name-face)
-   ;;
+
    ;; Do dependencies.  These get the function name face.
    (list makefile-dependency-regex 1 'font-lock-function-name-face)
    ;; Do dependencies.  These get the function name face.
    (list makefile-dependency-regex 1 'font-lock-function-name-face)
-   ;;
-   ;; Variable references even in targets/strings/comments:
-   '("\\$[({]\\([-a-zA-Z0-9_.]+\\)[}):]" 1 font-lock-constant-face prepend)
-   ;;
-   ;; Automatic variable references.
-   '("\\$\\([@%<?^+*]\\)" 1 font-lock-reference-face prepend)
-   ;;
+
+   ;; Variable references even in targets/strings/comments.
+   '("[^$]\\$[({]\\([-a-zA-Z0-9_.]+\\|[@%<?^+*][FD]?\\)[}):]"
+     1 font-lock-constant-face prepend)
+
+   ;; Automatic variable references and single character variable references,
+   ;; but not shell variables references.
+   '("[^$]\\$\\([@%<?^+*_]\\|[a-zA-Z0-9]\\>\\)"
+     1 font-lock-constant-face prepend)
+
+   ;; Fontify conditionals and includes.
+   ;; Note that plain `if' is an automake conditional, and not a bug.
+   (list
+    (concat "^\\(?: [ \t]*\\)?"
+           (regexp-opt '("-include" "-sinclude" "include" "sinclude" "ifeq"
+                         "if" "ifneq" "ifdef" "ifndef" "endif" "else"
+                         "define" "endef" "override"
+                         "export" "unexport" "vpath") t)
+           "\\>[ \t]*\\([^: \t\n#]*\\)")
+    '(1 font-lock-keyword-face) '(2 font-lock-variable-name-face))
+
    ;; Highlight lines that contain just whitespace.
    ;; They can cause trouble, especially if they start with a tab.
    '("^[ \t]+$" . makefile-space-face)
    ;; Highlight lines that contain just whitespace.
    ;; They can cause trouble, especially if they start with a tab.
    '("^[ \t]+$" . makefile-space-face)
@@ -285,6 +296,16 @@ not be enclosed in { } or ( )."
    ;; They can make a tab fail to be effective.
    '("^\\( +\\)\t" 1 makefile-space-face)))
 
    ;; They can make a tab fail to be effective.
    '("^\\( +\\)\t" 1 makefile-space-face)))
 
+(defconst makefile-font-lock-syntactic-keywords
+  ;; From sh-script.el.
+  ;; A `#' begins a comment in sh when it is unquoted and at the beginning
+  ;; of a word.  In the shell, words are separated by metacharacters.
+  ;; The list of special chars is taken from the single-unix spec of the
+  ;; shell command language (under `quoting') but with `$' removed.
+  '(("[^|&;<>()`\\\"' \t\n]\\(#+\\)" 1 "_")
+    ;; Change the syntax of a quoted newline so that it does not end a comment.
+    ("\\\\\n" 0 ".")))
+
 (defvar makefile-imenu-generic-expression
   (list
    (list "Dependencies" makefile-dependency-regex  1)
 (defvar makefile-imenu-generic-expression
   (list
    (list "Dependencies" makefile-dependency-regex  1)
@@ -312,13 +333,13 @@ not be enclosed in { } or ( )."
 ;;; ------------------------------------------------------------
 
 (defcustom makefile-brave-make "make"
 ;;; ------------------------------------------------------------
 
 (defcustom makefile-brave-make "make"
-  "How to invoke make, for `makefile-query-targets'.
+  "*How to invoke make, for `makefile-query-targets'.
 This should identify a `make' command that can handle the `-q' option."
   :type 'string
   :group 'makefile)
 
 (defcustom makefile-query-one-target-method 'makefile-query-by-make-minus-q
 This should identify a `make' command that can handle the `-q' option."
   :type 'string
   :group 'makefile)
 
 (defcustom makefile-query-one-target-method 'makefile-query-by-make-minus-q
-  "Function to call to determine whether a make target is up to date.
+  "*Function to call to determine whether a make target is up to date.
 The function must satisfy this calling convention:
 
 * As its first argument, it must accept the name of the target to
 The function must satisfy this calling convention:
 
 * As its first argument, it must accept the name of the target to
@@ -335,12 +356,18 @@ The function must satisfy this calling convention:
   :group 'makefile)
 
 (defcustom makefile-up-to-date-buffer-name "*Makefile Up-to-date overview*"
   :group 'makefile)
 
 (defcustom makefile-up-to-date-buffer-name "*Makefile Up-to-date overview*"
-  "Name of the Up-to-date overview buffer."
+  "*Name of the Up-to-date overview buffer."
   :type 'string
   :group 'makefile)
 
 ;;; --- end of up-to-date-overview configuration ------------------
 
   :type 'string
   :group 'makefile)
 
 ;;; --- end of up-to-date-overview configuration ------------------
 
+(defvar makefile-mode-abbrev-table nil
+  "Abbrev table in use in Makefile buffers.")
+(if makefile-mode-abbrev-table
+    ()
+  (define-abbrev-table 'makefile-mode-abbrev-table ()))
+
 (defvar makefile-mode-map nil
   "The keymap that is used in Makefile mode.")
 
 (defvar makefile-mode-map nil
   "The keymap that is used in Makefile mode.")
 
@@ -485,15 +512,15 @@ In the browser, use the following keys:
 
 Makefile mode can be configured by modifying the following variables:
 
 
 Makefile mode can be configured by modifying the following variables:
 
-makefile-browser-buffer-name:
+`makefile-browser-buffer-name':
     Name of the macro- and target browser buffer.
 
     Name of the macro- and target browser buffer.
 
-makefile-target-colon:
+`makefile-target-colon':
     The string that gets appended to all target names
     inserted by `makefile-insert-target'.
     \":\" or \"::\" are quite common values.
 
     The string that gets appended to all target names
     inserted by `makefile-insert-target'.
     \":\" or \"::\" are quite common values.
 
-makefile-macro-assign:
+`makefile-macro-assign':
    The string that gets appended to all macro names
    inserted by `makefile-insert-macro'.
    The normal value should be \" = \", since this is what
    The string that gets appended to all macro names
    inserted by `makefile-insert-macro'.
    The normal value should be \" = \", since this is what
@@ -501,35 +528,35 @@ makefile-macro-assign:
    allow a larger variety of different macro assignments, so you
    might prefer to use \" += \" or \" := \" .
 
    allow a larger variety of different macro assignments, so you
    might prefer to use \" += \" or \" := \" .
 
-makefile-tab-after-target-colon:
+`makefile-tab-after-target-colon':
    If you want a TAB (instead of a space) to be appended after the
    target colon, then set this to a non-nil value.
 
    If you want a TAB (instead of a space) to be appended after the
    target colon, then set this to a non-nil value.
 
-makefile-browser-leftmost-column:
+`makefile-browser-leftmost-column':
    Number of blanks to the left of the browser selection mark.
 
    Number of blanks to the left of the browser selection mark.
 
-makefile-browser-cursor-column:
+`makefile-browser-cursor-column':
    Column in which the cursor is positioned when it moves
    up or down in the browser.
 
    Column in which the cursor is positioned when it moves
    up or down in the browser.
 
-makefile-browser-selected-mark:
+`makefile-browser-selected-mark':
    String used to mark selected entries in the browser.
 
    String used to mark selected entries in the browser.
 
-makefile-browser-unselected-mark:
+`makefile-browser-unselected-mark':
    String used to mark unselected entries in the browser.
 
    String used to mark unselected entries in the browser.
 
-makefile-browser-auto-advance-after-selection-p:
+`makefile-browser-auto-advance-after-selection-p':
    If this variable is set to a non-nil value the cursor
    will automagically advance to the next line after an item
    has been selected in the browser.
 
    If this variable is set to a non-nil value the cursor
    will automagically advance to the next line after an item
    has been selected in the browser.
 
-makefile-pickup-everything-picks-up-filenames-p:
+`makefile-pickup-everything-picks-up-filenames-p':
    If this variable is set to a non-nil value then
    `makefile-pickup-everything' also picks up filenames as targets
    (i.e. it calls `makefile-pickup-filenames-as-targets'), otherwise
    filenames are omitted.
 
    If this variable is set to a non-nil value then
    `makefile-pickup-everything' also picks up filenames as targets
    (i.e. it calls `makefile-pickup-filenames-as-targets'), otherwise
    filenames are omitted.
 
-makefile-cleanup-continuations-p:
+`makefile-cleanup-continuations':
    If this variable is set to a non-nil value then Makefile mode
    will assure that no line in the file ends with a backslash
    (the continuation character) followed by any whitespace.
    If this variable is set to a non-nil value then Makefile mode
    will assure that no line in the file ends with a backslash
    (the continuation character) followed by any whitespace.
@@ -538,20 +565,23 @@ makefile-cleanup-continuations-p:
    IMPORTANT: Please note that enabling this option causes Makefile mode
    to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems necessary\".
 
    IMPORTANT: Please note that enabling this option causes Makefile mode
    to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems necessary\".
 
-makefile-browser-hook:
+`makefile-browser-hook':
    A function or list of functions to be called just before the
    browser is entered. This is executed in the makefile buffer.
 
    A function or list of functions to be called just before the
    browser is entered. This is executed in the makefile buffer.
 
-makefile-special-targets-list:
+`makefile-special-targets-list':
    List of special targets. You will be offered to complete
    on one of those in the minibuffer whenever you enter a `.'.
    at the beginning of a line in Makefile mode."
 
   (interactive)
   (kill-all-local-variables)
    List of special targets. You will be offered to complete
    on one of those in the minibuffer whenever you enter a `.'.
    at the beginning of a line in Makefile mode."
 
   (interactive)
   (kill-all-local-variables)
-  (make-local-variable 'local-write-file-hooks)
-  (setq local-write-file-hooks
-       '(makefile-cleanup-continuations makefile-warn-suspicious-lines))
+  (add-hook 'write-file-functions
+           'makefile-warn-suspicious-lines nil t)
+  (add-hook 'write-file-functions
+           'makefile-warn-continuations nil t)
+  (add-hook 'write-file-functions
+           'makefile-cleanup-continuations nil t)
   (make-local-variable 'makefile-target-table)
   (make-local-variable 'makefile-macro-table)
   (make-local-variable 'makefile-has-prereqs)
   (make-local-variable 'makefile-target-table)
   (make-local-variable 'makefile-macro-table)
   (make-local-variable 'makefile-has-prereqs)
@@ -560,7 +590,15 @@ makefile-special-targets-list:
 
   ;; Font lock.
   (make-local-variable 'font-lock-defaults)
 
   ;; Font lock.
   (make-local-variable 'font-lock-defaults)
-  (setq font-lock-defaults '(makefile-font-lock-keywords))
+  (setq font-lock-defaults
+       ;; SYNTAX-BEGIN set to backward-paragraph to avoid slow-down
+       ;; near the end of a large buffer, due to parse-partial-sexp's
+       ;; trying to parse all the way till the beginning of buffer.
+       '(makefile-font-lock-keywords
+         nil nil
+         ((?$ . "."))
+         backward-paragraph
+         (font-lock-syntactic-keywords . makefile-font-lock-syntactic-keywords)))
 
   ;; Add-log.
   (make-local-variable 'add-log-current-defun-function)
 
   ;; Add-log.
   (make-local-variable 'add-log-current-defun-function)
@@ -574,6 +612,9 @@ makefile-special-targets-list:
   (make-local-variable 'dabbrev-abbrev-skip-leading-regexp)
   (setq dabbrev-abbrev-skip-leading-regexp "\\$")
 
   (make-local-variable 'dabbrev-abbrev-skip-leading-regexp)
   (setq dabbrev-abbrev-skip-leading-regexp "\\$")
 
+  ;; Other abbrevs.
+  (setq local-abbrev-table makefile-mode-abbrev-table)
+
   ;; Filling.
   (make-local-variable 'fill-paragraph-function)
   (setq fill-paragraph-function 'makefile-fill-paragraph)
   ;; Filling.
   (make-local-variable 'fill-paragraph-function)
   (setq fill-paragraph-function 'makefile-fill-paragraph)
@@ -586,6 +627,9 @@ makefile-special-targets-list:
   (make-local-variable 'comment-start-skip)
   (setq comment-start-skip "#+[ \t]*")
 
   (make-local-variable 'comment-start-skip)
   (setq comment-start-skip "#+[ \t]*")
 
+  ;; Make sure TAB really inserts \t.
+  (set (make-local-variable 'indent-line-function) 'indent-to-left-margin)
+
   ;; become the current major mode
   (setq major-mode 'makefile-mode)
   (setq mode-name "Makefile")
   ;; become the current major mode
   (setq major-mode 'makefile-mode)
   (setq mode-name "Makefile")
@@ -723,7 +767,7 @@ Anywhere else just self-inserts."
     (setq makefile-has-prereqs nil)
     (save-excursion
       (goto-char (point-min))
     (setq makefile-has-prereqs nil)
     (save-excursion
       (goto-char (point-min))
-      (while (re-search-forward makefile-dependency-regex (point-max) t)
+      (while (re-search-forward makefile-dependency-regex nil t)
        (makefile-add-this-line-targets)))
     (message "Read targets OK.")))
 
        (makefile-add-this-line-targets)))
     (message "Read targets OK.")))
 
@@ -757,7 +801,7 @@ Anywhere else just self-inserts."
     (setq makefile-macro-table nil)
     (save-excursion
       (goto-char (point-min))
     (setq makefile-macro-table nil)
     (save-excursion
       (goto-char (point-min))
-      (while (re-search-forward makefile-macroassign-regex (point-max) t)
+      (while (re-search-forward makefile-macroassign-regex nil t)
        (makefile-add-this-line-macro)
        (forward-line 1)))
     (message "Read macros OK.")))
        (makefile-add-this-line-macro)
        (forward-line 1)))
     (message "Read macros OK.")))
@@ -766,15 +810,15 @@ Anywhere else just self-inserts."
   (save-excursion
     (beginning-of-line)
     (skip-chars-forward " \t")
   (save-excursion
     (beginning-of-line)
     (skip-chars-forward " \t")
-    (if (not (eolp))
-       (let* ((start-of-macro-name (point))
-              (line-number (1+ (count-lines (point-min) (point))))
-              (macro-name (progn
-                            (skip-chars-forward "^ \t:#=*")
-                            (buffer-substring start-of-macro-name (point)))))
-         (if (makefile-remember-macro macro-name)
-             (message "Picked up macro \"%s\" from line %d"
-                      macro-name line-number))))))
+    (unless (eolp)
+      (let* ((start-of-macro-name (point))
+            (line-number (1+ (count-lines (point-min) (point))))
+            (macro-name (progn
+                          (skip-chars-forward "^ \t:#=*")
+                          (buffer-substring start-of-macro-name (point)))))
+       (if (makefile-remember-macro macro-name)
+           (message "Picked up macro \"%s\" from line %d"
+                    macro-name line-number))))))
 
 (defun makefile-pickup-everything (arg)
   "Notice names of all macros and targets in Makefile.
 
 (defun makefile-pickup-everything (arg)
   "Notice names of all macros and targets in Makefile.
@@ -798,7 +842,7 @@ and adds all qualifying names to the list of known targets."
         (raw-filename-list (if dir
                                (file-name-all-completions "" dir)
                              (file-name-all-completions "" ""))))
         (raw-filename-list (if dir
                                (file-name-all-completions "" dir)
                              (file-name-all-completions "" ""))))
-    (mapcar '(lambda (name)
+    (mapcar (lambda (name)
               (if (and (not (file-directory-p name))
                        (not (string-match makefile-ignored-files-in-pickup-regex
                                           name)))
               (if (and (not (file-directory-p name))
                        (not (string-match makefile-ignored-files-in-pickup-regex
                                           name)))
@@ -984,23 +1028,35 @@ definition and conveniently use this command."
   (save-excursion
     (beginning-of-line)
     (cond
   (save-excursion
     (beginning-of-line)
     (cond
-     ((looking-at "^#+ ")
-      ;; Found a comment.  Set the fill prefix and then fill.
-      (let ((fill-prefix (buffer-substring-no-properties (match-beginning 0)
-                                                        (match-end 0)))
+     ((looking-at "^#+")
+      ;; Found a comment.  Set the fill prefix, and find the paragraph
+      ;; boundaries by searching for lines that look like comment-only
+      ;; lines.
+      (let ((fill-prefix (match-string-no-properties 0))
            (fill-paragraph-function nil))
            (fill-paragraph-function nil))
-       (fill-paragraph nil)
-       t))
+       (save-excursion
+         (save-restriction
+           (narrow-to-region
+            ;; Search backwards.
+            (save-excursion
+              (while (and (zerop (forward-line -1))
+                          (looking-at "^#")))
+              ;; We may have gone too far.  Go forward again.
+              (or (looking-at "^#")
+                  (forward-line 1))
+              (point))
+            ;; Search forwards.
+            (save-excursion
+              (while (looking-at "^#")
+                (forward-line))
+              (point)))
+           (fill-paragraph nil)
+           t))))
 
      ;; Must look for backslashed-region before looking for variable
      ;; assignment.
 
      ;; Must look for backslashed-region before looking for variable
      ;; assignment.
-     ((save-excursion
-       (end-of-line)
-       (or
-        (= (preceding-char) ?\\)
-        (progn
-          (end-of-line -1)
-          (= (preceding-char) ?\\))))
+     ((or (eq (char-before (line-end-position 1)) ?\\)
+         (eq (char-before (line-end-position 0)) ?\\))
       ;; A backslash region.  Find beginning and end, remove
       ;; backslashes, fill, and then reapply backslahes.
       (end-of-line)
       ;; A backslash region.  Find beginning and end, remove
       ;; backslashes, fill, and then reapply backslahes.
       (end-of-line)
@@ -1030,10 +1086,7 @@ definition and conveniently use this command."
       ;; Have a macro assign.  Fill just this line, and then backslash
       ;; resulting region.
       (save-restriction
       ;; Have a macro assign.  Fill just this line, and then backslash
       ;; resulting region.
       (save-restriction
-       (narrow-to-region (point) (save-excursion
-                                   (end-of-line)
-                                   (forward-char)
-                                   (point)))
+       (narrow-to-region (point) (line-beginning-position 2))
        (let ((fill-paragraph-function nil))
          (fill-paragraph nil))
        (makefile-backslash-region (point-min) (point-max) nil)))))
        (let ((fill-paragraph-function nil))
          (fill-paragraph nil))
        (makefile-backslash-region (point-min) (point-max) nil)))))
@@ -1160,8 +1213,7 @@ This is most useful in the process of creating continued lines when copying
 large dependencies from the browser to the client buffer.
 \(point) advances accordingly in the client buffer."
   (interactive)
 large dependencies from the browser to the client buffer.
 \(point) advances accordingly in the client buffer."
   (interactive)
-  (save-excursion
-    (set-buffer makefile-browser-client)
+  (with-current-buffer makefile-browser-client
     (end-of-line)
     (insert "\\\n\t")))
 
     (end-of-line)
     (insert "\\\n\t")))
 
@@ -1206,11 +1258,10 @@ Insertion takes place at point."
        (message "No macros or targets to browse! Consider running 'makefile-pickup-everything\'"))
     (let ((browser-buffer (get-buffer-create makefile-browser-buffer-name)))
        (pop-to-buffer browser-buffer)
        (message "No macros or targets to browse! Consider running 'makefile-pickup-everything\'"))
     (let ((browser-buffer (get-buffer-create makefile-browser-buffer-name)))
        (pop-to-buffer browser-buffer)
-       (make-variable-buffer-local 'makefile-browser-selection-vector)
        (makefile-browser-fill targets macros)
        (shrink-window-if-larger-than-buffer)
        (makefile-browser-fill targets macros)
        (shrink-window-if-larger-than-buffer)
-       (setq makefile-browser-selection-vector
-             (make-vector (+ (length targets) (length macros)) nil))
+       (set (make-local-variable 'makefile-browser-selection-vector)
+            (make-vector (+ (length targets) (length macros)) nil))
        (makefile-browser-start-interaction))))
 
 (defun makefile-switch-to-browser ()
        (makefile-browser-start-interaction))))
 
 (defun makefile-switch-to-browser ()
@@ -1319,7 +1370,7 @@ and generates the overview, one line per target name."
   (delete-file filename))              ; remove the tmpfile
 
 (defun makefile-query-by-make-minus-q (target &optional filename)
   (delete-file filename))              ; remove the tmpfile
 
 (defun makefile-query-by-make-minus-q (target &optional filename)
-  (not (zerop
+  (not (eq 0
        (call-process makefile-brave-make nil nil nil
                      "-f" filename "-q" target))))
 
        (call-process makefile-brave-make nil nil nil
                      "-f" filename "-q" target))))
 
@@ -1331,11 +1382,11 @@ and generates the overview, one line per target name."
 
 (defun makefile-cleanup-continuations ()
   (if (eq major-mode 'makefile-mode)
 
 (defun makefile-cleanup-continuations ()
   (if (eq major-mode 'makefile-mode)
-      (if (and makefile-cleanup-continuations-p
+      (if (and makefile-cleanup-continuations
               (not buffer-read-only))
          (save-excursion
            (goto-char (point-min))
               (not buffer-read-only))
          (save-excursion
            (goto-char (point-min))
-           (while (re-search-forward "\\\\[ \t]+$" (point-max) t)
+           (while (re-search-forward "\\\\[ \t]+$" nil t)
              (replace-match "\\" t t))))))
 
 
              (replace-match "\\" t t))))))
 
 
@@ -1350,9 +1401,17 @@ and generates the overview, one line per target name."
        (goto-char (point-min))
        (if (re-search-forward "^\\(\t+$\\| +\t\\)" nil t)
            (not (y-or-n-p
        (goto-char (point-min))
        (if (re-search-forward "^\\(\t+$\\| +\t\\)" nil t)
            (not (y-or-n-p
-                 (format "Suspicious line %d. Save anyway "
+                 (format "Suspicious line %d. Save anyway? "
+                         (count-lines (point-min) (point)))))))))
+
+(defun makefile-warn-continuations ()
+  (if (eq major-mode 'makefile-mode)
+      (save-excursion
+       (goto-char (point-min))
+       (if (re-search-forward "\\\\[ \t]+$" nil t)
+           (not (y-or-n-p
+                 (format "Suspicious continuation in line %d. Save anyway? "
                          (count-lines (point-min) (point)))))))))
                          (count-lines (point-min) (point)))))))))
-         
 \f
 
 ;;; ------------------------------------------------------------
 \f
 
 ;;; ------------------------------------------------------------
@@ -1427,20 +1486,20 @@ This acts according to the value of `makefile-tab-after-target-colon'."
   "Determine if point is on a macro line in the browser."
   (save-excursion
     (beginning-of-line)
   "Determine if point is on a macro line in the browser."
   (save-excursion
     (beginning-of-line)
-    (re-search-forward "\\$[{(]" (makefile-end-of-line-point) t)))
+    (re-search-forward "\\$[{(]" (line-end-position) t)))
 
 (defun makefile-browser-this-line-target-name ()
   "Extract the target name from a line in the browser."
   (save-excursion
     (end-of-line)
     (skip-chars-backward "^ \t")
 
 (defun makefile-browser-this-line-target-name ()
   "Extract the target name from a line in the browser."
   (save-excursion
     (end-of-line)
     (skip-chars-backward "^ \t")
-    (buffer-substring (point) (1- (makefile-end-of-line-point)))))
+    (buffer-substring (point) (1- (line-end-position)))))
 
 (defun makefile-browser-this-line-macro-name ()
   "Extract the macro name from a line in the browser."
   (save-excursion
     (beginning-of-line)
 
 (defun makefile-browser-this-line-macro-name ()
   "Extract the macro name from a line in the browser."
   (save-excursion
     (beginning-of-line)
-    (re-search-forward "\\$[{(]" (makefile-end-of-line-point) t)
+    (re-search-forward "\\$[{(]" (line-end-position) t)
     (let ((macro-start (point)))
       (skip-chars-forward "^})")
       (buffer-substring macro-start (point)))))
     (let ((macro-start (point)))
       (skip-chars-forward "^})")
       (buffer-substring macro-start (point)))))
@@ -1464,21 +1523,11 @@ Uses `makefile-use-curly-braces-for-macros-p'."
 (defun makefile-browser-toggle-state-for-line (n)
   (makefile-browser-set-state-for-line n (not (makefile-browser-get-state-for-line n))))
 
 (defun makefile-browser-toggle-state-for-line (n)
   (makefile-browser-set-state-for-line n (not (makefile-browser-get-state-for-line n))))
 
-(defun makefile-beginning-of-line-point ()
-  (save-excursion
-    (beginning-of-line)
-    (point)))
-
-(defun makefile-end-of-line-point ()
-  (save-excursion
-    (end-of-line)
-    (point)))
-
 (defun makefile-last-line-p ()
 (defun makefile-last-line-p ()
-  (= (makefile-end-of-line-point) (point-max)))
+  (= (line-end-position) (point-max)))
 
 (defun makefile-first-line-p ()
 
 (defun makefile-first-line-p ()
-  (= (makefile-beginning-of-line-point) (point-min)))
+  (= (line-beginning-position) (point-min)))
 
 \f
 
 
 \f
 
@@ -1493,21 +1542,16 @@ If it isn't in one, return nil."
       ;; Scan back line by line, noticing when we come to a
       ;; variable or rule definition, and giving up when we see
       ;; a line that is not part of either of those.
       ;; Scan back line by line, noticing when we come to a
       ;; variable or rule definition, and giving up when we see
       ;; a line that is not part of either of those.
-      (while (not found)
-       (cond
-        ((looking-at makefile-macroassign-regex)
-         (setq found (buffer-substring-no-properties (match-beginning 1)
-                                                       (match-end 1))))
-        ((looking-at makefile-dependency-regex)
-         (setq found (buffer-substring-no-properties (match-beginning 1)
-                                                     (match-end 1))))
-        ;; Don't keep looking across a blank line or comment.  Give up.
-        ((looking-at "$\\|#")
-         (setq found 'bobp))
-        ((bobp)
-         (setq found 'bobp)))
-       (or found
-           (forward-line -1)))
-      (if (stringp found) found))))
+      (while (not (or (setq found
+                           (when (or (looking-at makefile-macroassign-regex)
+                                     (looking-at makefile-dependency-regex))
+                             (match-string-no-properties 1)))
+                     ;; Don't keep looking across a blank line or comment.
+                     (looking-at "$\\|#")
+                     (not (zerop (forward-line -1))))))
+      found)))
+
+(provide 'make-mode)
 
 
+;;; arch-tag: bd23545a-de91-44fb-b1b2-feafbb2635a0
 ;;; make-mode.el ends here
 ;;; make-mode.el ends here