Refill some long/short copyright headers.
[bpt/emacs.git] / lisp / progmodes / ada-xref.el
index c63850e..85659ca 100644 (file)
@@ -1,20 +1,20 @@
 ;; ada-xref.el --- for lookup and completion in Ada mode
 
-;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-;;               2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2011  Free Software Foundation, Inc.
 
 ;; Author: Markus Heritsch <Markus.Heritsch@studbox.uni-stuttgart.de>
 ;;      Rolf Ebert <ebert@inf.enst.fr>
 ;;      Emmanuel Briot <briot@gnat.com>
 ;; Maintainer: Stephen Leake <stephen_leake@stephe-leake.org>
 ;; Keywords: languages ada xref
+;; Package: ada-mode
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -22,9 +22,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 ;;; This Package provides a set of functions to use the output of the
@@ -62,7 +60,7 @@ If nil, the cross-reference mode never runs gcc."
   :type 'boolean :group 'ada)
 
 (defcustom ada-xref-confirm-compile nil
-  "*Non-nil means ask for confirmation before compiling or running the application."
+  "*If non-nil, ask for confirmation before compiling or running the application."
   :type 'boolean :group 'ada)
 
 (defcustom ada-krunch-args "0"
@@ -70,6 +68,13 @@ If nil, the cross-reference mode never runs gcc."
 Set to 0, if you don't use crunched filenames.  This should be a string."
   :type 'string :group 'ada)
 
+(defcustom ada-gnat-cmd "gnat"
+  "Default GNAT project file parser.
+Will be run with args \"list -v -Pfile.gpr\".
+Default is standard GNAT distribution; alternate \"gnatpath\"
+is faster, available from Ada mode web site."
+  :type 'string :group 'ada)
+
 (defcustom ada-gnatls-args '("-v")
   "*Arguments to pass to `gnatls' to find location of the runtime.
 Typical use is to pass `--RTS=soft-floats' on some systems that support it.
@@ -96,6 +101,19 @@ but only ADA_INCLUDE_PATH."
   "Default options for `gnatmake'."
   :type 'string :group 'ada)
 
+(defcustom ada-prj-default-gpr-file ""
+  "Default GNAT project file.
+If non-empty, this file is parsed to set the source and object directories for
+the Ada mode project."
+  :type 'string :group 'ada)
+
+(defcustom ada-prj-ada-project-path-sep
+  (cond ((boundp 'path-separator) path-separator) ; 20.3+
+       ((memq system-type '(windows-nt ms-dos)) ";")
+       (t ":"))
+  "Default separator for ada_project_path project variable."
+  :type 'string :group 'ada)
+
 (defcustom ada-prj-gnatfind-switches "-rf"
   "Default switches to use for `gnatfind'.
 You should modify this variable, for instance to add `-a', if you are working
@@ -125,7 +143,7 @@ the filename at the end.  This is the same syntax as in the project file."
   :type 'string :group 'ada)
 
 (defcustom ada-prj-default-make-cmd
-  (concat "${cross_prefix}gnatmake -o ${main} ${main_unit} ${gnatmake_opt} "
+  (concat "${cross_prefix}gnatmake -o ${main} ${main} ${gnatmake_opt} "
          "-cargs ${comp_opt} -bargs ${bind_opt} -largs ${link_opt}")
   "*Default command to be used to compile the application.
 This is the same syntax as in the project file."
@@ -138,7 +156,7 @@ this string is not empty.  It is set whenever a project file is found."
   :type '(file :must-match t) :group 'ada)
 
 (defcustom ada-gnatstub-opts "-q -I${src_dir}"
-  "*List of the options to pass to `gnatsub' to generate the body of a package.
+  "*Options to pass to `gnatsub' to generate the body of a package.
 This has the same syntax as in the project file (with variable substitution)."
   :type 'string :group 'ada)
 
@@ -147,7 +165,7 @@ This has the same syntax as in the project file (with variable substitution)."
 Otherwise, ask the user for the name of the project file to use."
   :type 'boolean :group 'ada)
 
-(defconst is-windows (memq system-type (quote (windows-nt)))
+(defconst ada-on-ms-windows (memq system-type '(windows-nt))
   "True if we are running on Windows.")
 
 (defcustom ada-tight-gvd-integration nil
@@ -202,7 +220,7 @@ Used to go back to these positions.")
 On Windows systems using `cmdproxy.exe' as the shell,
 we need to use `/d' or the drive is never changed.")
 
-(defvar ada-command-separator (if is-windows " && " "\n")
+(defvar ada-command-separator (if ada-on-ms-windows " && " "\n")
   "Separator to use between multiple commands to `compile' or `start-process'.
 `cmdproxy.exe' doesn't recognize multiple-line commands, so we have to use
 \"&&\" for now.")
@@ -219,7 +237,7 @@ we need to use `/d' or the drive is never changed.")
 It has the format: (project project ...)
 A project has the format: (project-file . project-plist)
 \(See 'apropos plist' for operations on property lists).
-See `ada-xref-set-default-prj-values' for the list of valid properties.
+See `ada-default-prj-properties' for the list of valid properties.
 The current project is retrieved with `ada-xref-current-project'.
 Properties are retrieved with `ada-xref-get-project-field', set with
 `ada-xref-set-project-field'.  If project properties are accessed with no
@@ -262,68 +280,141 @@ project file, a (nil . default-properties) entry is created.")
 
 (defun ada-find-executable (exec-name)
   "Find the full path to the executable file EXEC-NAME.
-On Windows systems, this will properly handle .exe extension as well"
-  (or (ada-find-file-in-dir exec-name exec-path)
-      (ada-find-file-in-dir (concat exec-name ".exe") exec-path)
-      exec-name))
+If not found, throw an error.
+On Windows systems, this will properly handle .exe extension as well."
+  (let ((result (or (ada-find-file-in-dir exec-name exec-path)
+                   (ada-find-file-in-dir (concat exec-name ".exe") exec-path))))
+    (if result
+       result
+      (error "'%s' not found in path" exec-name))))
 
 (defun ada-initialize-runtime-library (cross-prefix)
   "Initialize the variables for the runtime library location.
 CROSS-PREFIX is the prefix to use for the `gnatls' command."
-  (save-excursion
-    (setq ada-xref-runtime-library-specs-path '()
-         ada-xref-runtime-library-ali-path   '())
-    (set-buffer (get-buffer-create "*gnatls*"))
-    (widen)
-    (erase-buffer)
-    ;;  Catch any error in the following form (i.e gnatls was not found)
-    (condition-case nil
-       ;;  Even if we get an error, delete the *gnatls* buffer
-       (unwind-protect
-           (progn
-             (let ((gnatls
-                    (ada-find-executable (concat cross-prefix "gnatls"))))
-                (apply 'call-process gnatls (append '(nil t nil) ada-gnatls-args)))
-             (goto-char (point-min))
-
-             ;;  Source path
-
-             (search-forward "Source Search Path:")
-             (forward-line 1)
-             (while (not (looking-at "^$"))
-               (back-to-indentation)
-               (if (looking-at "<Current_Directory>")
-                   (add-to-list 'ada-xref-runtime-library-specs-path  ".")
-                 (add-to-list 'ada-xref-runtime-library-specs-path
-                              (buffer-substring-no-properties
-                               (point)
-                                 (save-excursion (end-of-line) (point)))))
-               (forward-line 1))
-
-             ;;  Object path
-
-             (search-forward "Object Search Path:")
-             (forward-line 1)
-             (while (not (looking-at "^$"))
-               (back-to-indentation)
-               (if (looking-at "<Current_Directory>")
-                   (add-to-list 'ada-xref-runtime-library-ali-path ".")
-                 (add-to-list 'ada-xref-runtime-library-ali-path
-                              (buffer-substring-no-properties
-                               (point)
-                               (save-excursion (end-of-line) (point)))))
-               (forward-line 1))
-             )
-           (kill-buffer nil))
-      (error nil))
+  (let ((gnatls
+        (condition-case nil
+            ;; if gnatls not found, just give up (may not be using GNAT)
+            (ada-find-executable (concat cross-prefix "gnatls"))
+          (error nil))))
+    (if gnatls
+       (save-excursion
+         (setq ada-xref-runtime-library-specs-path '()
+               ada-xref-runtime-library-ali-path   '())
+         (set-buffer (get-buffer-create "*gnatls*"))
+         (widen)
+         (erase-buffer)
+         ;;  Even if we get an error, delete the *gnatls* buffer
+         (unwind-protect
+             (let ((status (apply 'call-process gnatls (append '(nil t nil) ada-gnatls-args))))
+               (goto-char (point-min))
+
+               ;; Since we didn't provide all the inputs gnatls expects, it returns status 4
+               (if (/= 4 status)
+                   (error (buffer-substring (point) (line-end-position))))
+
+               ;;  Source path
+
+               (search-forward "Source Search Path:")
+               (forward-line 1)
+               (while (not (looking-at "^$"))
+                 (back-to-indentation)
+                 (if (looking-at "<Current_Directory>")
+                     (add-to-list 'ada-xref-runtime-library-specs-path  ".")
+                   (add-to-list 'ada-xref-runtime-library-specs-path
+                                (buffer-substring-no-properties
+                                 (point)
+                                 (point-at-eol))))
+                 (forward-line 1))
+
+               ;;  Object path
+
+               (search-forward "Object Search Path:")
+               (forward-line 1)
+               (while (not (looking-at "^$"))
+                 (back-to-indentation)
+                 (if (looking-at "<Current_Directory>")
+                     (add-to-list 'ada-xref-runtime-library-ali-path ".")
+                   (add-to-list 'ada-xref-runtime-library-ali-path
+                                (buffer-substring-no-properties
+                                 (point)
+                                 (point-at-eol))))
+                 (forward-line 1))
+               )
+           (kill-buffer nil))))
+
     (set 'ada-xref-runtime-library-specs-path
         (reverse ada-xref-runtime-library-specs-path))
     (set 'ada-xref-runtime-library-ali-path
         (reverse ada-xref-runtime-library-ali-path))
     ))
 
+(defun ada-gnat-parse-gpr (plist gpr-file)
+  "Set gpr_file, src_dir and obj_dir properties in PLIST by parsing GPR-FILE.
+Return new value of PLIST.
+GPR_FILE must be full path to file, normalized.
+src_dir, obj_dir will include compiler runtime.
+Assumes environment variable ADA_PROJECT_PATH is set properly."
+  (with-current-buffer (get-buffer-create "*gnatls*")
+    (erase-buffer)
+
+    ;; this can take a long time; let the user know what's up
+    (message "Parsing %s ..." gpr-file)
+
+    ;;  Even if we get an error, delete the *gnatls* buffer
+    (unwind-protect
+       (let* ((cross-prefix (plist-get plist 'cross_prefix))
+              (gnat (concat cross-prefix ada-gnat-cmd))
+              ;; Putting quotes around gpr-file confuses gnatpath on Lynx; not clear why
+              (gpr-opt (concat "-P" gpr-file))
+              (src-dir '())
+              (obj-dir '())
+              (status (call-process gnat nil t nil "list" "-v" gpr-opt)))
+         (goto-char (point-min))
+
+         (if (/= 0 status)
+             (error (buffer-substring (point) (line-end-position))))
+
+         ;;  Source path
+
+         (search-forward "Source Search Path:")
+         (forward-line 1) ; first directory in list
+         (while (not (looking-at "^$")) ; terminate on blank line
+           (back-to-indentation) ; skip whitespace
+           (add-to-list 'src-dir
+                         (if (looking-at "<Current_Directory>")
+                             default-directory
+                          (expand-file-name
+                           (buffer-substring-no-properties
+                            (point) (line-end-position)))))
+           (forward-line 1))
+
+         ;;  Object path
+
+         (search-forward "Object Search Path:")
+         (forward-line 1)
+         (while (not (looking-at "^$"))
+           (back-to-indentation)
+           (add-to-list 'obj-dir
+                         (if (looking-at "<Current_Directory>")
+                             default-directory
+                          (expand-file-name
+                           (buffer-substring-no-properties
+                            (point) (line-end-position)))))
+           (forward-line 1))
+
+         ;; Set properties
+         (setq plist (plist-put plist 'gpr_file gpr-file))
+         (setq plist (plist-put plist 'src_dir src-dir))
+         (plist-put plist 'obj_dir obj-dir)
+         )
+      (kill-buffer nil)
+      (message "Parsing %s ... done" gpr-file)
+      )
+    ))
+
 (defun ada-treat-cmd-string (cmd-string)
-  "Replace meta-sequences like ${...} in CMD-STRING with the appropriate value.
+  "Replace variable references ${var} in CMD-STRING with the appropriate value.
+Also replace standard environment variables $var.
 Assumes project exists.
 As a special case, ${current} is replaced with the name of the current
 file, minus extension but with directory, and ${full_current} is
@@ -357,60 +448,8 @@ replaced by the name including the extension."
                            (mapconcat (lambda(x) (concat prefix x)) value " ")
                            t t cmd-string)))))
       ))
-  cmd-string)
+  (substitute-in-file-name cmd-string))
 
-(defun ada-xref-set-default-prj-values (symbol ada-buffer)
-  "Reset the properties in SYMBOL to the default values for ADA-BUFFER."
-
-  (let ((file      (buffer-file-name ada-buffer))
-       plist)
-    (save-excursion
-      (set-buffer ada-buffer)
-
-      (set 'plist
-          ;;  Try hard to find a project file, even if the current
-          ;;  buffer is not an Ada file or not associated with a file
-          (list 'filename (expand-file-name
-                           (cond
-                            (ada-prj-default-project-file
-                             ada-prj-default-project-file)
-                            (file (ada-prj-find-prj-file file t))
-                            (t
-                             (message (concat "Not editing an Ada file,"
-                                              "and no default project "
-                                              "file specified!"))
-                             "")))
-                'build_dir       (file-name-as-directory (expand-file-name "."))
-                'src_dir         (list ".")
-                'obj_dir         (list ".")
-                'casing          (if (listp ada-case-exception-file)
-                                     ada-case-exception-file
-                                   (list ada-case-exception-file))
-                'comp_opt        ada-prj-default-comp-opt
-                'bind_opt        ada-prj-default-bind-opt
-                'link_opt        ada-prj-default-link-opt
-                'gnatmake_opt    ada-prj-default-gnatmake-opt
-                'gnatfind_opt    ada-prj-gnatfind-switches
-                'main            (if file
-                                     (file-name-nondirectory
-                                      (file-name-sans-extension file))
-                                   "")
-                'main_unit       (if file
-                                     (file-name-nondirectory
-                                      (file-name-sans-extension file))
-                                   "")
-                'cross_prefix    ""
-                'remote_machine  ""
-                'comp_cmd        (list ada-prj-default-comp-cmd)
-                'check_cmd       (list ada-prj-default-check-cmd)
-                'make_cmd        (list ada-prj-default-make-cmd)
-                'run_cmd         (list (concat "./${main}" (if is-windows ".exe")))
-                'debug_pre_cmd   (list (concat ada-cd-command " ${build_dir}"))
-                'debug_cmd       (concat ada-prj-default-debugger
-                                         " ${main}" (if is-windows ".exe"))
-                'debug_post_cmd  (list nil)))
-      )
-    (set symbol plist)))
 
 (defun ada-xref-get-project-field (field)
   "Extract the value of FIELD from the current project file.
@@ -421,12 +460,20 @@ Note that for src_dir and obj_dir, you should rather use
 which will in addition return the default paths."
 
   (let* ((project-plist (cdr (ada-xref-current-project)))
-        value)
+        (value (plist-get project-plist field)))
 
-    (set 'value (plist-get project-plist field))
+    (cond
+     ((eq field 'gnatmake_opt)
+      (let ((gpr-file (plist-get project-plist 'gpr_file)))
+       (if (not (string= gpr-file ""))
+           (setq value (concat "-P\"" gpr-file "\" " value)))))
+
+     ;; FIXME: check for src_dir, obj_dir here, rather than requiring user to do it
+     (t
+      nil))
 
-    ;;  Substitute the ${...} constructs in all the strings, including
-    ;;  inside lists
+    ;; Substitute the ${...} constructs in all the strings, including
+    ;; inside lists
     (cond
      ((stringp value)
       (ada-treat-cmd-string value))
@@ -487,22 +534,16 @@ All the directories are returned as absolute directories."
           ["New..."  ada-prj-new t]
           ["Edit..." ada-prj-edit t]
           "---"
-          ;;  Add the new items
+          ;;  Add the project files
           ,@(mapcar
              (lambda (x)
-               (let ((name (or (car x) "<default>"))
-                     (command `(lambda ()
-                                 "Change the active project file."
-                                 (interactive)
-                                 (ada-parse-prj-file ,(car x))
-                                 (set 'ada-prj-default-project-file ,(car x))
-                                 (ada-xref-update-project-menu))))
+               (let* ((name (or (car x) "<default>"))
+                      (command `(lambda ()
+                                  "Select the current project file."
+                                  (interactive)
+                                  (ada-select-prj-file ,name))))
                  (vector
-                  (if (string= (file-name-extension name)
-                               ada-prj-file-extension)
-                      (file-name-sans-extension
-                       (file-name-nondirectory name))
-                    (file-name-nondirectory name))
+                  (file-name-nondirectory name)
                   command
                   :button (cons
                            :toggle
@@ -510,9 +551,6 @@ All the directories are returned as absolute directories."
                                   (car x))
                            ))))
 
-             ;; Parses all the known project files, and insert at
-             ;; least the default one (in case
-             ;; ada-xref-project-files is nil)
              (or ada-xref-project-files '(nil))))))
 
     (easy-menu-add-item ada-mode-menu '() submenu)))
@@ -531,8 +569,8 @@ All the directories are returned as absolute directories."
 
 (defun ada-do-file-completion (string predicate flag)
   "Completion function when reading a file from the minibuffer.
-Completion is attempted in all the directories in the source path, as
-defined in the project file."
+Completion is attempted in all the directories in the source path,
+as defined in the project file."
   ;; FIXME: doc arguments
 
   ;; This function is not itself interactive, but it is called as part
@@ -572,22 +610,20 @@ Completion is available."
 (defun ada-require-project-file ()
   "If the current project does not exist, load or create a default one.
 Should only be called from interactive functions."
-  (if (not (ada-xref-current-project t))
-      (ada-reread-prj-file)))
+  (if (string= "" ada-prj-default-project-file)
+      (ada-reread-prj-file (ada-prj-find-prj-file t))))
 
-(defun ada-xref-current-project-file (&optional no-user-question)
-  "Return the current project file name; never nil unless NO-USER-QUESTION.
-If NO-USER-QUESTION, don't prompt user for file.  Call
-`ada-require-project-file' first if a project must exist."
+(defun ada-xref-current-project-file ()
+  "Return the current project file name; never nil.
+Call `ada-require-project-file' first if a project must exist."
   (if (not (string= "" ada-prj-default-project-file))
       ada-prj-default-project-file
-    (ada-prj-find-prj-file nil no-user-question)))
+    (ada-prj-find-prj-file t)))
 
-(defun ada-xref-current-project (&optional no-user-question)
-  "Return the current project; nil if none.
-If NO-USER-QUESTION, don't prompt user for file.  Call
-`ada-require-project-file' first if a project must exist."
-  (let* ((file-name (ada-xref-current-project-file no-user-question)))
+(defun ada-xref-current-project ()
+  "Return the current project.
+Call `ada-require-project-file' first to ensure a project exists."
+  (let ((file-name (ada-xref-current-project-file)))
     (assoc file-name ada-xref-project-files)))
 
 (defun ada-show-current-project ()
@@ -596,9 +632,9 @@ If NO-USER-QUESTION, don't prompt user for file.  Call
   (message (ada-xref-current-project-file)))
 
 (defun ada-show-current-main ()
-  "Display current main unit name in message buffer."
+  "Display current main file name in message buffer."
   (interactive)
-  (message "ada-mode main_unit: %s" (ada-xref-get-project-field 'main_unit)))
+  (message "ada-mode main: %s" (ada-xref-get-project-field 'main)))
 
 (defun ada-xref-push-pos (filename position)
   "Push (FILENAME, POSITION) on the position ring for cross-references."
@@ -621,23 +657,16 @@ This is overridden on VMS to convert from VMS filenames to Unix filenames."
   name)
 ;; FIXME: use convert-standard-filename instead
 
-(defun ada-set-default-project-file (name &optional keep-existing)
-  "Set the file whose name is NAME as the default project file.
-If KEEP-EXISTING is true and a project file has already been loaded, nothing
-is done.  This is meant to be used from `ada-mode-hook', for instance, to force
-a project file unless the user has already loaded one."
+(defun ada-set-default-project-file (file)
+  "Set FILE as the current project file."
   (interactive "fProject file:")
-  (if (or (not keep-existing)
-         (not ada-prj-default-project-file)
-         (equal ada-prj-default-project-file ""))
-      (progn
-       (setq ada-prj-default-project-file name)
-       (ada-reread-prj-file name))))
+  (ada-parse-prj-file file)
+  (ada-select-prj-file file))
 
 ;; ------ Handling the project file -----------------------------
 
-(defun ada-prj-find-prj-file (&optional file no-user-question)
-  "Find the project file associated with FILE (or the current buffer if nil).
+(defun ada-prj-find-prj-file (&optional no-user-question)
+  "Find the project file associated with the current buffer.
 If the buffer is not in Ada mode, or not associated with a file,
 return `ada-prj-default-project-file'.  Otherwise, search for a file with
 the same base name as the Ada file, but extension given by
@@ -649,19 +678,15 @@ is non-nil, prompt the user to select one.  If none are found, return
   (let (selected)
 
     (if (not (and (derived-mode-p 'ada-mode)
-                  buffer-file-name))
+                 buffer-file-name))
 
        ;;  Not in an Ada buffer, or current buffer not associated
        ;;  with a file (for instance an emerge buffer)
-
-       (if (and ada-prj-default-project-file
-                (not (string= ada-prj-default-project-file "")))
-           (setq selected ada-prj-default-project-file)
-         (setq selected nil))
+       (setq selected nil)
 
       ;;  other cases: use a more complex algorithm
 
-      (let* ((current-file (or file (buffer-file-name)))
+      (let* ((current-file (buffer-file-name))
             (first-choice (concat
                            (file-name-sans-extension current-file)
                            ada-prj-file-extension))
@@ -723,161 +748,226 @@ is non-nil, prompt the user to select one.  If none are found, return
     (or selected "default.adp")
     ))
 
+(defun ada-default-prj-properties ()
+  "Return the default project properties list with the current buffer as main."
+
+  (let ((file (buffer-file-name nil)))
+    (list
+     ;; variable name alphabetical order
+     'ada_project_path (or (getenv "ADA_PROJECT_PATH") "")
+     'ada_project_path_sep  ada-prj-ada-project-path-sep
+     'bind_opt        ada-prj-default-bind-opt
+     'build_dir       default-directory
+     'casing          (if (listp ada-case-exception-file)
+                         ada-case-exception-file
+                       (list ada-case-exception-file))
+     'check_cmd       (list ada-prj-default-check-cmd) ;; FIXME: should not a list
+     'comp_cmd        (list ada-prj-default-comp-cmd) ;; FIXME: should not a list
+     'comp_opt        ada-prj-default-comp-opt
+     'cross_prefix    ""
+     'debug_cmd       (concat ada-prj-default-debugger
+                             " ${main}" (if ada-on-ms-windows ".exe")) ;; FIXME: don't need .exe?
+     'debug_post_cmd  (list nil)
+     'debug_pre_cmd   (list (concat ada-cd-command " ${build_dir}"))
+     'gnatmake_opt    ada-prj-default-gnatmake-opt
+     'gnatfind_opt    ada-prj-gnatfind-switches
+     'gpr_file        ada-prj-default-gpr-file
+     'link_opt        ada-prj-default-link-opt
+     'main            (if file
+                         (file-name-nondirectory
+                          (file-name-sans-extension file))
+                       "")
+     'make_cmd        (list ada-prj-default-make-cmd) ;; FIXME: should not a list
+     'obj_dir         (list ".")
+     'remote_machine  ""
+     'run_cmd         (list (concat "./${main}" (if ada-on-ms-windows ".exe")))
+     ;; FIXME: should not a list
+     ;; FIXME: don't need .exe?
+     'src_dir         (list ".")
+     )))
 
 (defun ada-parse-prj-file (prj-file)
-  "Read PRJ-FILE, set it as the active project."
-  ;; FIXME: doc nil, search, etc.
-  (if prj-file
-      (let (project src_dir obj_dir make_cmd comp_cmd check_cmd casing
-                   run_cmd debug_pre_cmd debug_post_cmd
-           (ada-buffer (current-buffer)))
-       (setq prj-file (expand-file-name prj-file))
-
-       ;;  Set the project file as the active one.
-       (setq ada-prj-default-project-file prj-file)
-
-       ;;  Initialize the project with the default values
-       (ada-xref-set-default-prj-values 'project (current-buffer))
-
-       ;;  Do not use find-file below, since we don't want to show this
-       ;;  buffer.  If the file is open through speedbar, we can't use
-       ;;  find-file anyway, since the speedbar frame is special and does not
-       ;;  allow the selection of a file in it.
-
-       (if (file-exists-p prj-file)
-           (progn
-             (let* ((buffer (run-hook-with-args-until-success
-                             'ada-load-project-hook prj-file)))
-               (unless buffer
-                 (setq buffer (find-file-noselect prj-file nil)))
-               (set-buffer buffer))
-
-             (widen)
-             (goto-char (point-min))
-
-             ;;  Now overrides these values with the project file
-             (while (not (eobp))
-               (if (looking-at "^\\([^=]+\\)=\\(.*\\)")
-                   (cond
-                    ;; fields that are lists or paths require special processing
-                    ;; FIXME: strip trailing spaces
-                    ((string= (match-string 1) "src_dir")
-                     (add-to-list 'src_dir
-                                  (file-name-as-directory (match-string 2))))
-                    ((string= (match-string 1) "obj_dir")
-                     (add-to-list 'obj_dir
-                                  (file-name-as-directory (match-string 2))))
-                    ((string= (match-string 1) "casing")
-                     (set 'casing (cons (match-string 2) casing)))
-                    ((string= (match-string 1) "build_dir")
-                     (set 'project
-                          (plist-put project 'build_dir
-                                     (file-name-as-directory (match-string 2)))))
-                    ((string= (match-string 1) "make_cmd")
-                     (add-to-list 'make_cmd (match-string 2)))
-                    ((string= (match-string 1) "comp_cmd")
-                     (add-to-list 'comp_cmd (match-string 2)))
-                    ((string= (match-string 1) "check_cmd")
-                     (add-to-list 'check_cmd (match-string 2)))
-                    ((string= (match-string 1) "run_cmd")
-                     (add-to-list 'run_cmd (match-string 2)))
-                    ((string= (match-string 1) "debug_pre_cmd")
-                     (add-to-list 'debug_pre_cmd (match-string 2)))
-                    ((string= (match-string 1) "debug_post_cmd")
-                     (add-to-list 'debug_post_cmd (match-string 2)))
-                    (t
-                     ;; any other field in the file is just copied
-                     (set 'project (plist-put project (intern (match-string 1))
-                                              (match-string 2))))))
-               (forward-line 1))
-
-             (if src_dir (set 'project (plist-put project 'src_dir
-                                                  (reverse src_dir))))
-             (if obj_dir (set 'project (plist-put project 'obj_dir
-                                                  (reverse obj_dir))))
-             (if casing  (set 'project (plist-put project 'casing
-                                                  (reverse casing))))
-             (if make_cmd (set 'project (plist-put project 'make_cmd
-                                                   (reverse make_cmd))))
-             (if comp_cmd (set 'project (plist-put project 'comp_cmd
-                                                   (reverse comp_cmd))))
-             (if check_cmd (set 'project (plist-put project 'check_cmd
-                                                    (reverse check_cmd))))
-             (if run_cmd (set 'project (plist-put project 'run_cmd
-                                                  (reverse run_cmd))))
-             (if debug_post_cmd (set 'project (plist-put project 'debug_post_cmd
-                                                          (reverse debug_post_cmd))))
-             (if debug_pre_cmd (set 'project (plist-put project 'debug_pre_cmd
-                                                         (reverse debug_pre_cmd))))
-
-             (set-buffer ada-buffer)
-             )
+  "Read PRJ-FILE, set project properties in `ada-xref-project-files'."
+  (let ((project (ada-default-prj-properties)))
 
-         ;;  Else the file wasn't readable (probably the default project).
-         ;;  We initialize it with the current environment variables.
-         ;;  We need to add the startup directory in front so that
-         ;;  files locally redefined are properly found.  We cannot
-         ;;  add ".", which varies too much depending on what the
-         ;;  current buffer is.
-         (set 'project
-              (plist-put project 'src_dir
-                         (append
-                          (list command-line-default-directory)
-                          (split-string (or (getenv "ADA_INCLUDE_PATH") "") ":")
-                          (list "." default-directory))))
-         (set 'project
-              (plist-put project 'obj_dir
-                         (append
-                          (list command-line-default-directory)
-                          (split-string (or (getenv "ADA_OBJECTS_PATH") "") ":")
-                          (list "." default-directory))))
-         )
+    (setq prj-file (expand-file-name prj-file))
+    (if (string= (file-name-extension prj-file) "gpr")
+       (set 'project (ada-gnat-parse-gpr project prj-file))
 
+      (set 'project (ada-parse-prj-file-1 prj-file project))
+      )
 
-       ;;  Delete the default project file from the list, if it is there.
-       ;;  Note that in that case, this default project is the only one in
-       ;;  the list
-       (if (assoc nil ada-xref-project-files)
-           (setq ada-xref-project-files nil))
+    ;; Store the project properties
+    (if (assoc prj-file ada-xref-project-files)
+       (setcdr (assoc prj-file ada-xref-project-files) project)
+      (add-to-list 'ada-xref-project-files (cons prj-file project)))
 
-       ;;  Memorize the newly read project file
-       (if (assoc prj-file ada-xref-project-files)
-           (setcdr (assoc prj-file ada-xref-project-files) project)
-         (add-to-list 'ada-xref-project-files (cons prj-file project)))
+    (ada-xref-update-project-menu)
+    ))
 
-       ;; Sets up the compilation-search-path so that Emacs is able to
-       ;; go to the source of the errors in a compilation buffer
-       (setq compilation-search-path (ada-xref-get-src-dir-field))
+(defun ada-parse-prj-file-1 (prj-file project)
+  "Parse the Ada mode project file PRJ-FILE, set project properties in PROJECT.
+Return new value of PROJECT."
+  (let ((ada-buffer (current-buffer))
+       ;; fields that are lists or otherwise require special processing
+       ada_project_path casing comp_cmd check_cmd
+       debug_pre_cmd debug_post_cmd gpr_file make_cmd obj_dir src_dir run_cmd)
+
+    ;; Give users a chance to use compiler-specific project file formats
+    (let ((buffer (run-hook-with-args-until-success
+                  'ada-load-project-hook prj-file)))
+      (unless buffer
+       ;; we load the project file with no warnings; if it does not
+       ;; exist, we stay in the Ada buffer; no project variable
+       ;; settings will be found. That works for the default
+       ;; "default.adp", which does not exist as a file.
+       (setq buffer (find-file-noselect prj-file nil)))
+      (set-buffer buffer))
 
-       ;; Set the casing exceptions file list
-       (if casing
-           (progn
-             (setq ada-case-exception-file (reverse casing))
-             (ada-case-read-exceptions)))
+    (widen)
+    (goto-char (point-min))
 
-       ;; Add the directories to the search path for ff-find-other-file
-       ;; Do not add the '/' or '\' at the end
-       (setq ada-search-directories-internal
-            (append (mapcar 'directory-file-name compilation-search-path)
-                    ada-search-directories))
+    ;; process each line
+    (while (not (eobp))
 
-       (ada-xref-update-project-menu)
-       )
+      ;; ignore lines that don't have the format "name=value", put
+      ;; 'name', 'value' in match-string.
+      (if (looking-at "^\\([^=\n]+\\)=\\(.*\\)")
+         (cond
+          ;; FIXME: strip trailing spaces
+          ;; variable name alphabetical order
+          ((string= (match-string 1) "ada_project_path")
+           (add-to-list 'ada_project_path
+                        (expand-file-name
+                         (substitute-in-file-name (match-string 2)))))
+
+          ((string= (match-string 1) "build_dir")
+           (set 'project
+                (plist-put project 'build_dir
+                           (file-name-as-directory (match-string 2)))))
+
+          ((string= (match-string 1) "casing")
+           (add-to-list 'casing
+                        (expand-file-name (substitute-in-file-name (match-string 2)))))
+
+          ((string= (match-string 1) "check_cmd")
+           (add-to-list 'check_cmd (match-string 2)))
+
+          ((string= (match-string 1) "comp_cmd")
+           (add-to-list 'comp_cmd (match-string 2)))
+
+          ((string= (match-string 1) "debug_post_cmd")
+           (add-to-list 'debug_post_cmd (match-string 2)))
+
+          ((string= (match-string 1) "debug_pre_cmd")
+           (add-to-list 'debug_pre_cmd (match-string 2)))
+
+          ((string= (match-string 1) "gpr_file")
+           ;; expand now; path is relative to Emacs project file
+           (setq gpr_file (expand-file-name (match-string 2))))
+
+          ((string= (match-string 1) "make_cmd")
+           (add-to-list 'make_cmd (match-string 2)))
+
+          ((string= (match-string 1) "obj_dir")
+           (add-to-list 'obj_dir
+                        (file-name-as-directory
+                         (expand-file-name (match-string 2)))))
+
+          ((string= (match-string 1) "run_cmd")
+           (add-to-list 'run_cmd (match-string 2)))
 
-    ;;  No prj file ? => Setup default values
-    ;;  Note that nil means that all compilation modes will first look in the
-    ;;  current directory, and only then in the current file's directory.  This
-    ;;  current file is assumed at this point to be in the common source
-    ;;  directory.
-    (setq compilation-search-path (list nil default-directory))
+          ((string= (match-string 1) "src_dir")
+           (add-to-list 'src_dir
+                        (file-name-as-directory
+                         (expand-file-name (match-string 2)))))
+
+          (t
+           ;; any other field in the file is just copied
+           (set 'project (plist-put project
+                                    (intern (match-string 1))
+                                    (match-string 2))))))
+
+      (forward-line 1))
+
+    ;; done reading file
+
+    ;; back to the user buffer
+    (set-buffer ada-buffer)
+
+    ;; process accumulated lists
+    (if ada_project_path
+       (let ((sep (plist-get project 'ada_project_path_sep)))
+         (setq ada_project_path (reverse ada_project_path))
+         (setq ada_project_path (mapconcat 'identity ada_project_path sep))
+         (set 'project (plist-put project 'ada_project_path ada_project_path))
+         ;; env var needed now for ada-gnat-parse-gpr
+         (setenv "ADA_PROJECT_PATH" ada_project_path)))
+
+    (if debug_post_cmd (set 'project (plist-put project 'debug_post_cmd (reverse debug_post_cmd))))
+    (if debug_pre_cmd (set 'project (plist-put project 'debug_pre_cmd (reverse debug_pre_cmd))))
+    (if casing (set 'project (plist-put project 'casing (reverse casing))))
+    (if check_cmd (set 'project (plist-put project 'check_cmd (reverse check_cmd))))
+    (if comp_cmd (set 'project (plist-put project 'comp_cmd (reverse comp_cmd))))
+    (if make_cmd (set 'project (plist-put project 'make_cmd (reverse make_cmd))))
+    (if run_cmd (set 'project (plist-put project 'run_cmd (reverse run_cmd))))
+
+    (if gpr_file
+       (progn
+         (set 'project (ada-gnat-parse-gpr project gpr_file))
+         ;; append Ada source and object directories to others from Emacs project file
+         (setq src_dir (append (plist-get project 'src_dir) src_dir))
+         (setq obj_dir (append (plist-get project 'obj_dir) obj_dir))
+         (setq ada-xref-runtime-library-specs-path '()
+               ada-xref-runtime-library-ali-path   '()))
+      )
+
+    ;; FIXME: gnatpath.exe doesn't output the runtime libraries, so always call ada-initialize-runtime-library
+    ;; if using a gpr_file, the runtime library directories are
+    ;; included in src_dir and obj_dir; otherwise they are in the
+    ;; 'runtime-library' variables.
+    ;; FIXME: always append to src_dir, obj_dir
+    (ada-initialize-runtime-library (or (ada-xref-get-project-field 'cross_prefix) ""))
+    ;;)
+
+    (if obj_dir (set 'project (plist-put project 'obj_dir (reverse obj_dir))))
+    (if src_dir (set 'project (plist-put project 'src_dir (reverse src_dir))))
+
+    project
     ))
 
+(defun ada-select-prj-file (file)
+  "Select FILE as the current project file."
+  (interactive)
+  (setq ada-prj-default-project-file (expand-file-name file))
+
+  (let ((casing (ada-xref-get-project-field 'casing)))
+    (if casing
+       (progn
+         ;; FIXME: use ada-get-absolute-dir here
+         (setq ada-case-exception-file casing)
+         (ada-case-read-exceptions))))
+
+  (let ((ada_project_path (ada-xref-get-project-field 'ada_project_path)))
+    (if ada_project_path
+       ;; FIXME: use ada-get-absolute-dir, mapconcat here
+       (setenv "ADA_PROJECT_PATH" ada_project_path)))
+
+  (setq compilation-search-path (ada-xref-get-src-dir-field))
+
+  (setq ada-search-directories-internal
+       ;; FIXME: why do we need directory-file-name here?
+       (append (mapcar 'directory-file-name compilation-search-path)
+               ada-search-directories))
+
+  ;; return 't', for decent display in message buffer when called interactively
+  t)
 
 (defun ada-find-references (&optional pos arg local-only)
   "Find all references to the entity under POS.
 Calls gnatfind to find the references.
-If ARG is t, the contents of the old *gnatfind* buffer is preserved.
-If LOCAL-ONLY is t, only the declarations in the current file are returned."
+If ARG is non-nil, the contents of the old *gnatfind* buffer is preserved.
+If LOCAL-ONLY is non-nil, only declarations in the current file are returned."
   (interactive "d\nP")
   (ada-require-project-file)
 
@@ -902,7 +992,7 @@ If LOCAL-ONLY is t, only the declarations in the current file are returned."
 (defun ada-find-local-references (&optional pos arg)
   "Find all references to the entity under POS.
 Calls `gnatfind' to find the references.
-If ARG is t, the contents of the old *gnatfind* buffer is preserved."
+If ARG is non-nil, the contents of the old *gnatfind* buffer is preserved."
   (interactive "d\nP")
   (ada-find-references pos arg t))
 
@@ -912,10 +1002,10 @@ If ARG is t, the contents of the old *gnatfind* buffer is preserved."
   (entity &optional file line column local-only append)
   "Search for references to any entity whose name is ENTITY.
 ENTITY was first found the location given by FILE, LINE and COLUMN.
-If LOCAL-ONLY is t, then list only the references in FILE, which
-is much faster.
-If APPEND is t, then append the output of the command to the existing
-buffer `*gnatfind*', if there is one."
+If LOCAL-ONLY is non-nil, then list only the references in FILE,
+which is much faster.
+If APPEND is non-nil, then append the output of the command to the
+existing buffer `*gnatfind*', if there is one."
   (interactive "sEntity name: ")
   (ada-require-project-file)
 
@@ -924,12 +1014,14 @@ buffer `*gnatfind*', if there is one."
   ;;  processed (gnatfind \"+\":...).
   (let* ((quote-entity
          (if (= (aref entity 0) ?\")
-             (if is-windows
+             (if ada-on-ms-windows
                  (concat "\\\"" (substring entity 1 -1) "\\\"")
                (concat "'\"" (substring entity 1 -1) "\"'"))
            entity))
         (switches (ada-xref-get-project-field 'gnatfind_opt))
-        (command (concat "gnat find " switches " "
+        ;; FIXME: use gpr_file
+        (cross-prefix (ada-xref-get-project-field 'cross_prefix))
+        (command (concat cross-prefix "gnat find " switches " "
                          quote-entity
                          (if file (concat ":" (file-name-nondirectory file)))
                          (if line (concat ":" line))
@@ -943,20 +1035,18 @@ buffer `*gnatfind*', if there is one."
             (not (string= ada-prj-default-project-file "")))
        (if (string-equal (file-name-extension ada-prj-default-project-file)
                          "gpr")
-           (setq command (concat command " -P" ada-prj-default-project-file))
-         (setq command (concat command " -p" ada-prj-default-project-file))))
+           (setq command (concat command " -P\"" ada-prj-default-project-file "\""))
+         (setq command (concat command " -p\"" ada-prj-default-project-file "\""))))
 
     (if (and append (get-buffer ada-gnatfind-buffer-name))
-       (save-excursion
-         (set-buffer "*gnatfind*")
+       (with-current-buffer "*gnatfind*"
          (setq old-contents (buffer-string))))
 
     (let ((compilation-error "reference"))
       (compilation-start command 'compilation-mode (lambda (mode) ada-gnatfind-buffer-name)))
 
     ;;  Hide the "Compilation" menu
-    (save-excursion
-      (set-buffer ada-gnatfind-buffer-name)
+    (with-current-buffer ada-gnatfind-buffer-name
       (local-unset-key [menu-bar compilation-menu])
 
       (if old-contents
@@ -1089,8 +1179,9 @@ The declation is shown in another frame if `ada-xref-other-buffer' is non-nil."
 
 (defun ada-get-absolute-dir-list (dir-list root-dir)
   "Return the list of absolute directories found in DIR-LIST.
-If a directory is a relative directory, ROOT-DIR is prepended."
-  (mapcar (lambda (x) (expand-file-name x root-dir)) dir-list))
+If a directory is a relative directory, ROOT-DIR is prepended.
+Project and environment variables are substituted."
+  (mapcar (lambda (x) (expand-file-name x (ada-treat-cmd-string root-dir))) dir-list))
 
 (defun ada-set-environment ()
   "Prepare an environment for Ada compilation.
@@ -1150,7 +1241,7 @@ If ARG is not nil, ask for user confirmation."
     (compile (ada-quote-cmd cmd))))
 
 (defun ada-set-main-compile-application ()
-  "Set main_unit and main project variables to current buffer, build main."
+  "Set main project variable to current buffer, build main."
   (interactive)
   (ada-require-project-file)
   (let* ((file (buffer-file-name (current-buffer)))
@@ -1164,12 +1255,11 @@ If ARG is not nil, ask for user confirmation."
                 (file-name-sans-extension file))
              ""))
       (ada-xref-set-project-field 'main main)
-      (ada-xref-set-project-field 'main_unit main)
       (ada-compile-application))))
 
 (defun ada-compile-current (&optional arg prj-field)
   "Recompile the current file.
-If ARG is nonil, ask for user confirmation of the command.
+If ARG is non-nil, ask for user confirmation of the command.
 PRJ-FIELD is the name of the field to use in the project file to get the
 command, and should be either `comp_cmd' (default) or `check_cmd'."
   (interactive "P")
@@ -1179,8 +1269,6 @@ command, and should be either `comp_cmd' (default) or `check_cmd'."
         (process-environment (ada-set-environment))
         (compilation-scroll-output t))
 
-    (setq compilation-search-path (ada-xref-get-src-dir-field))
-
     (unless cmd
       (setq cmd '("") arg t))
 
@@ -1196,13 +1284,13 @@ command, and should be either `comp_cmd' (default) or `check_cmd'."
 
 (defun ada-check-current (&optional arg)
   "Check the current file for syntax errors.
-If ARG is nonil, ask for user confirmation of the command."
+If ARG is non-nil, ask for user confirmation of the command."
   (interactive "P")
   (ada-compile-current arg 'check_cmd))
 
 (defun ada-run-application (&optional arg)
   "Run the application.
-if ARG is not-nil, ask for user confirmation."
+If ARG is non-nil, ask for user confirmation."
   (interactive)
   (ada-require-project-file)
 
@@ -1226,8 +1314,7 @@ if ARG is not-nil, ask for user confirmation."
                                            command)))
 
     ;; Run the command
-    (save-excursion
-      (set-buffer (get-buffer-create "*run*"))
+    (with-current-buffer (get-buffer-create "*run*")
       (set 'buffer-read-only nil)
 
       (erase-buffer)
@@ -1356,16 +1443,13 @@ project file."
       )))
 
 (defun ada-reread-prj-file (&optional filename)
-  "Reread either the current project, or FILENAME if non-nil."
+  "Reread either the current project, or FILENAME if non-nil.
+If FILENAME is non-nil, set it as current project."
   (interactive "P")
-  (if filename
-      (ada-parse-prj-file filename)
-    (ada-parse-prj-file (ada-prj-find-prj-file)))
-
-  ;; Reread the location of the standard runtime library
-  (ada-initialize-runtime-library
-   (or (ada-xref-get-project-field 'cross_prefix) ""))
-  )
+  (if (not filename)
+    (setq filename ada-prj-default-project-file))
+  (ada-parse-prj-file filename)
+  (ada-select-prj-file filename))
 
 ;; ------ Private routines
 
@@ -1434,7 +1518,7 @@ to gnatmake's behavior."
   (ada-find-file-in-dir file (ada-xref-get-src-dir-field)))
 
 (defun ada-get-ali-file-name (file)
-  "Create the ali file name for the ada-file FILE.
+  "Create the ali file name for the Ada file FILE.
 The file is searched for in every directory shown in the obj_dir lines of
 the project file."
 
@@ -1458,8 +1542,7 @@ the project file."
   ;;      the 'D' lines.  This is done repeatedly, in case the direct parent is
   ;;      also a separate.
 
-  (save-excursion
-    (set-buffer (get-file-buffer file))
+  (with-current-buffer (get-file-buffer file)
     (let ((short-ali-file-name
           (concat (file-name-sans-extension (file-name-nondirectory file))
                   ".ali"))
@@ -1723,7 +1806,7 @@ Information is extracted from the ali file."
          (progn
            (kill-buffer ali-buffer)
 
-           (error "No declaration of %s found." (ada-name-of identlist))
+           (error "No declaration of %s found" (ada-name-of identlist))
            )))
       )
 
@@ -1733,7 +1816,7 @@ Information is extracted from the ali file."
     (beginning-of-line)
     (if declaration-found
        (let ((current-line (buffer-substring
-                            (point) (save-excursion (end-of-line) (point)))))
+                            (point) (point-at-eol))))
          (save-excursion
            (forward-line 1)
            (beginning-of-line)
@@ -1812,7 +1895,8 @@ This function is disabled for operators, and only works for identifiers."
                   (ada-name-of identlist)))
           ;; one => should be the right one
           ((= len 1)
-           (goto-line (caar declist)))
+           (goto-char (point-min))
+           (forward-line (1- (caar declist))))
 
           ;; more than one => display choice list
           (t
@@ -1848,7 +1932,8 @@ This function is disabled for operators, and only works for identifiers."
                       (read-from-minibuffer "Enter No. of your choice: "))))
              )
            (set-buffer ali-buffer)
-           (goto-line (car (nth (1- choice) declist)))
+           (goto-char (point-min))
+           (forward-line (1- (car (nth (1- choice) declist))))
            ))))))
 
 
@@ -1953,13 +2038,11 @@ the declaration and documentation of the subprograms one is using."
        choice
        file)
 
-    (save-excursion
-
-      ;;  Do the grep in all the directories.  We do multiple shell
-      ;;  commands instead of one in case there is no .ali file in one
-      ;;  of the directory and the shell stops because of that.
+    ;;  Do the grep in all the directories.  We do multiple shell
+    ;;  commands instead of one in case there is no .ali file in one
+    ;;  of the directory and the shell stops because of that.
 
-      (set-buffer (get-buffer-create "*grep*"))
+    (with-current-buffer (get-buffer-create "*grep*")
       (while dirs
        (insert (shell-command-to-string
                 (concat
@@ -2058,8 +2141,8 @@ the declaration and documentation of the subprograms one is using."
 (defun ada-xref-change-buffer
   (file line column identlist &optional other-frame)
   "Select and display FILE, at LINE and COLUMN.
-If we do not end on the same identifier as IDENTLIST, find the closest
-match.  Kills the .ali buffer at the end.
+If we do not end on the same identifier as IDENTLIST, find the
+closest match.  Kills the .ali buffer at the end.
 If OTHER-FRAME is non-nil, creates a new frame to show the file."
 
   (let (declaration-buffer)
@@ -2077,7 +2160,8 @@ If OTHER-FRAME is non-nil, creates a new frame to show the file."
 
     ;; move the cursor to the correct position
     (push-mark)
-    (goto-line line)
+    (goto-char (point-min))
+    (forward-line (1- line))
     (move-to-column column)
 
     ;; If we are not on the identifier, the ali file was not up-to-date.
@@ -2142,8 +2226,7 @@ Return the position of the declaration in the buffer, or nil if not found."
        (unit-name nil)
        (body-name nil)
        (ali-name nil))
-    (save-excursion
-      (set-buffer buffer)
+    (with-current-buffer buffer
       (goto-char (point-min))
       (re-search-forward "^U \\([^ \t%]+\\)%[bs][ \t]+\\([^ \t]+\\)")
       (setq unit-name (match-string 1))
@@ -2186,16 +2269,15 @@ Return the position of the declaration in the buffer, or nil if not found."
 (defun ada-make-filename-from-adaname (adaname)
   "Determine the filename in which ADANAME is found.
 This is a GNAT specific function that uses gnatkrunch."
-  (let (krunch-buf)
-    (setq krunch-buf (generate-new-buffer "*gkrunch*"))
-    (save-excursion
-      (set-buffer krunch-buf)
+  (let ((krunch-buf (generate-new-buffer "*gkrunch*"))
+        (cross-prefix (plist-get (cdr (ada-xref-current-project)) 'cross_prefix)))
+    (with-current-buffer krunch-buf
       ;; send adaname to external process `gnatkr'.
       ;; Add a dummy extension, since gnatkr versions have two different
       ;; behaviors depending on the version:
       ;;   Up to 3.15:   "AA.BB.CC"  =>  aa-bb-cc
       ;;   After:        "AA.BB.CC"  =>  aa-bb.cc
-      (call-process "gnatkr" nil krunch-buf nil
+      (call-process (concat cross-prefix "gnatkr") nil krunch-buf nil
                    (concat adaname ".adb") ada-krunch-args)
       ;; fetch output of that process
       (setq adaname (buffer-substring
@@ -2213,65 +2295,59 @@ This is a GNAT specific function that uses gnatkrunch."
 
 (defun ada-make-body-gnatstub (&optional interactive)
   "Create an Ada package body in the current buffer.
-This function uses the `gnatstub' program to create the body.
-If INTERACTIVE is nil, kill the current buffer.
-This function typically is to be hooked into `ff-file-created-hook'."
+This function uses the `gnat stub' program to create the body.
+This function typically is to be hooked into `ff-file-created-hook'.
+If INTERACTIVE is nil, assume this is called from `ff-file-created-hook'."
   (interactive "p")
   (ada-require-project-file)
 
-  (save-some-buffers nil nil)
-
-  ;; If the current buffer is the body (as is the case when calling this
-  ;; function from ff-file-created-hook), then kill this temporary buffer
+  ;; If not interactive, assume we are being called from
+  ;; ff-file-created-hook. Then the current buffer is for the body
+  ;; file, but we will create a new one after gnat stub runs
   (unless interactive
     (set-buffer-modified-p nil)
     (kill-buffer (current-buffer)))
 
+  (save-some-buffers nil nil)
 
-  ;;  Make sure the current buffer is the spec (this might not be the case
-  ;;  if for instance the user was asked for a project file)
+  ;; Make sure the current buffer is the spec, so gnat stub gets the
+  ;; right package parameter (this might not be the case if for
+  ;; instance the user was asked for a project file)
 
   (unless (buffer-file-name (car (buffer-list)))
     (set-buffer (cadr (buffer-list))))
 
-  ;; Call the external process gnatstub
-  (let* ((gnatstub-opts (ada-treat-cmd-string ada-gnatstub-opts))
+  ;; Call the external process
+  (let* ((project-plist (cdr (ada-xref-current-project)))
+        (gnatstub-opts (ada-treat-cmd-string ada-gnatstub-opts))
+        (gpr-file (plist-get project-plist 'gpr_file))
         (filename      (buffer-file-name (car (buffer-list))))
         (output        (concat (file-name-sans-extension filename) ".adb"))
-        (gnatstub-cmd  (concat "gnatstub " gnatstub-opts " " filename))
-        (buffer        (get-buffer-create "*gnatstub*")))
-
-    (save-excursion
-      (set-buffer buffer)
+        (cross-prefix (plist-get project-plist 'cross_prefix))
+        (gnatstub-cmd  (concat cross-prefix "gnat stub"
+                               (if (not (string= gpr-file ""))
+                                   (concat " -P\"" gpr-file "\""))
+                               " " gnatstub-opts " " filename))
+        (buffer        (get-buffer-create "*gnat stub*")))
+
+    (with-current-buffer buffer
       (compilation-minor-mode 1)
       (erase-buffer)
       (insert gnatstub-cmd)
       (newline)
       )
-    ;; call gnatstub to create the body file
-    (call-process shell-file-name nil buffer nil "-c" gnatstub-cmd)
 
-    (if (save-excursion
-         (set-buffer buffer)
-         (goto-char (point-min))
-         (search-forward "command not found" nil t))
-       (progn
-         (message "gnatstub was not found -- using the basic algorithm")
-         (sleep-for 2)
-         (kill-buffer buffer)
-         (ada-make-body))
+    (call-process shell-file-name nil buffer nil "-c" gnatstub-cmd)
 
-      ;; Else clean up the output
+    ;; clean up the output
 
-      (if (file-exists-p output)
-         (progn
-           (find-file output)
-           (kill-buffer buffer))
+    (if (file-exists-p output)
+       (progn
+         (find-file output)
+         (kill-buffer buffer))
 
-       ;; display the error buffer
-       (display-buffer buffer)
-       )
-      )))
+      ;; file not created; display the error message
+      (display-buffer buffer))))
 
 (defun ada-xref-initialize ()
   "Function called by `ada-mode-hook' to initialize the ada-xref.el package.
@@ -2300,15 +2376,6 @@ For instance, it creates the gnat-specific menus, sets some hooks for
      'error-message
      "File not found in src-dir (check project file): ")
 
-;;  Initializes the cross references to the runtime library
-(ada-initialize-runtime-library "")
-
-;;  Add these standard directories to the search path
-(set 'ada-search-directories-internal
-     (append (mapcar 'directory-file-name ada-xref-runtime-library-specs-path)
-            ada-search-directories))
-
 (provide 'ada-xref)
 
-;; arch-tag: 415a39fe-577b-4676-b3b1-6ff6db7ca24e
 ;;; ada-xref.el ends here