]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/ada-mode.el
(compilation-start): Resurrect the version for systems that don't support
[gnu-emacs] / lisp / progmodes / ada-mode.el
index 9581fd436b3930e2180179eba67ce77258f8a3a8..ec5504e471c6020da09e2f7cc1a7660f554e7196 100644 (file)
@@ -1,7 +1,7 @@
 ;;; ada-mode.el --- major-mode for editing Ada sources
 
 ;; Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;;               2005, 2006, 2007  Free Software Foundation, Inc.
+;;               2005, 2006, 2007, 2008  Free Software Foundation, Inc.
 
 ;; Author: Rolf Ebert      <ebert@inf.enst.fr>
 ;;      Markus Heritsch <Markus.Heritsch@studbox.uni-stuttgart.de>
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
-;;; This mode is a major mode for editing Ada code.  This is a major
-;;; rewrite of the file packaged with Emacs-20.  The Ada mode is
-;;; composed of four Lisp files: ada-mode.el, ada-xref.el, ada-prj.el
-;;; and ada-stmt.el.  Only this file (ada-mode.el) is completely
-;;; independent from the GNU Ada compiler GNAT, distributed by Ada
-;;; Core Technologies.  All the other files rely heavily on features
-;;; provided only by GNAT.
-;;;
-;;; Note: this mode will not work with Emacs 19. If you are on a VMS
-;;; system, where the latest version of Emacs is 19.28, you will need
-;;; another file, called ada-vms.el, that provides some required
-;;; functions.
+;; This mode is a major mode for editing Ada code.  This is a major
+;; rewrite of the file packaged with Emacs-20.  The Ada mode is
+;; composed of four Lisp files: ada-mode.el, ada-xref.el, ada-prj.el
+;; and ada-stmt.el.  Only this file (ada-mode.el) is completely
+;; independent from the GNU Ada compiler GNAT, distributed by Ada
+;; Core Technologies.  All the other files rely heavily on features
+;; provided only by GNAT.
+;;
+;; Note: this mode will not work with Emacs 19. If you are on a VMS
+;; system, where the latest version of Emacs is 19.28, you will need
+;; another file, called ada-vms.el, that provides some required
+;; functions.
 
 ;;; Usage:
-;;; Emacs should enter Ada mode automatically when you load an Ada file.
-;;; By default, the valid extensions for Ada files are .ads, .adb or .ada
-;;; If the ada-mode does not start automatically, then simply type the
-;;; following command :
-;;;     M-x ada-mode
-;;;
-;;; By default, ada-mode is configured to take full advantage of the GNAT
-;;; compiler (the menus will include the cross-referencing features,...).
-;;; If you are using another compiler, you might want to set the following
-;;; variable in your .emacs (Note: do not set this in the ada-mode-hook, it
-;;; won't work) :
-;;;    (setq ada-which-compiler 'generic)
-;;;
-;;; This mode requires find-file.el to be present on your system.
+;; Emacs should enter Ada mode automatically when you load an Ada file.
+;; By default, the valid extensions for Ada files are .ads, .adb or .ada
+;; If the ada-mode does not start automatically, then simply type the
+;; following command :
+;;     M-x ada-mode
+;;
+;; By default, ada-mode is configured to take full advantage of the GNAT
+;; compiler (the menus will include the cross-referencing features,...).
+;; If you are using another compiler, you might want to set the following
+;; variable in your .emacs (Note: do not set this in the ada-mode-hook, it
+;; won't work) :
+;;    (setq ada-which-compiler 'generic)
+;;
+;; This mode requires find-file.el to be present on your system.
 
 ;;; History:
-;;; The first Ada mode for GNU Emacs was written by V. Broman in
-;;; 1985. He based his work on the already existing Modula-2 mode.
-;;; This was distributed as ada.el in versions of Emacs prior to 19.29.
-;;;
-;;; Lynn Slater wrote an extensive Ada mode in 1989. It consisted of
-;;; several files with support for dired commands and other nice
-;;; things. It is currently available from the PAL
-;;; (wuarchive.wustl.edu:/languages/ada) as ada-mode-1.06a.tar.Z.
-;;;
-;;; The probably very first Ada mode (called electric-ada.el) was
-;;; written by Steven D. Litvintchouk and Steven M. Rosen for the
-;;; Gosling Emacs. L. Slater based his development on ada.el and
-;;; electric-ada.el.
-;;;
-;;; A complete rewrite by M. Heritsch and R. Ebert has been done.
-;;; Some ideas from the Ada mode mailing list have been
-;;; added.  Some of the functionality of L. Slater's mode has not
-;;; (yet) been recoded in this new mode.  Perhaps you prefer sticking
-;;; to his version.
-;;;
-;;; A complete rewrite for Emacs-20 / GNAT-3.11 has been done by Ada Core
-;;; Technologies.
+;; The first Ada mode for GNU Emacs was written by V. Broman in
+;; 1985. He based his work on the already existing Modula-2 mode.
+;; This was distributed as ada.el in versions of Emacs prior to 19.29.
+;;
+;; Lynn Slater wrote an extensive Ada mode in 1989. It consisted of
+;; several files with support for dired commands and other nice
+;; things. It is currently available from the PAL
+;; (wuarchive.wustl.edu:/languages/ada) as ada-mode-1.06a.tar.Z.
+;;
+;; The probably very first Ada mode (called electric-ada.el) was
+;; written by Steven D. Litvintchouk and Steven M. Rosen for the
+;; Gosling Emacs. L. Slater based his development on ada.el and
+;; electric-ada.el.
+;;
+;; A complete rewrite by M. Heritsch and R. Ebert has been done.
+;; Some ideas from the Ada mode mailing list have been
+;; added.  Some of the functionality of L. Slater's mode has not
+;; (yet) been recoded in this new mode.  Perhaps you prefer sticking
+;; to his version.
+;;
+;; A complete rewrite for Emacs-20 / GNAT-3.11 has been done by Ada Core
+;; Technologies.
 
 ;;; Credits:
-;;;   Many thanks to John McCabe <john@assen.demon.co.uk> for sending so
-;;;     many patches included in this package.
-;;;   Christian Egli <Christian.Egli@hcsd.hac.com>:
-;;;     ada-imenu-generic-expression
-;;;   Many thanks also to the following persons that have contributed
-;;;   to the ada-mode
-;;;     Philippe Waroquiers (PW) <philippe@cfmu.eurocontrol.be> in particular,
-;;;     woodruff@stc.llnl.gov (John Woodruff)
-;;;     jj@ddci.dk (Jesper Joergensen)
-;;;     gse@ocsystems.com (Scott Evans)
-;;;     comar@gnat.com (Cyrille Comar)
-;;;     stephen.leake@gsfc.nasa.gov (Stephen Leake)
-;;;     robin-reply@reagans.org
-;;;    and others for their valuable hints.
+;;   Many thanks to John McCabe <john@assen.demon.co.uk> for sending so
+;;     many patches included in this package.
+;;   Christian Egli <Christian.Egli@hcsd.hac.com>:
+;;     ada-imenu-generic-expression
+;;   Many thanks also to the following persons that have contributed
+;;   to the ada-mode
+;;     Philippe Waroquiers (PW) <philippe@cfmu.eurocontrol.be> in particular,
+;;     woodruff@stc.llnl.gov (John Woodruff)
+;;     jj@ddci.dk (Jesper Joergensen)
+;;     gse@ocsystems.com (Scott Evans)
+;;     comar@gnat.com (Cyrille Comar)
+;;     stephen.leake@gsfc.nasa.gov (Stephen Leake)
+;;     robin-reply@reagans.org
+;;    and others for their valuable hints.
 
 ;;; Code:
-;;; Note: Every function in this package is compiler-independent.
-;;; The names start with  ada-
-;;; The variables that the user can edit can all be modified through
-;;;   the customize mode. They are sorted in alphabetical order in this
-;;;   file.
-
-;;; Supported packages.
-;;; This package supports a number of other Emacs modes. These other modes
-;;; should be loaded before the ada-mode, which will then setup some variables
-;;; to improve the support for Ada code.
-;;; Here is the list of these modes:
-;;;   `which-function-mode': Display the name of the subprogram the cursor is
-;;;      in in the mode line.
-;;;   `outline-mode': Provides the capability to collapse or expand the code
-;;;      for specific language constructs, for instance if you want to hide the
-;;;      code corresponding to a subprogram
-;;;   `align': This mode is now provided with Emacs 21, but can also be
-;;;      installed manually for older versions of Emacs. It provides the
-;;;      capability to automatically realign the selected region (for instance
-;;;      all ':=', ':' and '--' will be aligned on top of each other.
-;;;   `imenu': Provides a menu with the list of entities defined in the current
-;;;      buffer, and an easy way to jump to any of them
-;;;   `speedbar': Provides a separate file browser, and the capability for each
-;;;      file to see the list of entities defined in it and to jump to them
-;;;      easily
-;;;   `abbrev-mode': Provides the capability to define abbreviations, which
-;;;      are automatically expanded when you type them. See the Emacs manual.
+;; Note: Every function in this package is compiler-independent.
+;; The names start with  ada-
+;; The variables that the user can edit can all be modified through
+;;   the customize mode. They are sorted in alphabetical order in this
+;;   file.
+
+;; Supported packages.
+;; This package supports a number of other Emacs modes. These other modes
+;; should be loaded before the ada-mode, which will then setup some variables
+;; to improve the support for Ada code.
+;; Here is the list of these modes:
+;;   `which-function-mode': Display the name of the subprogram the cursor is
+;;      in in the mode line.
+;;   `outline-mode': Provides the capability to collapse or expand the code
+;;      for specific language constructs, for instance if you want to hide the
+;;      code corresponding to a subprogram
+;;   `align': This mode is now provided with Emacs 21, but can also be
+;;      installed manually for older versions of Emacs. It provides the
+;;      capability to automatically realign the selected region (for instance
+;;      all ':=', ':' and '--' will be aligned on top of each other.
+;;   `imenu': Provides a menu with the list of entities defined in the current
+;;      buffer, and an easy way to jump to any of them
+;;   `speedbar': Provides a separate file browser, and the capability for each
+;;      file to see the list of entities defined in it and to jump to them
+;;      easily
+;;   `abbrev-mode': Provides the capability to define abbreviations, which
+;;      are automatically expanded when you type them. See the Emacs manual.
 
 (require 'find-file nil t)
 (require 'align nil t)
 (defvar ispell-check-comments)
 (defvar skeleton-further-elements)
 
-(eval-and-compile
-  (defun ada-check-emacs-version (major minor &optional is-xemacs)
-    "Return t if Emacs's version is greater or equal to MAJOR.MINOR.
-If IS-XEMACS is non-nil, check for XEmacs instead of Emacs."
-    (let ((xemacs-running (or (string-match "Lucid"  emacs-version)
-                             (string-match "XEmacs" emacs-version))))
-      (and (or (and is-xemacs xemacs-running)
-              (not (or is-xemacs xemacs-running)))
-          (or (> emacs-major-version major)
-              (and (= emacs-major-version major)
-                   (>= emacs-minor-version minor)))))))
-
 (defun ada-mode-version ()
   "Return Ada mode version."
   (interactive)
-  (let ((version-string "3.7"))
+  (let ((version-string "4.00"))
     (if (interactive-p)
        (message version-string)
       version-string)))
@@ -462,6 +448,13 @@ The extensions should include a `.' if needed.")
 (defvar ada-mode-map (make-sparse-keymap)
   "Local keymap used for Ada mode.")
 
+(defvar ada-mode-extra-map (make-sparse-keymap)
+  "Keymap used for non-standard keybindings.")
+
+;; default is C-c C-q because it's free in ada-mode-map
+(defvar ada-mode-extra-prefix "\C-c\C-q"
+  "Prefix key to access `ada-mode-extra-map' functions.")
+
 (defvar ada-mode-abbrev-table nil
   "Local abbrev table for Ada mode.")
 
@@ -612,7 +605,7 @@ This variable defines several rules to use to align different lines.")
    "\\(\\(\\sw\\|[_.]\\)+\\)"
    "\\)")
   "Regexp matching Ada subprogram start.
-The actual start is at (match-beginning 4). The name is in (match-string 5).")
+The actual start is at (match-beginning 4).  The name is in (match-string 5).")
 
 (defconst ada-name-regexp
   "\\([a-zA-Z][a-zA-Z0-9_.']*[a-zA-Z0-9]\\)"
@@ -643,6 +636,7 @@ The package name is in (match-string 4).")
     (concat "\\("
            ";"                                        "\\|"
            "=>[ \t]*$"                                "\\|"
+           "=>[ \t]*--.*$"                            "\\|"
            "^[ \t]*separate[ \t]*(\\(\\sw\\|[_.]\\)+)"  "\\|"
            "\\<" (regexp-opt '("begin" "declare" "is" "do" "else" "generic"
                                "loop" "private" "record" "select"
@@ -797,13 +791,13 @@ the 4 file locations can be clicked on and jumped to."
 
       ;; set source marker
       (save-excursion
-        (compilation-find-file (point-marker) (match-string 1) "./")
-        (set-buffer file)
+       (compilation-find-file (point-marker) (match-string 1) "./")
+       (set-buffer file)
 
-        (if (stringp line)
-            (goto-line (string-to-number line)))
+       (if (stringp line)
+           (goto-line (string-to-number line)))
 
-        (setq source (point-marker)))
+       (setq source (point-marker)))
 
       (compilation-goto-locus error-pos source nil)
 
@@ -829,13 +823,12 @@ the 4 file locations can be clicked on and jumped to."
 ;; Thus their syntax property is changed automatically, and we can still use
 ;; the standard Emacs functions for sexp (see `ada-in-string-p')
 ;;
-;; On Emacs, this is done through the `syntax-table' text property. The
-;; modification is done automatically each time the user as typed a new
-;; character. This is already done in `font-lock-mode' (in
-;; `font-lock-syntactic-keywords', so we take advantage of the existing
-;; mechanism. If font-lock-mode is not activated, we do it by hand in
-;; `ada-after-change-function', thanks to `ada-deactivate-properties' and
-;; `ada-initialize-properties'.
+;; On Emacs, this is done through the `syntax-table' text property.  The
+;; corresponding action is applied automatically each time the buffer
+;; changes.  If `font-lock-mode' is enabled (the default) the action is
+;; set up by `font-lock-syntactic-keywords'.  Otherwise, we do it
+;; manually in `ada-after-change-function'.  The proper method is
+;; installed by `ada-handle-syntax-table-properties'.
 ;;
 ;; on XEmacs, the `syntax-table' property does not exist and we have to use a
 ;; slow advice to `parse-partial-sexp' to do the same thing.
@@ -852,7 +845,6 @@ The standard table declares `_' as a symbol constituent, the second one
 declares it as a word constituent."
   (interactive)
   (setq ada-mode-syntax-table (make-syntax-table))
-  (set-syntax-table  ada-mode-syntax-table)
 
   ;; define string brackets (`%' is alternative string bracket, but
   ;; almost never used as such and throws font-lock and indentation
@@ -936,50 +928,59 @@ declares it as a word constituent."
            (insert (caddar change))
            (setq change (cdr change)))))))
 
-(defun ada-deactivate-properties ()
-  "Deactivate Ada mode's properties handling.
-This would be a duplicate of font-lock if both are used at the same time."
-  (remove-hook 'after-change-functions 'ada-after-change-function t))
-
-(defun ada-initialize-properties ()
-  "Initialize some special text properties in the whole buffer.
-In particular, character constants are said to be strings, #...# are treated
-as numbers instead of gnatprep comments."
-  (save-excursion
-    (save-restriction
-      (widen)
-      (goto-char (point-min))
-      (while (re-search-forward "'.'" nil t)
-       (add-text-properties (match-beginning 0) (match-end 0)
-                            '(syntax-table ("'" . ?\"))))
-      (goto-char (point-min))
-      (while (re-search-forward "^[ \t]*#" nil t)
-       (add-text-properties (match-beginning 0) (match-end 0)
-                            '(syntax-table (11 . 10))))
-      (set-buffer-modified-p nil)
-
-      ;;  Setting this only if font-lock is not set won't work
-      ;;  if the user activates or deactivates font-lock-mode,
-      ;;  but will make things faster most of the time
-      (add-hook 'after-change-functions 'ada-after-change-function nil t)
-      )))
+(defun ada-set-syntax-table-properties ()
+  "Assign `syntax-table' properties in accessible part of buffer.
+In particular, character constants are said to be strings, #...#
+are treated as numbers instead of gnatprep comments."
+  (let ((modified (buffer-modified-p))
+       (buffer-undo-list t)
+       (inhibit-read-only t)
+       (inhibit-point-motion-hooks t)
+       (inhibit-modification-hooks t))
+    (remove-text-properties (point-min) (point-max) '(syntax-table nil))
+    (goto-char (point-min))
+    (while (re-search-forward
+           ;; The following regexp was adapted from
+           ;; `ada-font-lock-syntactic-keywords'.
+           "^[ \t]*\\(#\\(?:if\\|else\\|elsif\\|end\\)\\)\\|[^a-zA-Z0-9)]\\('\\)[^'\n]\\('\\)"
+           nil t)
+      (if (match-beginning 1)
+         (put-text-property
+              (match-beginning 1) (match-end 1) 'syntax-table '(11 . ?\n))
+       (put-text-property
+            (match-beginning 2) (match-end 2) 'syntax-table '(7 . ?'))
+       (put-text-property
+            (match-beginning 3) (match-end 3) 'syntax-table '(7 . ?'))))
+    (unless modified
+      (restore-buffer-modified-p nil))))
 
 (defun ada-after-change-function (beg end old-len)
   "Called when the region between BEG and END was changed in the buffer.
 OLD-LEN indicates what the length of the replaced text was."
-  (let ((inhibit-point-motion-hooks t)
-       (eol (point)))
+  (save-excursion
+    (save-restriction
+      (let ((from (progn (goto-char beg) (line-beginning-position)))
+           (to (progn (goto-char end) (line-end-position))))
+       (narrow-to-region from to)
+       (save-match-data
+         (ada-set-syntax-table-properties))))))
+
+(defun ada-initialize-syntax-table-properties ()
+  "Assign `syntax-table' properties in current buffer."
     (save-excursion
-      (save-match-data
-       (beginning-of-line)
-       (remove-text-properties (point) eol '(syntax-table nil))
-       (while (re-search-forward "'.'" eol t)
-         (add-text-properties (match-beginning 0) (match-end 0)
-                              '(syntax-table ("'" . ?\"))))
-       (beginning-of-line)
-       (if (looking-at "^[ \t]*#")
-           (add-text-properties (match-beginning 0) (match-end 0)
-                                '(syntax-table (11 . 10))))))))
+      (save-restriction
+       (widen)
+       (save-match-data
+         (ada-set-syntax-table-properties))))
+    (add-hook 'after-change-functions 'ada-after-change-function nil t))
+
+(defun ada-handle-syntax-table-properties ()
+  "Handle `syntax-table' properties."
+  (if font-lock-mode
+      ;; `font-lock-mode' will take care of `syntax-table' properties.
+      (remove-hook 'after-change-functions 'ada-after-change-function t)
+    ;; Take care of `syntax-table' properties manually.
+    (ada-initialize-syntax-table-properties)))
 
 ;;------------------------------------------------------------------
 ;;  Testing the grammatical context
@@ -1151,6 +1152,8 @@ If you use ada-xref.el:
   (interactive)
   (kill-all-local-variables)
 
+  (set-syntax-table ada-mode-syntax-table)
+
   (set (make-local-variable 'require-final-newline) mode-require-final-newline)
 
   ;;  Set the paragraph delimiters so that one can select a whole block
@@ -1183,13 +1186,9 @@ If you use ada-xref.el:
   ;;  the comment and the text. We do not want any, this is already
   ;;  included in comment-start
   (unless (featurep 'xemacs)
-    (progn
-      (if (ada-check-emacs-version 20 3)
-         (progn
-           (set (make-local-variable 'parse-sexp-ignore-comments) t)
-           (set (make-local-variable 'comment-padding) 0)))
-      (set (make-local-variable 'parse-sexp-lookup-properties) t)
-      ))
+    (set (make-local-variable 'parse-sexp-ignore-comments) t)
+    (set (make-local-variable 'comment-padding) 0)
+    (set (make-local-variable 'parse-sexp-lookup-properties) t))
 
   (set 'case-fold-search t)
   (if (boundp 'imenu-case-fold-search)
@@ -1198,9 +1197,6 @@ If you use ada-xref.el:
   (set (make-local-variable 'fill-paragraph-function)
        'ada-fill-comment-paragraph)
 
-  (set (make-local-variable 'imenu-generic-expression)
-       ada-imenu-generic-expression)
-
   ;;  Support for compile.el
   ;;  We just substitute our own functions to go to the error.
   (add-hook 'compilation-mode-hook
@@ -1215,22 +1211,13 @@ If you use ada-xref.el:
                'ada-compile-goto-error)))
 
   ;;  font-lock support :
-  ;;  We need to set some properties for XEmacs, and define some variables
-  ;;  for Emacs
 
-  (if (featurep 'xemacs)
-      ;;  XEmacs
-      (put 'ada-mode 'font-lock-defaults
-          '(ada-font-lock-keywords
-            nil t ((?\_ . "w") (?# . ".")) beginning-of-line))
-    ;;  Emacs
-    (set (make-local-variable 'font-lock-defaults)
-        '(ada-font-lock-keywords
-          nil t
-          ((?\_ . "w") (?# . "."))
-          beginning-of-line
-          (font-lock-syntactic-keywords . ada-font-lock-syntactic-keywords)))
-    )
+  (set (make-local-variable 'font-lock-defaults)
+       '(ada-font-lock-keywords
+        nil t
+        ((?\_ . "w") (?# . "."))
+        beginning-of-line
+        (font-lock-syntactic-keywords . ada-font-lock-syntactic-keywords)))
 
   ;; Set up support for find-file.el.
   (set (make-local-variable 'ff-other-file-alist)
@@ -1243,34 +1230,34 @@ If you use ada-xref.el:
 
   (make-local-variable 'ff-special-constructs)
   (mapc (lambda (pair) (add-to-list 'ff-special-constructs pair))
-        (list
-         ;; Top level child package declaration; go to the parent package.
-         (cons (eval-when-compile
-                 (concat "^\\(private[ \t]\\)?[ \t]*package[ \t]+"
-                         "\\(body[ \t]+\\)?"
-                         "\\(\\(\\sw\\|[_.]\\)+\\)\\.\\(\\sw\\|_\\)+[ \t\n]+is"))
-               (lambda ()
-                 (ff-get-file
-                  ada-search-directories-internal
-                  (ada-make-filename-from-adaname (match-string 3))
-                  ada-spec-suffixes)))
-
-         ;; A "separate" clause.
-         (cons "^separate[ \t\n]*(\\(\\(\\sw\\|[_.]\\)+\\))"
-               (lambda ()
-                 (ff-get-file
-                  ada-search-directories-internal
-                  (ada-make-filename-from-adaname (match-string 1))
-                  ada-spec-suffixes)))
-
-         ;; A "with" clause.
-         (cons "^with[ \t]+\\([a-zA-Z0-9_\\.]+\\)"
-               (lambda ()
-                 (ff-get-file
-                  ada-search-directories-internal
-                  (ada-make-filename-from-adaname (match-string 1))
-                  ada-spec-suffixes)))
-         ))
+       (list
+        ;; Top level child package declaration; go to the parent package.
+        (cons (eval-when-compile
+                (concat "^\\(private[ \t]\\)?[ \t]*package[ \t]+"
+                        "\\(body[ \t]+\\)?"
+                        "\\(\\(\\sw\\|[_.]\\)+\\)\\.\\(\\sw\\|_\\)+[ \t\n]+is"))
+              (lambda ()
+                (ff-get-file
+                 ada-search-directories-internal
+                 (ada-make-filename-from-adaname (match-string 3))
+                 ada-spec-suffixes)))
+
+        ;; A "separate" clause.
+        (cons "^separate[ \t\n]*(\\(\\(\\sw\\|[_.]\\)+\\))"
+              (lambda ()
+                (ff-get-file
+                 ada-search-directories-internal
+                 (ada-make-filename-from-adaname (match-string 1))
+                 ada-spec-suffixes)))
+
+        ;; A "with" clause.
+        (cons "^with[ \t]+\\([a-zA-Z0-9_\\.]+\\)"
+              (lambda ()
+                (ff-get-file
+                 ada-search-directories-internal
+                 (ada-make-filename-from-adaname (match-string 1))
+                 ada-spec-suffixes)))
+        ))
 
   ;;  Support for outline-minor-mode
   (set (make-local-variable 'outline-regexp)
@@ -1278,6 +1265,8 @@ If you use ada-xref.el:
   (set (make-local-variable 'outline-level) 'ada-outline-level)
 
   ;;  Support for imenu : We want a sorted index
+  (setq imenu-generic-expression ada-imenu-generic-expression)
+
   (setq imenu-sort-function 'imenu--sort-by-name)
 
   ;;  Support for ispell : Check only comments
@@ -1290,40 +1279,40 @@ If you use ada-xref.el:
 
   ;; Exclude comments alone on line from alignment.
   (add-to-list 'align-exclude-rules-list
-               '(ada-solo-comment
-                 (regexp  . "^\\(\\s-*\\)--")
-                 (modes   . '(ada-mode))))
+              '(ada-solo-comment
+                (regexp  . "^\\(\\s-*\\)--")
+                (modes   . '(ada-mode))))
   (add-to-list 'align-exclude-rules-list
-               '(ada-solo-use
-                 (regexp  . "^\\(\\s-*\\)\\<use\\>")
-                 (modes   . '(ada-mode))))
+              '(ada-solo-use
+                (regexp  . "^\\(\\s-*\\)\\<use\\>")
+                (modes   . '(ada-mode))))
 
   (setq ada-align-modes nil)
 
   (add-to-list 'ada-align-modes
-               '(ada-declaration-assign
-                 (regexp  . "[^:]\\(\\s-*\\):[^:]")
-                 (valid   . (lambda() (not (ada-in-comment-p))))
-                 (repeat . t)
-                 (modes   . '(ada-mode))))
+              '(ada-declaration-assign
+                (regexp  . "[^:]\\(\\s-*\\):[^:]")
+                (valid   . (lambda() (not (ada-in-comment-p))))
+                (repeat . t)
+                (modes   . '(ada-mode))))
   (add-to-list 'ada-align-modes
-               '(ada-associate
-                 (regexp  . "[^=]\\(\\s-*\\)=>")
-                 (valid   . (lambda() (not (ada-in-comment-p))))
-                 (modes   . '(ada-mode))))
+              '(ada-associate
+                (regexp  . "[^=]\\(\\s-*\\)=>")
+                (valid   . (lambda() (not (ada-in-comment-p))))
+                (modes   . '(ada-mode))))
   (add-to-list 'ada-align-modes
-               '(ada-comment
-                 (regexp  . "\\(\\s-*\\)--")
-                 (modes   . '(ada-mode))))
+              '(ada-comment
+                (regexp  . "\\(\\s-*\\)--")
+                (modes   . '(ada-mode))))
   (add-to-list 'ada-align-modes
-               '(ada-use
-                 (regexp  . "\\(\\s-*\\)\\<use\\s-")
-                 (valid   . (lambda() (not (ada-in-comment-p))))
-                 (modes   . '(ada-mode))))
+              '(ada-use
+                (regexp  . "\\(\\s-*\\)\\<use\\s-")
+                (valid   . (lambda() (not (ada-in-comment-p))))
+                (modes   . '(ada-mode))))
   (add-to-list 'ada-align-modes
-               '(ada-at
-                 (regexp . "\\(\\s-+\\)at\\>")
-                 (modes . '(ada-mode))))
+              '(ada-at
+                (regexp . "\\(\\s-+\\)at\\>")
+                (modes . '(ada-mode))))
 
   (setq align-mode-rules-list ada-align-modes)
 
@@ -1340,7 +1329,10 @@ If you use ada-xref.el:
   (setq which-func-functions '(ada-which-function))
 
   ;;  Support for indent-new-comment-line (Especially for XEmacs)
-  (setq comment-multi-line nil)
+  (set (make-local-variable 'comment-multi-line) nil)
+
+  ;;  Support for add-log
+  (set (make-local-variable 'add-log-current-defun-function) 'ada-which-function)
 
   (setq major-mode 'ada-mode
        mode-name "Ada")
@@ -1377,9 +1369,8 @@ If you use ada-xref.el:
   ;;  font-lock-mode
 
   (unless (featurep 'xemacs)
-    (progn
-      (ada-initialize-properties)
-      (add-hook 'font-lock-mode-hook 'ada-deactivate-properties nil t)))
+    (ada-initialize-syntax-table-properties)
+    (add-hook 'font-lock-mode-hook 'ada-handle-syntax-table-properties nil t))
 
   ;; the following has to be done after running the ada-mode-hook
   ;; because users might want to set the values of these variable
@@ -1403,14 +1394,11 @@ If you use ada-xref.el:
        (progn (goto-char (symbol-value 'beg)) (forward-word -1) (point))
        (goto-char aa-end)))))
 
-;;  transient-mark-mode and mark-active are not defined in XEmacs
 (defun ada-region-selected ()
-  "Return t if a region has been selected by the user and is still active."
-  (or (and (featurep 'xemacs) (funcall (symbol-function 'region-active-p)))
-      (and (not (featurep 'xemacs))
-          (symbol-value 'transient-mark-mode)
-          (symbol-value 'mark-active))))
-
+  "Should we operate on an active region?"
+  (if (fboundp 'use-region-p)
+      (use-region-p)
+    (region-active-p)))
 \f
 ;;-----------------------------------------------------------------
 ;;                      auto-casing
@@ -1431,12 +1419,12 @@ If you use ada-xref.el:
 Casing exception lists are `ada-case-exception' and `ada-case-exception-substring'."
   (find-file (expand-file-name file-name))
   (erase-buffer)
-  (mapcar (lambda (x) (insert (car x) "\n"))
-         (sort (copy-sequence ada-case-exception)
-               (lambda(a b) (string< (car a) (car b)))))
-  (mapcar (lambda (x) (insert "*" (car x) "\n"))
-           (sort (copy-sequence ada-case-exception-substring)
-                 (lambda(a b) (string< (car a) (car b)))))
+  (mapc (lambda (x) (insert (car x) "\n"))
+       (sort (copy-sequence ada-case-exception)
+             (lambda(a b) (string< (car a) (car b)))))
+  (mapc (lambda (x) (insert "*" (car x) "\n"))
+       (sort (copy-sequence ada-case-exception-substring)
+             (lambda(a b) (string< (car a) (car b)))))
   (save-buffer)
   (kill-buffer nil)
   )
@@ -1444,7 +1432,7 @@ Casing exception lists are `ada-case-exception' and `ada-case-exception-substrin
 (defun ada-create-case-exception (&optional word)
   "Define WORD as an exception for the casing system.
 If WORD is not given, then the current word in the buffer is used instead.
-The new words is added to the first file in `ada-case-exception-file'.
+The new word is added to the first file in `ada-case-exception-file'.
 The standard casing rules will no longer apply to this word."
   (interactive)
   (let ((previous-syntax-table (syntax-table))
@@ -1764,7 +1752,7 @@ adapt to unusal auto-casing schemes.  Since it does nothing, you can for
 instance use it for `ada-case-identifier' if you don't want any special
 auto-casing for identifiers, whereas keywords have to be lower-cased.
 See also `ada-auto-case' to disable auto casing altogether."
-  )
+  nil)
 
 (defun ada-capitalize-word (&optional arg)
   "Upcase first letter and letters following '_', lower case other letters.
@@ -2201,7 +2189,7 @@ The original line is indented first if `ada-indent-after-return' is non-nil."
 
 (defun ada-batch-reformat ()
   "Re-indent and re-case all the files found on the command line.
-This function should be used from the Unix/Windows command line, with a
+This function should be used from the command line, with a
 command like:
   emacs -batch -l ada-mode -f ada-batch-reformat file1 file2 ..."
 
@@ -2223,8 +2211,8 @@ Return the new position of point or nil if not found."
 
 (defun ada-indent-current ()
   "Indent current line as Ada code.
-Return the calculation that was done, including the reference point and the
-offset."
+Return the calculation that was done, including the reference point
+and the offset."
   (interactive)
   (let ((previous-syntax-table (syntax-table))
        (orgpoint (point-marker))
@@ -3510,11 +3498,13 @@ Moves point to the matching block start."
 Assumes point to be already positioned by `ada-goto-matching-start'.
 Moves point to the beginning of the declaration."
 
-  ;; named block without a `declare'
+  ;; named block without a `declare'; ada-goto-matching-start leaves
+  ;; point at start of 'begin' for a block.
   (if (save-excursion
        (ada-goto-previous-word)
        (looking-at (concat "\\<" defun-name "\\> *:")))
       t                                 ; do nothing
+    ;; else
     ;;
     ;; 'accept' or 'package' ?
     ;;
@@ -3528,7 +3518,9 @@ Moves point to the beginning of the declaration."
       ;; a named 'declare'-block ? => jump to the label
       ;;
       (if (looking-at "\\<declare\\>")
-         (backward-word 1)
+         (progn
+           (forward-comment -1)
+           (backward-word 1))
        ;;
        ;; no, => 'procedure'/'function'/'task'/'protected'
        ;;
@@ -4033,7 +4025,7 @@ Returns a cons cell of begin and end of match data or nil, if not found.
 If BACKWARD is non-nil, search backward; search forward otherwise.
 The search stops at pos LIMIT.
 If PARAMLISTS is nil, ignore parameter lists.
-The search is done using SEARCH-FUNC. SEARCH-FUNC can be optimized
+The search is done using SEARCH-FUNC.  SEARCH-FUNC can be optimized
 in case we are searching for a constant string.
 Point is moved at the beginning of the SEARCH-RE."
   (let (found
@@ -4548,15 +4540,16 @@ Moves to 'begin' if in a declarative part."
 (defun ada-create-keymap ()
   "Create the keymap associated with the Ada mode."
 
+  ;; All non-standard keys go into ada-mode-extra-map
+  (define-key ada-mode-map ada-mode-extra-prefix ada-mode-extra-map)
+
   ;; Indentation and Formatting
   (define-key ada-mode-map "\C-j"     'ada-indent-newline-indent-conditional)
   (define-key ada-mode-map "\C-m"     'ada-indent-newline-indent-conditional)
   (define-key ada-mode-map "\t"       'ada-tab)
   (define-key ada-mode-map "\C-c\t"   'ada-justified-indent-current)
   (define-key ada-mode-map "\C-c\C-l" 'ada-indent-region)
-  (if (featurep 'xemacs)
-      (define-key ada-mode-map '(shift tab)    'ada-untab)
-    (define-key ada-mode-map [(shift tab)]    'ada-untab))
+  (define-key ada-mode-map [(shift tab)]    'ada-untab)
   (define-key ada-mode-map "\C-c\C-f" 'ada-format-paramlist)
   ;; We don't want to make meta-characters case-specific.
 
@@ -4579,9 +4572,9 @@ Moves to 'begin' if in a declarative part."
   ;; On XEmacs, you can easily specify whether DEL should deletes
   ;; one character forward or one character backward. Take this into
   ;; account
-  (if (boundp 'delete-key-deletes-forward)
-      (define-key ada-mode-map [backspace] 'backward-delete-char-untabify)
-    (define-key ada-mode-map "\177" 'backward-delete-char-untabify))
+  (define-key ada-mode-map
+    (if (boundp 'delete-key-deletes-forward) [backspace] "\177")
+    'backward-delete-char-untabify)
 
   ;; Make body
   (define-key ada-mode-map "\C-c\C-n" 'ada-make-subprogram-body)
@@ -4593,30 +4586,28 @@ Moves to 'begin' if in a declarative part."
   ;; The following keys are bound to functions defined in ada-xref.el or
   ;; ada-prj,el., However, RMS rightly thinks that the code should be shared,
   ;; and activated only if the right compiler is used
-  (if (featurep 'xemacs)
-      (progn
-       (define-key ada-mode-map '(shift button3) 'ada-point-and-xref)
-       (define-key ada-mode-map '(control tab) 'ada-complete-identifier))
-    (define-key ada-mode-map [C-tab] 'ada-complete-identifier)
-    (define-key ada-mode-map [S-mouse-3] 'ada-point-and-xref))
 
-  (define-key ada-mode-map "\C-co"     'ff-find-other-file)
+  (define-key ada-mode-map (if (featurep 'xemacs) '(shift button3) [S-mouse-3])
+    'ada-point-and-xref)
+  (define-key ada-mode-map [(control tab)] 'ada-complete-identifier)
+
+  (define-key ada-mode-extra-map "o"     'ff-find-other-file)
   (define-key ada-mode-map "\C-c5\C-d" 'ada-goto-declaration-other-frame)
   (define-key ada-mode-map "\C-c\C-d"  'ada-goto-declaration)
   (define-key ada-mode-map "\C-c\C-s"  'ada-xref-goto-previous-reference)
   (define-key ada-mode-map "\C-c\C-c"  'ada-compile-application)
-  (define-key ada-mode-map "\C-cc"     'ada-change-prj)
-  (define-key ada-mode-map "\C-cd"     'ada-set-default-project-file)
-  (define-key ada-mode-map "\C-cg"     'ada-gdb-application)
+  (define-key ada-mode-extra-map "c"     'ada-change-prj)
+  (define-key ada-mode-extra-map "d"     'ada-set-default-project-file)
+  (define-key ada-mode-extra-map "g"     'ada-gdb-application)
   (define-key ada-mode-map "\C-c\C-m"  'ada-set-main-compile-application)
-  (define-key ada-mode-map "\C-cr"     'ada-run-application)
+  (define-key ada-mode-extra-map "r"     'ada-run-application)
   (define-key ada-mode-map "\C-c\C-o"  'ada-goto-parent)
   (define-key ada-mode-map "\C-c\C-r"  'ada-find-references)
-  (define-key ada-mode-map "\C-cl"     'ada-find-local-references)
+  (define-key ada-mode-extra-map "l"     'ada-find-local-references)
   (define-key ada-mode-map "\C-c\C-v"  'ada-check-current)
-  (define-key ada-mode-map "\C-cf"     'ada-find-file)
+  (define-key ada-mode-extra-map "f"     'ada-find-file)
 
-  (define-key ada-mode-map "\C-cu"  'ada-prj-edit)
+  (define-key ada-mode-extra-map "u"  'ada-prj-edit)
 
   ;;  The templates, defined in ada-stmt.el
 
@@ -4649,7 +4640,7 @@ Moves to 'begin' if in a declarative part."
     (define-key map "w"    'ada-while-loop)
     (define-key map "\C-x" 'ada-exception)
     (define-key map "x"    'ada-exit)
-    (define-key ada-mode-map "\C-ct" map))
+    (define-key ada-mode-extra-map "t" map))
   )
 
 
@@ -4825,10 +4816,9 @@ Moves to 'begin' if in a declarative part."
 ;; -------------------------------------------------------
 
 (defadvice comment-region (before ada-uncomment-anywhere disable)
-  (if (and arg
-          (listp arg)  ;;  a prefix with \C-u is of the form '(4), whereas
+  (if (and (consp arg)  ;;  a prefix with \C-u is of the form '(4), whereas
                       ;;  \C-u 2  sets arg to '2'  (fixed by S.Leake)
-          (string= mode-name "Ada"))
+          (derived-mode-p 'ada-mode))
       (save-excursion
        (let ((cs (concat "^[ \t]*" (regexp-quote comment-start))))
          (goto-char beg)
@@ -4969,11 +4959,11 @@ The paragraph is indented on the first line."
 ;; cursor at the correct position.
 ;; Standard Ada does not force any relation between unit names and file names,
 ;; so some of these functions can only be a good approximation. However, they
-;; are also overriden in `ada-xref'.el when we know that the user is using
+;; are also overridden in `ada-xref'.el when we know that the user is using
 ;; GNAT.
 ;; ---------------------------------------------------
 
-;; Overriden when we work with GNAT, to use gnatkrunch
+;; Overridden when we work with GNAT, to use gnatkrunch
 (defun ada-make-filename-from-adaname (adaname)
   "Determine the filename in which ADANAME is found.
 This matches the GNAT default naming convention, except for
@@ -5049,9 +5039,9 @@ Used in `ff-pre-load-hook'."
   (save-excursion
     (end-of-line);;  make sure we get the complete name
     (or (if (re-search-backward ada-procedure-start-regexp nil t)
-            (setq ff-function-name (match-string 5)))
-        (if (re-search-backward ada-package-start-regexp nil t)
-            (setq ff-function-name (match-string 4))))
+           (setq ff-function-name (match-string 5)))
+       (if (re-search-backward ada-package-start-regexp nil t)
+           (setq ff-function-name (match-string 4))))
     ))
 
 
@@ -5194,14 +5184,13 @@ Return nil if no body was found."
 
 (defconst ada-font-lock-syntactic-keywords
   ;; Mark single quotes as having string quote syntax in 'c' instances.
-  ;; As a special case, ''' will not be highlighted, but if we do not
-  ;; set this special case, then the rest of the buffer is highlighted as
-  ;; a string
+  ;; We used to explicitly avoid ''' as a special case for fear the buffer
+  ;; be highlighted as a string, but it seems this fear is unfounded.
+  ;;
   ;; This sets the properties of the characters, so that ada-in-string-p
   ;; correctly handles '"' too...
-  '(("[^a-zA-Z0-9)]\\('\\)[^'\n]\\('\\)" (1 (7 . ?')) (2 (7 . ?')))
-    ("^[ \t]*\\(#\\(if\\|else\\|elsif\\|end\\)\\)" (1 (11 . ?\n)))
-    ))
+  '(("[^a-zA-Z0-9)]\\('\\)[^\n]\\('\\)" (1 (7 . ?')) (2 (7 . ?')))
+    ("^[ \t]*\\(#\\(if\\|else\\|elsif\\|end\\)\\)" (1 (11 . ?\n)))))
 
 (defvar ada-font-lock-keywords
   (eval-when-compile
@@ -5253,7 +5242,7 @@ Return nil if no body was found."
                "null" "or" "others" "overriding" "private" "protected" "raise"
                "range" "record" "rem" "renames" "requeue" "return" "reverse"
                "select" "separate" "synchronized" "tagged" "task" "terminate"
-                "then" "until" "when" "while" "with" "xor") t)
+               "then" "until" "when" "while" "with" "xor") t)
             "\\>")
      ;;
      ;; Anything following end and not already fontified is a body name.
@@ -5390,13 +5379,15 @@ for `ada-procedure-start-regexp'."
        (insert "end " procname ";")
        (ada-indent-newline-indent)
        )
-       ;; else
+
        ((looking-at "[ \t\n]*is")
        ;; do nothing
        )
+
        ((looking-at "[ \t\n]*rename")
        ;; do nothing
        )
+
        (t
        (message "unknown syntax"))))
      (t
@@ -5520,7 +5511,6 @@ This function typically is to be hooked into `ff-file-created-hook'."
 (autoload 'ada-point-and-xref               "ada-xref" nil t)
 (autoload 'ada-reread-prj-file              "ada-xref" nil t)
 (autoload 'ada-run-application              "ada-xref" nil t)
-(autoload 'ada-set-default-project-file     "ada-xref" nil nil)
 (autoload 'ada-set-default-project-file     "ada-xref" nil t)
 (autoload 'ada-xref-goto-previous-reference "ada-xref" nil t)
 (autoload 'ada-set-main-compile-application "ada-xref" nil t)
@@ -5563,5 +5553,5 @@ This function typically is to be hooked into `ff-file-created-hook'."
 ;;; provide ourselves
 (provide 'ada-mode)
 
-;;; arch-tag: 1b7d45ec-1698-43b5-8d4a-e479ea023270
+;; arch-tag: 1b7d45ec-1698-43b5-8d4a-e479ea023270
 ;;; ada-mode.el ends here