]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/ada-mode.el
(inferior-python-mode-map): Remove erroneous C-c C-z binding.
[gnu-emacs] / lisp / progmodes / ada-mode.el
index 31652181dbc7141e97714ff2c988726d748e58b6..abc8db6d2c34f6d77121ce5269e22ddebb64a09f 100644 (file)
@@ -1,38 +1,40 @@
-;; @(#) ada-mode.el --- major-mode for editing Ada sources.
+;;; ada-mode.el --- major-mode for editing Ada sources
 
-;; Copyright (C) 1994, 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 95, 97, 98, 99, 2000, 2001, 2002, 03, 2004
+;;  Free Software Foundation, Inc.
 
 ;; Author: Rolf Ebert      <ebert@inf.enst.fr>
 ;;      Markus Heritsch <Markus.Heritsch@studbox.uni-stuttgart.de>
 ;;      Emmanuel Briot  <briot@gnat.com>
 ;; Maintainer: Emmanuel Briot <briot@gnat.com>
-;; Ada Core Technologies's version:   $Revision: 1.31 $
+;; Ada Core Technologies's version:   Revision: 1.188
 ;; Keywords: languages ada
 
-;; This file is not part of GNU Emacs
+;; This file is part of GNU Emacs.
 
-;; This program 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.
 
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
 ;; 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
-;; along with GNU Emacs; see the file COPYING.  If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
 
 ;;; Commentary:
 ;;; This mode is a major mode for editing Ada83 and Ada95 source code.
-;;; This is a major rewrite of the file packaged with Emacs-20.2.  The
-;;; ada-mode is composed of four lisp file, ada-mode.el, ada-xref.el,
+;;; 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 provides only by Gnat.
+;;; 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
 ;;;     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 is this package is compiler-independent.
+;;; 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.
+
+(eval-when-compile
+  (require 'ispell nil t)
+  (require 'find-file nil t)
+  (require 'align nil t)
+  (require 'which-func nil t)
+  (require 'compile nil t))
 
 ;; this function is needed at compile time
 (eval-and-compile
     "Returns 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))))
+                              (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)))))))
-  
-
-;;  We create a constant for that, for efficiency only
-;;  This should not be evaluated at compile time, only a runtime
-(defconst ada-xemacs (boundp 'running-xemacs)
-  "Return t if we are using XEmacs.")
-
-(unless ada-xemacs
-  (require 'outline))
+               (not (or is-xemacs xemacs-running)))
+           (or (> emacs-major-version major)
+               (and (= emacs-major-version major)
+                    (>= emacs-minor-version minor)))))))
 
-(eval-and-compile
-  (condition-case nil (require 'find-file) (error nil)))
 
 ;;  This call should not be made in the release that is done for the
-;;  official FSF Emacs, since it does nothing useful for the latest version
-;;  (require 'ada-support)
+;;  official Emacs, since it does nothing useful for the latest version
+;;(if (not (ada-check-emacs-version 21 1))
+;;    (require 'ada-support))
 
 (defvar ada-mode-hook nil
   "*List of functions to call when Ada mode is invoked.
-This hook is automatically executed after the ada-mode is
+This hook is automatically executed after the `ada-mode' is
 fully loaded.
 This is a good place to add Ada environment specific bindings.")
 
@@ -164,21 +185,40 @@ An example is :
                         >>>>>>>>>Value);  -- from ada-broken-indent"
   :type 'integer :group 'ada)
 
+(defcustom ada-continuation-indent ada-broken-indent
+  "*Number of columns to indent the continuation of broken lines in
+parenthesis.
+
+An example is :
+   Func (Param1,
+         >>>>>Param2);"
+  :type 'integer :group 'ada)
+
 (defcustom ada-case-attribute 'ada-capitalize-word
   "*Function to call to adjust the case of Ada attributes.
-It may be `downcase-word', `upcase-word', `ada-loose-case-word' or
-`ada-capitalize-word'."
+It may be `downcase-word', `upcase-word', `ada-loose-case-word',
+`ada-capitalize-word' or `ada-no-auto-case'."
   :type '(choice (const downcase-word)
                  (const upcase-word)
                  (const ada-capitalize-word)
-                 (const ada-loose-case-word))
+                 (const ada-loose-case-word)
+                 (const ada-no-auto-case))
   :group 'ada)
 
-(defcustom ada-case-exception-file "~/.emacs_case_exceptions"
-  "*File name for the dictionary of special casing exceptions for identifiers.
-This file should contain one word per line, that gives the casing
-to be used for that words in Ada files."
-  :type 'file :group 'ada)
+(defcustom ada-case-exception-file
+  (list (convert-standard-filename' "~/.emacs_case_exceptions"))
+  "*List of special casing exceptions dictionaries for identifiers.
+The first file is the one where new exceptions will be saved by Emacs
+when you call `ada-create-case-exception'.
+
+These files should contain one word per line, that gives the casing
+to be used for that word in Ada files. If the line starts with the
+character *, then the exception will be used for substrings that either
+start at the beginning of a word or after a _ character, and end either
+at the end of the word or at a _ character. Each line can be terminated by
+a comment."
+  :type '(repeat (file))
+  :group 'ada)
 
 (defcustom ada-case-keyword 'downcase-word
   "*Function to call to adjust the case of an Ada keywords.
@@ -187,7 +227,8 @@ It may be `downcase-word', `upcase-word', `ada-loose-case-word' or
   :type '(choice (const downcase-word)
                  (const upcase-word)
                  (const ada-capitalize-word)
-                 (const ada-loose-case-word))
+                 (const ada-loose-case-word)
+                 (const ada-no-auto-case))
   :group 'ada)
 
 (defcustom ada-case-identifier 'ada-loose-case-word
@@ -197,7 +238,8 @@ It may be `downcase-word', `upcase-word', `ada-loose-case-word' or
   :type '(choice (const downcase-word)
                  (const upcase-word)
                  (const ada-capitalize-word)
-                 (const ada-loose-case-word))
+                 (const ada-loose-case-word)
+                 (const ada-no-auto-case))
   :group 'ada)
 
 (defcustom ada-clean-buffer-before-saving t
@@ -217,8 +259,42 @@ begin
   "*Non-nil means automatically indent after RET or LFD."
   :type 'boolean :group 'ada)
 
+(defcustom ada-indent-align-comments t
+  "*Non-nil means align comments on previous line comments, if any.
+If nil, indentation is calculated as usual.
+Note that indentation is calculated only if `ada-indent-comment-as-code' is t.
+
+For instance:
+    A := 1;   --  A multi-line comment
+              --  aligned if ada-indent-align-comments is t"
+  :type 'boolean :group 'ada)
+
 (defcustom ada-indent-comment-as-code t
-  "*Non-nil means indent comment lines as code."
+  "*Non-nil means indent comment lines as code.
+nil means do not auto-indent comments."
+  :type 'boolean :group 'ada)
+
+(defcustom ada-indent-handle-comment-special nil
+  "*Non-nil if comment lines should be handled specially inside
+parenthesis.
+By default, if the line that contains the open parenthesis has some
+text following it, then the following lines will be indented in the
+same column as this text. This will not be true if the first line is
+a comment and `ada-indent-handle-comment-special' is t.
+
+type A is
+  (   Value_1,    --  common behavior, when not a comment
+      Value_2);
+
+type A is
+  (   --  `ada-indent-handle-comment-special' is nil
+      Value_1,
+      Value_2);
+
+type A is
+  (   --  `ada-indent-handle-comment-special' is non-nil
+   Value_1,
+   Value_2);"
   :type 'boolean :group 'ada)
 
 (defcustom ada-indent-is-separate t
@@ -233,6 +309,17 @@ An example is:
    >>>>>>>>>>>record    --  from ada-indent-record-rel-type"
   :type 'integer :group 'ada)
 
+(defcustom ada-indent-renames ada-broken-indent
+  "*Indentation for renames relative to the matching function statement.
+If ada-indent-return is null or negative, the indentation is done relative to
+the open parenthesis (if there is no parenthesis, ada-broken-indent is used).
+
+An example is:
+   function A (B : Integer)
+       return C;      --  from ada-indent-return
+   >>>renames Foo;    --  from ada-indent-renames"
+  :type 'integer :group 'ada)
+
 (defcustom ada-indent-return 0
   "*Indentation for 'return' relative to the matching 'function' statement.
 If ada-indent-return is null or negative, the indentation is done relative to
@@ -247,10 +334,10 @@ An example is:
   "*Non-nil means indent according to the innermost open parenthesis."
   :type 'boolean :group 'ada)
 
-(defcustom ada-fill-comment-prefix "-- "
+(defcustom ada-fill-comment-prefix "--  "
   "*Text inserted in the first columns when filling a comment paragraph.
-Note: if you modify this variable, you will have to restart the ada-mode to
-reread this variable."
+Note: if you modify this variable, you will have to invoke `ada-mode'
+again to take account of the new value."
   :type 'string :group 'ada)
 
 (defcustom ada-fill-comment-postfix " --"
@@ -264,7 +351,9 @@ with `ada-fill-comment-paragraph-postfix'."
 An example is:
 procedure Foo is
 begin
->>>>>>>>>>>>Label:  --  from ada-label-indent"
+>>>>>>>>>>>>Label:  --  from ada-label-indent
+
+This is also used for <<..>> labels"
   :type 'integer :group 'ada)
 
 (defcustom ada-language-version 'ada95
@@ -278,21 +367,30 @@ not to 'begin'."
 
 (defcustom ada-popup-key '[down-mouse-3]
   "*Key used for binding the contextual menu.
-If nil, no contextual menu is available.")
+If nil, no contextual menu is available."
+  :type '(restricted-sexp :match-alternatives (stringp vectorp))
+  :group 'ada)
 
 (defcustom ada-search-directories
-  '("." "$ADA_INCLUDE_PATH" "/usr/adainclude" "/usr/local/adainclude"
-    "/opt/gnu/adainclude")
+  (append '(".")
+         (split-string (or (getenv "ADA_INCLUDE_PATH") "") ":")
+         '("/usr/adainclude" "/usr/local/adainclude"
+           "/opt/gnu/adainclude"))
   "*List of directories to search for Ada files.
-See the description for the `ff-search-directories' variable.
-Emacs will automatically add the paths defined in your project file, and if you
-are using the GNAT compiler the output of the gnatls command to find where the
-runtime really is."
+See the description for the `ff-search-directories' variable. This variable
+is the initial value of this variable, and is copied and modified in
+`ada-search-directories-internal'."
   :type '(repeat (choice :tag "Directory"
                          (const :tag "default" nil)
                          (directory :format "%v")))
   :group 'ada)
 
+(defvar ada-search-directories-internal ada-search-directories
+  "Internal version of `ada-search-directories'.
+Its value is the concatenation of the search path as read in the project file
+and the standard runtime location, and the value of the user-defined
+ada-search-directories.")
+
 (defcustom ada-stmt-end-indent 0
   "*Number of columns to indent the end of a statement on a separate line.
 
@@ -312,6 +410,14 @@ Must be one of :
                  (const always-tab))
   :group 'ada)
 
+(defcustom ada-use-indent ada-broken-indent
+  "*Indentation for the lines in a 'use' statement.
+
+An example is:
+   use Ada.Text_IO,
+   >>>>>Ada.Numerics;    --  from ada-use-indent"
+  :type 'integer :group 'ada)
+
 (defcustom ada-when-indent 3
   "*Indentation for 'when' relative to 'exception' or 'case'.
 
@@ -320,6 +426,14 @@ An example is:
    >>>>>>>>when B =>     --  from ada-when-indent"
   :type 'integer :group 'ada)
 
+(defcustom ada-with-indent ada-broken-indent
+  "*Indentation for the lines in a 'with' statement.
+
+An example is:
+   with Ada.Text_IO,
+   >>>>>Ada.Numerics;    --  from ada-with-indent"
+  :type 'integer :group 'ada)
+
 (defcustom ada-which-compiler 'gnat
   "*Name of the compiler to use.
 This will determine what features are made available through the ada-mode.
@@ -343,12 +457,15 @@ The extensions should include a `.' if needed.")
   "List of possible suffixes for Ada spec files.
 The extensions should include a `.' if needed.")
 
-(defvar ada-mode-menu (make-sparse-keymap)
+(defvar ada-mode-menu (make-sparse-keymap "Ada")
   "Menu for ada-mode.")
 
 (defvar ada-mode-map (make-sparse-keymap)
   "Local keymap used for Ada mode.")
 
+(defvar ada-mode-abbrev-table nil
+  "Local abbrev table for Ada mode.")
+
 (defvar ada-mode-syntax-table nil
   "Syntax table to be used for editing Ada source code.")
 
@@ -374,6 +491,12 @@ This variable is used to define `ada-83-keywords' and `ada-95-keywords'"))
 (defvar ada-case-exception '()
   "Alist of words (entities) that have special casing.")
 
+(defvar ada-case-exception-substring '()
+  "Alist of substrings (entities) that have special casing.
+The substrings are detected for word constituant when the word
+is not itself in ada-case-exception, and only for substrings that
+either are at the beginning or end of the word, or start after '_'.")
+
 (defvar ada-lfd-binding nil
   "Variable to save key binding of LFD when casing is activated.")
 
@@ -381,6 +504,56 @@ This variable is used to define `ada-83-keywords' and `ada-95-keywords'"))
   "Variable used by find-file to find the name of the other package.
 See `ff-other-file-alist'.")
 
+(defvar ada-align-list
+    '(("[^:]\\(\\s-*\\):[^:]" 1 t)
+      ("[^=]\\(\\s-+\\)=[^=]" 1 t)
+      ("\\(\\s-*\\)use\\s-" 1)
+      ("\\(\\s-*\\)--" 1))
+    "Ada support for align.el <= 2.2
+This variable provides regular expressions on which to align different lines.
+See `align-mode-alist' for more information.")
+
+(defvar ada-align-modes
+  '((ada-declaration
+     (regexp  . "[^:]\\(\\s-*\\):[^:]")
+     (valid   . (lambda() (not (ada-in-comment-p))))
+     (modes   . '(ada-mode)))
+    (ada-assignment
+     (regexp  . "[^=]\\(\\s-+\\)=[^=]")
+     (valid   . (lambda() (not (ada-in-comment-p))))
+     (modes   . '(ada-mode)))
+    (ada-comment
+     (regexp  . "\\(\\s-*\\)--")
+     (modes   . '(ada-mode)))
+    (ada-use
+     (regexp  . "\\(\\s-*\\)use\\s-")
+     (valid   . (lambda() (not (ada-in-comment-p))))
+     (modes   . '(ada-mode)))
+    )
+  "Ada support for align.el >= 2.8
+This variable defines several rules to use to align different lines.")
+
+(defconst ada-align-region-separate
+  (concat
+   "^\\s-*\\($\\|\\("
+   "begin\\|"
+   "declare\\|"
+   "else\\|"
+   "end\\|"
+   "exception\\|"
+   "for\\|"
+   "function\\|"
+   "generic\\|"
+   "if\\|"
+   "is\\|"
+   "procedure\\|"
+   "record\\|"
+   "return\\|"
+   "type\\|"
+   "when"
+   "\\)\\>\\)")
+  "see the variable `align-region-separate' for more information.")
+
 ;;; ---- Below are the regexp used in this package for parsing
 
 (defconst ada-83-keywords
@@ -404,8 +577,20 @@ See `ff-other-file-alist'.")
   "\\(\\sw\\|[_.]\\)+"
   "Regexp matching Ada (qualified) identifiers.")
 
+;;  "with" needs to be included in the regexp, so that we can insert new lines
+;;  after the declaration of the parameter for a generic.
 (defvar ada-procedure-start-regexp
-  "^[ \t]*\\(procedure\\|function\\|task\\)[ \t\n]+\\(\\(\\sw\\|[_.]\\)+\\)"
+  (concat
+   "^[ \t]*\\(with[ \t]+\\)?\\(procedure\\|function\\|task\\)[ \t\n]+"
+
+   ;;  subprogram name: operator ("[+/=*]")
+   "\\("
+   "\\(\"[^\"]+\"\\)"
+
+   ;;  subprogram name: name
+   "\\|"
+   "\\(\\(\\sw\\|[_.]\\)+\\)"
+   "\\)")
   "Regexp used to find Ada procedures/functions.")
 
 (defvar ada-package-start-regexp
@@ -429,8 +614,9 @@ See `ff-other-file-alist'.")
             ";"                                        "\\|"
             "=>[ \t]*$"                                "\\|"
             "^[ \t]*separate[ \t]*(\\(\\sw\\|[_.]\\)+)"  "\\|"
-            "\\<" (regexp-opt '("begin" "declare" "is" "do" "else" "generic" "loop"
-                                "private" "record" "select" "then") t) "\\>"  "\\|"
+            "\\<" (regexp-opt '("begin" "declare" "is" "do" "else" "generic"
+                                "loop" "private" "record" "select"
+                                "then abort" "then") t) "\\>"  "\\|"
             "^[ \t]*" (regexp-opt '("function" "package" "procedure")
                                   t) "\\>\\(\\sw\\|[ \t_.]\\)+\\<is\\>"        "\\|"
             "^[ \t]*exception\\>"
@@ -451,11 +637,10 @@ A new statement starts after these.")
   (eval-when-compile
     (concat "\\<"
             (regexp-opt
-             '("is" "separate" "end" "declare" "if" "new" "begin" "generic") t)
+             '("is" "separate" "end" "declare" "if" "new" "begin" "generic" "when") t)
             "\\>"))
   "Regexp used in ada-goto-matching-decl-start.")
 
-
 (defvar ada-loop-start-re
   "\\<\\(for\\|while\\|loop\\)\\>"
   "Regexp for the start of a loop.")
@@ -473,66 +658,67 @@ A new statement starts after these.")
 (defvar ada-contextual-menu-on-identifier nil
   "Set to true when the right mouse button was clicked on an identifier.")
 
-(defvar ada-contextual-menu
-  "Defines the menu to use when the user presses the right mouse button.
+(defvar ada-contextual-menu-last-point nil
+  "Position of point just before displaying the menu.
+This is a list (point buffer).
+Since `ada-popup-menu' moves the point where the user clicked, the region
+is modified. Therefore no command from the menu knows what the user selected
+before displaying the contextual menu.
+To get the original region, restore the point to this position before
+calling `region-end' and `region-beginning'.
+Modify this variable if you want to restore the point to another position.")
+
+(easy-menu-define ada-contextual-menu nil
+  "Menu to use when the user presses the right mouse button.
 The variable `ada-contextual-menu-on-identifier' will be set to t before
 displaying the menu if point was on an identifier."
-  (if ada-xemacs
-      '("Ada"
-       ["Goto Declaration/Body" ada-goto-declaration
-        :included ada-contextual-menu-on-identifier]
-       ["Goto Previous Reference" ada-xref-goto-previous-reference]
-       ["List References" ada-find-references
-        :included ada-contextual-menu-on-identifier]
-       ["-" nil nil]
-       ["Other File" ff-find-other-file]
-       ["Goto Parent Unit" ada-goto-parent]
-       )
-    
-    (let ((map (make-sparse-keymap "Ada")))
-      ;; The identifier part
-      (if (equal ada-which-compiler 'gnat)
-         (progn
-           (define-key-after map [Ref]
-             '(menu-item "Goto Declaration/Body"
-                         ada-point-and-xref
-                         :visible ada-contextual-menu-on-identifier
-                         ) t)
-           (define-key-after map [Prev]
-             '("Goto Previous Reference" .ada-xref-goto-previous-reference) t)
-           (define-key-after map [List]
-             '(menu-item "List References"
-                         ada-find-references
-                         :visible ada-contextual-menu-on-identifier) t)
-           (define-key-after map [-] '("-" nil) t)
-           ))
-      (define-key-after map [Other] '("Other file" . ff-find-other-file) t)
-      (define-key-after map [Parent] '("Goto Parent Unit" . ada-goto-parent)t)
-      map)))
-
+  '("Ada"
+    ["Goto Declaration/Body" ada-point-and-xref
+     :included ada-contextual-menu-on-identifier]
+    ["Goto Body" ada-point-and-xref-body
+     :included ada-contextual-menu-on-identifier]
+    ["Goto Previous Reference" ada-xref-goto-previous-reference]
+    ["List References" ada-find-references
+     :included ada-contextual-menu-on-identifier]
+    ["List Local References" ada-find-local-references
+      :included ada-contextual-menu-on-identifier]
+    ["-"                nil nil]
+    ["Other File"       ff-find-other-file]
+    ["Goto Parent Unit" ada-goto-parent]))
 
 \f
 ;;------------------------------------------------------------------
 ;; Support for imenu  (see imenu.el)
 ;;------------------------------------------------------------------
 
+(defconst ada-imenu-comment-re "\\([ \t]*--.*\\)?")
+
+(defconst ada-imenu-subprogram-menu-re
+  (concat "^[ \t]*\\(procedure\\|function\\)[ \t\n]+"
+         "\\(\\(\\sw\\|_\\)+\\)[ \t\n]*\\([ \t\n]\\|([^)]+)"
+         ada-imenu-comment-re
+         "\\)[ \t\n]*"
+         "\\(return[ \t\n]+\\(\\sw\\|[_.]\\)+[ \t\n]*\\)?is[ \t\n]"))
+
 (defvar ada-imenu-generic-expression
   (list
-   '(nil "^[ \t]*\\(procedure\\|function\\)[ \t\n]+\\(\\(\\sw\\|_\\)+\\)[ \t\n]*\\([ \t\n]\\|([^)]+)\\)[ \t\n]*\\(return[ \t\n]+\\(\\sw\\|[_.]\\)+[ \t\n]*\\)?is[ \t\n]" 2)
+   (list nil ada-imenu-subprogram-menu-re 2)
    (list "*Specs*"
          (concat
           "^[ \t]*\\(procedure\\|function\\)[ \t\n]+\\(\\(\\sw\\|_\\)+\\)"
           "\\("
-          "\\([ \t\n]+\\|[ \t\n]*([^)]+)\\)";; parameter list or simple space
+          "\\(" ada-imenu-comment-re "[ \t\n]+\\|[ \t\n]*([^)]+)"
+         ada-imenu-comment-re "\\)";; parameter list or simple space
           "\\([ \t\n]*return[ \t\n]+\\(\\sw\\|[_.]\\)+[ \t\n]*\\)?"
           "\\)?;") 2)
-   '("*Tasks*" "^[ \t]*task[ \t]+\\(\\(body\\|type\\)[ \t]+\\)?\\(\\(\\sw\\|_\\)+\\)" 3)
+   '("*Tasks*" "^[ \t]*task[ \t]+\\(type[ \t]+\\)?\\(\\(body[ \t]+\\)?\\(\\sw\\|_\\)+\\)" 2)
    '("*Type Defs*" "^[ \t]*\\(sub\\)?type[ \t]+\\(\\(\\sw\\|_\\)+\\)" 2)
+   '("*Protected*"
+     "^[ \t]*protected[ \t]+\\(type[ \t]+\\)?\\(\\(body[ \t]+\\)?\\(\\sw\\|_\\)+\\)" 2)
    '("*Packages*" "^[ \t]*package[ \t]+\\(\\(body[ \t]+\\)?\\(\\sw\\|[_.]\\)+\\)" 1))
   "Imenu generic expression for Ada mode.
-See `imenu-generic-expression'. This variable will create two submenus, one
-for type and subtype definitions, the other for subprograms declarations.
-The main menu will reference the bodies of the subprograms.")
+See `imenu-generic-expression'. This variable will create several submenus for
+each type of entity that can be found in an Ada file.")
 
 \f
 ;;------------------------------------------------------------
@@ -540,7 +726,7 @@ The main menu will reference the bodies of the subprograms.")
 ;;------------------------------------------------------------
 
 (defun ada-compile-mouse-goto-error ()
-  "Mouse interface for `ada-compile-goto-error'."
+  "Mouse interface for ada-compile-goto-error."
   (interactive)
   (mouse-set-point last-input-event)
   (ada-compile-goto-error (point))
@@ -560,28 +746,43 @@ both file locations can be clicked on and jumped to."
   (cond
    ;;  special case: looking at a filename:line not at the beginning of a line
    ((and (not (bolp))
-        (looking-at
-         "\\(\\(\\sw\\|[_-.]\\)+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?"))
-    (let ((line (match-string 3))
+         (looking-at
+          "\\([-_.a-zA-Z0-9]+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?"))
+    (let ((line (match-string 2))
+          file
           (error-pos (point-marker))
           source)
       (save-excursion
         (save-restriction
           (widen)
-          (set-buffer (compilation-find-file (point-marker) (match-string 1)
-                                             "./"))
+          ;;  Use funcall so as to prevent byte-compiler warnings
+          ;;  `ada-find-file' is not defined if ada-xref wasn't loaded. But
+          ;;  if we can find it, we should use it instead of
+          ;;  `compilation-find-file', since the latter doesn't know anything
+          ;;  about source path.
+
+          (if (functionp 'ada-find-file)
+              (setq file (funcall (symbol-function 'ada-find-file)
+                                  (match-string 1)))
+            (setq file (funcall (symbol-function 'compilation-find-file)
+                                (point-marker) (match-string 1)
+                                "./")))
+          (set-buffer file)
+
           (if (stringp line)
               (goto-line (string-to-number line)))
-          (set 'source (point-marker))))
-      (compilation-goto-locus (cons source error-pos))
+          (setq source (point-marker))))
+      (funcall (symbol-function 'compilation-goto-locus)
+               (cons source error-pos))
       ))
 
    ;; otherwise, default behavior
    (t
-    (compile-goto-error))
+    (funcall (symbol-function 'compile-goto-error)))
    )
   (recenter))
 
+\f
 ;;-------------------------------------------------------------------------
 ;; Grammar related function
 ;; The functions below work with the syntax class of the characters in an Ada
@@ -617,7 +818,7 @@ both file locations can be clicked on and jumped to."
 The standard table declares `_' as a symbol constituent, the second one
 declares it as a word constituent."
   (interactive)
-  (set 'ada-mode-syntax-table (make-syntax-table))
+  (setada-mode-syntax-table (make-syntax-table))
   (set-syntax-table  ada-mode-syntax-table)
 
   ;; define string brackets (`%' is alternative string bracket, but
@@ -650,7 +851,7 @@ declares it as a word constituent."
 
   ;; See the comment above on grammar related function for the special
   ;; setup for '#'.
-  (if ada-xemacs
+  (if (featurep 'xemacs)
       (modify-syntax-entry ?#  "<" ada-mode-syntax-table)
     (modify-syntax-entry ?#  "$" ada-mode-syntax-table))
 
@@ -665,14 +866,14 @@ declares it as a word constituent."
   (modify-syntax-entry ?\( "()" ada-mode-syntax-table)
   (modify-syntax-entry ?\) ")(" ada-mode-syntax-table)
 
-  (set 'ada-mode-symbol-syntax-table (copy-syntax-table ada-mode-syntax-table))
+  (setada-mode-symbol-syntax-table (copy-syntax-table ada-mode-syntax-table))
   (modify-syntax-entry ?_ "w" ada-mode-symbol-syntax-table)
   )
 
 ;;  Support of special characters in XEmacs (see the comments at the beginning
 ;;  of the section on Grammar related functions).
 
-(if ada-xemacs
+(if (featurep 'xemacs)
     (defadvice parse-partial-sexp (around parse-partial-sexp-protect-constants)
       "Handles special character constants and gnatprep statements."
       (let (change)
@@ -682,25 +883,25 @@ declares it as a word constituent."
         (save-excursion
           (goto-char from)
           (while (re-search-forward "'\\([(\")#]\\)'" to t)
-            (set 'change (cons (list (match-beginning 1)
+            (setchange (cons (list (match-beginning 1)
                                      1
                                      (match-string 1))
                                change))
             (replace-match "'A'"))
           (goto-char from)
           (while (re-search-forward "\\(#[0-9a-fA-F]*#\\)" to t)
-            (set 'change (cons (list (match-beginning 1)
+            (setchange (cons (list (match-beginning 1)
                                      (length (match-string 1))
                                      (match-string 1))
                                change))
-           (replace-match (make-string (length (match-string 1)) ?@))))
+            (replace-match (make-string (length (match-string 1)) ?@))))
         ad-do-it
         (save-excursion
           (while change
             (goto-char (caar change))
             (delete-char (cadar change))
             (insert (caddar change))
-            (set 'change (cdr change)))))))
+            (setchange (cdr change)))))))
 
 (defun ada-deactivate-properties ()
   "Deactivate ada-mode's properties handling.
@@ -727,7 +928,6 @@ as numbers instead of gnatprep comments."
       ;;  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
-      (make-local-hook 'after-change-functions)
       (add-hook 'after-change-functions 'ada-after-change-function nil t)
       )))
 
@@ -746,40 +946,85 @@ OLD-LEN indicates what the length of the replaced text was."
         (beginning-of-line)
         (if (looking-at "^[ \t]*#")
             (add-text-properties (match-beginning 0) (match-end 0)
-                                 '(syntax-table (11 . 10))))
-        ))))
+                                 '(syntax-table (11 . 10))))))))
+
+;;------------------------------------------------------------------
+;;  Testing the grammatical context
+;;------------------------------------------------------------------
+
+(defsubst ada-in-comment-p (&optional parse-result)
+  "Returns t if inside a comment."
+  (nth 4 (or parse-result
+             (parse-partial-sexp
+              (line-beginning-position) (point)))))
+
+(defsubst ada-in-string-p (&optional parse-result)
+  "Returns t if point is inside a string.
+If parse-result is non-nil, use is instead of calling parse-partial-sexp."
+  (nth 3 (or parse-result
+             (parse-partial-sexp
+              (line-beginning-position) (point)))))
+
+(defsubst ada-in-string-or-comment-p (&optional parse-result)
+  "Returns t if inside a comment or string."
+  (setq parse-result (or parse-result
+                         (parse-partial-sexp
+                          (line-beginning-position) (point))))
+  (or (ada-in-string-p parse-result) (ada-in-comment-p parse-result)))
 
 
 ;;------------------------------------------------------------------
 ;; Contextual menus
-;; The Ada-mode comes with fully contextual menus, bound by default
-;; on the right mouse button.
+;; The Ada-mode comes with contextual menus, bound by default to the right
+;; mouse button.
 ;; Add items to this menu by modifying `ada-contextual-menu'. Note that the
 ;; variable `ada-contextual-menu-on-identifier' is set automatically to t
 ;; if the mouse button was pressed on an identifier.
 ;;------------------------------------------------------------------
 
+(defun ada-call-from-contextual-menu (function)
+  "Execute FUNCTION when called from the contextual menu.
+It forces Emacs to change the cursor position."
+  (interactive)
+  (funcall function)
+  (setq ada-contextual-menu-last-point
+        (list (point) (current-buffer))))
+
 (defun ada-popup-menu (position)
   "Pops up a contextual menu, depending on where the user clicked.
-POSITION is the location the mouse was clicked on."
+POSITION is the location the mouse was clicked on.
+Sets `ada-contextual-menu-last-point' to the current position before
+displaying the menu. When a function from the menu is called, the point is
+where the mouse button was clicked."
   (interactive "e")
-  (save-excursion
+
+  ;;  declare this as a local variable, so that the function called
+  ;;  in the contextual menu does not hide the region in
+  ;;  transient-mark-mode.
+  (let ((deactivate-mark nil))
+    (setq ada-contextual-menu-last-point
+         (list (point) (current-buffer)))
     (mouse-set-point last-input-event)
-    
+
     (setq ada-contextual-menu-on-identifier
-         (and (char-after)
-              (or (= (char-syntax (char-after)) ?w)
-                  (= (char-after) ?_))
-              (not (ada-in-string-or-comment-p))
-              (save-excursion (skip-syntax-forward "w")
-                              (not (ada-after-keyword-p)))
-              ))
-    (let (choice)
-      (if ada-xemacs
-         (set 'choice (popup-menu ada-contextual-menu))
-       (set 'choice (x-popup-menu position ada-contextual-menu)))
-      (if choice
-         (funcall (lookup-key ada-contextual-menu (vector (car choice))))))))
+          (and (char-after)
+               (or (= (char-syntax (char-after)) ?w)
+                   (= (char-after) ?_))
+               (not (ada-in-string-or-comment-p))
+               (save-excursion (skip-syntax-forward "w")
+                               (not (ada-after-keyword-p)))
+               ))
+    (if (fboundp 'popup-menu)
+       (funcall (symbol-function 'popup-menu) ada-contextual-menu)
+      (let (choice)
+       (setq choice (x-popup-menu position ada-contextual-menu))
+       (if choice
+           (funcall (lookup-key ada-contextual-menu (vector (car choice)))))))
+
+    (set-buffer (cadr ada-contextual-menu-last-point))
+    (goto-char (car ada-contextual-menu-last-point))
+    ))
+
 
 ;;------------------------------------------------------------------
 ;; Misc functions
@@ -793,39 +1038,42 @@ extensions.
 SPEC and BODY are two regular expressions that must match against the file
 name"
   (let* ((reg (concat (regexp-quote body) "$"))
-        (tmp (assoc reg ada-other-file-alist)))
+         (tmp (assoc reg ada-other-file-alist)))
     (if tmp
-       (setcdr tmp (list (cons spec (cadr tmp))))
+        (setcdr tmp (list (cons spec (cadr tmp))))
       (add-to-list 'ada-other-file-alist (list reg (list spec)))))
-  
+
   (let* ((reg (concat (regexp-quote spec) "$"))
-        (tmp (assoc reg ada-other-file-alist)))
+         (tmp (assoc reg ada-other-file-alist)))
     (if tmp
-       (setcdr tmp (list (cons body (cadr tmp))))
+        (setcdr tmp (list (cons body (cadr tmp))))
       (add-to-list 'ada-other-file-alist (list reg (list body)))))
 
-  (add-to-list 'auto-mode-alist (cons spec 'ada-mode))
-  (add-to-list 'auto-mode-alist (cons body 'ada-mode))
+  (add-to-list 'auto-mode-alist
+              (cons (concat (regexp-quote spec) "\\'") 'ada-mode))
+  (add-to-list 'auto-mode-alist
+              (cons (concat (regexp-quote body) "\\'") 'ada-mode))
 
   (add-to-list 'ada-spec-suffixes spec)
   (add-to-list 'ada-body-suffixes body)
 
   ;; Support for speedbar (Specifies that we want to see these files in
   ;; speedbar)
-  (condition-case nil
+  (if (fboundp 'speedbar-add-supported-extension)
       (progn
-        (require 'speedbar)
-        (speedbar-add-supported-extension spec)
-        (speedbar-add-supported-extension body)))
+        (funcall (symbol-function 'speedbar-add-supported-extension)
+                 spec)
+        (funcall (symbol-function 'speedbar-add-supported-extension)
+                 body)))
   )
 
 
-
 ;;;###autoload
 (defun ada-mode ()
   "Ada mode is the major mode for editing Ada code.
 
 Bindings are as follows: (Note: 'LFD' is control-j.)
+\\{ada-mode-map}
 
  Indent line                                          '\\[ada-tab]'
  Indent line, insert newline and indent the new line. '\\[newline-and-indent]'
@@ -863,18 +1111,13 @@ If you use find-file.el:
 If you use ada-xref.el:
  Goto declaration:          '\\[ada-point-and-xref]' on the identifier
                          or '\\[ada-goto-declaration]' with point on the identifier
- Complete identifier:       '\\[ada-complete-identifier]'"
+ Complete identifier:       '\\[ada-complete-identifier]'."
 
   (interactive)
   (kill-all-local-variables)
 
   (set (make-local-variable 'require-final-newline) t)
 
-  (make-local-variable 'comment-start)
-  (if ada-fill-comment-prefix
-      (set 'comment-start ada-fill-comment-prefix)
-    (set 'comment-start "-- "))
-
   ;;  Set the paragraph delimiters so that one can select a whole block
   ;;  simply with M-h
   (set (make-local-variable 'paragraph-start) "[ \t\n\f]*$")
@@ -894,8 +1137,8 @@ If you use ada-xref.el:
   ;; aligned under the latest parameter, not under the declaration start).
   (set (make-local-variable 'comment-line-break-function)
        (lambda (&optional soft) (let ((fill-prefix nil))
-                                 (indent-new-comment-line soft))))
-  
+                                  (indent-new-comment-line soft))))
+
   (set (make-local-variable 'indent-line-function)
        'ada-indent-current-function)
 
@@ -904,7 +1147,7 @@ If you use ada-xref.el:
   ;;  Emacs 20.3 defines a comment-padding to insert spaces between
   ;;  the comment and the text. We do not want any, this is already
   ;;  included in comment-start
-  (unless ada-xemacs
+  (unless (featurep 'xemacs)
     (progn
       (if (ada-check-emacs-version 20 3)
           (progn
@@ -927,20 +1170,20 @@ If you use ada-xref.el:
   ;;  We just substitute our own functions to go to the error.
   (add-hook 'compilation-mode-hook
             (lambda()
-              (set 'compile-auto-highlight 40)
-               (define-key compilation-minor-mode-map [mouse-2]
-                 'ada-compile-mouse-goto-error)
-               (define-key compilation-minor-mode-map "\C-c\C-c"
-                 'ada-compile-goto-error)
-               (define-key compilation-minor-mode-map "\C-m"
-                 'ada-compile-goto-error)
-               ))
+             (set (make-local-variable 'compile-auto-highlight) 40)
+             ;; FIXME: This has global impact!  -stef
+             (define-key compilation-minor-mode-map [mouse-2]
+               'ada-compile-mouse-goto-error)
+             (define-key compilation-minor-mode-map "\C-c\C-c"
+               'ada-compile-goto-error)
+             (define-key compilation-minor-mode-map "\C-m"
+               'ada-compile-goto-error)))
 
   ;;  font-lock support :
   ;;  We need to set some properties for XEmacs, and define some variables
   ;;  for Emacs
 
-  (if ada-xemacs
+  (if (featurep 'xemacs)
       ;;  XEmacs
       (put 'ada-mode 'font-lock-defaults
            '(ada-font-lock-keywords
@@ -953,115 +1196,212 @@ If you use ada-xref.el:
            beginning-of-line
            (font-lock-syntactic-keywords . ada-font-lock-syntactic-keywords)))
     )
-  
+
   ;; Set up support for find-file.el.
-  (set (make-variable-buffer-local 'ff-other-file-alist)
+  (set (make-local-variable 'ff-other-file-alist)
        'ada-other-file-alist)
-  (set (make-variable-buffer-local 'ff-search-directories)
-       'ada-search-directories)
-  (setq ff-post-load-hooks    'ada-set-point-accordingly
-       ff-file-created-hooks 'ada-make-body)
-  (add-hook 'ff-pre-load-hooks 'ada-which-function-are-we-in)
-  
+  (set (make-local-variable 'ff-search-directories)
+       'ada-search-directories-internal)
+  (setq ff-post-load-hook    'ada-set-point-accordingly
+        ff-file-created-hook 'ada-make-body)
+  (add-hook 'ff-pre-load-hook 'ada-which-function-are-we-in)
+
   ;; Some special constructs for find-file.el
   ;; We do not need to add the construction for 'with', which is in the
   ;; standard find-file.el
-  ;; Go to the parent package :
   (make-local-variable 'ff-special-constructs)
+
+  ;; Go to the parent package :
   (add-to-list 'ff-special-constructs
-              (cons (eval-when-compile
-                      (concat "^\\(private[ \t]\\)?[ \t]*package[ \t]+"
-                              "\\(body[ \t]+\\)?"
-                              "\\(\\(\\sw\\|[_.]\\)+\\)\\.\\(\\sw\\|_\\)+[ \t\n]+is"))
-                    (lambda ()
-                       (set 'fname (ff-get-file
-                                    ff-search-directories
-                                    (ada-make-filename-from-adaname
-                                     (match-string 3))
-                                    ada-spec-suffixes)))))
+               (cons (eval-when-compile
+                       (concat "^\\(private[ \t]\\)?[ \t]*package[ \t]+"
+                               "\\(body[ \t]+\\)?"
+                               "\\(\\(\\sw\\|[_.]\\)+\\)\\.\\(\\sw\\|_\\)+[ \t\n]+is"))
+                     (lambda ()
+                      (if (fboundp 'ff-get-file)
+                          (if (boundp 'fname)
+                              (set 'fname (ff-get-file
+                                           ada-search-directories-internal
+                                           (ada-make-filename-from-adaname
+                                            (match-string 3))
+                                           ada-spec-suffixes)))))))
   ;; Another special construct for find-file.el : when in a separate clause,
   ;; go to the correct package.
   (add-to-list 'ff-special-constructs
-              (cons "^separate[ \t\n]*(\\(\\(\\sw\\|[_.]\\)+\\))"
-                    (lambda ()
-                       (set 'fname (ff-get-file
-                                    ff-search-directories
-                                    (ada-make-filename-from-adaname
-                                     (match-string 1))
-                                    ada-spec-suffixes)))))
+               (cons "^separate[ \t\n]*(\\(\\(\\sw\\|[_.]\\)+\\))"
+                     (lambda ()
+                      (if (fboundp 'ff-get-file)
+                          (if (boundp 'fname)
+                              (setq fname (ff-get-file
+                                           ada-search-directories-internal
+                                           (ada-make-filename-from-adaname
+                                            (match-string 1))
+                                           ada-spec-suffixes)))))))
+
   ;; Another special construct, that redefines the one in find-file.el. The
   ;; old one can handle only one possible type of extension for Ada files
-  (add-to-list 'ff-special-constructs
-              (cons "^with[ \t]+\\([a-zA-Z0-9_\\.]+\\)" 
-                    (lambda ()
-                       (set 'fname (ff-get-file
-                                    ff-search-directories
-                                    (ada-make-filename-from-adaname
-                                     (match-string 1))
-                                    ada-spec-suffixes)))))
-  
+  ;;  remove from the list the standard "with..." that is put by find-file.el,
+  ;;  since it uses the old ada-spec-suffix variable
+  ;; This one needs to replace the standard one defined in find-file.el (with
+  ;;  Emacs <= 20.4), since that one uses the old variable ada-spec-suffix
+  (let ((old-construct
+         (assoc "^with[ \t]+\\([a-zA-Z0-9_\\.]+\\)" ff-special-constructs))
+        (new-cdr
+         (lambda ()
+          (if (fboundp 'ff-get-file)
+              (if (boundp 'fname)
+                  (set 'fname (ff-get-file
+                               ada-search-directories-internal
+                               (ada-make-filename-from-adaname
+                                (match-string 1))
+                               ada-spec-suffixes)))))))
+    (if old-construct
+        (setcdr old-construct new-cdr)
+      (add-to-list 'ff-special-constructs
+                   (cons "^with[ \t]+\\([a-zA-Z0-9_\\.]+\\)"
+                         new-cdr))))
+
   ;;  Support for outline-minor-mode
   (set (make-local-variable 'outline-regexp)
-       "\\([ \t]*\\(procedure\\|function\\|package\\|with\\|use\\)\\|--\\|end\\)")
+       "\\([ \t]*\\(procedure\\|function\\|package\\|if\\|while\\|for\\|declare\\|case\\|end\\|begin\\|loop\\)\\|--\\)")
   (set (make-local-variable 'outline-level) 'ada-outline-level)
 
   ;;  Support for imenu : We want a sorted index
-  (set 'imenu-sort-function 'imenu--sort-by-name)
+  (setq imenu-sort-function 'imenu--sort-by-name)
+
+  ;;  Support for ispell : Check only comments
+  (set (make-local-variable 'ispell-check-comments) 'exclusive)
+
+  ;;  Support for align.el <= 2.2, if present
+  ;;  align.el is distributed with Emacs 21, but not with earlier versions.
+  (if (boundp 'align-mode-alist)
+      (add-to-list 'align-mode-alist '(ada-mode . ada-align-list)))
+
+  ;;  Support for align.el >= 2.8, if present
+  (if (boundp 'align-dq-string-modes)
+      (progn
+       (add-to-list 'align-dq-string-modes 'ada-mode)
+       (add-to-list 'align-open-comment-modes 'ada-mode)
+       (set (make-variable-buffer-local 'align-region-separate)
+            ada-align-region-separate)
+
+       ;; Exclude comments alone on line from alignment.
+       (add-to-list 'align-exclude-rules-list
+                    '(ada-solo-comment
+                      (regexp  . "^\\(\\s-*\\)--")
+                      (modes   . '(ada-mode))))
+       (add-to-list 'align-exclude-rules-list
+                    '(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))))
+       (add-to-list 'ada-align-modes
+                    '(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))))
+       (add-to-list 'ada-align-modes
+                    '(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))))
+
+
+       (setq align-mode-rules-list ada-align-modes)
+       ))
 
   ;;  Set up the contextual menu
   (if ada-popup-key
       (define-key ada-mode-map ada-popup-key 'ada-popup-menu))
 
+  ;;  Support for Abbreviations (the user still need to "M-x abbrev-mode"
+  (define-abbrev-table 'ada-mode-abbrev-table ())
+  (setq local-abbrev-table ada-mode-abbrev-table)
+
+  ;;  Support for which-function mode
+  ;; which-function-mode does not work with nested subprograms, since it is
+  ;; based only on the regexps generated by imenu, and thus can only detect the
+  ;; beginning of subprograms, not the end.
+  ;; Fix is: redefine a new function ada-which-function, and call it when the
+  ;; major-mode is ada-mode.
+
+  (make-local-variable 'which-func-functions)
+  (setq which-func-functions '(ada-which-function))
+
   ;;  Support for indent-new-comment-line (Especially for XEmacs)
-  (set 'comment-multi-line nil)
-  (defconst comment-indent-function (lambda () comment-column))
+  (setq comment-multi-line nil)
 
-  (set 'major-mode 'ada-mode)
-  (set 'mode-name "Ada")
+  (setq major-mode 'ada-mode
+       mode-name "Ada")
 
   (use-local-map ada-mode-map)
 
-  (if ada-xemacs
-      (easy-menu-add ada-mode-menu ada-mode-map))
-  
+  (easy-menu-add ada-mode-menu ada-mode-map)
+
   (set-syntax-table ada-mode-syntax-table)
 
   (if ada-clean-buffer-before-saving
       (progn
         ;; remove all spaces at the end of lines in the whole buffer.
-        (add-hook 'local-write-file-hooks 'ada-remove-trailing-spaces)
+       (add-hook 'local-write-file-hooks 'delete-trailing-whitespace)
         ;; convert all tabs to the correct number of spaces.
         (add-hook 'local-write-file-hooks
                   (lambda () (untabify (point-min) (point-max))))))
 
   (run-hooks 'ada-mode-hook)
 
+  ;;  To be run after the hook, in case the user modified
+  ;;  ada-fill-comment-prefix
+  (make-local-variable 'comment-start)
+  (if ada-fill-comment-prefix
+      (set 'comment-start ada-fill-comment-prefix)
+    (set 'comment-start "-- "))
+
   ;;  Run this after the hook to give the users a chance to activate
   ;;  font-lock-mode
 
-  (unless ada-xemacs
+  (unless (featurep 'xemacs)
     (progn
       (ada-initialize-properties)
-      (make-local-hook 'font-lock-mode-hook)
       (add-hook 'font-lock-mode-hook 'ada-deactivate-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
   ;; inside the hook (MH)
-  ;; Note that we add the new elements at the end of ada-other-file-alist
-  ;; since some user might want to give priority to some other extensions
-  ;; first (for instance, a .adb file could be associated with a .ads
-  ;; or a .ads.gp (gnatprep)).
-  ;; This is why we can't use add-to-list here.
 
   (cond ((eq ada-language-version 'ada83)
-         (set 'ada-keywords ada-83-keywords))
+         (setada-keywords ada-83-keywords))
         ((eq ada-language-version 'ada95)
-         (set 'ada-keywords ada-95-keywords)))
+         (setada-keywords ada-95-keywords)))
 
   (if ada-auto-case
       (ada-activate-keys-for-case)))
 
+
+;;  transient-mark-mode and mark-active are not defined in XEmacs
+(defun ada-region-selected ()
+  "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))))
+
 \f
 ;;-----------------------------------------------------------------
 ;;                      auto-casing
@@ -1074,8 +1414,26 @@ If you use ada-xref.el:
 ;; However, in most cases, the user will want to define some exceptions to
 ;; these casing rules. This is done through a list of files, that contain
 ;; one word per line. These files are stored in `ada-case-exception-file'.
+;; For backward compatibility, this variable can also be a string.
 ;;-----------------------------------------------------------------
 
+(defun ada-save-exceptions-to-file (file-name)
+  "Save the exception lists `ada-case-exception' and
+`ada-case-exception-substring' to the file FILE-NAME."
+
+  ;;  Save the list in the file
+  (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)))))
+  (save-buffer)
+  (kill-buffer nil)
+  )
+
 (defun ada-create-case-exception (&optional word)
   "Defines WORD as an exception for the casing system.
 If WORD is not given, then the current word in the buffer is used instead.
@@ -1083,98 +1441,184 @@ The new words 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))
-       (exception-list '()))
+        file-name
+        )
+
+    (cond ((stringp ada-case-exception-file)
+           (setq file-name ada-case-exception-file))
+          ((listp ada-case-exception-file)
+           (setq file-name (car ada-case-exception-file)))
+          (t
+           (error (concat "No exception file specified. "
+                         "See variable ada-case-exception-file."))))
+
     (set-syntax-table ada-mode-symbol-syntax-table)
     (unless word
       (save-excursion
-       (skip-syntax-backward "w")
-       (set 'word (buffer-substring-no-properties
-                  (point) (save-excursion (forward-word 1) (point))))))
+        (skip-syntax-backward "w")
+        (setq word (buffer-substring-no-properties
+                    (point) (save-excursion (forward-word 1) (point))))))
+    (set-syntax-table previous-syntax-table)
 
     ;;  Reread the exceptions file, in case it was modified by some other,
-    ;;  and to keep the end-of-line comments that may exist in it.
-    (if (file-readable-p (expand-file-name ada-case-exception-file))
-       (let ((buffer (current-buffer)))
-         (find-file (expand-file-name ada-case-exception-file))
-         (set-syntax-table ada-mode-symbol-syntax-table)
-         (widen)
-         (goto-char (point-min))
-         (while (not (eobp))
-           (add-to-list 'exception-list
-                        (list
-                         (buffer-substring-no-properties
-                          (point) (save-excursion (forward-word 1) (point)))
-                         (buffer-substring-no-properties
-                          (save-excursion (forward-word 1) (point))
-                          (save-excursion (end-of-line) (point)))
-                         t))
-           (forward-line 1))
-         (kill-buffer nil)
-         (set-buffer buffer)))
-    
+    (ada-case-read-exceptions-from-file file-name)
+
     ;;  If the word is already in the list, even with a different casing
     ;;  we simply want to replace it.
-    (if (and (not (equal exception-list '()))
-            (assoc-ignore-case word exception-list))
-       (setcar (assoc-ignore-case word exception-list)
-               word)
-      (add-to-list 'exception-list (list word "" t))
-      )
-
     (if (and (not (equal ada-case-exception '()))
-            (assoc-ignore-case word ada-case-exception))
-       (setcar (assoc-ignore-case word ada-case-exception)
-               word)
+             (assoc-ignore-case word ada-case-exception))
+        (setcar (assoc-ignore-case word ada-case-exception) word)
       (add-to-list 'ada-case-exception (cons word t))
       )
 
-    ;;  Save the list in the file
-    (find-file (expand-file-name ada-case-exception-file))
-    (erase-buffer)
-    (mapcar (lambda (x) (insert (car x) (nth 1 x) "\n"))
-           (sort exception-list
-                 (lambda(a b) (string< (car a) (car b)))))
-    (save-buffer)
-    (kill-buffer nil)
-    (set-syntax-table previous-syntax-table)
+    (ada-save-exceptions-to-file file-name)
     ))
-  
-(defun ada-case-read-exceptions ()
-  "Parse `ada-case-exception-file' for the dictionary of casing exceptions."
+
+(defun ada-create-case-exception-substring (&optional word)
+  "Defines the substring WORD as an exception for the casing system.
+If WORD is not given, then the current word in the buffer is used instead,
+or the selected region if any is active.
+The new words is added to the first file in `ada-case-exception-file'.
+When auto-casing a word, this substring will be special-cased, unless the
+word itself has a special casing."
   (interactive)
-  (set 'ada-case-exception '())
-  (if (file-readable-p (expand-file-name ada-case-exception-file))
+  (let ((file-name
+        (cond ((stringp ada-case-exception-file)
+               ada-case-exception-file)
+              ((listp ada-case-exception-file)
+               (car ada-case-exception-file))
+              (t
+               (error (concat "No exception file specified. "
+                              "See variable ada-case-exception-file."))))))
+
+    ;;  Find the substring to define as an exception. Order is: the parameter,
+    ;;  if any, or the selected region, or the word under the cursor
+    (cond
+     (word   nil)
+
+     ((ada-region-selected)
+      (setq word (buffer-substring-no-properties
+                 (region-beginning) (region-end))))
+
+     (t
+      (let ((underscore-syntax (char-syntax ?_)))
+       (unwind-protect
+           (progn
+             (modify-syntax-entry ?_ "." (syntax-table))
+             (save-excursion
+               (skip-syntax-backward "w")
+               (set 'word (buffer-substring-no-properties
+                           (point)
+                           (save-excursion (forward-word 1) (point))))))
+         (modify-syntax-entry ?_ (make-string 1 underscore-syntax)
+                              (syntax-table))))))
+
+    ;;  Reread the exceptions file, in case it was modified by some other,
+    (ada-case-read-exceptions-from-file file-name)
+
+    ;;  If the word is already in the list, even with a different casing
+    ;;  we simply want to replace it.
+    (if (and (not (equal ada-case-exception-substring '()))
+             (assoc-ignore-case word ada-case-exception-substring))
+        (setcar (assoc-ignore-case word ada-case-exception-substring) word)
+      (add-to-list 'ada-case-exception-substring (cons word t))
+      )
+
+    (ada-save-exceptions-to-file file-name)
+
+    (message (concat "Defining " word " as a casing exception"))))
+
+(defun ada-case-read-exceptions-from-file (file-name)
+  "Read the content of the casing exception file FILE-NAME."
+  (if (file-readable-p (expand-file-name file-name))
       (let ((buffer (current-buffer)))
-       (find-file (expand-file-name ada-case-exception-file))
-       (set-syntax-table ada-mode-symbol-syntax-table)
+        (find-file (expand-file-name file-name))
+        (set-syntax-table ada-mode-symbol-syntax-table)
         (widen)
         (goto-char (point-min))
         (while (not (eobp))
-          (add-to-list 'ada-case-exception
-                       (cons
-                        (buffer-substring-no-properties
-                         (point) (save-excursion (forward-word 1) (point)))
-                        t))
+
+          ;; If the item is already in the list, even with an other casing,
+          ;; do not add it again. This way, the user can easily decide which
+          ;; priority should be applied to each casing exception
+          (let ((word (buffer-substring-no-properties
+                       (point) (save-excursion (forward-word 1) (point)))))
+
+           ;;  Handling a substring ?
+           (if (char-equal (string-to-char word) ?*)
+               (progn
+                 (setq word (substring word 1))
+                 (unless (assoc-ignore-case word ada-case-exception-substring)
+                   (add-to-list 'ada-case-exception-substring (cons word t))))
+             (unless (assoc-ignore-case word ada-case-exception)
+               (add-to-list 'ada-case-exception (cons word t)))))
+
           (forward-line 1))
         (kill-buffer nil)
-        (set-buffer buffer)
-       )))
+        (set-buffer buffer)))
+  )
+
+(defun ada-case-read-exceptions ()
+  "Read all the casing exception files from `ada-case-exception-file'."
+  (interactive)
+
+  ;;  Reinitialize the casing exception list
+  (setq ada-case-exception '()
+       ada-case-exception-substring '())
+
+  (cond ((stringp ada-case-exception-file)
+         (ada-case-read-exceptions-from-file ada-case-exception-file))
+
+        ((listp ada-case-exception-file)
+         (mapcar 'ada-case-read-exceptions-from-file
+                 ada-case-exception-file))))
+
+(defun ada-adjust-case-substring ()
+  "Adjust case of substrings in the previous word."
+  (interactive)
+  (let ((substrings            ada-case-exception-substring)
+       (max                   (point))
+       (case-fold-search      t)
+       (underscore-syntax     (char-syntax ?_))
+       re)
+
+    (save-excursion
+       (forward-word -1)
+
+       (unwind-protect
+         (progn
+           (modify-syntax-entry ?_ "." (syntax-table))
+
+           (while substrings
+             (setq re (concat "\\b" (regexp-quote (caar substrings)) "\\b"))
+
+             (save-excursion
+                (while (re-search-forward re max t)
+                  (replace-match (caar substrings) t)))
+             (setq substrings (cdr substrings))
+             )
+           )
+        (modify-syntax-entry ?_ (make-string 1 underscore-syntax) (syntax-table)))
+       )))
 
 (defun ada-adjust-case-identifier ()
   "Adjust case of the previous identifier.
 The auto-casing is done according to the value of `ada-case-identifier' and
 the exceptions defined in `ada-case-exception-file'."
+  (interactive)
   (if (or (equal ada-case-exception '())
           (equal (char-after) ?_))
-      (funcall ada-case-identifier -1)
+      (progn
+       (funcall ada-case-identifier -1)
+       (ada-adjust-case-substring))
 
     (progn
       (let ((end   (point))
             (start (save-excursion (skip-syntax-backward "w")
-                                  (point)))
+                                   (point)))
             match)
         ;;  If we have an exception, replace the word by the correct casing
-        (if (set 'match (assoc-ignore-case (buffer-substring start end)
+        (if (setmatch (assoc-ignore-case (buffer-substring start end)
                                            ada-case-exception))
 
             (progn
@@ -1182,124 +1626,147 @@ the exceptions defined in `ada-case-exception-file'."
               (insert (car match)))
 
           ;;  Else simply re-case the word
-          (funcall ada-case-identifier -1))))))
+          (funcall ada-case-identifier -1)
+         (ada-adjust-case-substring))))))
 
 (defun ada-after-keyword-p ()
-  "Returns t if cursor is after a keyword."
+  "Returns t if cursor is after a keyword that is not an attribute."
   (save-excursion
     (forward-word -1)
-    (and (not (and (char-before) (= (char-before) ?_)));; unless we have a _
+    (and (not (and (char-before)
+                   (or (= (char-before) ?_)
+                       (= (char-before) ?'))));; unless we have a _ or '
          (looking-at (concat ada-keywords "[^_]")))))
 
 (defun ada-adjust-case (&optional force-identifier)
   "Adjust the case of the word before the just typed character.
 If FORCE-IDENTIFIER is non-nil then also adjust keyword as identifier."
-  (let ((previous-syntax-table (syntax-table)))
-    (set-syntax-table ada-mode-symbol-syntax-table)
-
-    (forward-char -1)
-
-    ;;  Do nothing in some cases
-    (if (and (> (point) 1)
-
-            ;;  or if at the end of a character constant
-            (not (and (eq (char-after) ?')
-                      (eq (char-before (1- (point))) ?')))
-
-            ;;  or if the previous character was not part of a word
-            (eq (char-syntax (char-before)) ?w)
-
-            ;;  if in a string or a comment
-            (not (ada-in-string-or-comment-p))
-            )
-       
-       (if (save-excursion
-             (forward-word -1)
-             (or (= (point) (point-min))
-                 (backward-char 1))
-             (= (char-after) ?'))
-           (funcall ada-case-attribute -1)
-         (if (and
-              (not force-identifier) ; (MH)
-              (ada-after-keyword-p))
-             (funcall ada-case-keyword -1)
-           (ada-adjust-case-identifier))))
-    (forward-char 1)
-    (set-syntax-table previous-syntax-table)
-    )
+  (if (not (bobp))
+      (progn
+       (forward-char -1)
+       (if (and (not (bobp))
+                ;;  or if at the end of a character constant
+                (not (and (eq (following-char) ?')
+                          (eq (char-before (1- (point))) ?')))
+                ;;  or if the previous character was not part of a word
+                (eq (char-syntax (char-before)) ?w)
+                ;;  if in a string or a comment
+                (not (ada-in-string-or-comment-p))
+                )
+           (if (save-excursion
+                 (forward-word -1)
+                 (or (= (point) (point-min))
+                     (backward-char 1))
+                 (= (following-char) ?'))
+               (funcall ada-case-attribute -1)
+             (if (and
+                  (not force-identifier)     ; (MH)
+                  (ada-after-keyword-p))
+                 (funcall ada-case-keyword -1)
+               (ada-adjust-case-identifier))))
+       (forward-char 1)
+       ))
   )
 
 (defun ada-adjust-case-interactive (arg)
   "Adjust the case of the previous word, and process the character just typed.
 ARG is the prefix the user entered with \C-u."
   (interactive "P")
-  (let ((lastk last-command-char))
-    (cond ((or (eq lastk ?\n)
-               (eq lastk ?\r))
-           ;; horrible kludge
-           (insert " ")
-           (ada-adjust-case)
-           ;; horrible De-kludge
-           (delete-backward-char 1)
-           ;; some special keys and their bindings
-           (cond
-            ((eq lastk ?\n)
-             (funcall ada-lfd-binding))
-            ((eq lastk ?\r)
-             (funcall ada-ret-binding))))
-          ((eq lastk ?\C-i) (ada-tab))
-          ((self-insert-command (prefix-numeric-value arg))))
-    ;; if there is a keyword in front of the underscore
-    ;; then it should be part of an identifier (MH)
-    (if (eq lastk ?_)
-        (ada-adjust-case t)
-      (ada-adjust-case))))
 
+  (if ada-auto-case
+      (let ((lastk last-command-char)
+            (previous-syntax-table (syntax-table)))
+
+       (unwind-protect
+           (progn
+             (set-syntax-table ada-mode-symbol-syntax-table)
+             (cond ((or (eq lastk ?\n)
+                        (eq lastk ?\r))
+                    ;; horrible kludge
+                    (insert " ")
+                    (ada-adjust-case)
+                    ;; horrible dekludge
+                    (delete-backward-char 1)
+                    ;; some special keys and their bindings
+                    (cond
+                     ((eq lastk ?\n)
+                      (funcall ada-lfd-binding))
+                     ((eq lastk ?\r)
+                      (funcall ada-ret-binding))))
+                   ((eq lastk ?\C-i) (ada-tab))
+                   ;; Else just insert the character
+              ((self-insert-command (prefix-numeric-value arg))))
+             ;; if there is a keyword in front of the underscore
+             ;; then it should be part of an identifier (MH)
+             (if (eq lastk ?_)
+                 (ada-adjust-case t)
+               (ada-adjust-case))
+             )
+         ;; Restore the syntax table
+         (set-syntax-table previous-syntax-table))
+        )
+
+    ;; Else, no auto-casing
+    (cond
+     ((eq last-command-char ?\n)
+      (funcall ada-lfd-binding))
+     ((eq last-command-char ?\r)
+      (funcall ada-ret-binding))
+     (t
+      (self-insert-command (prefix-numeric-value arg))))
+    ))
 
 (defun ada-activate-keys-for-case ()
   "Modifies the key bindings for all the keys that should readjust the casing."
   (interactive)
-  ;; save original key bindings to allow swapping ret/lfd
-  ;; when casing is activated
-  ;; the 'or ...' is there to be sure that the value will not
-  ;; be changed again when Ada mode is called more than once (MH)
-  (or ada-ret-binding
-      (set 'ada-ret-binding (key-binding "\C-M")))
-  (or ada-lfd-binding
-      (set 'ada-lfd-binding (key-binding "\C-j")))
-  ;; call case modifying function after certain keys.
+  ;; Save original key-bindings to allow swapping ret/lfd
+  ;; when casing is activated.
+  ;; The 'or ...' is there to be sure that the value will not
+  ;; be changed again when Ada mode is called more than once
+  (or ada-ret-binding    (setq ada-ret-binding (key-binding "\C-M")))
+  (or ada-lfd-binding    (setq ada-lfd-binding (key-binding "\C-j")))
+
+  ;; Call case modifying function after certain keys.
   (mapcar (function (lambda(key) (define-key
                                    ada-mode-map
                                    (char-to-string key)
                                    'ada-adjust-case-interactive)))
-          '( ?` ?~ ?! ?_ ?@ ?# ?$ ?% ?^ ?& ?* ?( ?)  ?- ?= ?+ ?[ ?{ ?] ?}
-               ?\\ ?| ?\; ?: ?' ?\" ?< ?, ?. ?> ?? ?/ ?\n 32 ?\r )))
+          '( ?` ?_ ?# ?% ?& ?* ?( ?) ?- ?= ?+
+                ?| ?\; ?: ?' ?\" ?< ?, ?. ?> ?/ ?\n 32 ?\r )))
 
 (defun ada-loose-case-word (&optional arg)
   "Upcase first letter and letters following `_' in the following word.
 No other letter is modified.
 ARG is ignored, and is there for compatibility with `capitalize-word' only."
   (interactive)
-  (let ((pos (point))
-        (first t))
-    (skip-syntax-backward "w")
-    (while (or first
-               (search-forward "_" pos t))
-      (and first
-           (set 'first nil))
-      (insert-char (upcase (following-char)) 1)
-      (delete-char 1))
-    (goto-char pos)))
+  (save-excursion
+    (let ((end   (save-excursion (skip-syntax-forward  "w") (point)))
+          (first t))
+      (skip-syntax-backward "w")
+      (while (and (or first (search-forward "_" end t))
+                  (< (point) end))
+        (and first
+             (setq first nil))
+        (insert-char (upcase (following-char)) 1)
+        (delete-char 1)))))
+
+(defun ada-no-auto-case (&optional arg)
+  "Does nothing.
+This function can be used for the auto-casing variables in the ada-mode, to
+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."
+  )
 
 (defun ada-capitalize-word (&optional arg)
   "Upcase first letter and letters following '_', lower case other letters.
 ARG is ignored, and is there for compatibility with `capitalize-word' only."
   (interactive)
-  (let ((pos (point)))
-    (skip-syntax-backward "w")
+  (let ((end   (save-excursion (skip-syntax-forward  "w") (point)))
+        (begin (save-excursion (skip-syntax-backward "w") (point))))
     (modify-syntax-entry ?_ "_")
-    (capitalize-region (point) pos)
-    (goto-char pos)
+    (capitalize-region begin end)
     (modify-syntax-entry ?_ "w")))
 
 (defun ada-adjust-case-region (from to)
@@ -1320,12 +1787,12 @@ Attention: This function might take very long for big regions !"
           ;; loop: look for all identifiers, keywords, and attributes
           ;;
           (while (re-search-backward "\\<\\(\\sw+\\)\\>" from t)
-            (set 'end (match-end 1))
-            (set 'attribp
+            (setend (match-end 1))
+            (setattribp
                  (and (> (point) from)
                       (save-excursion
                         (forward-char -1)
-                        (set 'attribp (looking-at "'.[^']")))))
+                        (setattribp (looking-at "'.[^']")))))
             (or
              ;; do nothing if it is a string or comment
              (ada-in-string-or-comment-p)
@@ -1333,8 +1800,8 @@ Attention: This function might take very long for big regions !"
                ;;
                ;; get the identifier or keyword or attribute
                ;;
-               (set 'begin (point))
-               (set 'keywordp (looking-at ada-keywords))
+               (setbegin (point))
+               (setkeywordp (looking-at ada-keywords))
                (goto-char end)
                ;;
                ;; casing according to user-option
@@ -1365,7 +1832,8 @@ ATTENTION: This function might take very long for big buffers !"
 ;;       ... )
 ;;    This is done in `ada-scan-paramlist'.
 ;;  - Delete and recreate the parameter list in function
-;;    `ada-format-paramlist'.
+;;    `ada-insert-paramlist'.
+;; Both steps are called from `ada-format-paramlist'.
 ;; Note: Comments inside the parameter list are lost.
 ;;       The syntax has to be correct, or the reformating will fail.
 ;;--------------------------------------------------------------
@@ -1391,22 +1859,23 @@ ATTENTION: This function might take very long for big buffers !"
            (concat ada-subprog-start-re "\\|\\<body\\>" ) t nil)
           (down-list 1)
           (backward-char 1)
-          (set 'begin (point))
+          (setbegin (point))
 
           ;; find end of parameter-list
           (forward-sexp 1)
-          (set 'delend (point))
+          (setdelend (point))
           (delete-char -1)
+          (insert "\n")
 
           ;; find end of last parameter-declaration
           (forward-comment -1000)
-          (set 'end (point))
+          (setend (point))
 
           ;; build a list of all elements of the parameter-list
-          (set 'paramlist (ada-scan-paramlist (1+ begin) end))
+          (setparamlist (ada-scan-paramlist (1+ begin) end))
 
           ;; delete the original parameter-list
-          (delete-region begin (1- delend))
+          (delete-region begin  delend)
 
           ;; insert the new parameter-list
           (goto-char begin)
@@ -1434,26 +1903,26 @@ Returns the equivalent internal parameter list."
 
       ;; find first character of parameter-declaration
       (ada-goto-next-non-ws)
-      (set 'apos (point))
+      (setapos (point))
 
       ;; find last character of parameter-declaration
-      (if (set 'match-cons
+      (if (setmatch-cons
                (ada-search-ignore-string-comment "[ \t\n]*;" nil end t))
           (progn
-            (set 'epos (car match-cons))
-            (set 'semipos (cdr match-cons)))
-        (set 'epos end))
+            (setepos (car match-cons))
+            (setsemipos (cdr match-cons)))
+        (setepos end))
 
       ;; read name(s) of parameter(s)
       (goto-char apos)
       (looking-at "\\(\\(\\sw\\|[_, \t\n]\\)*\\(\\sw\\|_\\)\\)[ \t\n]*:[^=]")
 
-      (set 'param (list (match-string 1)))
+      (setparam (list (match-string 1)))
       (ada-search-ignore-string-comment ":" nil epos t 'search-forward)
 
       ;; look for 'in'
-      (set 'apos (point))
-      (set 'param
+      (setapos (point))
+      (setparam
            (append param
                    (list
                     (consp
@@ -1462,7 +1931,7 @@ Returns the equivalent internal parameter list."
 
       ;; look for 'out'
       (goto-char apos)
-      (set 'param
+      (setparam
            (append param
                    (list
                     (consp
@@ -1471,7 +1940,7 @@ Returns the equivalent internal parameter list."
 
       ;; look for 'access'
       (goto-char apos)
-      (set 'param
+      (setparam
            (append param
                    (list
                     (consp
@@ -1486,28 +1955,30 @@ Returns the equivalent internal parameter list."
         (ada-goto-next-non-ws))
 
       ;; read type of parameter
-      (looking-at "\\<\\(\\sw\\|[_.']\\)+\\>")
-      (set 'param
+      ;; We accept spaces in the name, since some software like Rose
+      ;; generates something like: "A : B 'Class"
+      (looking-at "\\<\\(\\sw\\|[_.' \t]\\)+\\>")
+      (setq param
            (append param
                    (list (match-string 0))))
 
       ;; read default-expression, if there is one
-      (goto-char (set 'apos (match-end 0)))
-      (set 'param
+      (goto-char (setapos (match-end 0)))
+      (setparam
            (append param
                    (list
-                    (if (set 'match-cons
+                    (if (setmatch-cons
                              (ada-search-ignore-string-comment
                               ":=" nil epos t 'search-forward))
                         (buffer-substring (car match-cons) epos)
                       nil))))
 
       ;; add this parameter-declaration to the list
-      (set 'paramlist (append paramlist (list param)))
+      (setparamlist (append paramlist (list param)))
 
       ;; check if it was the last parameter
       (if (eq epos end)
-          (set 'notend nil)
+          (setnotend nil)
         (goto-char semipos))
       )
     (reverse paramlist)))
@@ -1517,7 +1988,6 @@ Returns the equivalent internal parameter list."
   (let ((i (length paramlist))
         (parlen 0)
         (typlen 0)
-        (temp 0)
         (inp nil)
         (outp nil)
         (accessp nil)
@@ -1526,22 +1996,22 @@ Returns the equivalent internal parameter list."
 
     ;; loop until last parameter
     (while (not (zerop i))
-      (set 'i (1- i))
+      (seti (1- i))
 
       ;; get max length of parameter-name
-      (set 'parlen (max parlen (length (nth 0 (nth i paramlist)))))
+      (setparlen (max parlen (length (nth 0 (nth i paramlist)))))
 
       ;; get max length of type-name
-      (set 'typlen (max typlen (length (nth 4 (nth i paramlist)))))
+      (settyplen (max typlen (length (nth 4 (nth i paramlist)))))
 
       ;; is there any 'in' ?
-      (set 'inp (or inp (nth 1 (nth i paramlist))))
+      (setinp (or inp (nth 1 (nth i paramlist))))
 
       ;; is there any 'out' ?
-      (set 'outp (or outp (nth 2 (nth i paramlist))))
+      (setoutp (or outp (nth 2 (nth i paramlist))))
 
       ;; is there any 'access' ?
-      (set 'accessp (or accessp (nth 3 (nth i paramlist))))
+      (setaccessp (or accessp (nth 3 (nth i paramlist))))
       )
 
     ;; does paramlist already start on a separate line ?
@@ -1568,19 +2038,19 @@ Returns the equivalent internal parameter list."
     (insert "(")
     (ada-indent-current)
 
-    (set 'firstcol (current-column))
-    (set 'i (length paramlist))
+    (setfirstcol (current-column))
+    (seti (length paramlist))
 
     ;; loop until last parameter
     (while (not (zerop i))
-      (set 'i (1- i))
-      (set 'column firstcol)
+      (seti (1- i))
+      (setcolumn firstcol)
 
       ;; insert parameter-name, space and colon
       (insert (nth 0 (nth i paramlist)))
       (indent-to (+ column parlen 1))
       (insert ": ")
-      (set 'column (current-column))
+      (setcolumn (current-column))
 
       ;; insert 'in' or space
       (if (nth 1 (nth i paramlist))
@@ -1604,7 +2074,7 @@ Returns the equivalent internal parameter list."
       (if (nth 3 (nth i paramlist))
           (insert "access "))
 
-      (set 'column (current-column))
+      (setcolumn (current-column))
 
       ;; insert type-name and, if necessary, space and default-expression
       (insert (nth 4 (nth i paramlist)))
@@ -1628,174 +2098,64 @@ Returns the equivalent internal parameter list."
       (ada-indent-newline-indent))
     ))
 
-\f
-;;;----------------------------;;;
-;;; Move To Matching Start/End ;;;
-;;;----------------------------;;;
-(defun ada-move-to-start ()
-  "Moves point to the matching start of the current Ada structure."
-  (interactive)
-  (let ((pos (point))
-        (previous-syntax-table (syntax-table)))
-    (unwind-protect
-        (progn
-          (set-syntax-table ada-mode-symbol-syntax-table)
-
-          (message "searching for block start ...")
-          (save-excursion
-            ;;
-            ;; do nothing if in string or comment or not on 'end ...;'
-            ;;            or if an error occurs during processing
-            ;;
-            (or
-             (ada-in-string-or-comment-p)
-             (and (progn
-                    (or (looking-at "[ \t]*\\<end\\>")
-                        (backward-word 1))
-                    (or (looking-at "[ \t]*\\<end\\>")
-                        (backward-word 1))
-                    (or (looking-at "[ \t]*\\<end\\>")
-                        (error "not on end ...;")))
-                  (ada-goto-matching-start 1)
-                  (set 'pos (point))
 
-                  ;;
-                  ;; on 'begin' => go on, according to user option
-                  ;;
-                  ada-move-to-declaration
-                  (looking-at "\\<begin\\>")
-                  (ada-goto-matching-decl-start)
-                  (set 'pos (point))))
+\f
+;;;----------------------------------------------------------------
+;;  Indentation Engine
+;;  All indentations are indicated as a two-element string:
+;;     - position of reference in the buffer
+;;     - offset to indent from this position (can also be a symbol or a list
+;;       that are evaluated)
+;;  Thus the total indentation for a line is the column number of the reference
+;;  position plus whatever value the evaluation of the second element provides.
+;;  This mechanism is used so that the ada-mode can "explain" how the
+;;  indentation was calculated, by showing which variables were used.
+;;
+;;  The indentation itself is done in only one pass: first we try to guess in
+;;  what context we are by looking at the following keyword or punctuation
+;;  sign. If nothing remarkable is found, just try to guess the indentation
+;;  based on previous lines.
+;;
+;;  The relevant functions for indentation are:
+;;  - `ada-indent-region': Re-indent a region of text
+;;  - `ada-justified-indent-current': Re-indent the current line and shows the
+;;    calculation that were done
+;;  - `ada-indent-current': Re-indent the current line
+;;  - `ada-get-current-indent': Calculate the indentation for the current line,
+;;    based on the context (see above).
+;;  - `ada-get-indent-*': Calculate the indentation in a specific context.
+;;    For efficiency, these functions do not check they are in the correct
+;;    context.
+;;;----------------------------------------------------------------
 
-            )                           ; end of save-excursion
+(defun ada-indent-region (beg end)
+  "Indent the region between BEG end END."
+  (interactive "*r")
+  (goto-char beg)
+  (let ((block-done 0)
+        (lines-remaining (count-lines beg end))
+        (msg (format "%%4d out of %4d lines remaining ..."
+                     (count-lines beg end)))
+        (endmark (copy-marker end)))
+    ;; catch errors while indenting
+    (while (< (point) endmark)
+      (if (> block-done 39)
+          (progn
+           (setq lines-remaining (- lines-remaining block-done)
+                 block-done     0)
+           (message msg lines-remaining)))
+      (if (= (char-after) ?\n) nil
+        (ada-indent-current))
+      (forward-line 1)
+      (setq block-done      (1+ block-done)))
+    (message "indenting ... done")))
 
-          ;; now really move to the found position
-          (goto-char pos)
-          (message "searching for block start ... done"))
-
-      ;;
-      ;; restore syntax-table
-      ;;
-      (set-syntax-table previous-syntax-table))))
-
-(defun ada-move-to-end ()
-  "Moves point to the matching end of the current block around point.
-Moves to 'begin' if in a declarative part."
-  (interactive)
-  (let ((pos (point))
-        (previous-syntax-table (syntax-table)))
-    (unwind-protect
-        (progn
-          (set-syntax-table ada-mode-symbol-syntax-table)
-
-          (message "searching for block end ...")
-          (save-excursion
-
-            (forward-char 1)
-            (cond
-             ;; directly on 'begin'
-             ((save-excursion
-                (ada-goto-previous-word)
-                (looking-at "\\<begin\\>"))
-              (ada-goto-matching-end 1))
-             ;; on first line of defun declaration
-             ((save-excursion
-                (and (ada-goto-stmt-start)
-                     (looking-at "\\<function\\>\\|\\<procedure\\>" )))
-              (ada-search-ignore-string-comment "begin" nil nil nil
-                                               'word-search-forward))
-             ;; on first line of task declaration
-             ((save-excursion
-                (and (ada-goto-stmt-start)
-                     (looking-at "\\<task\\>" )
-                     (forward-word 1)
-                     (ada-goto-next-non-ws)
-                     (looking-at "\\<body\\>")))
-              (ada-search-ignore-string-comment "begin" nil nil nil
-                                               'word-search-forward))
-             ;; accept block start
-             ((save-excursion
-                (and (ada-goto-stmt-start)
-                     (looking-at "\\<accept\\>" )))
-              (ada-goto-matching-end 0))
-             ;; package start
-             ((save-excursion
-                (and (ada-goto-matching-decl-start t)
-                     (looking-at "\\<package\\>")))
-              (ada-goto-matching-end 1))
-             ;; inside a 'begin' ... 'end' block
-             ((save-excursion
-                (ada-goto-matching-decl-start t))
-              (ada-search-ignore-string-comment "begin" nil nil nil
-                                               'word-search-forward))
-             ;; (hopefully ;-) everything else
-             (t
-              (ada-goto-matching-end 1)))
-            (set 'pos (point))
-           )
-
-          ;; now really move to the found position
-          (goto-char pos)
-          (message "searching for block end ... done"))
-
-      ;; restore syntax-table
-      (set-syntax-table previous-syntax-table))))
-
-\f
-;;;----------------------------------------------------------------
-;;  Indentation Engine
-;;  All indentations are indicated as a two-element string:
-;;     - position of reference in the buffer
-;;     - offset to indent from this position (can also be a symbol or a list
-;;       that are evaluated)
-;;  Thus the total indentation for a line is the column number of the reference
-;;  position plus whatever value the evaluation of the second element provides.
-;;  This mechanism is used so that the ada-mode can "explain" how the
-;;  indentation was calculated, by showing which variables were used.
-;;
-;;  The indentation itself is done in only one pass: first we try to guess in
-;;  what context we are by looking at the following keyword or punctuation
-;;  sign. If nothing remarkable is found, just try to guess the indentation
-;;  based on previous lines.
-;;
-;;  The relevant functions for indentation are:
-;;  - `ada-indent-region': Re-indent a region of text
-;;  - `ada-justified-indent-current': Re-indent the current line and shows the
-;;    calculation that were done
-;;  - `ada-indent-current': Re-indent the current line
-;;  - `ada-get-current-indent': Calculate the indentation for the current line,
-;;    based on the context (see above).
-;;  - `ada-get-indent-*': Calculate the indentation in a specific context.
-;;    For efficiency, these functions do not check the correct context.
-;;;----------------------------------------------------------------
-
-(defun ada-indent-region (beg end)
-  "Indent the region between BEG and END."
-  (interactive "*r")
-  (goto-char beg)
-  (let ((block-done 0)
-        (lines-remaining (count-lines beg end))
-        (msg (format "indenting %4d lines %%4d lines remaining ..."
-                     (count-lines beg end)))
-        (endmark (copy-marker end)))
-    ;; catch errors while indenting
-    (while (< (point) endmark)
-      (if (> block-done 39)
-          (progn (message msg lines-remaining)
-                 (set 'block-done 0)))
-      (if (looking-at "^$") nil
-        (ada-indent-current))
-      (forward-line 1)
-      (set 'block-done (1+ block-done))
-      (set 'lines-remaining (1- lines-remaining)))
-    (message "indenting ... done")))
-
-(defun ada-indent-newline-indent ()
-  "Indents the current line, inserts a newline and then indents the new line."
-  (interactive "*")
-  (ada-indent-current)
-  (newline)
-  (ada-indent-current))
+(defun ada-indent-newline-indent ()
+  "Indents the current line, inserts a newline and then indents the new line."
+  (interactive "*")
+  (ada-indent-current)
+  (newline)
+  (ada-indent-current))
 
 (defun ada-indent-newline-indent-conditional ()
   "Insert a newline and indent it.
@@ -1812,357 +2172,543 @@ This function is intended to be bound to the \C-m and \C-j keys."
 
   (let ((cur-indent (ada-indent-current)))
 
-    (message nil)
-    (if (equal (cdr cur-indent) '(0))
-       (message "same indentation")
-      (message (mapconcat (lambda(x)
-                           (cond
-                            ((symbolp x)
-                             (symbol-name x))
-                            ((numberp x)
-                             (number-to-string x))
-                            ((listp x)
-                             (concat "- " (symbol-name (cadr x))))
-                            ))
-                         (cdr cur-indent)
-                         " + ")))
+    (let ((line (save-excursion
+                 (goto-char (car cur-indent))
+                 (count-lines 1 (point)))))
+
+      (if (equal (cdr cur-indent) '(0))
+         (message (concat "same indentation as line " (number-to-string line)))
+       (message (mapconcat (lambda(x)
+                             (cond
+                              ((symbolp x)
+                               (symbol-name x))
+                              ((numberp x)
+                               (number-to-string x))
+                              ((listp x)
+                               (concat "- " (symbol-name (cadr x))))
+                              ))
+                           (cdr cur-indent)
+                           " + "))))
     (save-excursion
       (goto-char (car cur-indent))
       (sit-for 1))))
 
+(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
+command like:
+  emacs -batch -l ada-mode -f ada-batch-reformat file1 file2 ..."
+
+  (while command-line-args-left
+    (let ((source (car command-line-args-left)))
+      (message (concat "formating " source))
+      (find-file source)
+      (ada-indent-region (point-min) (point-max))
+      (ada-adjust-case-buffer)
+      (write-file source))
+    (setq command-line-args-left (cdr command-line-args-left)))
+  (message "Done")
+  (kill-emacs 0))
+
+(defsubst ada-goto-previous-word ()
+  "Moves point to the beginning of the previous word of Ada code.
+Returns the new position of point or nil if not found."
+  (ada-goto-next-word t))
+
 (defun ada-indent-current ()
   "Indent current line as Ada code.
 Returns the calculation that was done, including the reference point and the
 offset."
   (interactive)
   (let ((previous-syntax-table (syntax-table))
-       (orgpoint (point-marker))
-       cur-indent tmp-indent
-       prev-indent)
-    
-    (set-syntax-table ada-mode-symbol-syntax-table)
-    
-    ;;  This need to be done here so that the advice is not always activated
-    ;;  (this might interact badly with other modes)
-    (if ada-xemacs
-        (ad-activate 'parse-partial-sexp t))
+        (orgpoint (point-marker))
+        cur-indent tmp-indent
+        prev-indent)
 
     (unwind-protect
         (progn
+          (set-syntax-table ada-mode-symbol-syntax-table)
 
-         (save-excursion
-           (set 'cur-indent
-                ;; Not First line in the buffer ?
-                
-                (if (save-excursion (zerop (forward-line -1)))
-                    (progn
-                      (back-to-indentation)
-                      (ada-get-current-indent))
-                  
-                  ;; first line in the buffer
-                  (list (point-min) 0))))
-           
-         ;; Evaluate the list to get the column to indent to
-         ;; prev-indent contains the column to indent to
-         (set 'prev-indent (save-excursion (goto-char (car cur-indent))
-                                           (current-column)))
-         (set 'tmp-indent (cdr cur-indent))
-         (while (not (null tmp-indent))
-           (cond
-            ((numberp (car tmp-indent))
-             (set 'prev-indent (+ prev-indent (car tmp-indent))))
-            (t
-             (set 'prev-indent (+ prev-indent (eval (car tmp-indent)))))
-            )
-           (set 'tmp-indent (cdr tmp-indent)))
-         
-         ;; only re-indent if indentation is different then the current
-         (if (= (save-excursion (back-to-indentation) (current-column)) prev-indent)
-             nil
-           (beginning-of-line)
-           (delete-horizontal-space)
-           (indent-to prev-indent))
-         ;;
-         ;; restore position of point
-         ;;
-         (goto-char orgpoint)
-         (if (< (current-column) (current-indentation))
-             (back-to-indentation))))
+          ;;  This need to be done here so that the advice is not always
+          ;;  activated (this might interact badly with other modes)
+          (if (featurep 'xemacs)
+              (ad-activate 'parse-partial-sexp t))
+
+          (save-excursion
+            (setq cur-indent
+
+                 ;; Not First line in the buffer ?
+                 (if (save-excursion (zerop (forward-line -1)))
+                     (progn
+                       (back-to-indentation)
+                       (ada-get-current-indent))
+
+                   ;; first line in the buffer
+                   (list (point-min) 0))))
+
+          ;; Evaluate the list to get the column to indent to
+          ;; prev-indent contains the column to indent to
+         (if cur-indent
+             (setq prev-indent (save-excursion (goto-char (car cur-indent))
+                                               (current-column))
+                   tmp-indent (cdr cur-indent))
+           (setq prev-indent 0  tmp-indent '()))
+
+          (while (not (null tmp-indent))
+            (cond
+             ((numberp (car tmp-indent))
+              (setq prev-indent (+ prev-indent (car tmp-indent))))
+             (t
+              (setq prev-indent (+ prev-indent (eval (car tmp-indent)))))
+             )
+            (setq tmp-indent (cdr tmp-indent)))
+
+          ;; only re-indent if indentation is different then the current
+          (if (= (save-excursion (back-to-indentation) (current-column)) prev-indent)
+              nil
+            (beginning-of-line)
+            (delete-horizontal-space)
+            (indent-to prev-indent))
+          ;;
+          ;; restore position of point
+          ;;
+          (goto-char orgpoint)
+          (if (< (current-column) (current-indentation))
+              (back-to-indentation)))
+
+      ;; restore syntax-table
+      (set-syntax-table previous-syntax-table)
+      (if (featurep 'xemacs)
+          (ad-deactivate 'parse-partial-sexp))
+      )
 
-    ;; restore syntax-table
-    (if ada-xemacs
-       (ad-deactivate 'parse-partial-sexp))
-    (set-syntax-table previous-syntax-table)
     cur-indent
     ))
 
 (defun ada-get-current-indent ()
-  "Returns the indentation to use for the current line."
+  "Return the indentation to use for the current line."
   (let (column
-       pos
-       match-cons
-       (orgpoint (save-excursion
-                   (beginning-of-line)
-                   (forward-comment -10000)
-                   (forward-line 1)
-                   (point))))
+        pos
+        match-cons
+       result
+        (orgpoint (save-excursion
+                    (beginning-of-line)
+                    (forward-comment -10000)
+                    (forward-line 1)
+                    (point))))
+
+    (setq result
     (cond
-     ;;
-     ;; preprocessor line (gnatprep)
-     ;;
-     ((and (equal ada-which-compiler 'gnat)
-           (looking-at "#[ \t]*\\(if\\|else\\|elsif\\|end[ \t]*if\\)"))
-      (list (save-excursion (beginning-of-line) (point)) 0))
 
-     ;;
+     ;;-----------------------------
      ;; in open parenthesis, but not in parameter-list
-     ;;
-     ((and
-       ada-indent-to-open-paren
-       (not (ada-in-paramlist-p))
-       (set 'column (ada-in-open-paren-p)))
+     ;;-----------------------------
+
+     ((and ada-indent-to-open-paren
+          (not (ada-in-paramlist-p))
+          (setq column (ada-in-open-paren-p)))
+
       ;; check if we have something like this  (Table_Component_Type =>
       ;;                                          Source_File_Record)
       (save-excursion
-        (if (and (skip-chars-backward " \t")
-                 (= (char-before) ?\n)
-                 (not (forward-comment -10000))
-                 (= (char-before) ?>))
-           (list column 'ada-broken-indent);; ??? Could use a different variable
-         (list column 0))))
 
-     ;;
-     ;; end
-     ;;
-     ((looking-at "\\<end\\>")
-      (let ((label 0))
-        (save-excursion
-          (ada-goto-matching-start 1)
+       ;;  Align the closing parenthesis on the opening one
+       (if (= (following-char) ?\))
+           (save-excursion
+             (goto-char column)
+             (skip-chars-backward " \t")
+             (list (1- (point)) 0))
+
+         (if (and (skip-chars-backward " \t")
+                  (= (char-before) ?\n)
+                  (not (forward-comment -10000))
+                  (= (char-before) ?>))
+             ;; ??? Could use a different variable
+             (list column 'ada-broken-indent)
+
+           ;;  We want all continuation lines to be indented the same
+           ;;  (ada-broken-line from the opening parenthesis. However, in
+           ;;  parameter list, each new parameter should be indented at the
+           ;;  column as the opening parenthesis.
+
+           ;;  A special case to handle nested boolean expressions, as in
+           ;;    ((B
+           ;;        and then C) --  indented by ada-broken-indent
+           ;;     or else D)     --  indenting this line.
+           ;;  ??? This is really a hack, we should have a proper way to go to
+           ;;  ??? the beginning of the statement
+
+           (if (= (char-before) ?\))
+               (backward-sexp))
+
+           (if (memq (char-before) '(?, ?\; ?\( ?\)))
+               (list column 0)
+             (list column 'ada-continuation-indent)
+             )))))
+
+     ;;---------------------------
+     ;;   at end of buffer
+     ;;---------------------------
+
+     ((not (char-after))
+      (ada-indent-on-previous-lines nil orgpoint orgpoint))
 
-          ;;
-          ;; found 'loop' => skip back to 'while' or 'for'
-          ;;                 if 'loop' is not on a separate line
-          ;;
-          (if (save-excursion
-                (beginning-of-line)
-                (looking-at ".+\\<loop\\>"))
-              (if (save-excursion
-                    (and
-                     (set 'match-cons
-                          (ada-search-ignore-string-comment ada-loop-start-re t))
-                     (not (looking-at "\\<loop\\>"))))
-                  (progn
-                    (goto-char (car match-cons))
-                    (save-excursion
-                      (beginning-of-line)
-                      (if (looking-at ada-named-block-re)
-                          (set 'label (- ada-label-indent)))))))
+     ;;---------------------------
+     ;;  starting with e
+     ;;---------------------------
 
-         (list (+ (save-excursion (back-to-indentation) (point)) label) 0))))
-     ;;
-     ;; exception
-     ;;
-     ((looking-at "\\<exception\\>")
-      (save-excursion
-        (ada-goto-matching-start 1)
-       (list (save-excursion (back-to-indentation) (point)) 0)))
-     ;;
-     ;; when
-     ;;
-     ((looking-at "\\<when\\>")
-      (save-excursion
-        (ada-goto-matching-start 1)
-       (list (save-excursion (back-to-indentation) (point)) 'ada-when-indent)))
-     ;;
-     ;; else
-     ;;
-     ((looking-at "\\<else\\>")
-      (if (save-excursion  (ada-goto-previous-word)
-                          (looking-at "\\<or\\>"))
-         (ada-indent-on-previous-lines nil orgpoint orgpoint)
-        (save-excursion
-          (ada-goto-matching-start 1 nil t)
-         (list (progn (back-to-indentation) (point)) 0))))
-     ;;
-     ;; elsif
-     ;;
-     ((looking-at "\\<elsif\\>")
+     ((= (downcase (char-after)) ?e)
+      (cond
+
+       ;; -------  end  ------
+
+       ((looking-at "end\\>")
+       (let ((label 0)
+             limit)
+         (save-excursion
+           (ada-goto-matching-start 1)
+
+           ;;
+           ;; found 'loop' => skip back to 'while' or 'for'
+           ;;                 if 'loop' is not on a separate line
+           ;; Stop the search for 'while' and 'for' when a ';' is encountered.
+           ;;
+           (if (save-excursion
+                 (beginning-of-line)
+                 (looking-at ".+\\<loop\\>"))
+               (progn
+                 (save-excursion
+                   (setq limit (car (ada-search-ignore-string-comment ";" t))))
+                 (if (save-excursion
+                       (and
+                        (setq match-cons
+                             (ada-search-ignore-string-comment ada-loop-start-re t limit))
+                        (not (looking-at "\\<loop\\>"))))
+                     (progn
+                       (goto-char (car match-cons))
+                       (save-excursion
+                         (beginning-of-line)
+                         (if (looking-at ada-named-block-re)
+                             (setq label (- ada-label-indent))))))))
+
+           ;; found 'record' =>
+           ;;  if the keyword is found at the beginning of a line (or just
+           ;;  after limited, we indent on it, otherwise we indent on the
+           ;;  beginning of the type declaration)
+           ;;      type A is (B : Integer;
+           ;;                 C : Integer) is record
+           ;;          end record;   --  This is badly indented otherwise
+           (if (looking-at "record")
+               (if (save-excursion
+                     (beginning-of-line)
+                     (looking-at "^[ \t]*\\(record\\|limited record\\)"))
+                   (list (save-excursion (back-to-indentation) (point)) 0)
+                 (list (save-excursion
+                         (car (ada-search-ignore-string-comment "\\<type\\>" t)))
+                       0))
+
+             ;;  Else keep the same indentation as the beginning statement
+             (list (+ (save-excursion (back-to-indentation) (point)) label) 0)))))
+
+       ;; ------  exception  ----
+
+       ((looking-at "exception\\>")
+       (save-excursion
+         (ada-goto-matching-start 1)
+         (list (save-excursion (back-to-indentation) (point)) 0)))
+
+       ;; else
+
+       ((looking-at "else\\>")
+       (if (save-excursion  (ada-goto-previous-word)
+                            (looking-at "\\<or\\>"))
+           (ada-indent-on-previous-lines nil orgpoint orgpoint)
+         (save-excursion
+           (ada-goto-matching-start 1 nil t)
+           (list (progn (back-to-indentation) (point)) 0))))
+
+       ;; elsif
+
+       ((looking-at "elsif\\>")
+       (save-excursion
+         (ada-goto-matching-start 1 nil t)
+         (list (progn (back-to-indentation) (point)) 0)))
+
+       ))
+
+     ;;---------------------------
+     ;;  starting with w (when)
+     ;;---------------------------
+
+     ((and (= (downcase (char-after)) ?w)
+          (looking-at "when\\>"))
       (save-excursion
-        (ada-goto-matching-start 1 nil t)
-       (list (progn (back-to-indentation) (point)) 0)))
-     ;;
-     ;; then
-     ;;
-     ((looking-at "\\<then\\>")
+       (ada-goto-matching-start 1)
+       (list (save-excursion (back-to-indentation) (point))
+             'ada-when-indent)))
+
+     ;;---------------------------
+     ;;   starting with t (then)
+     ;;---------------------------
+
+     ((and (= (downcase (char-after)) ?t)
+          (looking-at "then\\>"))
       (if (save-excursion (ada-goto-previous-word)
-                         (looking-at "\\<and\\>"))
+                         (looking-at "and\\>"))
          (ada-indent-on-previous-lines nil orgpoint orgpoint)
-        (save-excursion
-          ;;  Select has been added for the statement:  "select ... then abort"
-          (ada-search-ignore-string-comment "\\<\\(elsif\\|if\\|select\\)\\>" t nil)
-         (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent))))
-     ;;
-     ;; loop
-     ;;
-     ((looking-at "\\<loop\\>")
-      (set 'pos (point))
+       (save-excursion
+         ;;  Select has been added for the statement: "select ... then abort"
+         (ada-search-ignore-string-comment
+          "\\<\\(elsif\\|if\\|select\\)\\>" t nil)
+         (list (progn (back-to-indentation) (point))
+               'ada-stmt-end-indent))))
+
+     ;;---------------------------
+     ;;   starting with l (loop)
+     ;;---------------------------
+
+     ((and (= (downcase (char-after)) ?l)
+          (looking-at "loop\\>"))
+      (setq pos (point))
       (save-excursion
         (goto-char (match-end 0))
         (ada-goto-stmt-start)
         (if (looking-at "\\<\\(loop\\|if\\)\\>")
-           (ada-indent-on-previous-lines nil orgpoint orgpoint)
-         (unless (looking-at ada-loop-start-re)
-           (ada-search-ignore-string-comment ada-loop-start-re
-                                             nil pos))
-         (if (looking-at "\\<loop\\>")
-             (ada-indent-on-previous-lines nil orgpoint orgpoint)
-           (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent)))))
-     ;;
-     ;; begin
-     ;;
-     ((looking-at "\\<begin\\>")
+            (ada-indent-on-previous-lines nil orgpoint orgpoint)
+          (unless (looking-at ada-loop-start-re)
+            (ada-search-ignore-string-comment ada-loop-start-re
+                                              nil pos))
+          (if (looking-at "\\<loop\\>")
+              (ada-indent-on-previous-lines nil orgpoint orgpoint)
+            (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent)))))
+
+     ;;----------------------------
+     ;;    starting with l (limited) or r (record)
+     ;;----------------------------
+
+     ((or (and (= (downcase (char-after)) ?l)
+              (looking-at "limited\\>"))
+         (and (= (downcase (char-after)) ?r)
+              (looking-at "record\\>")))
+
+      (save-excursion
+       (ada-search-ignore-string-comment
+        "\\<\\(type\\|use\\)\\>" t nil)
+       (if (looking-at "\\<use\\>")
+           (ada-search-ignore-string-comment "for" t nil nil
+                                             'word-search-backward))
+       (list (progn (back-to-indentation) (point))
+             'ada-indent-record-rel-type)))
+
+     ;;---------------------------
+     ;;   starting with b (begin)
+     ;;---------------------------
+
+     ((and (= (downcase (char-after)) ?b)
+          (looking-at "begin\\>"))
       (save-excursion
         (if (ada-goto-matching-decl-start t)
-           (list (progn (back-to-indentation) (point)) 0)
-         (ada-indent-on-previous-lines nil orgpoint orgpoint))))
-     ;;
-     ;; is
-     ;;
-     ((looking-at "\\<is\\>")
+            (list (progn (back-to-indentation) (point)) 0)
+          (ada-indent-on-previous-lines nil orgpoint orgpoint))))
+
+     ;;---------------------------
+     ;;   starting with i (is)
+     ;;---------------------------
+
+     ((and (= (downcase (char-after)) ?i)
+          (looking-at "is\\>"))
+
       (if (and ada-indent-is-separate
-              (save-excursion
-                (goto-char (match-end 0))
-                (ada-goto-next-non-ws (save-excursion (end-of-line)
-                                                      (point)))
-                (looking-at "\\<abstract\\>\\|\\<separate\\>")))
+               (save-excursion
+                 (goto-char (match-end 0))
+                 (ada-goto-next-non-ws (save-excursion (end-of-line)
+                                                       (point)))
+                 (looking-at "\\<abstract\\>\\|\\<separate\\>")))
           (save-excursion
             (ada-goto-stmt-start)
-           (list (progn (back-to-indentation) (point)) 'ada-indent))
+            (list (progn (back-to-indentation) (point)) 'ada-indent))
         (save-excursion
           (ada-goto-stmt-start)
-         (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent))))
-     ;;
-     ;; record
-     ;;
-     ((looking-at "\\<record\\>")
+         (if (looking-at "\\<package\\|procedure\\|function\\>")
+             (list (progn (back-to-indentation) (point)) 0)
+           (list (progn (back-to-indentation) (point)) 'ada-indent)))))
+
+     ;;---------------------------
+     ;;  starting with r (return, renames)
+     ;;---------------------------
+
+     ((and (= (downcase (char-after)) ?r)
+          (looking-at "re\\(turn\\|names\\)\\>"))
+
       (save-excursion
-        (ada-search-ignore-string-comment
-         "\\<\\(type\\|use\\)\\>" t nil)
-        (if (looking-at "\\<use\\>")
-            (ada-search-ignore-string-comment "for" t nil nil 'word-search-backward))
-       (list (progn (back-to-indentation) (point)) 'ada-indent-record-rel-type)))
-     ;;
-     ;; 'or'      as statement-start
-     ;; 'private' as statement-start
-     ;;
-     ((or (ada-looking-at-semi-or)
-         (ada-looking-at-semi-private))
+       (let ((var 'ada-indent-return))
+         ;;  If looking at a renames, skip the 'return' statement too
+         (if (looking-at "renames")
+             (let (pos)
+               (save-excursion
+                 (set 'pos (ada-search-ignore-string-comment ";\\|return\\>" t)))
+               (if (and pos
+                        (= (downcase (char-after (car pos))) ?r))
+                   (goto-char (car pos)))
+               (set 'var 'ada-indent-renames)))
+
+         (forward-comment -1000)
+         (if (= (char-before) ?\))
+             (forward-sexp -1)
+           (forward-word -1))
+
+         ;; If there is a parameter list, and we have a function declaration
+         ;; or a access to subprogram declaration
+         (let ((num-back 1))
+           (if (and (= (following-char) ?\()
+                    (save-excursion
+                      (or (progn
+                            (backward-word 1)
+                            (looking-at "\\(function\\|procedure\\)\\>"))
+                          (progn
+                            (backward-word 1)
+                            (set 'num-back 2)
+                            (looking-at "\\(function\\|procedure\\)\\>")))))
+
+               ;; The indentation depends of the value of ada-indent-return
+               (if (<= (eval var) 0)
+                   (list (point) (list '- var))
+                 (list (progn (backward-word num-back) (point))
+                       var))
+
+             ;; Else there is no parameter list, but we have a function
+             ;; Only do something special if the user want to indent
+             ;; relative to the "function" keyword
+             (if (and (> (eval var) 0)
+                      (save-excursion (forward-word -1)
+                                      (looking-at "function\\>")))
+                 (list (progn (forward-word -1) (point)) var)
+
+               ;; Else...
+               (ada-indent-on-previous-lines nil orgpoint orgpoint)))))))
+
+     ;;--------------------------------
+     ;;   starting with 'o' or 'p'
+     ;;   'or'      as statement-start
+     ;;   'private' as statement-start
+     ;;--------------------------------
+
+     ((and (or (= (downcase (char-after)) ?o)
+              (= (downcase (char-after)) ?p))
+          (or (ada-looking-at-semi-or)
+              (ada-looking-at-semi-private)))
       (save-excursion
-        (ada-goto-matching-start 1)
+       ;;  ??? Wasn't this done already in ada-looking-at-semi-or ?
+       (ada-goto-matching-start 1)
        (list (progn (back-to-indentation) (point)) 0)))
-     ;;
-     ;; new/abstract/separate
-     ;;
-     ((looking-at "\\<\\(new\\|abstract\\|separate\\)\\>")
-      (ada-indent-on-previous-lines nil orgpoint orgpoint))
-     ;;
-     ;; return
-     ;;
-     ((looking-at "\\<return\\>")
-      (save-excursion
-       (forward-comment -1000)
-       (if (= (char-before) ?\))
-           (forward-sexp -1)
-         (forward-word -1))
 
-       ;; If there is a parameter list, and we have a function declaration
-        (if (and (= (char-after) ?\()
-                 (save-excursion
-                   (backward-sexp 2)
-                   (looking-at "\\<function\\>")))
-
-           ;; The indentation depends of the value of ada-indent-return
-           (if (<= ada-indent-return 0)
-               (list (point) (- ada-indent-return))
-             (list (progn (backward-sexp 2) (point)) ada-indent-return))
-
-         ;; Else there is no parameter list, but we have a function
-         ;; Only do something special if the user want to indent relative
-         ;; to the "function" keyword
-         (if (and (> ada-indent-return 0)
-                  (save-excursion (forward-word -1)
-                                  (looking-at "\\<function\\>")))
-             (list (progn (forward-word -1) (point)) ada-indent-return)
-
-           ;; Else...
-           (ada-indent-on-previous-lines nil orgpoint orgpoint)))))
-     ;;
-     ;; do
-     ;;
-     ((looking-at "\\<do\\>")
+     ;;--------------------------------
+     ;;   starting with 'd'  (do)
+     ;;--------------------------------
+
+     ((and (= (downcase (char-after)) ?d)
+          (looking-at "do\\>"))
       (save-excursion
         (ada-goto-stmt-start)
-       (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent)))
-     ;;
+        (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent)))
+
+     ;;--------------------------------
+     ;;   starting with '-'  (comment)
+     ;;--------------------------------
+
+     ((= (char-after) ?-)
+      (if ada-indent-comment-as-code
+
+         ;;  Indent comments on previous line comments if required
+         ;;  We must use a search-forward (even if the code is more complex),
+         ;;  since we want to find the beginning of the comment.
+         (let (pos)
+
+           (if (and ada-indent-align-comments
+                    (save-excursion
+                      (forward-line -1)
+                      (beginning-of-line)
+                      (while (and (not pos)
+                                  (search-forward "--"
+                                                   (save-excursion
+                                                     (end-of-line) (point))
+                                                   t))
+                        (unless (ada-in-string-p)
+                          (setq pos (point))))
+                      pos))
+               (list (- pos 2) 0)
+
+           ;;  Else always on previous line
+           (ada-indent-on-previous-lines nil orgpoint orgpoint)))
+
+       ;; Else same indentation as the previous line
+        (list (save-excursion (back-to-indentation) (point)) 0)))
+
+     ;;--------------------------------
+     ;;   starting with '#'  (preprocessor line)
+     ;;--------------------------------
+
+     ((and (= (char-after) ?#)
+          (equal ada-which-compiler 'gnat)
+           (looking-at "#[ \t]*\\(if\\|els\\(e\\|if\\)\\|end[ \t]*if\\)"))
+      (list (save-excursion (beginning-of-line) (point)) 0))
+
+     ;;--------------------------------
+     ;;   starting with ')' (end of a parameter list)
+     ;;--------------------------------
+
+     ((and (not (eobp)) (= (char-after) ?\)))
+      (save-excursion
+        (forward-char 1)
+        (backward-sexp 1)
+        (list (point) 0)))
+
+     ;;---------------------------------
+     ;; new/abstract/separate
+     ;;---------------------------------
+
+     ((looking-at "\\(new\\|abstract\\|separate\\)\\>")
+      (ada-indent-on-previous-lines nil orgpoint orgpoint))
+
+     ;;---------------------------------
      ;; package/function/procedure
-     ;;
-     ((and (looking-at "\\<\\(package\\|function\\|procedure\\)\\>")
-           (save-excursion
-             (forward-char 1)
-             (ada-goto-stmt-start)
-             (looking-at "\\<\\(package\\|function\\|procedure\\)\\>")))
+     ;;---------------------------------
+
+     ((and (or (= (downcase (char-after)) ?p) (= (downcase (char-after)) ?f))
+          (looking-at "\\<\\(package\\|function\\|procedure\\)\\>"))
       (save-excursion
-        ;; look for 'generic'
-        (if (and (ada-goto-matching-decl-start t)
-                 (looking-at "generic"))
+       ;;  Go up until we find either a generic section, or the end of the
+       ;;  previous subprogram/package
+       (let (found)
+         (while (and (not found)
+                     (ada-search-ignore-string-comment
+            "\\<\\(generic\\|end\\|begin\\|package\\|procedure\\|function\\)\\>" t))
+
+           ;;  avoid "with procedure"... in generic parts
+           (save-excursion
+             (forward-word -1)
+             (setq found (not (looking-at "with"))))))
+
+       (if (looking-at "generic")
            (list (progn (back-to-indentation) (point)) 0)
          (ada-indent-on-previous-lines nil orgpoint orgpoint))))
-     ;;
+
+     ;;---------------------------------
      ;; label
-     ;;
-     ((looking-at "\\<\\(\\sw\\|_\\)+[ \t\n]*:[^=]")
+     ;;---------------------------------
+
+     ((looking-at "\\(\\sw\\|_\\)+[ \t\n]*:[^=]")
       (if (ada-in-decl-p)
-         (ada-indent-on-previous-lines nil orgpoint orgpoint)
-       (set 'pos (ada-indent-on-previous-lines nil orgpoint orgpoint))
-       (list (car pos)
-             (cadr pos)
-             'ada-label-indent)))
-     ;;
-     ;; identifier and other noindent-statements
-     ;;
-     ((looking-at "\\<\\(\\sw\\|_\\)+[ \t\n]*")
-      (ada-indent-on-previous-lines nil orgpoint orgpoint))
-     ;;
-     ;; beginning of a parameter list
-     ;;
-     ((and (not (eobp)) (= (char-after) ?\())
-      (ada-indent-on-previous-lines nil orgpoint orgpoint))
-     ;;
-     ;; end of a parameter list
-     ;;
-     ((and (not (eobp)) (= (char-after) ?\)))
-      (save-excursion
-        (forward-char 1)
-        (backward-sexp 1)
-       (list (point) 0)))
-     ;;
-     ;; comment
-     ;;
-     ((looking-at "--")
-      (if ada-indent-comment-as-code
-         ;; If previous line is a comment, indent likewise
-         (save-excursion
-           (forward-line -1)
-           (beginning-of-line)
-           (if (looking-at "[ \t]*--")
-               (list (progn (back-to-indentation) (point)) 0)
-             (ada-indent-on-previous-lines nil orgpoint orgpoint)))
-       (list (save-excursion (back-to-indentation) (point)) 0)))
-     ;;
-     ;; unknown syntax
-     ;;
-     (t
-      (ada-indent-on-previous-lines nil orgpoint orgpoint)))))
+          (ada-indent-on-previous-lines nil orgpoint orgpoint)
+        (append (ada-indent-on-previous-lines nil orgpoint orgpoint)
+                '(ada-label-indent))))
+
+     ))
+
+    ;;---------------------------------
+    ;; Other syntaxes
+    ;;---------------------------------
+    (or        result (ada-indent-on-previous-lines nil orgpoint orgpoint))))
 
 (defun ada-indent-on-previous-lines (&optional nomove orgpoint initial-pos)
   "Calculate the indentation for the new line after ORGPOINT.
@@ -2171,69 +2717,79 @@ If NOMOVE is nil, moves point to the beginning of the current statement.
 if INITIAL-POS is non-nil, moves point to INITIAL-POS before calculation."
   (if initial-pos
       (goto-char initial-pos))
-  (let ((oldpoint (point))
-        result)
-    ;;
+  (let ((oldpoint (point)))
+
     ;; Is inside a parameter-list ?
-    ;;
     (if (ada-in-paramlist-p)
-        (set 'result (ada-get-indent-paramlist))
+        (ada-get-indent-paramlist)
 
-      ;;
       ;; move to beginning of current statement
-      ;;
       (unless nomove
         (ada-goto-stmt-start))
 
-      (unless result
-        (progn
-          ;;
-          ;; no beginning found => don't change indentation
-          ;;
-          (if (and (eq oldpoint (point))
-                   (not nomove))
-              (set 'result (ada-get-indent-nochange))
+      ;; no beginning found => don't change indentation
+      (if (and (eq oldpoint (point))
+               (not nomove))
+          (ada-get-indent-nochange)
 
-            (cond
-             ;;
-             ((and
-               ada-indent-to-open-paren
-               (ada-in-open-paren-p))
-              (set 'result (ada-get-indent-open-paren)))
-             ;;
-             ((looking-at "end\\>")
-              (set 'result (ada-get-indent-end orgpoint)))
-             ;;
-             ((looking-at ada-loop-start-re)
-              (set 'result (ada-get-indent-loop orgpoint)))
-             ;;
-             ((looking-at ada-subprog-start-re)
-              (set 'result (ada-get-indent-subprog orgpoint)))
-             ;;
-             ((looking-at ada-block-start-re)
-              (set 'result (ada-get-indent-block-start orgpoint)))
-             ;;
-             ((looking-at "\\(sub\\)?type\\>")
-              (set 'result (ada-get-indent-type orgpoint)))
-            ;;
-             ((looking-at "\\(els\\)?if\\>")
-              (set 'result (ada-get-indent-if orgpoint)))
-             ;;
-             ((looking-at "case\\>")
-              (set 'result (ada-get-indent-case orgpoint)))
-             ;;
-             ((looking-at "when\\>")
-              (set 'result (ada-get-indent-when orgpoint)))
-             ;;
-             ((looking-at "\\(\\sw\\|_\\)+[ \t\n]*:[^=]")
-              (set 'result (ada-get-indent-label orgpoint)))
-             ;;
-             ((looking-at "separate\\>")
-              (set 'result (ada-get-indent-nochange)))
-             (t
-              (set 'result (ada-get-indent-noindent orgpoint))))))))
-
-    result))
+        (cond
+         ;;
+         ((and
+           ada-indent-to-open-paren
+           (ada-in-open-paren-p))
+          (ada-get-indent-open-paren))
+         ;;
+         ((looking-at "end\\>")
+          (ada-get-indent-end orgpoint))
+         ;;
+         ((looking-at ada-loop-start-re)
+          (ada-get-indent-loop orgpoint))
+         ;;
+         ((looking-at ada-subprog-start-re)
+          (ada-get-indent-subprog orgpoint))
+         ;;
+         ((looking-at ada-block-start-re)
+          (ada-get-indent-block-start orgpoint))
+         ;;
+         ((looking-at "\\(sub\\)?type\\>")
+          (ada-get-indent-type orgpoint))
+         ;;
+         ;; "then" has to be included in the case of "select...then abort"
+         ;; statements, since (goto-stmt-start) at the beginning of
+         ;; the current function would leave the cursor on that position
+         ((looking-at "\\(\\(els\\)?if\\>\\)\\|then abort\\\>")
+          (ada-get-indent-if orgpoint))
+         ;;
+         ((looking-at "case\\>")
+          (ada-get-indent-case orgpoint))
+         ;;
+         ((looking-at "when\\>")
+          (ada-get-indent-when orgpoint))
+         ;;
+         ((looking-at "\\(\\sw\\|_\\)+[ \t\n]*:[^=]")
+          (ada-get-indent-label orgpoint))
+         ;;
+         ((looking-at "separate\\>")
+          (ada-get-indent-nochange))
+
+        ;; A label
+        ((looking-at "<<")
+          (list (+ (save-excursion (back-to-indentation) (point))
+                  (- ada-label-indent))))
+
+        ;;
+        ((looking-at "with\\>\\|use\\>")
+         ;;  Are we still in that statement, or are we in fact looking at
+         ;;  the previous one ?
+         (if (save-excursion (search-forward ";" oldpoint t))
+             (list (progn (back-to-indentation) (point)) 0)
+           (list (point) (if (looking-at "with")
+                             'ada-with-indent
+                           'ada-use-indent))))
+        ;;
+         (t
+          (ada-get-indent-noindent orgpoint)))))
+    ))
 
 (defun ada-get-indent-open-paren ()
   "Calculates the indentation when point is behind an unclosed parenthesis."
@@ -2262,78 +2818,83 @@ if INITIAL-POS is non-nil, moves point to INITIAL-POS before calculation."
       (ada-goto-next-non-ws)
       (list (point) 0))
 
+     ;;  After an affectation (default parameter value in subprogram
+     ;;  declaration)
+     ((and (= (following-char) ?=) (= (preceding-char) ?:))
+      (back-to-indentation)
+      (list (point) 'ada-broken-indent))
+
      ;; inside a parameter declaration
      (t
       (goto-char (cdr (ada-search-ignore-string-comment "(\\|;" t nil t)))
       (ada-goto-next-non-ws)
-      (list (point) 'ada-broken-indent)))))
+      (list (point) 0)))))
 
 (defun ada-get-indent-end (orgpoint)
   "Calculates the indentation when point is just before an end_statement.
 ORGPOINT is the limit position used in the calculation."
   (let ((defun-name nil)
-        (label 0)
         (indent nil))
-    ;;
+
     ;; is the line already terminated by ';' ?
-    ;;
     (if (save-excursion
           (ada-search-ignore-string-comment ";" nil orgpoint nil
-                                           'search-forward))
-        ;;
+                                            'search-forward))
+
         ;; yes, look what's following 'end'
-        ;;
         (progn
           (forward-word 1)
           (ada-goto-next-non-ws)
           (cond
-          ((looking-at "\\<\\(loop\\|select\\|if\\|case\\)\\>")
-           (save-excursion (ada-check-matching-start (match-string 0)))
-           (list (save-excursion (back-to-indentation) (point)) 0))
-           
+           ((looking-at "\\<\\(loop\\|select\\|if\\|case\\)\\>")
+            (save-excursion (ada-check-matching-start (match-string 0)))
+            (list (save-excursion (back-to-indentation) (point)) 0))
+
            ;;
            ;; loop/select/if/case/record/select
            ;;
            ((looking-at "\\<record\\>")
             (save-excursion
               (ada-check-matching-start (match-string 0))
-             ;;  we are now looking at the matching "record" statement
-             (forward-word 1)
-             (ada-goto-stmt-start)
-             ;;  now on the matching type declaration, or use clause
-             (unless (looking-at "\\(for\\|type\\)\\>")
-               (ada-search-ignore-string-comment "\\<type\\>" t))
-             (list (progn (back-to-indentation) (point)) 0)))
+              ;;  we are now looking at the matching "record" statement
+              (forward-word 1)
+              (ada-goto-stmt-start)
+              ;;  now on the matching type declaration, or use clause
+              (unless (looking-at "\\(for\\|type\\)\\>")
+                (ada-search-ignore-string-comment "\\<type\\>" t))
+              (list (progn (back-to-indentation) (point)) 0)))
            ;;
            ;; a named block end
            ;;
            ((looking-at ada-ident-re)
-           (set 'defun-name (match-string 0))
-           (save-excursion
-             (ada-goto-matching-start 0)
-             (ada-check-defun-name defun-name))
-           (list (progn (back-to-indentation) (point)) 0))
+            (setq defun-name (match-string 0))
+            (save-excursion
+              (ada-goto-matching-start 0)
+              (ada-check-defun-name defun-name))
+            (list (progn (back-to-indentation) (point)) 0))
            ;;
            ;; a block-end without name
            ;;
            ((= (char-after) ?\;)
-           (save-excursion
-             (ada-goto-matching-start 0)
-             (if (looking-at "\\<begin\\>")
-                 (progn
-                   (set 'indent (list (point) 0))
-                   (if (ada-goto-matching-decl-start t)
-                       (list (progn (back-to-indentation) (point)) 0)
-                     indent)))))
+            (save-excursion
+              (ada-goto-matching-start 0)
+              (if (looking-at "\\<begin\\>")
+                  (progn
+                    (setq indent (list (point) 0))
+                    (if (ada-goto-matching-decl-start t)
+                        (list (progn (back-to-indentation) (point)) 0)
+                      indent))
+               (list (progn (back-to-indentation) (point)) 0)
+               )))
            ;;
            ;; anything else - should maybe signal an error ?
            ;;
            (t
-           (list (save-excursion (back-to-indentation) (point))
-                 'ada-broken-indent))))
+            (list (save-excursion (back-to-indentation) (point))
+                  'ada-broken-indent))))
 
       (list (save-excursion (back-to-indentation) (point))
-           'ada-broken-indent))))
+            'ada-broken-indent))))
 
 (defun ada-get-indent-case (orgpoint)
   "Calculates the indentation when point is just before a case statement.
@@ -2345,7 +2906,7 @@ ORGPOINT is the limit position used in the calculation."
      ;; case..is..when..=>
      ;;
      ((save-excursion
-        (set 'match-cons (and
+        (setmatch-cons (and
                           ;; the `=>' must be after the keyword `is'.
                           (ada-search-ignore-string-comment
                            "is" nil orgpoint nil 'word-search-forward)
@@ -2355,12 +2916,12 @@ ORGPOINT is the limit position used in the calculation."
         (goto-char (car match-cons))
         (unless (ada-search-ignore-string-comment "when" t opos)
           (error "missing 'when' between 'case' and '=>'"))
-       (list (save-excursion (back-to-indentation) (point)) 'ada-indent)))
+        (list (save-excursion (back-to-indentation) (point)) 'ada-indent)))
      ;;
      ;; case..is..when
      ;;
      ((save-excursion
-        (set 'match-cons (ada-search-ignore-string-comment
+        (setmatch-cons (ada-search-ignore-string-comment
                           "when" nil orgpoint nil 'word-search-forward)))
       (goto-char (cdr match-cons))
       (list (save-excursion (back-to-indentation) (point)) 'ada-broken-indent))
@@ -2368,7 +2929,7 @@ ORGPOINT is the limit position used in the calculation."
      ;; case..is
      ;;
      ((save-excursion
-        (set 'match-cons (ada-search-ignore-string-comment
+        (setmatch-cons (ada-search-ignore-string-comment
                           "is" nil orgpoint nil 'word-search-forward)))
       (list (save-excursion (back-to-indentation) (point)) 'ada-when-indent))
      ;;
@@ -2376,14 +2937,14 @@ ORGPOINT is the limit position used in the calculation."
      ;;
      (t
       (list (save-excursion (back-to-indentation) (point))
-           'ada-broken-indent)))))
+            'ada-broken-indent)))))
 
 (defun ada-get-indent-when (orgpoint)
-  "Calcules the indentation when point is just before a when statement.
+  "Calculates the indentation when point is just before a when statement.
 ORGPOINT is the limit position used in the calculation."
   (let ((cur-indent (save-excursion (back-to-indentation) (point))))
     (if (ada-search-ignore-string-comment "[ \t\n]*=>" nil orgpoint)
-       (list cur-indent 'ada-indent)
+        (list cur-indent 'ada-indent)
       (list cur-indent 'ada-broken-indent))))
 
 (defun ada-get-indent-if (orgpoint)
@@ -2394,25 +2955,25 @@ ORGPOINT is the limit position used in the calculation."
     ;;
     ;; Move to the correct then (ignore all "and then")
     ;;
-    (while (and (set 'match-cons (ada-search-ignore-string-comment
+    (while (and (setmatch-cons (ada-search-ignore-string-comment
                                   "\\<\\(then\\|and[ \t]*then\\)\\>"
                                   nil orgpoint))
-                (= (char-after (car match-cons)) ?a)))
+                (= (downcase (char-after (car match-cons))) ?a)))
     ;; If "then" was found (we are looking at it)
     (if match-cons
         (progn
           ;;
           ;; 'then' first in separate line ?
           ;; => indent according to 'then',
-         ;; => else indent according to 'if'
+          ;; => else indent according to 'if'
           ;;
           (if (save-excursion
                 (back-to-indentation)
                 (looking-at "\\<then\\>"))
-              (set 'cur-indent (save-excursion (back-to-indentation) (point))))
-         ;; skip 'then'
+              (setcur-indent (save-excursion (back-to-indentation) (point))))
+          ;; skip 'then'
           (forward-word 1)
-         (list cur-indent 'ada-indent))
+          (list cur-indent 'ada-indent))
 
       (list cur-indent 'ada-broken-indent))))
 
@@ -2423,11 +2984,28 @@ ORGPOINT is the limit position used in the calculation."
     (cond
      ((save-excursion
         (forward-word 1)
-        (set 'pos (ada-goto-next-non-ws orgpoint)))
+        (setpos (ada-goto-next-non-ws orgpoint)))
       (goto-char pos)
       (save-excursion
         (ada-indent-on-previous-lines t orgpoint)))
 
+     ;;  Special case for record types, for instance for:
+     ;;     type A is (B : Integer;
+     ;;                C : Integer) is record
+     ;;         null;   --  This is badly indented otherwise
+     ((looking-at "record")
+
+      ;;  If record is at the beginning of the line, indent from there
+      (if (save-excursion
+           (beginning-of-line)
+           (looking-at "^[ \t]*\\(record\\|limited record\\)"))
+         (list (save-excursion (back-to-indentation) (point)) 'ada-indent)
+
+       ;;  else indent relative to the type command
+       (list (save-excursion
+               (car (ada-search-ignore-string-comment "\\<type\\>" t)))
+             'ada-indent)))
+
      ;; nothing follows the block-start
      (t
       (list (save-excursion (back-to-indentation) (point)) 'ada-indent)))))
@@ -2442,14 +3020,14 @@ ORGPOINT is the limit position used in the calculation."
     ;; is there an 'is' in front of point ?
     ;;
     (if (save-excursion
-          (set 'match-cons
+          (setmatch-cons
                (ada-search-ignore-string-comment
                 "\\<\\(is\\|do\\)\\>" nil orgpoint)))
         ;;
         ;; yes, then skip to its end
         ;;
         (progn
-          (set 'foundis t)
+          (setfoundis t)
           (goto-char (cdr match-cons)))
       ;;
       ;; no, then goto next non-ws, if there is one in front of point
@@ -2474,7 +3052,7 @@ ORGPOINT is the limit position used in the calculation."
      ((and
        foundis
        (save-excursion
-         (set 'match-cons
+         (setmatch-cons
               (ada-search-ignore-string-comment
                "\\<\\(separate\\|new\\|abstract\\)\\>"
                nil orgpoint))))
@@ -2486,15 +3064,14 @@ ORGPOINT is the limit position used in the calculation."
      ;;
      ((and
        foundis
-       (save-excursion (set 'match-cons (ada-goto-next-non-ws orgpoint)))
+       (save-excursion (setmatch-cons (ada-goto-next-non-ws orgpoint)))
        (goto-char match-cons)
        (ada-indent-on-previous-lines t orgpoint)))
      ;;
      ;; no 'is' but ';'
      ;;
      ((save-excursion
-        (ada-search-ignore-string-comment ";" nil orgpoint nil
-                                         'search-forward))
+        (ada-search-ignore-string-comment ";" nil orgpoint nil 'search-forward))
       (list cur-indent 0))
      ;;
      ;; no 'is' or ';'
@@ -2511,42 +3088,50 @@ ORGPOINT is the limit position used in the calculation."
 
       (cond
 
-       ;;  This one is called when indenting a line preceded by a multiline
+       ;;  This one is called when indenting a line preceded by a multi-line
        ;;  subprogram declaration (in that case, we are at this point inside
        ;;  the parameter declaration list)
        ((ada-in-paramlist-p)
         (ada-previous-procedure)
-       (list (save-excursion (back-to-indentation) (point)) 0))
+        (list (save-excursion (back-to-indentation) (point)) 0))
 
        ;;  This one is called when indenting the second line of a multi-line
        ;;  declaration section, in a declare block or a record declaration
        ((looking-at "[ \t]*\\(\\sw\\|_\\)*[ \t]*,[ \t]*$")
-       (list (save-excursion (back-to-indentation) (point))
-             'ada-broken-decl-indent))
+        (list (save-excursion (back-to-indentation) (point))
+              'ada-broken-decl-indent))
 
        ;;  This one is called in every over case when indenting a line at the
        ;;  top level
        (t
         (if (looking-at ada-named-block-re)
-            (set 'label (- ada-label-indent))
-
-          ;;  "with private" or "null record" cases
-          (if (or (and (re-search-forward "\\<private\\>" orgpoint t)
-                       (save-excursion (forward-char -7);; skip back "private"
-                                       (ada-goto-previous-word)
-                                       (looking-at "with")))
-                 (and (re-search-forward "\\<record\\>" orgpoint t)
-                      (save-excursion (forward-char -6);; skip back "record"
-                                      (ada-goto-previous-word)
-                                      (looking-at "null"))))
-              (progn
-                (re-search-backward "\\<\\(type\\|subtype\\)\\>" nil t)
-               (list (save-excursion (back-to-indentation) (point)) 0))))
+            (setq label (- ada-label-indent))
+
+          (let (p)
+
+            ;;  "with private" or "null record" cases
+            (if (or (save-excursion
+                      (and (ada-search-ignore-string-comment "\\<private\\>" nil orgpoint)
+                           (setq p (point))
+                           (save-excursion (forward-char -7);; skip back "private"
+                                           (ada-goto-previous-word)
+                                           (looking-at "with"))))
+                    (save-excursion
+                      (and (ada-search-ignore-string-comment "\\<record\\>" nil orgpoint)
+                           (setq p (point))
+                           (save-excursion (forward-char -6);; skip back "record"
+                                           (ada-goto-previous-word)
+                                           (looking-at "null")))))
+                (progn
+                  (goto-char p)
+                  (re-search-backward "\\<\\(type\\|subtype\\)\\>" nil t)
+                  (list (save-excursion (back-to-indentation) (point)) 0)))))
         (if (save-excursion
-              (ada-search-ignore-string-comment ";" nil orgpoint nil 'search-forward))
-           (list (+ (save-excursion (back-to-indentation) (point)) label) 0)
-         (list (+ (save-excursion (back-to-indentation) (point)) label)
-               'ada-broken-indent)))))))
+              (ada-search-ignore-string-comment ";" nil orgpoint nil
+                                                'search-forward))
+            (list (+ (save-excursion (back-to-indentation) (point)) label) 0)
+          (list (+ (save-excursion (back-to-indentation) (point)) label)
+                'ada-broken-indent)))))))
 
 (defun ada-get-indent-label (orgpoint)
   "Calculates the indentation when before a label or variable declaration.
@@ -2557,15 +3142,15 @@ ORGPOINT is the limit position used in the calculation."
     (cond
      ;; loop label
      ((save-excursion
-        (set 'match-cons (ada-search-ignore-string-comment
-                         ada-loop-start-re nil orgpoint)))
+        (setmatch-cons (ada-search-ignore-string-comment
+                          ada-loop-start-re nil orgpoint)))
       (goto-char (car match-cons))
       (ada-get-indent-loop orgpoint))
 
      ;; declare label
      ((save-excursion
-        (set 'match-cons (ada-search-ignore-string-comment
-                         "\\<declare\\|begin\\>" nil orgpoint)))
+        (setmatch-cons (ada-search-ignore-string-comment
+                          "\\<declare\\|begin\\>" nil orgpoint)))
       (goto-char (car match-cons))
       (list (save-excursion (back-to-indentation) (point)) 'ada-indent))
 
@@ -2574,7 +3159,7 @@ ORGPOINT is the limit position used in the calculation."
       (if (save-excursion
             (ada-search-ignore-string-comment ";" nil orgpoint))
           (list cur-indent 0)
-       (list cur-indent 'ada-broken-indent)))
+        (list cur-indent 'ada-broken-indent)))
 
      ;; nothing follows colon
      (t
@@ -2586,7 +3171,7 @@ ORGPOINT is the limit position used in the calculation."
   (let ((match-cons nil)
         (pos (point))
 
-       ;; If looking at a named block, skip the label
+        ;; If looking at a named block, skip the label
         (label (save-excursion
                  (beginning-of-line)
                  (if (looking-at ada-named-block-re)
@@ -2600,16 +3185,16 @@ ORGPOINT is the limit position used in the calculation."
      ;;
      ((save-excursion
         (ada-search-ignore-string-comment ";" nil orgpoint nil
-                                         'search-forward))
+                                          'search-forward))
       (list (+ (save-excursion (back-to-indentation) (point)) label) 0))
      ;;
      ;; simple loop
      ;;
      ((looking-at "loop\\>")
-      (set 'pos (ada-get-indent-block-start orgpoint))
+      (setpos (ada-get-indent-block-start orgpoint))
       (if (equal label 0)
-         pos
-       (list (+ (car pos) label) (cdr pos))))
+          pos
+        (list (+ (car pos) label) (cdr pos))))
 
      ;;
      ;; 'for'- loop (or also a for ... use statement)
@@ -2631,17 +3216,21 @@ ORGPOINT is the limit position used in the calculation."
            ;; check if there is a 'record' before point
            ;;
            (progn
-             (set 'match-cons (ada-search-ignore-string-comment
+             (setmatch-cons (ada-search-ignore-string-comment
                                "record" nil orgpoint nil 'word-search-forward))
              t)))
         (if match-cons
-            (goto-char (car match-cons)))
-       (list (save-excursion (back-to-indentation) (point)) 'ada-indent))
+           (progn
+             (goto-char (car match-cons))
+             (list (save-excursion (back-to-indentation) (point)) 'ada-indent))
+         (list (save-excursion (back-to-indentation) (point)) 'ada-broken-indent))
+       )
+
        ;;
        ;; for..loop
        ;;
        ((save-excursion
-          (set 'match-cons (ada-search-ignore-string-comment
+          (setmatch-cons (ada-search-ignore-string-comment
                             "loop" nil orgpoint nil 'word-search-forward)))
         (goto-char (car match-cons))
         ;;
@@ -2652,14 +3241,14 @@ ORGPOINT is the limit position used in the calculation."
                   (back-to-indentation)
                   (looking-at "\\<loop\\>"))
           (goto-char pos))
-       (list (+ (save-excursion (back-to-indentation) (point)) label)
-             'ada-indent))
+        (list (+ (save-excursion (back-to-indentation) (point)) label)
+              'ada-indent))
        ;;
        ;; for-statement is broken
        ;;
        (t
-       (list (+ (save-excursion (back-to-indentation) (point)) label)
-             'ada-broken-indent))))
+        (list (+ (save-excursion (back-to-indentation) (point)) label)
+              'ada-broken-indent))))
 
      ;;
      ;; 'while'-loop
@@ -2669,7 +3258,7 @@ ORGPOINT is the limit position used in the calculation."
       ;; while..loop ?
       ;;
       (if (save-excursion
-            (set 'match-cons (ada-search-ignore-string-comment
+            (setmatch-cons (ada-search-ignore-string-comment
                               "loop" nil orgpoint nil 'word-search-forward)))
 
           (progn
@@ -2682,12 +3271,11 @@ ORGPOINT is the limit position used in the calculation."
                       (back-to-indentation)
                       (looking-at "\\<loop\\>"))
               (goto-char pos))
-           (list (+ (save-excursion (back-to-indentation) (point)) label)
-                 'ada-indent))
-
-       (list (+ (save-excursion (back-to-indentation) (point)) label)
-             'ada-broken-indent))))))
+            (list (+ (save-excursion (back-to-indentation) (point)) label)
+                  'ada-indent))
 
+        (list (+ (save-excursion (back-to-indentation) (point)) label)
+              'ada-broken-indent))))))
 
 (defun ada-get-indent-type (orgpoint)
   "Calculates the indentation when before a type statement.
@@ -2699,7 +3287,7 @@ ORGPOINT is the limit position used in the calculation."
      ;;
      ((save-excursion
         (and
-         (set 'match-dat (ada-search-ignore-string-comment
+         (setmatch-dat (ada-search-ignore-string-comment
                           "end" nil orgpoint nil 'word-search-forward))
          (ada-goto-next-non-ws)
          (looking-at "\\<record\\>")
@@ -2712,7 +3300,7 @@ ORGPOINT is the limit position used in the calculation."
      ;; record type
      ;;
      ((save-excursion
-        (set 'match-dat (ada-search-ignore-string-comment
+        (setmatch-dat (ada-search-ignore-string-comment
                          "record" nil orgpoint nil 'word-search-forward)))
       (goto-char (car match-dat))
       (list (save-excursion (back-to-indentation) (point)) 'ada-indent))
@@ -2721,7 +3309,7 @@ ORGPOINT is the limit position used in the calculation."
      ;;
      ((save-excursion
         (ada-search-ignore-string-comment ";" nil orgpoint nil
-                                         'search-forward))
+                                          'search-forward))
       (list (save-excursion (back-to-indentation) (point)) 0))
      ;;
      ;; "type ... is", but not "type ... is ...", which is broken
@@ -2729,7 +3317,7 @@ ORGPOINT is the limit position used in the calculation."
      ((save-excursion
         (and
          (ada-search-ignore-string-comment "is" nil orgpoint nil
-                                          'word-search-forward)
+                                           'word-search-forward)
          (not (ada-goto-next-non-ws orgpoint))))
       (list (save-excursion (back-to-indentation) (point)) 'ada-broken-indent))
      ;;
@@ -2737,7 +3325,7 @@ ORGPOINT is the limit position used in the calculation."
      ;;
      (t
       (list (save-excursion (back-to-indentation) (point))
-           'ada-broken-indent)))))
+            'ada-broken-indent)))))
 
 \f
 ;; -----------------------------------------------------------
@@ -2752,42 +3340,41 @@ open parenthesis."
   (let ((match-dat nil)
         (orgpoint (point)))
 
-    (set 'match-dat (ada-search-prev-end-stmt))
+    (setmatch-dat (ada-search-prev-end-stmt))
     (if match-dat
 
-        ;;
-        ;; found a previous end-statement => check if anything follows
-        ;;
-        (unless (looking-at "declare")
-          (progn
-            (unless (save-excursion
-                      (goto-char (cdr match-dat))
-                      (ada-goto-next-non-ws orgpoint))
-              ;;
-              ;; nothing follows => it's the end-statement directly in
-              ;;                    front of point => search again
-              ;;
-              (set 'match-dat (ada-search-prev-end-stmt)))
-            ;;
-            ;; if found the correct end-statement => goto next non-ws
-            ;;
-            (if match-dat
-                (goto-char (cdr match-dat)))
-            (ada-goto-next-non-ws)
-            ))
-
-      ;;
-      ;; no previous end-statement => we are at the beginning of the
-      ;;                              accessible part of the buffer
-      ;;
-      (progn
-        (goto-char (point-min))
-        ;;
-        ;; skip to the very first statement, if there is one
-        ;;
-        (unless (ada-goto-next-non-ws orgpoint)
-          (goto-char orgpoint))))
+       ;;
+       ;; found a previous end-statement => check if anything follows
+       ;;
+       (unless (looking-at "declare")
+         (progn
+           (unless (save-excursion
+                     (goto-char (cdr match-dat))
+                     (ada-goto-next-non-ws orgpoint))
+             ;;
+             ;; nothing follows => it's the end-statement directly in
+             ;;                    front of point => search again
+             ;;
+             (setq match-dat (ada-search-prev-end-stmt)))
+           ;;
+           ;; if found the correct end-statement => goto next non-ws
+           ;;
+           (if match-dat
+               (goto-char (cdr match-dat)))
+           (ada-goto-next-non-ws)
+           ))
 
+      ;;
+      ;; no previous end-statement => we are at the beginning of the
+      ;;                              accessible part of the buffer
+      ;;
+      (progn
+       (goto-char (point-min))
+       ;;
+       ;; skip to the very first statement, if there is one
+         ;;
+       (unless (ada-goto-next-non-ws orgpoint)
+         (goto-char orgpoint))))
     (point)))
 
 
@@ -2796,40 +3383,46 @@ open parenthesis."
 Returns a cons cell whose car is the beginning and whose cdr the end of the
 match."
   (let ((match-dat nil)
-        (found nil)
-        parse)
+        (found nil))
 
-    ;;
     ;; search until found or beginning-of-buffer
-    ;;
     (while
         (and
          (not found)
-         (set 'match-dat (ada-search-ignore-string-comment
+         (setmatch-dat (ada-search-ignore-string-comment
                           ada-end-stmt-re t)))
 
       (goto-char (car match-dat))
       (unless (ada-in-open-paren-p)
-        (if (and (looking-at
-                  "\\<\\(record\\|loop\\|select\\|else\\|then\\)\\>")
-                 (save-excursion
-                   (ada-goto-previous-word)
-                   (looking-at "\\<\\(end\\|or\\|and\\)\\>[ \t]*[^;]")))
-            (forward-word -1)
+       (cond
 
-          (save-excursion
-            (goto-char (cdr match-dat))
-            (ada-goto-next-non-ws)
-            (looking-at "(")
-            ;;  words that can go after an 'is'
-            (unless (looking-at
-                     (eval-when-compile
-                       (concat "\\<"
-                               (regexp-opt '("separate" "access" "array"
-                                            "abstract" "new") t)
-                               "\\>\\|(")))
-              (set 'found t))))
-        ))
+        ((and (looking-at
+               "\\<\\(record\\|loop\\|select\\|else\\|then\\)\\>")
+              (save-excursion
+                (ada-goto-previous-word)
+                (looking-at "\\<\\(end\\|or\\|and\\)\\>[ \t]*[^;]")))
+         (forward-word -1))
+
+        ((looking-at "is")
+         (setq found
+               (and (save-excursion (ada-goto-previous-word)
+                                    (ada-goto-previous-word)
+                                    (not (looking-at "subtype")))
+
+                   (save-excursion (goto-char (cdr match-dat))
+                                   (ada-goto-next-non-ws)
+                                   ;;  words that can go after an 'is'
+                                   (not (looking-at
+                                    (eval-when-compile
+                                      (concat "\\<"
+                                              (regexp-opt
+                                               '("separate" "access" "array"
+                                                 "abstract" "new") t)
+                                              "\\>\\|("))))))))
+
+        (t
+         (setq found t))
+        )))
 
     (if found
         match-dat
@@ -2841,7 +3434,7 @@ match."
 Stop the search at LIMIT.
 Do not call this function from within a string."
   (unless limit
-    (set 'limit (point-max)))
+    (setlimit (point-max)))
   (while (and (<= (point) limit)
               (progn (forward-comment 10000)
                      (if (and (not (eobp))
@@ -2872,8 +3465,8 @@ Returns the new position of point or nil if not found."
         (old-syntax (char-to-string (char-syntax ?_))))
     (modify-syntax-entry ?_ "w")
     (unless backward
-      (skip-syntax-forward "w"));;  ??? Used to have . too
-    (if (set 'match-cons
+      (skip-syntax-forward "w"))
+    (if (setmatch-cons
              (if backward
                  (ada-search-ignore-string-comment "\\w" t nil t)
                (ada-search-ignore-string-comment "\\w" nil nil t)))
@@ -2893,12 +3486,6 @@ Returns the new position of point or nil if not found."
   )
 
 
-(defsubst ada-goto-previous-word ()
-  "Moves point to the beginning of the previous word of Ada code.
-Returns the new position of point or nil if not found."
-  (ada-goto-next-word t))
-
-
 (defun ada-check-matching-start (keyword)
   "Signals an error if matching block start is not KEYWORD.
 Moves point to the matching block start."
@@ -2920,7 +3507,7 @@ Moves point to the beginning of the declaration."
     ;;
     ;; 'accept' or 'package' ?
     ;;
-    (unless (looking-at "\\<\\(accept\\|package\\|task\\|protected\\)\\>")
+    (unless (looking-at ada-subprog-start-re)
       (ada-goto-matching-decl-start))
     ;;
     ;; 'begin' of 'procedure'/'function'/'task' or 'declare'
@@ -2952,22 +3539,33 @@ Moves point to the beginning of the declaration."
                (buffer-substring (point)
                                  (progn (forward-sexp 1) (point))))))))
 
-(defun ada-goto-matching-decl-start (&optional noerror)
+(defun ada-goto-matching-decl-start (&optional noerror recursive)
   "Moves point to the matching declaration start of the current 'begin'.
 If NOERROR is non-nil, it only returns nil if no match was found."
   (let ((nest-count 1)
-        (first t)
-        (flag nil)
+
+       ;;  first should be set to t if we should stop at the first
+       ;;  "begin" we encounter.
+        (first (not recursive))
         (count-generic nil)
+       (stop-at-when nil)
         )
 
+    ;;  Ignore "when" most of the time, except if we are looking at the
+    ;;  beginning of a block (structure:  case .. is
+    ;;                                    when ... =>
+    ;;                                       begin ...
+    ;;                                       exception ... )
+    (if (looking-at "begin")
+        (setq stop-at-when t))
+
     (if (or
          (looking-at "\\<\\(package\\|procedure\\|function\\)\\>")
          (save-excursion
            (ada-search-ignore-string-comment
-           "\\<\\(package\\|procedure\\|function\\|generic\\)\\>" t)
+            "\\<\\(package\\|procedure\\|function\\|generic\\)\\>" t)
            (looking-at "generic")))
-        (set 'count-generic t))
+        (setcount-generic t))
 
     ;; search backward for interesting keywords
     (while (and
@@ -2981,48 +3579,56 @@ If NOERROR is non-nil, it only returns nil if no match was found."
        ((looking-at "end")
         (ada-goto-matching-start 1 noerror)
 
-       ;;  In some case, two begin..end block can follow each other closely,
-       ;;  which we have to detect, as in
-       ;;     procedure P is
-       ;;        procedure Q is
-       ;;        begin
-       ;;        end;
+        ;;  In some case, two begin..end block can follow each other closely,
+        ;;  which we have to detect, as in
+        ;;     procedure P is
+        ;;        procedure Q is
+        ;;        begin
+        ;;        end;
         ;;     begin    --  here we should go to procedure, not begin
-       ;;     end
-
-       (let ((loop-again 0))
-         (if (looking-at "begin")
-             (set 'loop-again 1))
-
-         (save-excursion
-           (while (not (= loop-again 0))
-             
-             ;;  If begin was just there as the beginning of a block (with no
-             ;;  declare) then do nothing, otherwise just register that we
-             ;;  have to find the statement that required the begin
-             
-             (ada-search-ignore-string-comment
-              "declare\\|begin\\|end\\|procedure\\|function\\|task\\|package"
-              t)
-
-             (if (looking-at "end")
-                 (set 'loop-again (1+ loop-again))
-
-               (set 'loop-again (1- loop-again))
-               (unless (looking-at "begin")
-                   (set 'nest-count (1+ nest-count))))
-             ))
-         ))
+        ;;     end
+
+        (if (looking-at "begin")
+            (let ((loop-again t))
+              (save-excursion
+                (while loop-again
+                  ;;  If begin was just there as the beginning of a block
+                  ;;  (with no declare) then do nothing, otherwise just
+                  ;;  register that we have to find the statement that
+                  ;;  required the begin
+
+                  (ada-search-ignore-string-comment
+                   "\\<\\(declare\\|begin\\|end\\|procedure\\|function\\|task\\|package\\)\\>"
+                   t)
+
+                  (if (looking-at "end")
+                     (ada-goto-matching-start 1 noerror t)
+                   ;; (ada-goto-matching-decl-start noerror t)
+
+                    (setq loop-again nil)
+                    (unless (looking-at "begin")
+                      (setq nest-count (1+ nest-count))))
+                  ))
+              )))
        ;;
        ((looking-at "generic")
         (if count-generic
             (progn
-              (set 'first nil)
-              (set 'nest-count (1- nest-count)))))
+              (setq first nil)
+              (setq nest-count (1- nest-count)))))
+       ;;
+       ((looking-at "if")
+       (save-excursion
+         (forward-word -1)
+         (unless (looking-at "\\<end[ \t\n]*if\\>")
+           (progn
+             (setq nest-count (1- nest-count))
+             (setq first nil)))))
+
        ;;
-       ((looking-at "declare\\|generic\\|if")
-        (set 'nest-count (1- nest-count))
-        (set 'first nil))
+       ((looking-at "declare\\|generic")
+        (setnest-count (1- nest-count))
+        (setq first t))
        ;;
        ((looking-at "is")
         ;; check if it is only a type definition, but not a protected
@@ -3044,15 +3650,15 @@ If NOERROR is non-nil, it only returns nil if no match was found."
                   (skip-chars-backward "a-zA-Z0-9_.'")
                   (ada-goto-previous-word)
                   (and
-                   (looking-at "\\<\\(sub\\)?type\\>")
+                   (looking-at "\\<\\(sub\\)?type\\|case\\>")
                    (save-match-data
                      (ada-goto-previous-word)
                      (not (looking-at "\\<protected\\>"))))
                   ))                    ; end of `or'
             (goto-char (match-beginning 0))
           (progn
-            (set 'nest-count (1- nest-count))
-            (set 'first nil))))
+            (setnest-count (1- nest-count))
+            (setfirst nil))))
 
        ;;
        ((looking-at "new")
@@ -3063,19 +3669,29 @@ If NOERROR is non-nil, it only returns nil if no match was found."
        ;;
        ((and first
              (looking-at "begin"))
-        (set 'nest-count 0)
-        (set 'flag t))
+        (setq nest-count 0))
+       ;;
+       ((looking-at "when")
+       (save-excursion
+          (forward-word -1)
+          (unless (looking-at "\\<exit[ \t\n]*when\\>")
+            (progn
+              (if stop-at-when
+                  (setq nest-count (1- nest-count)))
+              ))))
+       ;;
+       ((looking-at "begin")
+       (setq first nil))
        ;;
        (t
-        (set 'nest-count (1+ nest-count))
-        (set 'first nil)))
+        (setnest-count (1+ nest-count))
+        (setfirst nil)))
 
       );; end of loop
 
     ;; check if declaration-start is really found
     (if (and
          (zerop nest-count)
-         (not flag)
          (if (looking-at "is")
              (ada-search-ignore-string-comment ada-subprog-start-re t)
            (looking-at "declare\\|generic")))
@@ -3111,12 +3727,12 @@ If GOTOTHEN is non-nil, point moves to the 'then' following 'if'."
           (cond
            ;; found block end => increase nest depth
            ((looking-at "end")
-            (set 'nest-count (1+ nest-count)))
+            (setnest-count (1+ nest-count)))
 
            ;; found loop/select/record/case/if => check if it starts or
            ;; ends a block
            ((looking-at "loop\\|select\\|record\\|case\\|if")
-            (set 'pos (point))
+            (setpos (point))
             (save-excursion
               ;;
               ;; check if keyword follows 'end'
@@ -3124,11 +3740,11 @@ If GOTOTHEN is non-nil, point moves to the 'then' following 'if'."
               (ada-goto-previous-word)
               (if (looking-at "\\<end\\>[ \t]*[^;]")
                   ;; it ends a block => increase nest depth
-                  (progn
-                    (set 'nest-count (1+ nest-count))
-                    (set 'pos (point)))
+                 (setq nest-count (1+ nest-count)
+                       pos        (point))
+
                 ;; it starts a block => decrease nest depth
-                (set 'nest-count (1- nest-count))))
+                (setnest-count (1- nest-count))))
             (goto-char pos))
 
            ;; found package start => check if it really is a block
@@ -3142,16 +3758,19 @@ If GOTOTHEN is non-nil, point moves to the 'then' following 'if'."
                     (goto-char (car pos))
                   (error (concat
                           "No matching 'is' or 'renames' for 'package' at"
-                         " line "
-                          (number-to-string (count-lines (point-min)
-                                                        (1+ current)))))))
+                          " line "
+                          (number-to-string (count-lines 1 (1+ current)))))))
               (unless (looking-at "renames")
                 (progn
                   (forward-word 1)
                   (ada-goto-next-non-ws)
                   ;; ignore it if it is only a declaration with 'new'
-                  (if (not (looking-at "\\<\\(new\\|separate\\)\\>"))
-                      (set 'nest-count (1- nest-count)))))))
+                 ;; We could have  package Foo is new ....
+                 ;;  or            package Foo is separate;
+                 ;;  or            package Foo is begin null; end Foo
+                 ;;                     for elaboration code (elaboration)
+                  (if (not (looking-at "\\<\\(new\\|separate\\|begin\\)\\>"))
+                      (setq nest-count (1- nest-count)))))))
            ;; found task start => check if it has a body
            ((looking-at "task")
             (save-excursion
@@ -3164,117 +3783,169 @@ If GOTOTHEN is non-nil, point moves to the 'then' following 'if'."
                 (forward-word 2);; skip "type"
                 (ada-goto-next-non-ws);; skip type name
 
-               ;; Do nothing if we are simply looking at a simple
-               ;; "task type name;" statement with no block
-               (unless (looking-at ";")
-                 (progn
-                   ;; Skip the parameters
-                   (if (looking-at "(")
-                       (ada-search-ignore-string-comment ")" nil))
-                   (let ((tmp (ada-search-ignore-string-comment
-                               "\\<\\(is\\|;\\)\\>" nil)))
-                     (if tmp
-                         (progn
-                           (goto-char (car tmp))
-                           (if (looking-at "is")
-                               (set 'nest-count (1- nest-count)))))))))
+                ;; Do nothing if we are simply looking at a simple
+                ;; "task type name;" statement with no block
+                (unless (looking-at ";")
+                  (progn
+                    ;; Skip the parameters
+                    (if (looking-at "(")
+                        (ada-search-ignore-string-comment ")" nil))
+                    (let ((tmp (ada-search-ignore-string-comment
+                                "\\<\\(is\\|;\\)\\>" nil)))
+                      (if tmp
+                          (progn
+                            (goto-char (car tmp))
+                            (if (looking-at "is")
+                                (setq nest-count (1- nest-count)))))))))
                (t
-               ;; Check if that task declaration had a block attached to
-               ;; it (i.e do nothing if we have just "task name;")
-               (unless (progn (forward-word 1)
-                              (looking-at "[ \t]*;"))
-                 (set 'nest-count (1- nest-count)))))))
+                ;; Check if that task declaration had a block attached to
+                ;; it (i.e do nothing if we have just "task name;")
+                (unless (progn (forward-word 1)
+                               (looking-at "[ \t]*;"))
+                  (setq nest-count (1- nest-count)))))))
            ;; all the other block starts
            (t
-            (set 'nest-count (1- nest-count)))) ; end of 'cond'
+            (setnest-count (1- nest-count)))) ; end of 'cond'
 
           ;; match is found, if nest-depth is zero
           ;;
-          (set 'found (zerop nest-count))))) ; end of loop
+          (setfound (zerop nest-count))))) ; end of loop
 
-    (if found
-        ;;
-        ;; match found => is there anything else to do ?
-        ;;
-        (progn
-          (cond
-           ;;
-           ;; found 'if' => skip to 'then', if it's on a separate line
-           ;;                               and GOTOTHEN is non-nil
-           ;;
-           ((and
-             gotothen
-             (looking-at "if")
-             (save-excursion
-               (ada-search-ignore-string-comment "then" nil nil nil
-                                                'word-search-forward)
-               (back-to-indentation)
-               (looking-at "\\<then\\>")))
-            (goto-char (match-beginning 0)))
-           ;;
-           ;; found 'do' => skip back to 'accept'
-           ;;
-           ((looking-at "do")
-            (unless (ada-search-ignore-string-comment "accept" t nil nil
-                                                     'word-search-backward)
-              (error "missing 'accept' in front of 'do'"))))
-          (point))
+    (if (bobp)
+       (point)
+      (if found
+         ;;
+         ;; match found => is there anything else to do ?
+         ;;
+         (progn
+           (cond
+            ;;
+            ;; found 'if' => skip to 'then', if it's on a separate line
+            ;;                               and GOTOTHEN is non-nil
+            ;;
+            ((and
+              gotothen
+              (looking-at "if")
+              (save-excursion
+                (ada-search-ignore-string-comment "then" nil nil nil
+                                                  'word-search-forward)
+                (back-to-indentation)
+                (looking-at "\\<then\\>")))
+             (goto-char (match-beginning 0)))
 
-      (if noerror
-          nil
-        (error "no matching start")))))
+            ;;
+            ;; found 'do' => skip back to 'accept'
+            ;;
+            ((looking-at "do")
+             (unless (ada-search-ignore-string-comment
+                      "accept" t nil nil
+                      'word-search-backward)
+               (error "missing 'accept' in front of 'do'"))))
+           (point))
+
+       (if noerror
+           nil
+         (error "no matching start"))))))
 
 
 (defun ada-goto-matching-end (&optional nest-level noerror)
   "Moves point to the end of a block.
 Which block depends on the value of NEST-LEVEL, which defaults to zero.
 If NOERROR is non-nil, it only returns nil if found no matching start."
-  (let ((nest-count (if nest-level nest-level 0))
-        (found nil))
+  (let ((nest-count (or nest-level 0))
+       (regex (eval-when-compile
+                (concat "\\<"
+                        (regexp-opt '("end" "loop" "select" "begin" "case"
+                                      "if" "task" "package" "record" "do"
+                                      "procedure" "function") t)
+                        "\\>")))
+       found
+        pos
+
+       ;;  First is used for subprograms: they are generally handled
+       ;;  recursively, but of course we do not want to do that the
+       ;;  first time (see comment below about subprograms)
+       (first (not (looking-at "declare"))))
+
+    ;;  If we are already looking at one of the keywords, this shouldn't count
+    ;;  in the nesting loop below, so we just make sure we don't count it.
+    ;;  "declare" is a special case because we need to look after the "begin"
+    ;;  keyword
+    (if (looking-at "\\<if\\|loop\\|case\\|begin\\>")
+       (forward-char 1))
 
     ;;
     ;; search forward for interesting keywords
     ;;
     (while (and
             (not found)
-            (ada-search-ignore-string-comment
-             (eval-when-compile
-               (concat "\\<"
-                       (regexp-opt '("end" "loop" "select" "begin" "case"
-                                     "if" "task" "package" "record" "do") t)
-                       "\\>")) nil))
+            (ada-search-ignore-string-comment regex nil))
 
       ;;
       ;; calculate nest-depth
       ;;
       (backward-word 1)
       (cond
+       ;; procedures and functions need to be processed recursively, in
+       ;; case they are defined in a declare/begin block, as in:
+       ;;    declare  --  NL 0   (nested level)
+       ;;      A : Boolean;
+       ;;      procedure B (C : D) is
+       ;;      begin --  NL 1
+       ;;         null;
+       ;;      end B;   --  NL 0, and we would exit
+       ;;    begin
+       ;;    end; --  we should exit here
+       ;; processing them recursively avoids the need for any special
+       ;; handling.
+       ;; Nothing should be done if we have only the specs or a
+       ;; generic instantion.
+
+       ((and (looking-at "\\<procedure\\|function\\>"))
+       (if first
+           (forward-word 1)
+
+         (setq pos (point))
+         (ada-search-ignore-string-comment "is\\|;")
+         (if (= (char-before) ?s)
+             (progn
+               (ada-goto-next-non-ws)
+               (unless (looking-at "\\<new\\>")
+                 (progn
+                   (goto-char pos)
+                   (ada-goto-matching-end 0 t)))))))
+
        ;; found block end => decrease nest depth
        ((looking-at "\\<end\\>")
-        (set 'nest-count (1- nest-count))
-        ;; skip the following keyword
-        (if (progn
-              (skip-chars-forward "end")
-              (ada-goto-next-non-ws)
-              (looking-at "\\<\\(loop\\|select\\|record\\|case\\|if\\)\\>"))
-            (forward-word 1)))
-       ;; found package start => check if it really starts a block
+        (setq nest-count (1- nest-count)
+             found (<= nest-count 0))
+         ;; skip the following keyword
+       (if (progn
+             (skip-chars-forward "end")
+             (ada-goto-next-non-ws)
+             (looking-at "\\<\\(loop\\|select\\|record\\|case\\|if\\)\\>"))
+           (forward-word 1)))
+
+       ;; found package start => check if it really starts a block, and is not
+       ;; in fact a generic instantiation for instance
        ((looking-at "\\<package\\>")
         (ada-search-ignore-string-comment "is" nil nil nil
-                                         'word-search-forward)
+                                          'word-search-forward)
         (ada-goto-next-non-ws)
         ;; ignore and skip it if it is only a 'new' package
         (if (looking-at "\\<new\\>")
             (goto-char (match-end 0))
-          (set 'nest-count (1+ nest-count))))
+          (setq nest-count (1+ nest-count)
+               found      (<= nest-count 0))))
+
        ;; all the other block starts
        (t
-        (set 'nest-count (1+ nest-count))
+       (if (not first)
+           (setq nest-count (1+ nest-count)))
+       (setq found      (<= nest-count 0))
         (forward-word 1)))              ; end of 'cond'
 
-      ;; match is found, if nest-depth is zero
-      ;;
-      (set 'found (zerop nest-count)))  ; end of loop
+      (setq first nil))
 
     (if found
         t
@@ -3285,7 +3956,7 @@ If NOERROR is non-nil, it only returns nil if found no matching start."
 
 
 (defun ada-search-ignore-string-comment
-  (search-re &optional backward limit paramlists search-func )
+  (search-re &optional backward limit paramlists search-func)
   "Regexp-search for SEARCH-RE, ignoring comments, strings.
 If PARAMLISTS is nil, ignore parameter lists. Returns a cons cell of
 begin and end of match data or nil, if not found.
@@ -3301,7 +3972,7 @@ Point is moved at the beginning of the search-re."
         (previous-syntax-table (syntax-table)))
 
     (unless search-func
-      (set 'search-func (if backward 're-search-backward 're-search-forward)))
+      (setsearch-func (if backward 're-search-backward 're-search-forward)))
 
     ;;
     ;; search until found or end-of-buffer
@@ -3313,10 +3984,10 @@ Point is moved at the beginning of the search-re."
                     (or (and backward (<= limit (point)))
                         (>= limit (point))))
                 (funcall search-func search-re limit 1))
-      (set 'begin (match-beginning 0))
-      (set 'end (match-end 0))
+      (setbegin (match-beginning 0))
+      (setend (match-end 0))
 
-      (set 'parse-result (parse-partial-sexp
+      (setparse-result (parse-partial-sexp
                           (save-excursion (beginning-of-line) (point))
                           (point)))
 
@@ -3325,7 +3996,7 @@ Point is moved at the beginning of the search-re."
        ;; If inside a string, skip it (and the following comments)
        ;;
        ((ada-in-string-p parse-result)
-        (if ada-xemacs
+        (if (featurep 'xemacs)
             (search-backward "\"" nil t)
           (goto-char (nth 8 parse-result)))
         (unless backward (forward-sexp 1)))
@@ -3334,11 +4005,11 @@ Point is moved at the beginning of the search-re."
        ;; There is a special code for comments at the end of the file
        ;;
        ((ada-in-comment-p parse-result)
-        (if ada-xemacs
-           (progn
-             (forward-line 1)
-             (beginning-of-line)
-             (forward-comment -1))
+        (if (featurep 'xemacs)
+            (progn
+              (forward-line 1)
+              (beginning-of-line)
+              (forward-comment -1))
           (goto-char (nth 8 parse-result)))
         (unless backward
           ;;  at the end of the file, it is not possible to skip a comment
@@ -3365,7 +4036,7 @@ Point is moved at the beginning of the search-re."
        ;; found what we were looking for
        ;;
        (t
-        (set 'found t))))               ; end of loop
+        (setfound t))))               ; end of loop
 
     (set-syntax-table previous-syntax-table)
 
@@ -3382,7 +4053,7 @@ Point is moved at the beginning of the search-re."
 Assumes point to be at the end of a statement."
   (or (ada-in-paramlist-p)
       (save-excursion
-       (ada-goto-matching-decl-start t))))
+        (ada-goto-matching-decl-start t))))
 
 
 (defun ada-looking-at-semi-or ()
@@ -3396,44 +4067,49 @@ Assumes point to be at the end of a statement."
 
 
 (defun ada-looking-at-semi-private ()
-  "Returns t if looking-at an 'private' following a semicolon.
+  "Returns t if looking at the start of a private section in a package.
 Returns nil if the private is part of the package name, as in
 'private package A is...' (this can only happen at top level)."
   (save-excursion
     (and (looking-at "\\<private\\>")
          (not (looking-at "\\<private[ \t]*\\(package\\|generic\\)"))
-         (progn (forward-comment -1000)
-                (= (char-before) ?\;)))))
-
-(defsubst ada-in-comment-p (&optional parse-result)
-  "Returns t if inside a comment."
-  (nth 4 (or parse-result
-             (parse-partial-sexp
-              (save-excursion (beginning-of-line) (point)) (point)))))
 
-(defsubst ada-in-string-p (&optional parse-result)
-  "Returns t if point is inside a string.
-If parse-result is non-nil, use is instead of calling parse-partial-sexp."
-  (nth 3 (or parse-result
-             (parse-partial-sexp
-              (save-excursion (beginning-of-line) (point)) (point)))))
+        ;;  Make sure this is the start of a private section (ie after
+        ;;  a semicolon or just after the package declaration, but not
+        ;;  after a 'type ... is private' or 'is new ... with private'
+        ;;
+        ;;  Note that a 'private' statement at the beginning of the buffer
+        ;;  does not indicate a private section, since this is instead a
+        ;;  'private procedure ...'
+        (progn (forward-comment -1000)
+               (and (not (bobp))
+                    (or (= (char-before) ?\;)
+                        (and (forward-word -3)
+                             (looking-at "\\<package\\>"))))))))
 
-(defsubst ada-in-string-or-comment-p (&optional parse-result)
-  "Returns t if inside a comment or string."
-  (set 'parse-result (or parse-result
-                         (parse-partial-sexp
-                          (save-excursion (beginning-of-line) (point)) (point))))
-  (or (ada-in-string-p parse-result) (ada-in-comment-p parse-result)))
 
 (defun ada-in-paramlist-p ()
   "Returns t if point is inside a parameter-list."
   (save-excursion
     (and
-     (re-search-backward "(\\|)" nil t)
+     (ada-search-ignore-string-comment "(\\|)" t nil t)
      ;; inside parentheses ?
      (= (char-after) ?\()
-     (backward-word 2)
-     
+
+     ;; We could be looking at two things here:
+     ;;  operator definition:   function "." (
+     ;;  subprogram definition: procedure .... (
+     ;; Let's skip back over the first one
+     (progn
+       (skip-chars-backward " \t\n")
+       (if (= (char-before) ?\")
+           (backward-char 3)
+         (backward-word 1))
+       t)
+
+     ;; and now over the second one
+     (backward-word 1)
+
      ;; We should ignore the case when the reserved keyword is in a
      ;; comment (for instance, when we have:
      ;;    -- .... package
@@ -3441,7 +4117,7 @@ If parse-result is non-nil, use is instead of calling parse-partial-sexp."
      ;; we should return nil
 
      (not (ada-in-string-or-comment-p))
-     
+
      ;; right keyword two words before parenthesis ?
      ;; Type is in this list because of discriminants
      (looking-at (eval-when-compile
@@ -3450,30 +4126,50 @@ If parse-result is non-nil, use is instead of calling parse-partial-sexp."
                            "task\\|entry\\|accept\\|"
                            "access[ \t]+procedure\\|"
                            "access[ \t]+function\\|"
-                          "pragma\\|"
+                           "pragma\\|"
                            "type\\)\\>"))))))
 
+(defun ada-search-ignore-complex-boolean (regexp backwardp)
+  "Like `ada-search-ignore-string-comment', except that it also ignores
+boolean expressions 'and then' and 'or else'."
+  (let (result)
+  (while (and (setq result (ada-search-ignore-string-comment regexp backwardp))
+             (save-excursion (forward-word -1)
+                             (looking-at "and then\\|or else"))))
+  result))
+
 (defun ada-in-open-paren-p ()
   "Returns the position of the first non-ws behind the last unclosed
 parenthesis, or nil."
   (save-excursion
     (let ((parse (parse-partial-sexp
-                 (point)
-                 (or (car (ada-search-ignore-string-comment
-                           "\\<\\(;\\|is\\|then\\|loop\\|begin\\|else\\)\\>"
-                           t))
-                     (point-min)))))
-      
+                  (point)
+                  (or (car (ada-search-ignore-complex-boolean
+                            "\\<\\(;\\|is\\|then\\|loop\\|begin\\|else\\)\\>"
+                            t))
+                      (point-min)))))
+
       (if (nth 1 parse)
           (progn
             (goto-char (1+ (nth 1 parse)))
-            (skip-chars-forward " \t")
-           (point))))))
+
+           ;;  Skip blanks, if they are not followed by a comment
+           ;;  See:
+           ;;  type A is (   Value_0,
+           ;;                Value_1);
+           ;;  type B is (   --  comment
+           ;;             Value_2);
+
+           (if (or (not ada-indent-handle-comment-special)
+                   (not (looking-at "[ \t]+--")))
+               (skip-chars-forward " \t"))
+
+            (point))))))
 
 \f
-;;;-----------------------------------------------------------
-;;; Behavior Of TAB Key
-;;;-----------------------------------------------------------
+;; -----------------------------------------------------------
+;; --  Behavior Of TAB Key
+;; -----------------------------------------------------------
 
 (defun ada-tab ()
   "Do indenting or tabbing according to `ada-tab-policy'.
@@ -3482,11 +4178,7 @@ of the region.  Otherwise, operates only on the current line."
   (interactive)
   (cond ((eq ada-tab-policy 'indent-rigidly) (ada-tab-hard))
         ((eq ada-tab-policy 'indent-auto)
-         ;;  transient-mark-mode and mark-active are not defined in XEmacs
-         (if (or (and ada-xemacs (region-active-p))
-                 (and (not ada-xemacs)
-                      transient-mark-mode
-                      mark-active))
+        (if (ada-region-selected)
              (ada-indent-region (region-beginning) (region-end))
            (ada-indent-current)))
         ((eq ada-tab-policy 'always-tab) (error "not implemented"))
@@ -3533,6 +4225,8 @@ of the region.  Otherwise, operates only on the current line."
 ;; --  Miscellaneous
 ;; ------------------------------------------------------------
 
+;;  Not needed any more for Emacs 21.2, but still needed for backward
+;;  compatibility
 (defun ada-remove-trailing-spaces  ()
   "Remove trailing spaces in the whole buffer."
   (interactive)
@@ -3544,39 +4238,208 @@ of the region.  Otherwise, operates only on the current line."
         (while (re-search-forward "[ \t]+$" (point-max) t)
           (replace-match "" nil nil))))))
 
-(defun ada-ff-other-window ()
-  "Find other file in other window using `ff-find-other-file'."
-  (interactive)
-  (and (fboundp 'ff-find-other-file)
-       (ff-find-other-file t)))
-
 (defun ada-gnat-style ()
   "Clean up comments, `(' and `,' for GNAT style checking switch."
   (interactive)
   (save-excursion
+
+    ;;  The \n is required, or the line after an empty comment line is
+    ;;  simply ignored.
     (goto-char (point-min))
-    (while (re-search-forward "-- ?\\([^ -]\\)" nil t)
-      (replace-match "--  \\1"))
+    (while (re-search-forward "--[ \t]*\\([^-\n]\\)" nil t)
+      (replace-match "--  \\1")
+      (forward-line 1)
+      (beginning-of-line))
+
     (goto-char (point-min))
     (while (re-search-forward "\\>(" nil t)
-      (replace-match " ("))
+      (if (not (ada-in-string-or-comment-p))
+         (replace-match " (")))
+    (goto-char (point-min))
+    (while (re-search-forward ";--" nil t)
+      (forward-char -1)
+      (if (not (ada-in-string-or-comment-p))
+         (replace-match "; --")))
+    (goto-char (point-min))
+    (while (re-search-forward "([ \t]+" nil t)
+      (if (not (ada-in-string-or-comment-p))
+         (replace-match "(")))
+    (goto-char (point-min))
+    (while (re-search-forward ")[ \t]+)" nil t)
+      (if (not (ada-in-string-or-comment-p))
+         (replace-match "))")))
+    (goto-char (point-min))
+    (while (re-search-forward "\\>:" nil t)
+      (if (not (ada-in-string-or-comment-p))
+         (replace-match " :")))
+
+    ;;  Make sure there is a space after a ','.
+    ;;  Always go back to the beginning of the match, since otherwise
+    ;;  a statement like  ('F','D','E') is incorrectly modified.
+    (goto-char (point-min))
+    (while (re-search-forward ",[ \t]*\\(.\\)" nil t)
+      (if (not (save-excursion
+                (goto-char (match-beginning 0))
+                (ada-in-string-or-comment-p)))
+         (replace-match ", \\1")))
+
+    ;;  Operators should be surrounded by spaces.
     (goto-char (point-min))
-    (while (re-search-forward ",\\<" nil t)
-      (replace-match ", "))
+    (while (re-search-forward
+           "[ \t]*\\(/=\\|\\*\\*\\|:=\\|\\.\\.\\|[-:+*/]\\)[ \t]*"
+           nil t)
+      (goto-char (match-beginning 1))
+      (if (or (looking-at "--")
+             (ada-in-string-or-comment-p))
+         (progn
+           (forward-line 1)
+           (beginning-of-line))
+       (cond
+        ((string= (match-string 1) "/=")
+         (replace-match " /= "))
+        ((string= (match-string 1) "..")
+         (replace-match " .. "))
+        ((string= (match-string 1) "**")
+         (replace-match " ** "))
+        ((string= (match-string 1) ":=")
+         (replace-match " := "))
+        (t
+         (replace-match " \\1 ")))
+       (forward-char 1)))
     ))
 
 
 \f
 ;; -------------------------------------------------------------
-;; --  Moving To Procedures/Packages
+;; --  Moving To Procedures/Packages/Statements
 ;; -------------------------------------------------------------
 
+(defun ada-move-to-start ()
+  "Moves point to the matching start of the current Ada structure."
+  (interactive)
+  (let ((pos (point))
+        (previous-syntax-table (syntax-table)))
+    (unwind-protect
+        (progn
+          (set-syntax-table ada-mode-symbol-syntax-table)
+
+          (save-excursion
+            ;;
+            ;; do nothing if in string or comment or not on 'end ...;'
+            ;;            or if an error occurs during processing
+            ;;
+            (or
+             (ada-in-string-or-comment-p)
+             (and (progn
+                    (or (looking-at "[ \t]*\\<end\\>")
+                        (backward-word 1))
+                    (or (looking-at "[ \t]*\\<end\\>")
+                        (backward-word 1))
+                    (or (looking-at "[ \t]*\\<end\\>")
+                        (error "not on end ...;")))
+                  (ada-goto-matching-start 1)
+                  (setq pos (point))
+
+                  ;;
+                  ;; on 'begin' => go on, according to user option
+                  ;;
+                  ada-move-to-declaration
+                  (looking-at "\\<begin\\>")
+                  (ada-goto-matching-decl-start)
+                  (setq pos (point))))
+
+            )                           ; end of save-excursion
+
+          ;; now really move to the found position
+          (goto-char pos))
+
+      ;; restore syntax-table
+      (set-syntax-table previous-syntax-table))))
+
+(defun ada-move-to-end ()
+  "Moves point to the matching end of the block around point.
+Moves to 'begin' if in a declarative part."
+  (interactive)
+  (let ((pos (point))
+       decl-start
+        (previous-syntax-table (syntax-table)))
+    (unwind-protect
+        (progn
+          (set-syntax-table ada-mode-symbol-syntax-table)
+
+          (save-excursion
+
+            (cond
+             ;; Go to the beginning of the current word, and check if we are
+             ;; directly on 'begin'
+            ((save-excursion
+               (skip-syntax-backward "w")
+               (looking-at "\\<begin\\>"))
+             (ada-goto-matching-end 1)
+             )
+
+            ;; on first line of subprogram body
+            ;; Do nothing for specs or generic instantion, since these are
+            ;; handled as the general case (find the enclosing block)
+            ;; We also need to make sure that we ignore nested subprograms
+            ((save-excursion
+               (and (skip-syntax-backward "w")
+                    (looking-at "\\<function\\>\\|\\<procedure\\>" )
+                    (ada-search-ignore-string-comment "is\\|;")
+                    (not (= (char-before) ?\;))
+                    ))
+             (skip-syntax-backward "w")
+             (ada-goto-matching-end 0 t))
+
+             ;; on first line of task declaration
+             ((save-excursion
+                (and (ada-goto-stmt-start)
+                     (looking-at "\\<task\\>" )
+                     (forward-word 1)
+                     (ada-goto-next-non-ws)
+                     (looking-at "\\<body\\>")))
+              (ada-search-ignore-string-comment "begin" nil nil nil
+                                                'word-search-forward))
+             ;; accept block start
+             ((save-excursion
+                (and (ada-goto-stmt-start)
+                     (looking-at "\\<accept\\>" )))
+              (ada-goto-matching-end 0))
+             ;; package start
+             ((save-excursion
+               (setq decl-start (and (ada-goto-matching-decl-start t) (point)))
+                (and decl-start (looking-at "\\<package\\>")))
+              (ada-goto-matching-end 1))
+
+            ;;  On a "declare" keyword
+            ((save-excursion
+               (skip-syntax-backward "w")
+               (looking-at "\\<declare\\>"))
+             (ada-goto-matching-end 0 t))
+
+             ;; inside a 'begin' ... 'end' block
+             (decl-start
+             (goto-char decl-start)
+             (ada-goto-matching-end 0 t))
+
+             ;; (hopefully ;-) everything else
+             (t
+              (ada-goto-matching-end 1)))
+            (setq pos (point))
+            )
+
+          ;; now really move to the position found
+          (goto-char pos))
+
+      ;; restore syntax-table
+      (set-syntax-table previous-syntax-table))))
+
 (defun ada-next-procedure ()
   "Moves point to next procedure."
   (interactive)
   (end-of-line)
   (if (re-search-forward ada-procedure-start-regexp nil t)
-      (goto-char (match-beginning 1))
+      (goto-char (match-beginning 2))
     (error "No more functions/procedures/tasks")))
 
 (defun ada-previous-procedure ()
@@ -3584,7 +4447,7 @@ of the region.  Otherwise, operates only on the current line."
   (interactive)
   (beginning-of-line)
   (if (re-search-backward ada-procedure-start-regexp nil t)
-      (goto-char (match-beginning 1))
+      (goto-char (match-beginning 2))
     (error "No more functions/procedures/tasks")))
 
 (defun ada-next-package ()
@@ -3617,9 +4480,9 @@ of the region.  Otherwise, operates only on the current line."
   (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 ada-xemacs
+  (if (featurep 'xemacs)
       (define-key ada-mode-map '(shift tab)    'ada-untab)
-    (define-key ada-mode-map [S-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.
 
@@ -3637,8 +4500,14 @@ of the region.  Otherwise, operates only on the current line."
   (define-key ada-mode-map "\C-c\C-b" 'ada-adjust-case-buffer)
   (define-key ada-mode-map "\C-c\C-t" 'ada-case-read-exceptions)
   (define-key ada-mode-map "\C-c\C-y" 'ada-create-case-exception)
+  (define-key ada-mode-map "\C-c\C-\M-y" 'ada-create-case-exception-substring)
 
-  (define-key ada-mode-map "\177"     'backward-delete-char-untabify)
+  ;; 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))
 
   ;; Make body
   (define-key ada-mode-map "\C-c\C-n" 'ada-make-subprogram-body)
@@ -3646,71 +4515,232 @@ of the region.  Otherwise, operates only on the current line."
   ;; Use predefined function of Emacs19 for comments (RE)
   (define-key ada-mode-map "\C-c;"    'comment-region)
   (define-key ada-mode-map "\C-c:"    'ada-uncomment-region)
+
+  ;; 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 "\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-map "\C-cr"     '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-map "\C-c\C-v"  'ada-check-current)
+  (define-key ada-mode-map "\C-cf"     'ada-find-file)
+
+  (define-key ada-mode-map "\C-cu"  'ada-prj-edit)
+
+  ;;  The templates, defined in ada-stmt.el
+
+  (let ((map (make-sparse-keymap)))
+    (define-key map "h"    'ada-header)
+    (define-key map "\C-a" 'ada-array)
+    (define-key map "b"    'ada-exception-block)
+    (define-key map "d"    'ada-declare-block)
+    (define-key map "c"    'ada-case)
+    (define-key map "\C-e" 'ada-elsif)
+    (define-key map "e"    'ada-else)
+    (define-key map "\C-k" 'ada-package-spec)
+    (define-key map "k"    'ada-package-body)
+    (define-key map "\C-p" 'ada-procedure-spec)
+    (define-key map "p"    'ada-subprogram-body)
+    (define-key map "\C-f" 'ada-function-spec)
+    (define-key map "f"    'ada-for-loop)
+    (define-key map "i"    'ada-if)
+    (define-key map "l"    'ada-loop)
+    (define-key map "\C-r" 'ada-record)
+    (define-key map "\C-s" 'ada-subtype)
+    (define-key map "S"    'ada-tabsize)
+    (define-key map "\C-t" 'ada-task-spec)
+    (define-key map "t"    'ada-task-body)
+    (define-key map "\C-y" 'ada-type)
+    (define-key map "\C-v" 'ada-private)
+    (define-key map "u"    'ada-use)
+    (define-key map "\C-u" 'ada-with)
+    (define-key map "\C-w" 'ada-when)
+    (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))
   )
 
 
 (defun ada-create-menu ()
-  "Create the ada menu as shown in the menu bar.
-This function is designed to be extensible, so that each compiler-specific file
-can add its own items."
-
-  ;;  Note that the separators must have different length in the submenus
-  (autoload 'easy-menu-define "easymenu")
-  (autoload 'imenu "imenu")
-  (easy-menu-define
-   ada-mode-menu ada-mode-map "Menu keymap for Ada mode"
-   '("Ada"
-     ("Help"
-      ["Ada Mode" (info "ada-mode") t])
-     ["Customize" (customize-group 'ada)  (>= emacs-major-version 20)]
-     ("Goto"
-      ["Next compilation error"  next-error t]
-      ["Previous Package" ada-previous-package t]
-      ["Next Package" ada-next-package t]
-      ["Previous Procedure" ada-previous-procedure t]
-      ["Next Procedure" ada-next-procedure t]
-      ["Goto Start Of Statement" ada-move-to-start t]
-      ["Goto End Of Statement" ada-move-to-end t]
-      ["-" nil nil]
-      ["Other File" ff-find-other-file t]
-      ["Other File Other Window" ada-ff-other-window t])
-     ("Edit"
-      ["Indent Line"  ada-indent-current-function t]
-      ["Justify Current Indentation" ada-justified-indent-current t]
-      ["Indent Lines in Selection" ada-indent-region t]
-      ["Indent Lines in File" (ada-indent-region (point-min) (point-max)) t]
-      ["Format Parameter List" ada-format-paramlist t]
-      ["-" nil nil]
-      ["Comment Selection" comment-region t]
-      ["Uncomment Selection" ada-uncomment-region t]
-      ["--" nil nil]
-      ["Fill Comment Paragraph" fill-paragraph t]
-      ["Fill Comment Paragraph Justify" ada-fill-comment-paragraph-justify t]
-      ["Fill Comment Paragraph Postfix" ada-fill-comment-paragraph-postfix t]
-      ["---" nil nil]
-      ["Adjust Case Selection"  ada-adjust-case-region t]
-      ["Adjust Case Buffer"     ada-adjust-case-buffer t]
-      ["Create Case Exception"  ada-create-case-exception t]
-      ["Reload Case Exceptions" ada-case-read-exceptions t]
-      ["----" nil nil]
-      ["Make body for subprogram" ada-make-subprogram-body t]
-      )
-     ["Index" imenu t]
-     ))
-
-  (if ada-xemacs
-      (progn
-        (easy-menu-add ada-mode-menu ada-mode-map)
-        (define-key ada-mode-map [menu-bar] ada-mode-menu)
-        (set 'mode-popup-menu (cons "Ada mode" ada-mode-menu))
-       )
-    )
-  )
+  "Create the ada menu as shown in the menu bar."
+  (let ((m '("Ada"
+            ("Help"
+             ["Ada Mode"               (info "ada-mode") t]
+             ["GNAT User's Guide"      (info "gnat_ugn")
+              (eq ada-which-compiler 'gnat)]
+             ["GNAT Reference Manual"  (info "gnat_rm")
+              (eq ada-which-compiler 'gnat)]
+             ["Gcc Documentation"      (info "gcc")
+              (eq ada-which-compiler 'gnat)]
+             ["Gdb Documentation"      (info "gdb")
+              (eq ada-which-compiler 'gnat)]
+             ["Ada95 Reference Manual" (info "arm95")
+              (eq ada-which-compiler 'gnat)])
+            ("Options"  :included (eq major-mode 'ada-mode)
+             ["Auto Casing" (setq ada-auto-case (not ada-auto-case))
+              :style toggle :selected ada-auto-case]
+             ["Auto Indent After Return"
+              (setq ada-indent-after-return (not ada-indent-after-return))
+              :style toggle :selected ada-indent-after-return]
+             ["Automatically Recompile For Cross-references"
+              (setq ada-xref-create-ali (not ada-xref-create-ali))
+              :style toggle :selected ada-xref-create-ali
+              :included (eq ada-which-compiler 'gnat)]
+             ["Confirm Commands"
+              (setq ada-xref-confirm-compile (not ada-xref-confirm-compile))
+              :style toggle :selected ada-xref-confirm-compile
+              :included (eq ada-which-compiler 'gnat)]
+             ["Show Cross-references In Other Buffer"
+              (setq ada-xref-other-buffer (not ada-xref-other-buffer))
+              :style toggle :selected ada-xref-other-buffer
+              :included (eq ada-which-compiler 'gnat)]
+             ["Tight Integration With GNU Visual Debugger"
+              (setq ada-tight-gvd-integration (not ada-tight-gvd-integration))
+              :style toggle :selected ada-tight-gvd-integration
+              :included (string-match "gvd" ada-prj-default-debugger)])
+            ["Customize"     (customize-group 'ada)
+             :included (fboundp 'customize-group)]
+            ["Check file"    ada-check-current   (eq ada-which-compiler 'gnat)]
+            ["Compile file"  ada-compile-current (eq ada-which-compiler 'gnat)]
+            ["Build"         ada-compile-application
+             (eq ada-which-compiler 'gnat)]
+            ["Run"           ada-run-application     t]
+            ["Debug"         ada-gdb-application (eq ada-which-compiler 'gnat)]
+            ["------"        nil nil]
+            ("Project"
+              :included (eq ada-which-compiler 'gnat)
+             ["Load..."      ada-set-default-project-file t]
+             ["New..."       ada-prj-new                  t]
+             ["Edit..."      ada-prj-edit                 t])
+            ("Goto"   :included (eq major-mode 'ada-mode)
+             ["Goto Declaration/Body"   ada-goto-declaration
+              (eq ada-which-compiler 'gnat)]
+             ["Goto Body"               ada-goto-body
+              (eq ada-which-compiler 'gnat)]
+             ["Goto Declaration Other Frame"
+              ada-goto-declaration-other-frame
+              (eq ada-which-compiler 'gnat)]
+             ["Goto Previous Reference" ada-xref-goto-previous-reference
+              (eq ada-which-compiler 'gnat)]
+             ["List Local References"   ada-find-local-references
+              (eq ada-which-compiler 'gnat)]
+             ["List References"         ada-find-references
+              (eq ada-which-compiler 'gnat)]
+             ["Goto Reference To Any Entity" ada-find-any-references
+              (eq ada-which-compiler 'gnat)]
+             ["Goto Parent Unit"        ada-goto-parent
+              (eq ada-which-compiler 'gnat)]
+             ["--"                      nil                              nil]
+             ["Next compilation error"  next-error             t]
+             ["Previous Package"        ada-previous-package   t]
+             ["Next Package"            ada-next-package       t]
+             ["Previous Procedure"      ada-previous-procedure t]
+             ["Next Procedure"          ada-next-procedure     t]
+             ["Goto Start Of Statement" ada-move-to-start      t]
+             ["Goto End Of Statement"   ada-move-to-end        t]
+             ["-"                       nil                    nil]
+             ["Other File"              ff-find-other-file     t]
+             ["Other File Other Window" ada-ff-other-window    t])
+            ("Edit"   :included (eq major-mode 'ada-mode)
+             ["Search File On Source Path"  ada-find-file                t]
+             ["------"                      nil                          nil]
+             ["Complete Identifier"         ada-complete-identifier      t]
+             ["-----"                       nil                          nil]
+             ["Indent Line"                 ada-indent-current-function  t]
+             ["Justify Current Indentation" ada-justified-indent-current t]
+             ["Indent Lines in Selection"   ada-indent-region            t]
+             ["Indent Lines in File"
+              (ada-indent-region (point-min) (point-max))                t]
+             ["Format Parameter List"       ada-format-paramlist         t]
+             ["-"                           nil                          nil]
+             ["Comment Selection"           comment-region               t]
+             ["Uncomment Selection"         ada-uncomment-region         t]
+             ["--"                          nil                          nil]
+             ["Fill Comment Paragraph"      fill-paragraph               t]
+             ["Fill Comment Paragraph Justify"
+              ada-fill-comment-paragraph-justify                         t]
+             ["Fill Comment Paragraph Postfix"
+              ada-fill-comment-paragraph-postfix                         t]
+             ["---"                         nil                          nil]
+             ["Adjust Case Selection"       ada-adjust-case-region       t]
+             ["Adjust Case in File"         ada-adjust-case-buffer       t]
+             ["Create Case Exception"       ada-create-case-exception    t]
+             ["Create Case Exception Substring"
+              ada-create-case-exception-substring                        t]
+             ["Reload Case Exceptions"      ada-case-read-exceptions     t]
+             ["----"                        nil                          nil]
+             ["Make body for subprogram"    ada-make-subprogram-body     t]
+             ["-----"                       nil                          nil]
+              ["Narrow to subprogram"        ada-narrow-to-defun          t])
+            ("Templates"
+             :included  (eq major-mode 'ada-mode)
+             ["Header"          ada-header          t]
+             ["-"               nil                 nil]
+             ["Package Body"    ada-package-body    t]
+             ["Package Spec"    ada-package-spec    t]
+             ["Function Spec"   ada-function-spec   t]
+             ["Procedure Spec"  ada-procedure-spec  t]
+             ["Proc/func Body"  ada-subprogram-body t]
+             ["Task Body"       ada-task-body       t]
+             ["Task Spec"       ada-task-spec       t]
+             ["Declare Block"   ada-declare-block   t]
+             ["Exception Block" ada-exception-block t]
+             ["--"              nil                 nil]
+             ["Entry"           ada-entry           t]
+             ["Entry family"    ada-entry-family    t]
+             ["Select"          ada-select          t]
+             ["Accept"          ada-accept          t]
+             ["Or accept"       ada-or-accep        t]
+             ["Or delay"        ada-or-delay        t]
+             ["Or terminate"    ada-or-terminate    t]
+             ["---"             nil                 nil]
+             ["Type"            ada-type            t]
+             ["Private"         ada-private         t]
+             ["Subtype"         ada-subtype         t]
+             ["Record"          ada-record          t]
+             ["Array"           ada-array           t]
+             ["----"            nil                 nil]
+             ["If"              ada-if              t]
+             ["Else"            ada-else            t]
+             ["Elsif"           ada-elsif           t]
+             ["Case"            ada-case            t]
+             ["-----"           nil                 nil]
+             ["While Loop"      ada-while-loop      t]
+             ["For Loop"        ada-for-loop        t]
+             ["Loop"            ada-loop            t]
+             ["------"          nil                 nil]
+             ["Exception"       ada-exception       t]
+             ["Exit"            ada-exit            t]
+             ["When"            ada-when            t])
+            )))
+
+    (easy-menu-define ada-mode-menu ada-mode-map "Menu keymap for Ada mode" m)
+    (if (featurep 'xemacs)
+       (progn
+         (define-key ada-mode-map [menu-bar] ada-mode-menu)
+         (set 'mode-popup-menu (cons "Ada mode" ada-mode-menu))))))
 
 \f
 ;; -------------------------------------------------------
 ;;     Commenting/Uncommenting code
-;;  The two following calls are provided to enhance the standard
+;;  The following two calls are provided to enhance the standard
 ;;  comment-region function, which only allows uncommenting if the
 ;;  comment is at the beginning of a line. If the line have been re-indented,
 ;;  we are unable to use comment-region, which makes no sense.
@@ -3719,9 +4749,10 @@ can add its own items."
 ;;  function for justifying the comments.
 ;; -------------------------------------------------------
 
-(defadvice comment-region (before ada-uncomment-anywhere)
+(defadvice comment-region (before ada-uncomment-anywhere disable)
   (if (and arg
-           (< arg 0)
+           (listp 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"))
       (save-excursion
         (let ((cs (concat "^[ \t]*" (regexp-quote comment-start))))
@@ -3733,9 +4764,16 @@ can add its own items."
 (defun ada-uncomment-region (beg end &optional arg)
   "Delete `comment-start' at the beginning of a line in the region."
   (interactive "r\nP")
-  (ad-activate 'comment-region)
-  (comment-region beg end (- (or arg 1)))
-  (ad-deactivate 'comment-region))
+
+  ;;  This advice is not needed anymore with Emacs21. However, for older
+  ;;  versions, as well as for XEmacs, we still need to enable it.
+  (if (or (<= emacs-major-version 20) (featurep 'xemacs))
+      (progn
+       (ad-activate 'comment-region)
+       (comment-region beg end (- (or arg 2)))
+       (ad-deactivate 'comment-region))
+    (comment-region beg end (list (- (or arg 2))))
+    (ada-indent-region beg end)))
 
 (defun ada-fill-comment-paragraph-justify ()
   "Fills current comment paragraph and justifies each line as well."
@@ -3761,55 +4799,62 @@ The paragraph is indented on the first line."
            (not (looking-at "[ \t]*--")))
       (error "not inside comment"))
 
-  (let* ((indent)
-         (from)
-         (to)
-         (opos             (point-marker))
+  (let* (indent from to
+         (opos (point-marker))
+
+         ;; Sets this variable to nil, otherwise it prevents
+         ;; fill-region-as-paragraph to work on Emacs <= 20.2
+         (parse-sexp-lookup-properties nil)
 
-        ;; Sets this variable to nil, otherwise it prevents
-        ;; fill-region-as-paragraph to work on Emacs <= 20.2
-        (parse-sexp-lookup-properties nil)
-        
          fill-prefix
          (fill-column (current-fill-column)))
 
     ;;  Find end of paragraph
     (back-to-indentation)
-    (while (and (not (eobp)) (looking-at "--[ \t]*[^ \t\n]"))
+    (while (and (not (eobp)) (looking-at ".*--[ \t]*[^ \t\n]"))
       (forward-line 1)
-      (back-to-indentation))
+
+      ;;  If we were at the last line in the buffer, create a dummy empty
+      ;;  line at the end of the buffer.
+      (if (eobp)
+         (insert "\n")
+       (back-to-indentation)))
     (beginning-of-line)
-    (set 'to (point-marker))
+    (setto (point-marker))
     (goto-char opos)
 
     ;;  Find beginning of paragraph
     (back-to-indentation)
-    (while (and (not (bobp)) (looking-at "--[ \t]*[^ \t\n]"))
+    (while (and (not (bobp)) (looking-at ".*--[ \t]*[^ \t\n]"))
       (forward-line -1)
       (back-to-indentation))
-    (forward-line 1)
+
+    ;;  We want one line above the first one, unless we are at the beginning
+    ;;  of the buffer
+    (unless (bobp)
+      (forward-line 1))
     (beginning-of-line)
-    (set 'from (point-marker))
+    (setfrom (point-marker))
 
     ;;  Calculate the indentation we will need for the paragraph
     (back-to-indentation)
-    (set 'indent (current-column))
+    (setindent (current-column))
     ;;  unindent the first line of the paragraph
     (delete-region from (point))
 
     ;;  Remove the old postfixes
     (goto-char from)
-    (while (re-search-forward (concat ada-fill-comment-postfix "\n") to t)
+    (while (re-search-forward "--\n" to t)
       (replace-match "\n"))
 
     (goto-char (1- to))
-    (set 'to (point-marker))
+    (setto (point-marker))
 
     ;;  Indent and justify the paragraph
-    (set 'fill-prefix ada-fill-comment-prefix)
+    (setfill-prefix ada-fill-comment-prefix)
     (set-left-margin from to indent)
     (if postfix
-        (set 'fill-column (- fill-column (length ada-fill-comment-postfix))))
+        (setfill-column (- fill-column (length ada-fill-comment-postfix))))
 
     (fill-region-as-paragraph from to justify)
 
@@ -3827,7 +4872,7 @@ The paragraph is indented on the first line."
 
     ;;  In Emacs <= 20.2 and XEmacs <=20.4, there is a bug, and a newline is
     ;;  inserted at the end. Delete it
-    (if (or ada-xemacs
+    (if (or (featurep 'xemacs)
             (<= emacs-major-version 19)
             (and (= emacs-major-version 20)
                  (<= emacs-minor-version 2)))
@@ -3838,6 +4883,7 @@ The paragraph is indented on the first line."
 
     (goto-char opos)))
 
+
 ;; ---------------------------------------------------
 ;;    support for find-file.el
 ;; These functions are used by find-file to guess the file names from
@@ -3856,36 +4902,163 @@ The paragraph is indented on the first line."
   "Determine the filename in which ADANAME is found.
 This is a generic function, independent from any compiler."
   (while (string-match "\\." adaname)
-    (set 'adaname (replace-match "-" t t adaname)))
-  adaname
+    (setadaname (replace-match "-" t t adaname)))
+  (downcase adaname)
   )
 
 (defun ada-other-file-name ()
-  "Return the name of the other file (the body if current-buffer is the spec,
-or the spec otherwise."
-  (let ((ff-always-try-to-create nil)
-        (buffer                  (current-buffer))
-        name)
-    (ff-find-other-file nil t)  ;; same window, ignore 'with' lines
-
-    ;;  If the other file was not found, return an empty string
-    (if (equal buffer (current-buffer))
-        ""
-      (set 'name (buffer-file-name))
-      (switch-to-buffer buffer)
-      name)))
+  "Return the name of the other file.
+The name returned is the body if current-buffer is the spec, or the spec
+otherwise."
+
+  (let ((is-spec nil)
+       (is-body nil)
+       (suffixes ada-spec-suffixes)
+       (name  (buffer-file-name)))
+
+    ;;  Guess whether we have a spec or a body, and get the basename of the
+    ;;  file. Since the extension may not start with '.', we can not use
+    ;;  file-name-extension
+    (while (and (not is-spec)
+               suffixes)
+      (if (string-match (concat "\\(.*\\)" (car suffixes) "$") name)
+         (setq is-spec t
+               name    (match-string 1 name)))
+      (setq suffixes (cdr suffixes)))
+
+    (if (not is-spec)
+       (progn
+         (setq suffixes ada-body-suffixes)
+         (while (and (not is-body)
+                     suffixes)
+           (if (string-match (concat "\\(.*\\)" (car suffixes) "$") name)
+               (setq is-body t
+                     name    (match-string 1 name)))
+           (setq suffixes (cdr suffixes)))))
+
+    ;;  If this wasn't in either list, return name itself
+    (if (not (or is-spec is-body))
+       name
+
+      ;;  Else find the other possible names
+      (if is-spec
+         (setq suffixes ada-body-suffixes)
+       (setq suffixes ada-spec-suffixes))
+      (setq is-spec name)
+
+      (while suffixes
+
+       ;;  If we are using project file, search for the other file in all
+       ;;  the possible src directories.
+
+       (if (fboundp 'ada-find-src-file-in-dir)
+           (let ((other
+                  (ada-find-src-file-in-dir
+                   (file-name-nondirectory (concat name (car suffixes))))))
+             (if other
+                 (set 'is-spec other)))
+
+         ;;  Else search in the current directory
+         (if (file-exists-p (concat name (car suffixes)))
+             (setq is-spec (concat name (car suffixes)))))
+       (setq suffixes (cdr suffixes)))
+
+      is-spec)))
 
 (defun ada-which-function-are-we-in ()
   "Return the name of the function whose definition/declaration point is in.
 Redefines the function `ff-which-function-are-we-in'."
-  (set 'ff-function-name nil)
+  (setff-function-name nil)
   (save-excursion
-    (end-of-line)   ;;  make sure we get the complete name
+    (end-of-line);;  make sure we get the complete name
     (if (or (re-search-backward ada-procedure-start-regexp nil t)
             (re-search-backward ada-package-start-regexp nil t))
-        (set 'ff-function-name (match-string 0)))
+        (setff-function-name (match-string 0)))
     ))
 
+
+(defvar ada-last-which-function-line -1
+  "Last on which ada-which-function was called")
+(defvar ada-last-which-function-subprog 0
+  "Last subprogram name returned by ada-which-function")
+(make-variable-buffer-local 'ada-last-which-function-subprog)
+(make-variable-buffer-local 'ada-last-which-function-line)
+
+
+(defun ada-which-function ()
+  "Returns the name of the function whose body the point is in.
+This function works even in the case of nested subprograms, whereas the
+standard Emacs function `which-function' does not.
+Since the search can be long, the results are cached."
+
+  (let ((line (count-lines 1 (point)))
+        (pos (point))
+        end-pos
+        func-name indent
+        found)
+
+    ;;  If this is the same line as before, simply return the same result
+    (if (= line ada-last-which-function-line)
+        ada-last-which-function-subprog
+
+      (save-excursion
+        ;; In case the current line is also the beginning of the body
+        (end-of-line)
+
+       ;;  Are we looking at "function Foo\n    (paramlist)"
+       (skip-chars-forward " \t\n(")
+
+       (condition-case nil
+           (up-list 1)
+         (error nil))
+
+       (skip-chars-forward " \t\n")
+       (if (looking-at "return")
+           (progn
+             (forward-word 1)
+             (skip-chars-forward " \t\n")
+             (skip-chars-forward "a-zA-Z0-9_'")))
+
+        ;; Can't simply do forward-word, in case the "is" is not on the
+        ;; same line as the closing parenthesis
+        (skip-chars-forward "is \t\n")
+
+        ;; No look for the closest subprogram body that has not ended yet.
+        ;; Not that we expect all the bodies to be finished by "end <name>",
+        ;; or a simple "end;" indented in the same column as the start of
+       ;; the subprogram. The goal is to be as efficient as possible.
+
+        (while (and (not found)
+                    (re-search-backward ada-imenu-subprogram-menu-re nil t))
+
+         ;; Get the function name, but not the properties, or this changes
+         ;; the face in the modeline on Emacs 21
+          (setq func-name (match-string-no-properties 2))
+          (if (and (not (ada-in-comment-p))
+                   (not (save-excursion
+                          (goto-char (match-end 0))
+                          (looking-at "[ \t\n]*new"))))
+              (save-excursion
+               (back-to-indentation)
+               (setq indent (current-column))
+                (if (ada-search-ignore-string-comment
+                     (concat "end[ \t]+" func-name "[ \t]*;\\|^"
+                            (make-string indent ? ) "end;"))
+                    (setq end-pos (point))
+                  (setq end-pos (point-max)))
+                (if (>= end-pos pos)
+                    (setq found func-name))))
+          )
+        (setq ada-last-which-function-line line
+              ada-last-which-function-subprog found)
+        found))))
+
+(defun ada-ff-other-window ()
+  "Find other file in other window using `ff-find-other-file'."
+  (interactive)
+  (and (fboundp 'ff-find-other-file)
+       (ff-find-other-file t)))
+
 (defun ada-set-point-accordingly ()
   "Move to the function declaration that was set by
 `ff-which-function-are-we-in'."
@@ -3893,9 +5066,42 @@ Redefines the function `ff-which-function-are-we-in'."
       (progn
         (goto-char (point-min))
         (unless (ada-search-ignore-string-comment
-                (concat ff-function-name "\\b") nil)
+                 (concat ff-function-name "\\b") nil)
           (goto-char (point-min))))))
 
+(defun ada-get-body-name (&optional spec-name)
+  "Returns the file name for the body of SPEC-NAME.
+If SPEC-NAME is nil, returns the body for the current package.
+Returns nil if no body was found."
+  (interactive)
+
+  (unless spec-name (setq spec-name (buffer-file-name)))
+
+  ;; Remove the spec extension. We can not simply remove the file extension,
+  ;; but we need to take into account the specific non-GNAT extensions that the
+  ;; user might have specified.
+
+  (let ((suffixes ada-spec-suffixes)
+       end)
+    (while suffixes
+      (setq end (- (length spec-name) (length (car suffixes))))
+      (if (string-equal (car suffixes) (substring spec-name end))
+         (setq spec-name (substring spec-name 0 end)))
+      (setq suffixes (cdr suffixes))))
+
+  ;; If find-file.el was available, use its functions
+  (if (fboundp 'ff-get-file-name)
+      (ff-get-file-name ada-search-directories-internal
+                        (ada-make-filename-from-adaname
+                         (file-name-nondirectory
+                          (file-name-sans-extension spec-name)))
+                        ada-body-suffixes)
+    ;; Else emulate it very simply
+    (concat (ada-make-filename-from-adaname
+             (file-name-nondirectory
+              (file-name-sans-extension spec-name)))
+            ".adb")))
+
 \f
 ;; ---------------------------------------------------
 ;;    support for font-lock.el
@@ -3916,7 +5122,7 @@ Redefines the function `ff-which-function-are-we-in'."
   ;; a string
   ;; This sets the properties of the characters, so that ada-in-string-p
   ;; correctly handles '"' too...
-  '(("\\('\\)[^'\n]\\('\\)" (1 (7 . ?')) (2 (7 . ?')))
+  '(("[^a-zA-Z0-9)]\\('\\)[^'\n]\\('\\)" (1 (7 . ?')) (2 (7 . ?')))
     ("^[ \t]*\\(#\\(if\\|else\\|elsif\\|end\\)\\)" (1 (11 . ?\n)))
     ))
 
@@ -3954,7 +5160,7 @@ Redefines the function `ff-which-function-are-we-in'."
      ;;
      ;; Optional keywords followed by a type name.
      (list (concat                      ; ":[ \t]*"
-            "\\<\\(access[ \t]+all\\|access\\|constant\\|in[ \t]+out\\|in\\|out\\)\\>"
+            "\\<\\(access[ \t]+all\\|access[ \t]+constant\\|access\\|constant\\|in[ \t]+reverse\\|\\|in[ \t]+out\\|in\\|out\\)\\>"
             "[ \t]*"
             "\\(\\sw+\\(\\.\\sw*\\)*\\)?")
            '(1 font-lock-keyword-face nil t) '(2 font-lock-type-face nil t))
@@ -3970,7 +5176,7 @@ Redefines the function `ff-which-function-are-we-in'."
                 "null" "or" "others" "private" "protected" "raise"
                 "range" "record" "rem" "renames" "requeue" "return" "reverse"
                 "select" "separate" "tagged" "task" "terminate" "then" "until"
-                "when" "while" "xor") t)
+                "when" "while" "with" "xor") t)
              "\\>")
      ;;
      ;; Anything following end and not already fontified is a body name.
@@ -3987,15 +5193,26 @@ Redefines the function `ff-which-function-are-we-in'."
                  font-lock-type-face) nil t))
      ;;
      ;; Keywords followed by a (comma separated list of) reference.
-     (list (concat "\\<\\(goto\\|raise\\|use\\|with\\)\\>" ; "when" removed
-                   "[ \t\n]*\\(\\(\\sw\\|[_.|, \t\n]\\)+\\)\\W")
+     ;; Note that font-lock only works on single lines, thus we can not
+     ;; correctly highlight a with_clause that spans multiple lines.
+     (list (concat "\\<\\(goto\\|raise\\|use\\|with\\)"
+                   "[ \t]+\\([a-zA-Z0-9_., \t]+\\)\\W")
            '(1 font-lock-keyword-face) '(2 font-lock-reference-face nil t))
+
      ;;
      ;; Goto tags.
      '("<<\\(\\sw+\\)>>" 1 font-lock-reference-face)
+
+     ;; Highlight based-numbers (R. Reagan <robin-reply@reagans.org>)
+     (list "\\([0-9]+#[0-9a-fA-F_]+#\\)" '(1 font-lock-constant-face t))
+
+     ;; Ada unnamed numerical constants
+     (list "\\W\\([-+]?[0-9._]+\\)\\>" '(1 font-lock-constant-face))
+
      ))
   "Default expressions to highlight in Ada mode.")
 
+
 ;; ---------------------------------------------------------
 ;;  Support for outline.el
 ;; ---------------------------------------------------------
@@ -4008,6 +5225,33 @@ Redefines the function `ff-which-function-are-we-in'."
       (back-to-indentation)
       (current-column))))
 
+;; ---------------------------------------------------------
+;;  Support for narrow-to-region
+;; ---------------------------------------------------------
+
+(defun ada-narrow-to-defun (&optional arg)
+  "make text outside current subprogram invisible.
+The subprogram visible is the one that contains or follow point.
+Optional ARG is ignored.
+Use `M-x widen' to go back to the full visibility for the buffer"
+
+  (interactive)
+  (save-excursion
+    (let (end)
+      (widen)
+      (forward-line 1)
+      (ada-previous-procedure)
+
+      (save-excursion
+        (beginning-of-line)
+        (setq end (point)))
+
+      (ada-move-to-end)
+      (end-of-line)
+      (narrow-to-region end (point))
+      (message
+       "Use M-x widen to get back to full visibility in the buffer"))))
+
 ;; ---------------------------------------------------------
 ;;    Automatic generation of code
 ;; The Ada-mode has a set of function to automatically generate a subprogram
@@ -4026,11 +5270,11 @@ for ada-procedure-start-regexp."
   (let (func-found procname functype)
     (cond
      ((or (looking-at "^[ \t]*procedure")
-          (set 'func-found (looking-at "^[ \t]*function")))
+          (setfunc-found (looking-at "^[ \t]*function")))
       ;; treat it as a proc/func
       (forward-word 2)
       (forward-word -1)
-      (set 'procname (buffer-substring (point) (cdr match))) ; store  proc name
+      (setprocname (buffer-substring (point) (cdr match))) ; store  proc name
 
       ;; goto end of procname
       (goto-char (cdr match))
@@ -4044,7 +5288,7 @@ for ada-procedure-start-regexp."
           (progn
             (forward-word 1)
             (skip-chars-forward " \t\n")
-            (set 'functype (buffer-substring (point)
+            (setfunctype (buffer-substring (point)
                                              (progn
                                                (skip-chars-forward
                                                 "a-zA-Z0-9_\.")
@@ -4099,19 +5343,19 @@ This function typically is to be hooked into `ff-file-created-hooks'."
   (ada-mode)
 
   (let (found ada-procedure-or-package-start-regexp)
-    (if (set 'found
+    (if (setfound
              (ada-search-ignore-string-comment ada-package-start-regexp nil))
         (progn (goto-char (cdr found))
                (insert " body")
                )
       (error "No package"))
 
-    (set 'ada-procedure-or-package-start-regexp
+    (setada-procedure-or-package-start-regexp
          (concat ada-procedure-start-regexp
                  "\\|"
                  ada-package-start-regexp))
 
-    (while (set 'found
+    (while (setfound
                 (ada-search-ignore-string-comment
                  ada-procedure-or-package-start-regexp nil))
       (progn
@@ -4121,11 +5365,13 @@ This function typically is to be hooked into `ff-file-created-hooks'."
                    (insert " body"))
           (ada-gen-treat-proc found))))))
 
+
 (defun ada-make-subprogram-body ()
   "Make one dummy subprogram body from spec surrounding point."
   (interactive)
   (let* ((found (re-search-backward ada-procedure-start-regexp nil t))
-         (spec  (match-beginning 0)))
+         (spec  (match-beginning 0))
+         body-file)
     (if found
         (progn
           (goto-char spec)
@@ -4134,22 +5380,14 @@ This function typically is to be hooked into `ff-file-created-hooks'."
               (progn
                 (ada-search-ignore-string-comment ")" nil)
                 (ada-search-ignore-string-comment ";" nil)))
-          (set 'spec (buffer-substring spec (point)))
-
-         ;; If find-file.el was available, use its functions
-         (if (functionp 'ff-get-file)
-             (find-file (ff-get-file
-                         ff-search-directories
-                         (ada-make-filename-from-adaname
-                          (file-name-nondirectory
-                           (file-name-sans-extension (buffer-name))))
-                         ada-body-suffixes))
-           ;; Else emulate it very simply
-           (find-file (concat (ada-make-filename-from-adaname
-                               (file-name-nondirectory
-                                (file-name-sans-extension (buffer-name))))
-                              ".adb")))
-           
+          (setq spec (buffer-substring spec (point)))
+
+          ;; If find-file.el was available, use its functions
+          (setq body-file (ada-get-body-name))
+          (if body-file
+              (find-file body-file)
+            (error "No body found for the package. Create it first."))
+
           (save-restriction
             (widen)
             (goto-char (point-max))
@@ -4187,18 +5425,68 @@ This function typically is to be hooked into `ff-file-created-hooks'."
 ;;  Read the special cases for exceptions
 (ada-case-read-exceptions)
 
-;; include the other ada-mode files
-
+;;  Setup auto-loading of the other ada-mode files.
 (if (equal ada-which-compiler 'gnat)
     (progn
-      ;; The order here is important: ada-xref defines the Project
-      ;; submenu, and ada-prj adds to it.
-      (condition-case nil  (require 'ada-prj) (error nil))
-      (require 'ada-xref)
+      (autoload 'ada-change-prj                   "ada-xref" nil t)
+      (autoload 'ada-check-current                "ada-xref" nil t)
+      (autoload 'ada-compile-application          "ada-xref" nil t)
+      (autoload 'ada-compile-current              "ada-xref" nil t)
+      (autoload 'ada-complete-identifier          "ada-xref" nil t)
+      (autoload 'ada-find-file                    "ada-xref" nil t)
+      (autoload 'ada-find-any-references          "ada-xref" nil t)
+      (autoload 'ada-find-src-file-in-dir         "ada-xref" nil t)
+      (autoload 'ada-find-local-references        "ada-xref" nil t)
+      (autoload 'ada-find-references              "ada-xref" nil t)
+      (autoload 'ada-gdb-application              "ada-xref" nil t)
+      (autoload 'ada-goto-declaration             "ada-xref" nil t)
+      (autoload 'ada-goto-declaration-other-frame "ada-xref" nil t)
+      (autoload 'ada-goto-parent                  "ada-xref" nil t)
+      (autoload 'ada-make-body-gnatstub           "ada-xref" nil t)
+      (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-customize                    "ada-prj"  nil t)
+      (autoload 'ada-prj-edit                     "ada-prj"  nil t)
+      (autoload 'ada-prj-new                      "ada-prj"  nil t)
+      (autoload 'ada-prj-save                     "ada-prj"  nil t)
       ))
-(condition-case nil (require 'ada-stmt) (error nil))
+
+(autoload 'ada-array           "ada-stmt" nil t)
+(autoload 'ada-case            "ada-stmt" nil t)
+(autoload 'ada-declare-block   "ada-stmt" nil t)
+(autoload 'ada-else            "ada-stmt" nil t)
+(autoload 'ada-elsif           "ada-stmt" nil t)
+(autoload 'ada-exception       "ada-stmt" nil t)
+(autoload 'ada-exception-block "ada-stmt" nil t)
+(autoload 'ada-exit            "ada-stmt" nil t)
+(autoload 'ada-for-loop        "ada-stmt" nil t)
+(autoload 'ada-function-spec   "ada-stmt" nil t)
+(autoload 'ada-header          "ada-stmt" nil t)
+(autoload 'ada-if              "ada-stmt" nil t)
+(autoload 'ada-loop            "ada-stmt" nil t)
+(autoload 'ada-package-body    "ada-stmt" nil t)
+(autoload 'ada-package-spec    "ada-stmt" nil t)
+(autoload 'ada-private         "ada-stmt" nil t)
+(autoload 'ada-procedure-spec  "ada-stmt" nil t)
+(autoload 'ada-record          "ada-stmt" nil t)
+(autoload 'ada-subprogram-body "ada-stmt" nil t)
+(autoload 'ada-subtype         "ada-stmt" nil t)
+(autoload 'ada-tabsize         "ada-stmt" nil t)
+(autoload 'ada-task-body       "ada-stmt" nil t)
+(autoload 'ada-task-spec       "ada-stmt" nil t)
+(autoload 'ada-type            "ada-stmt" nil t)
+(autoload 'ada-use             "ada-stmt" nil t)
+(autoload 'ada-when            "ada-stmt" nil t)
+(autoload 'ada-while-loop      "ada-stmt" nil t)
+(autoload 'ada-with            "ada-stmt" nil t)
 
 ;;; provide ourselves
 (provide 'ada-mode)
 
+;;; arch-tag: 1b7d45ec-1698-43b5-8d4a-e479ea023270
 ;;; ada-mode.el ends here