(ange-ftp-gwp-start, ange-ftp-nslookup-host)
[bpt/emacs.git] / lisp / progmodes / ada-xref.el
CommitLineData
3afbc435 1;;; ada-xref.el --- for lookup and completion in Ada mode
797aab3c 2
c94ca9e0 3;; Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 2001, 2002, 2003
4884c50b 4;; Free Software Foundation, Inc.
797aab3c
GM
5
6;; Author: Markus Heritsch <Markus.Heritsch@studbox.uni-stuttgart.de>
7;; Rolf Ebert <ebert@inf.enst.fr>
8;; Emmanuel Briot <briot@gnat.com>
9;; Maintainer: Emmanuel Briot <briot@gnat.com>
c94ca9e0 10;; Ada Core Technologies's version: Revision: 1.181
797aab3c
GM
11;; Keywords: languages ada xref
12
874d7995 13;; This file is part of GNU Emacs.
797aab3c 14
2be7dabc 15;; GNU Emacs is free software; you can redistribute it and/or modify
797aab3c
GM
16;; it under the terms of the GNU General Public License as published by
17;; the Free Software Foundation; either version 2, or (at your option)
18;; any later version.
19
2be7dabc 20;; GNU Emacs is distributed in the hope that it will be useful,
797aab3c
GM
21;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23;; GNU General Public License for more details.
24
25;; You should have received a copy of the GNU General Public License
2be7dabc
GM
26;; along with GNU Emacs; see the file COPYING. If not, write to the
27;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
28;; Boston, MA 02111-1307, USA.
797aab3c
GM
29
30;;; Commentary:
31;;; This Package provides a set of functions to use the output of the
32;;; cross reference capabilities of the GNAT Ada compiler
33;;; for lookup and completion in Ada mode.
34;;;
797aab3c
GM
35;;; If a file *.`adp' exists in the ada-file directory, then it is
36;;; read for configuration informations. It is read only the first
37;;; time a cross-reference is asked for, and is not read later.
38
39;;; You need Emacs >= 20.2 to run this package
40
3afbc435
PJ
41;;; Code:
42
797aab3c
GM
43;; ----- Requirements -----------------------------------------------------
44
45(require 'compile)
46(require 'comint)
7abe197c
JB
47(require 'find-file)
48(require 'ada-mode)
797aab3c 49
797aab3c
GM
50;; ------ Use variables
51(defcustom ada-xref-other-buffer t
eec3232e
GM
52 "*If nil, always display the cross-references in the same buffer.
53Otherwise create either a new buffer or a new frame."
797aab3c
GM
54 :type 'boolean :group 'ada)
55
93cdce20 56(defcustom ada-xref-create-ali nil
eec3232e
GM
57 "*If non-nil, run gcc whenever the cross-references are not up-to-date.
58If nil, the cross-reference mode will never run gcc."
797aab3c
GM
59 :type 'boolean :group 'ada)
60
61(defcustom ada-xref-confirm-compile nil
eec3232e
GM
62 "*If non-nil, always ask for user confirmation before compiling or running
63the application."
797aab3c
GM
64 :type 'boolean :group 'ada)
65
66(defcustom ada-krunch-args "0"
eec3232e
GM
67 "*Maximum number of characters for filenames created by gnatkr.
68Set to 0, if you don't use crunched filenames. This should be a string."
797aab3c
GM
69 :type 'string :group 'ada)
70
c94ca9e0
JB
71(defcustom ada-gnatls-args '("-v")
72 "*Arguments to pass to gnatfind when the location of the runtime is searched.
73Typical use is to pass --RTS=soft-floats on some systems that support it.
74
75You can also add -I- if you do not want the current directory to be included.
76Otherwise, going from specs to bodies and back will first look for files in the
77current directory. This only has an impact if you are not using project files,
78but only ADA_INCLUDE_PATH."
79 :type '(repeat string) :group 'ada)
80
4884c50b 81(defcustom ada-prj-default-comp-opt "-gnatq -gnatQ"
15ea3b67
GM
82 "Default compilation options."
83 :type 'string :group 'ada)
84
85(defcustom ada-prj-default-bind-opt ""
86 "Default binder options."
87 :type 'string :group 'ada)
88
89(defcustom ada-prj-default-link-opt ""
90 "Default linker options."
91 :type 'string :group 'ada)
92
93(defcustom ada-prj-default-gnatmake-opt "-g"
94 "Default options for gnatmake."
95 :type 'string :group 'ada)
96
4884c50b
SM
97(defcustom ada-prj-gnatfind-switches "-rf"
98 "Default switches to use for gnatfind.
99You should modify this variable, for instance to add -a, if you are working
100in an environment where most ALI files are write-protected.
101The command gnatfind is used every time you choose the menu
102\"Show all references\"."
103 :type 'string :group 'ada)
104
eec3232e 105(defcustom ada-prj-default-comp-cmd
93cdce20
SM
106 (concat "${cross_prefix}gnatmake -u -c ${gnatmake_opt} ${full_current} -cargs"
107 " ${comp_opt}")
797aab3c 108 "*Default command to be used to compile a single file.
15ea3b67
GM
109Emacs will add the filename at the end of this command. This is the same
110syntax as in the project file."
111 :type 'string :group 'ada)
112
113(defcustom ada-prj-default-debugger "${cross_prefix}gdb"
114 "*Default name of the debugger. We recommend either `gdb',
115`gdb --emacs_gdbtk' or `ddd --tty -fullname'."
797aab3c
GM
116 :type 'string :group 'ada)
117
118(defcustom ada-prj-default-make-cmd
15ea3b67
GM
119 (concat "${cross_prefix}gnatmake -o ${main} ${main_unit} ${gnatmake_opt} "
120 "-cargs ${comp_opt} -bargs ${bind_opt} -largs ${link_opt}")
797aab3c
GM
121 "*Default command to be used to compile the application.
122This is the same syntax as in the project file."
123 :type 'string :group 'ada)
124
125(defcustom ada-prj-default-project-file ""
eec3232e
GM
126 "*Name of the project file to use for every Ada file.
127Emacs will not try to use the standard algorithm to find the project file if
128this string is not empty."
797aab3c
GM
129 :type '(file :must-match t) :group 'ada)
130
131(defcustom ada-gnatstub-opts "-q -I${src_dir}"
eec3232e
GM
132 "*List of the options to pass to gnatsub to generate the body of a package.
133This has the same syntax as in the project file (with variable substitution)."
797aab3c
GM
134 :type 'string :group 'ada)
135
136(defcustom ada-always-ask-project nil
eec3232e 137 "*If nil, use default values when no project file was found.
15ea3b67
GM
138Otherwise, ask the user for the name of the project file to use."
139 :type 'boolean :group 'ada)
797aab3c 140
4884c50b
SM
141(defconst is-windows (memq system-type (quote (windows-nt)))
142 "True if we are running on windows NT or windows 95.")
143
144(defcustom ada-tight-gvd-integration nil
145 "*If non-nil, a new Emacs frame will be swallowed in GVD when debugging.
75497862
KS
146If GVD is not the debugger used, nothing happens."
147 :type 'boolean :group 'ada)
4884c50b 148
93cdce20
SM
149(defcustom ada-xref-search-with-egrep t
150 "*If non-nil, use egrep to find the possible declarations for an entity.
151This alternate method is used when the exact location was not found in the
152information provided by GNAT. However, it might be expensive if you have a lot
153of sources, since it will search in all the files in your project."
154 :type 'boolean :group 'ada)
155
156(defvar ada-load-project-hook nil
157 "Hook that is run when loading a project file.
158Each function in this hook takes one argument FILENAME, that is the name of
159the project file to load.
160This hook should be used to support new formats for the project files.
161
162If the function can load the file with the given filename, it should create a
163buffer that contains a conversion of the file to the standard format of the
164project files, and return that buffer. (the usual \"src_dir=\" or \"obj_dir=\"
165lines). It should return nil if it doesn't know how to convert that project
166file.")
167
168
797aab3c
GM
169;; ------- Nothing to be modified by the user below this
170(defvar ada-last-prj-file ""
eec3232e 171 "Name of the last project file entered by the user.")
797aab3c 172
15ea3b67 173(defvar ada-check-switch "-gnats"
eec3232e 174 "Switch added to the command line to check the current file.")
797aab3c 175
4884c50b 176(defconst ada-project-file-extension ".adp"
eec3232e 177 "The extension used for project files.")
797aab3c 178
15ea3b67
GM
179(defvar ada-xref-runtime-library-specs-path '()
180 "Directories where the specs for the standard library is found.
181This is used for cross-references.")
182
183(defvar ada-xref-runtime-library-ali-path '()
184 "Directories where the ali for the standard library is found.
185This is used for cross-references.")
186
797aab3c 187(defvar ada-xref-pos-ring '()
eec3232e
GM
188 "List of positions selected by the cross-references functions.
189Used to go back to these positions.")
797aab3c 190
4884c50b
SM
191(defvar ada-cd-command
192 (if (string-match "cmdproxy.exe" shell-file-name)
193 "cd /d"
194 "cd")
195 "Command to use to change to a specific directory. On windows systems
196using cmdproxy.exe as the shell, we need to use /d or the drive is never
197changed.")
198
199(defvar ada-command-separator (if is-windows " && " "\n")
200 "Separator to use when sending multiple commands to `compile' or
201`start-process'.
202cmdproxy.exe doesn't recognize multiple-line commands, so we have to use
203\"&&\" for now.")
204
797aab3c 205(defconst ada-xref-pos-ring-max 16
eec3232e 206 "Number of positions kept in the list ada-xref-pos-ring.")
797aab3c
GM
207
208(defvar ada-operator-re
15ea3b67 209 "\\+\\|-\\|/\\|\\*\\*\\|\\*\\|=\\|&\\|abs\\|mod\\|rem\\|and\\|not\\|or\\|xor\\|<=\\|<\\|>=\\|>"
eec3232e 210 "Regexp to match for operators.")
797aab3c 211
15ea3b67
GM
212(defvar ada-xref-project-files '()
213 "Associative list of project files.
214It has the following format:
fea24571 215\((project_name . value) (project_name . value) ...)
15ea3b67
GM
216As always, the values of the project file are defined through properties.")
217
c94ca9e0
JB
218
219;; ----- Identlist manipulation -------------------------------------------
220;; An identlist is a vector that is used internally to reference an identifier
221;; To facilitate its use, we provide the following macros
222
223(defmacro ada-make-identlist () (make-vector 8 nil))
224(defmacro ada-name-of (identlist) (list 'aref identlist 0))
225(defmacro ada-line-of (identlist) (list 'aref identlist 1))
226(defmacro ada-column-of (identlist) (list 'aref identlist 2))
227(defmacro ada-file-of (identlist) (list 'aref identlist 3))
228(defmacro ada-ali-index-of (identlist) (list 'aref identlist 4))
229(defmacro ada-declare-file-of (identlist) (list 'aref identlist 5))
230(defmacro ada-references-of (identlist) (list 'aref identlist 6))
231(defmacro ada-on-declaration (identlist) (list 'aref identlist 7))
232
233(defmacro ada-set-name (identlist name) (list 'aset identlist 0 name))
234(defmacro ada-set-line (identlist line) (list 'aset identlist 1 line))
235(defmacro ada-set-column (identlist col) (list 'aset identlist 2 col))
236(defmacro ada-set-file (identlist file) (list 'aset identlist 3 file))
237(defmacro ada-set-ali-index (identlist index) (list 'aset identlist 4 index))
238(defmacro ada-set-declare-file (identlist file) (list 'aset identlist 5 file))
239(defmacro ada-set-references (identlist ref) (list 'aset identlist 6 ref))
240(defmacro ada-set-on-declaration (ident value) (list 'aset ident 7 value))
241
242(defsubst ada-get-ali-buffer (file)
243 "Reads the ali file into a new buffer, and returns this buffer's name"
244 (find-file-noselect (ada-get-ali-file-name file)))
245
246
247;; -----------------------------------------------------------------------
248
4884c50b
SM
249(defun ada-quote-cmd (cmd)
250 "Duplicates all \\ characters in CMD so that it can be passed to `compile'"
251 (mapconcat 'identity (split-string cmd "\\\\") "\\\\"))
15ea3b67 252
4884c50b
SM
253(defun ada-initialize-runtime-library (cross-prefix)
254 "Initializes the variables for the runtime library location.
255CROSS-PREFIX is the prefix to use for the gnatls command"
15ea3b67 256 (save-excursion
4884c50b
SM
257 (setq ada-xref-runtime-library-specs-path '()
258 ada-xref-runtime-library-ali-path '())
15ea3b67
GM
259 (set-buffer (get-buffer-create "*gnatls*"))
260 (widen)
261 (erase-buffer)
262 ;; Catch any error in the following form (i.e gnatls was not found)
263 (condition-case nil
264 ;; Even if we get an error, delete the *gnatls* buffer
265 (unwind-protect
266 (progn
c94ca9e0
JB
267 (apply 'call-process (concat cross-prefix "gnatls")
268 (append '(nil t nil) ada-gnatls-args))
15ea3b67
GM
269 (goto-char (point-min))
270
271 ;; Source path
a1506d29 272
15ea3b67
GM
273 (search-forward "Source Search Path:")
274 (forward-line 1)
275 (while (not (looking-at "^$"))
276 (back-to-indentation)
c94ca9e0
JB
277 (if (looking-at "<Current_Directory>")
278 (add-to-list 'ada-xref-runtime-library-specs-path ".")
15ea3b67
GM
279 (add-to-list 'ada-xref-runtime-library-specs-path
280 (buffer-substring-no-properties
281 (point)
282 (save-excursion (end-of-line) (point)))))
283 (forward-line 1))
284
285 ;; Object path
a1506d29 286
15ea3b67
GM
287 (search-forward "Object Search Path:")
288 (forward-line 1)
289 (while (not (looking-at "^$"))
290 (back-to-indentation)
c94ca9e0
JB
291 (if (looking-at "<Current_Directory>")
292 (add-to-list 'ada-xref-runtime-library-ali-path ".")
15ea3b67
GM
293 (add-to-list 'ada-xref-runtime-library-ali-path
294 (buffer-substring-no-properties
295 (point)
296 (save-excursion (end-of-line) (point)))))
297 (forward-line 1))
298 )
299 (kill-buffer nil))
300 (error nil))
301 (set 'ada-xref-runtime-library-specs-path
302 (reverse ada-xref-runtime-library-specs-path))
303 (set 'ada-xref-runtime-library-ali-path
304 (reverse ada-xref-runtime-library-ali-path))
305 ))
306
307
308(defun ada-treat-cmd-string (cmd-string)
309 "Replace meta-sequences like ${...} in CMD-STRING with the appropriate value.
310The project file must have been loaded first.
311As a special case, ${current} is replaced with the name of the currently
4884c50b
SM
312edited file, minus extension but with directory, and ${full_current} is
313replaced by the name including the extension."
15ea3b67
GM
314
315 (while (string-match "\\(-[^-\$IO]*[IO]\\)?\${\\([^}]+\\)}" cmd-string)
4884c50b
SM
316 (let (value
317 (name (match-string 2 cmd-string)))
318 (cond
319 ((string= name "current")
320 (setq value (file-name-sans-extension (buffer-file-name))))
321 ((string= name "full_current")
322 (setq value (buffer-file-name)))
323 (t
15ea3b67 324 (save-match-data
4884c50b
SM
325 (setq value (ada-xref-get-project-field (intern name))))))
326
327 ;; Check if there is an environment variable with the same name
328 (if (null value)
329 (if (not (setq value (getenv name)))
330 (message (concat "No environment variable " name " found"))))
a1506d29 331
15ea3b67
GM
332 (cond
333 ((null value)
4884c50b 334 (setq cmd-string (replace-match "" t t cmd-string)))
15ea3b67 335 ((stringp value)
4884c50b 336 (setq cmd-string (replace-match value t t cmd-string)))
15ea3b67
GM
337 ((listp value)
338 (let ((prefix (match-string 1 cmd-string)))
4884c50b 339 (setq cmd-string (replace-match
15ea3b67
GM
340 (mapconcat (lambda(x) (concat prefix x)) value " ")
341 t t cmd-string)))))
342 ))
343 cmd-string)
344
345(defun ada-xref-set-default-prj-values (symbol ada-buffer)
346 "Reset the properties in SYMBOL to the default values for ADA-BUFFER."
347
348 (let ((file (buffer-file-name ada-buffer))
349 plist)
350 (save-excursion
351 (set-buffer ada-buffer)
a1506d29 352
15ea3b67
GM
353 (set 'plist
354 ;; Try hard to find a default value for filename, so that the user
355 ;; can edit his project file even if the current buffer is not an
356 ;; Ada file or not even associated with a file
4884c50b
SM
357 (list 'filename (expand-file-name
358 (cond
4884c50b
SM
359 (ada-prj-default-project-file
360 ada-prj-default-project-file)
c94ca9e0 361 (file (ada-prj-find-prj-file file t))
4884c50b
SM
362 (t
363 (message (concat "Not editing an Ada file,"
364 "and no default project "
365 "file specified!"))
366 "")))
15ea3b67
GM
367 'build_dir (file-name-as-directory (expand-file-name "."))
368 'src_dir (list ".")
369 'obj_dir (list ".")
370 'casing (if (listp ada-case-exception-file)
371 ada-case-exception-file
372 (list ada-case-exception-file))
373 'comp_opt ada-prj-default-comp-opt
374 'bind_opt ada-prj-default-bind-opt
375 'link_opt ada-prj-default-link-opt
376 'gnatmake_opt ada-prj-default-gnatmake-opt
4884c50b 377 'gnatfind_opt ada-prj-gnatfind-switches
15ea3b67 378 'main (if file
4884c50b
SM
379 (file-name-nondirectory
380 (file-name-sans-extension file))
15ea3b67
GM
381 "")
382 'main_unit (if file
383 (file-name-nondirectory
384 (file-name-sans-extension file))
385 "")
386 'cross_prefix ""
387 'remote_machine ""
4884c50b
SM
388 'comp_cmd (list (concat ada-cd-command " ${build_dir}")
389 ada-prj-default-comp-cmd)
390 'check_cmd (list (concat ada-prj-default-comp-cmd " "
391 ada-check-switch))
392 'make_cmd (list (concat ada-cd-command " ${build_dir}")
393 ada-prj-default-make-cmd)
394 'run_cmd (list (concat ada-cd-command " ${build_dir}")
395 (concat "${main}"
396 (if is-windows ".exe")))
397 'debug_pre_cmd (list (concat ada-cd-command
398 " ${build_dir}"))
15ea3b67
GM
399 'debug_cmd (concat ada-prj-default-debugger
400 (if is-windows " ${main}.exe"
4884c50b
SM
401 " ${main}"))
402 'debug_post_cmd (list nil)))
15ea3b67
GM
403 )
404 (set symbol plist)))
a1506d29 405
15ea3b67 406(defun ada-xref-get-project-field (field)
4884c50b 407 "Extract the value of FIELD from the current project file.
15ea3b67 408The project file must have been loaded first.
4884c50b
SM
409A default value is returned if the file was not found.
410
411Note that for src_dir and obj_dir, you should rather use
412`ada-xref-get-src-dir-field' or `ada-xref-get-obj-dir-field' which will in
413addition return the default paths."
15ea3b67 414
4884c50b 415 (let ((file-name ada-prj-default-project-file)
15ea3b67
GM
416 file value)
417
4884c50b
SM
418 ;; Get the project file (either the current one, or a default one)
419 (setq file (or (assoc file-name ada-xref-project-files)
420 (assoc nil ada-xref-project-files)))
a1506d29 421
15ea3b67
GM
422 ;; If the file was not found, use the default values
423 (if file
424 ;; Get the value from the file
425 (set 'value (plist-get (cdr file) field))
426
427 ;; Create a default nil file that contains the default values
428 (ada-xref-set-default-prj-values 'value (current-buffer))
429 (add-to-list 'ada-xref-project-files (cons nil value))
4884c50b 430 (ada-xref-update-project-menu)
15ea3b67
GM
431 (set 'value (plist-get value field))
432 )
4884c50b
SM
433
434 ;; Substitute the ${...} constructs in all the strings, including
435 ;; inside lists
436 (cond
437 ((stringp value)
438 (ada-treat-cmd-string value))
439 ((null value)
440 nil)
441 ((listp value)
442 (mapcar (lambda(x) (if x (ada-treat-cmd-string x) x)) value))
443 (t
444 value)
445 )
446 ))
447
448
449(defun ada-xref-get-src-dir-field ()
450 "Return the full value for src_dir, including the default directories.
451All the directories are returned as absolute directories."
452
453 (let ((build-dir (ada-xref-get-project-field 'build_dir)))
454 (append
455 ;; Add ${build_dir} in front of the path
456 (list build-dir)
a1506d29 457
4884c50b
SM
458 (ada-get-absolute-dir-list (ada-xref-get-project-field 'src_dir)
459 build-dir)
a1506d29 460
4884c50b
SM
461 ;; Add the standard runtime at the end
462 ada-xref-runtime-library-specs-path)))
463
464(defun ada-xref-get-obj-dir-field ()
465 "Return the full value for obj_dir, including the default directories.
466All the directories are returned as absolute directories."
467
468 (let ((build-dir (ada-xref-get-project-field 'build_dir)))
469 (append
470 ;; Add ${build_dir} in front of the path
471 (list build-dir)
a1506d29 472
4884c50b
SM
473 (ada-get-absolute-dir-list (ada-xref-get-project-field 'obj_dir)
474 build-dir)
a1506d29 475
4884c50b
SM
476 ;; Add the standard runtime at the end
477 ada-xref-runtime-library-ali-path)))
478
479(defun ada-xref-update-project-menu ()
480 "Update the menu Ada->Project, with the list of available project files."
96a483d9
SM
481 ;; Create the standard items.
482 (let ((submenu
483 `("Project"
484 ["Load..." ada-set-default-project-file t]
485 ["New..." ada-prj-new t]
486 ["Edit..." ada-prj-edit t]
487 "---"
488 ;; Add the new items
489 ,@(mapcar
490 (lambda (x)
491 (let ((name (or (car x) "<default>"))
492 (command `(lambda ()
493 "Change the active project file."
494 (interactive)
495 (ada-parse-prj-file ,(car x))
496 (set 'ada-prj-default-project-file ,(car x))
497 (ada-xref-update-project-menu))))
498 (vector
499 (if (string= (file-name-extension name)
500 ada-project-file-extension)
501 (file-name-sans-extension
502 (file-name-nondirectory name))
503 (file-name-nondirectory name))
504 command
505 :button (cons
506 :toggle
507 (equal ada-prj-default-project-file
508 (car x))
509 ))))
75497862 510
96a483d9
SM
511 ;; Parses all the known project files, and insert at
512 ;; least the default one (in case
513 ;; ada-xref-project-files is nil)
514 (or ada-xref-project-files '(nil))))))
75497862 515
96a483d9 516 (easy-menu-add-item ada-mode-menu '() submenu)))
4884c50b
SM
517
518
519;;-------------------------------------------------------------
520;;-- Searching a file anywhere on the source path.
521;;--
522;;-- The following functions provide support for finding a file anywhere
523;;-- on the source path, without providing an explicit directory.
524;;-- They also provide file name completion in the minibuffer.
525;;--
526;;-- Public subprograms: ada-find-file
527;;--
528;;-------------------------------------------------------------
529
530(defun ada-do-file-completion (string predicate flag)
531 "Completion function when reading a file from the minibuffer.
532Completion is attempted in all the directories in the source path, as
533defined in the project file."
534 (let (list
535 (dirs (ada-xref-get-src-dir-field)))
536
537 (while dirs
538 (if (file-directory-p (car dirs))
539 (set 'list (append list (file-name-all-completions string (car dirs)))))
540 (set 'dirs (cdr dirs)))
541 (cond ((equal flag 'lambda)
542 (assoc string list))
543 (flag
544 list)
545 (t
546 (try-completion string
547 (mapcar (lambda (x) (cons x 1)) list)
548 predicate)))))
549
550;;;###autoload
551(defun ada-find-file (filename)
552 "Open a file anywhere in the source path.
553Completion is available."
554 (interactive
555 (list (completing-read "File: " 'ada-do-file-completion)))
556 (let ((file (ada-find-src-file-in-dir filename)))
557 (if file
558 (find-file file)
559 (error (concat filename " not found in src_dir")))))
560
797aab3c 561
797aab3c
GM
562;; ----- Utilities -------------------------------------------------
563
564(defun ada-require-project-file ()
4884c50b
SM
565 "If no project file is currently active, load a default one."
566 (if (or (not ada-prj-default-project-file)
567 (not ada-xref-project-files)
568 (string= ada-prj-default-project-file ""))
15ea3b67 569 (ada-reread-prj-file)))
a1506d29 570
797aab3c 571(defun ada-xref-push-pos (filename position)
eec3232e 572 "Push (FILENAME, POSITION) on the position ring for cross-references."
797aab3c
GM
573 (setq ada-xref-pos-ring (cons (list position filename) ada-xref-pos-ring))
574 (if (> (length ada-xref-pos-ring) ada-xref-pos-ring-max)
575 (setcdr (nthcdr (1- ada-xref-pos-ring-max) ada-xref-pos-ring) nil)))
576
577(defun ada-xref-goto-previous-reference ()
eec3232e 578 "Go to the previous cross-reference we were on."
797aab3c
GM
579 (interactive)
580 (if ada-xref-pos-ring
eec3232e
GM
581 (let ((pos (car ada-xref-pos-ring)))
582 (setq ada-xref-pos-ring (cdr ada-xref-pos-ring))
583 (find-file (car (cdr pos)))
584 (goto-char (car pos)))))
797aab3c
GM
585
586(defun ada-convert-file-name (name)
eec3232e
GM
587 "Converts from NAME to a name that can be used by the compilation commands.
588This is overriden on VMS to convert from VMS filenames to Unix filenames."
797aab3c
GM
589 name)
590
c94ca9e0
JB
591(defun ada-set-default-project-file (name &optional keep-existing)
592 "Set the file whose name is NAME as the default project file.
593If KEEP-EXISTING is true and a project file has already been loaded, nothing
594is done. This is meant to be used from ada-mode-hook, for instance to force
595a project file unless the user has already loaded one."
eec3232e 596 (interactive "fProject file:")
c94ca9e0
JB
597 (if (or (not keep-existing)
598 (not ada-prj-default-project-file)
599 (equal ada-prj-default-project-file ""))
600 (progn
601 (setq ada-prj-default-project-file name)
602 (ada-reread-prj-file name))))
15ea3b67
GM
603
604;; ------ Handling the project file -----------------------------
797aab3c 605
c94ca9e0
JB
606(defun ada-prj-find-prj-file (&optional file no-user-question)
607 "Find the prj file associated with FILE (or the current buffer if nil).
15ea3b67
GM
608If NO-USER-QUESTION is non-nil, use a default file if not project file was
609found, and do not ask the user.
610If the buffer is not an Ada buffer, associate it with the default project
611file. If none is set, return nil."
797aab3c 612
15ea3b67 613 (let (selected)
797aab3c 614
4884c50b
SM
615 ;; Use the active project file if there is one.
616 ;; This is also valid if we don't currently have an Ada buffer, or if
617 ;; the current buffer is not a real file (for instance an emerge buffer)
a1506d29 618
15ea3b67 619 (if (or (not (string= mode-name "Ada"))
c94ca9e0
JB
620 (not (buffer-file-name)))
621
622 (if (and ada-prj-default-project-file
623 (not (string= ada-prj-default-project-file "")))
624 (setq selected ada-prj-default-project-file)
625 (setq selected nil))
a1506d29 626
4884c50b 627 ;; other cases: use a more complex algorithm
a1506d29 628
c94ca9e0 629 (let* ((current-file (or file (buffer-file-name)))
4884c50b
SM
630 (first-choice (concat
631 (file-name-sans-extension current-file)
632 ada-project-file-extension))
633 (dir (file-name-directory current-file))
a1506d29 634
4884c50b
SM
635 ;; on Emacs 20.2, directory-files does not work if
636 ;; parse-sexp-lookup-properties is set
637 (parse-sexp-lookup-properties nil)
638 (prj-files (directory-files
639 dir t
640 (concat ".*" (regexp-quote
641 ada-project-file-extension) "$")))
642 (choice nil))
a1506d29 643
4884c50b 644 (cond
a1506d29 645
4884c50b
SM
646 ;; Else if there is a project file with the same name as the Ada
647 ;; file, but not the same extension.
648 ((file-exists-p first-choice)
649 (set 'selected first-choice))
a1506d29 650
4884c50b
SM
651 ;; Else if only one project file was found in the current directory
652 ((= (length prj-files) 1)
653 (set 'selected (car prj-files)))
a1506d29 654
4884c50b
SM
655 ;; Else if there are multiple files, ask the user
656 ((and (> (length prj-files) 1) (not no-user-question))
657 (save-window-excursion
658 (with-output-to-temp-buffer "*choice list*"
659 (princ "There are more than one possible project file.\n")
660 (princ "Which one should we use ?\n\n")
661 (princ " no. file name \n")
662 (princ " --- ------------------------\n")
663 (let ((counter 1))
664 (while (<= counter (length prj-files))
665 (princ (format " %2d) %s\n"
666 counter
667 (nth (1- counter) prj-files)))
668 (setq counter (1+ counter))
c94ca9e0 669
4884c50b
SM
670 ))) ; end of with-output-to ...
671 (setq choice nil)
672 (while (or
673 (not choice)
674 (not (integerp choice))
675 (< choice 1)
676 (> choice (length prj-files)))
677 (setq choice (string-to-int
678 (read-from-minibuffer "Enter No. of your choice: "))))
679 (set 'selected (nth (1- choice) prj-files))))
a1506d29 680
4884c50b
SM
681 ;; Else if no project file was found in the directory, ask a name
682 ;; to the user, using as a default value the last one entered by
683 ;; the user
684 ((= (length prj-files) 0)
685 (unless (or no-user-question (not ada-always-ask-project))
686 (setq ada-last-prj-file
687 (read-file-name
688 (concat "project file [" ada-last-prj-file "]:")
689 nil ada-last-prj-file))
690 (unless (string= ada-last-prj-file "")
691 (set 'selected ada-last-prj-file))))
692 )))
c94ca9e0
JB
693
694 (or selected "default.adp")
797aab3c
GM
695 ))
696
697
15ea3b67
GM
698(defun ada-parse-prj-file (prj-file)
699 "Reads and parses the PRJ-FILE file if it was found.
700The current buffer should be the ada-file buffer."
701 (if prj-file
4884c50b
SM
702 (let (project src_dir obj_dir make_cmd comp_cmd check_cmd casing
703 run_cmd debug_pre_cmd debug_post_cmd
15ea3b67 704 (ada-buffer (current-buffer)))
4884c50b 705 (setq prj-file (expand-file-name prj-file))
15ea3b67 706
c94ca9e0
JB
707 ;; Set the project file as the active one.
708 (setq ada-prj-default-project-file prj-file)
709
15ea3b67
GM
710 ;; Initialize the project with the default values
711 (ada-xref-set-default-prj-values 'project (current-buffer))
712
713 ;; Do not use find-file below, since we don't want to show this
714 ;; buffer. If the file is open through speedbar, we can't use
715 ;; find-file anyway, since the speedbar frame is special and does not
716 ;; allow the selection of a file in it.
717
c94ca9e0
JB
718 (if (file-exists-p prj-file)
719 (progn
720 (let* ((buffer (run-hook-with-args-until-success
721 'ada-load-project-hook prj-file)))
722 (unless buffer
7abe197c
JB
723 (setq buffer (find-file-noselect prj-file nil)))
724 (set-buffer buffer))
725
726 (widen)
727 (goto-char (point-min))
728
729 ;; Now overrides these values with the project file
730 (while (not (eobp))
731 (if (looking-at "^\\([^=]+\\)=\\(.*\\)")
732 (cond
733 ((string= (match-string 1) "src_dir")
734 (add-to-list 'src_dir
735 (file-name-as-directory (match-string 2))))
736 ((string= (match-string 1) "obj_dir")
737 (add-to-list 'obj_dir
738 (file-name-as-directory (match-string 2))))
739 ((string= (match-string 1) "casing")
740 (set 'casing (cons (match-string 2) casing)))
741 ((string= (match-string 1) "build_dir")
742 (set 'project
743 (plist-put project 'build_dir
744 (file-name-as-directory (match-string 2)))))
745 ((string= (match-string 1) "make_cmd")
746 (add-to-list 'make_cmd (match-string 2)))
747 ((string= (match-string 1) "comp_cmd")
748 (add-to-list 'comp_cmd (match-string 2)))
749 ((string= (match-string 1) "check_cmd")
750 (add-to-list 'check_cmd (match-string 2)))
751 ((string= (match-string 1) "run_cmd")
752 (add-to-list 'run_cmd (match-string 2)))
753 ((string= (match-string 1) "debug_pre_cmd")
754 (add-to-list 'debug_pre_cmd (match-string 2)))
755 ((string= (match-string 1) "debug_post_cmd")
756 (add-to-list 'debug_post_cmd (match-string 2)))
757 (t
758 (set 'project (plist-put project (intern (match-string 1))
759 (match-string 2))))))
760 (forward-line 1))
761
762 (if src_dir (set 'project (plist-put project 'src_dir
763 (reverse src_dir))))
764 (if obj_dir (set 'project (plist-put project 'obj_dir
765 (reverse obj_dir))))
766 (if casing (set 'project (plist-put project 'casing
767 (reverse casing))))
768 (if make_cmd (set 'project (plist-put project 'make_cmd
769 (reverse make_cmd))))
770 (if comp_cmd (set 'project (plist-put project 'comp_cmd
771 (reverse comp_cmd))))
772 (if check_cmd (set 'project (plist-put project 'check_cmd
773 (reverse check_cmd))))
774 (if run_cmd (set 'project (plist-put project 'run_cmd
775 (reverse run_cmd))))
776 (set 'project (plist-put project 'debug_post_cmd
777 (reverse debug_post_cmd)))
c94ca9e0
JB
778 (set 'project (plist-put project 'debug_pre_cmd
779 (reverse debug_pre_cmd)))
780
781 ;; Kill the project buffer
782 (kill-buffer nil)
783 (set-buffer ada-buffer)
784 )
785
786 ;; Else the file wasn't readable (probably the default project).
787 ;; We initialize it with the current environment variables.
788 ;; We need to add the startup directory in front so that
789 ;; files locally redefined are properly found. We cannot
790 ;; add ".", which varies too much depending on what the
791 ;; current buffer is.
792 (set 'project
793 (plist-put project 'src_dir
794 (append
795 (list command-line-default-directory)
796 (split-string (or (getenv "ADA_INCLUDE_PATH") "") ":")
797 (list "." default-directory))))
798 (set 'project
799 (plist-put project 'obj_dir
800 (append
801 (list command-line-default-directory)
802 (split-string (or (getenv "ADA_OBJECTS_PATH") "") ":")
803 (list "." default-directory))))
804 )
805
4884c50b
SM
806
807 ;; Delete the default project file from the list, if it is there.
808 ;; Note that in that case, this default project is the only one in
809 ;; the list
810 (if (assoc nil ada-xref-project-files)
811 (setq ada-xref-project-files nil))
a1506d29 812
15ea3b67
GM
813 ;; Memorize the newly read project file
814 (if (assoc prj-file ada-xref-project-files)
815 (setcdr (assoc prj-file ada-xref-project-files) project)
816 (add-to-list 'ada-xref-project-files (cons prj-file project)))
4884c50b 817
15ea3b67
GM
818 ;; Sets up the compilation-search-path so that Emacs is able to
819 ;; go to the source of the errors in a compilation buffer
4884c50b
SM
820 (setq compilation-search-path (ada-xref-get-src-dir-field))
821
822 ;; Set the casing exceptions file list
823 (if casing
824 (progn
825 (setq ada-case-exception-file (reverse casing))
826 (ada-case-read-exceptions)))
a1506d29 827
15ea3b67
GM
828 ;; Add the directories to the search path for ff-find-other-file
829 ;; Do not add the '/' or '\' at the end
7abe197c 830 (setq ada-search-directories-internal
15ea3b67
GM
831 (append (mapcar 'directory-file-name compilation-search-path)
832 ada-search-directories))
a1506d29 833
4884c50b 834 (ada-xref-update-project-menu)
15ea3b67 835 )
4884c50b
SM
836
837 ;; No prj file ? => Setup default values
838 ;; Note that nil means that all compilation modes will first look in the
839 ;; current directory, and only then in the current file's directory. This
840 ;; current file is assumed at this point to be in the common source
841 ;; directory.
842 (setq compilation-search-path (list nil default-directory))
15ea3b67 843 ))
a1506d29
JB
844
845
93cdce20 846(defun ada-find-references (&optional pos arg local-only)
eec3232e 847 "Find all references to the entity under POS.
93cdce20
SM
848Calls gnatfind to find the references.
849if ARG is t, the contents of the old *gnatfind* buffer is preserved.
850if LOCAL-ONLY is t, only the declarations in the current file are returned."
851 (interactive "d
852P")
797aab3c
GM
853 (ada-require-project-file)
854
855 (let* ((identlist (ada-read-identifier pos))
15ea3b67
GM
856 (alifile (ada-get-ali-file-name (ada-file-of identlist)))
857 (process-environment (ada-set-environment)))
797aab3c
GM
858
859 (set-buffer (get-file-buffer (ada-file-of identlist)))
860
861 ;; if the file is more recent than the executable
862 (if (or (buffer-modified-p (current-buffer))
863 (file-newer-than-file-p (ada-file-of identlist) alifile))
864 (ada-find-any-references (ada-name-of identlist)
865 (ada-file-of identlist)
93cdce20 866 nil nil local-only arg)
797aab3c
GM
867 (ada-find-any-references (ada-name-of identlist)
868 (ada-file-of identlist)
869 (ada-line-of identlist)
93cdce20 870 (ada-column-of identlist) local-only arg)))
797aab3c
GM
871 )
872
93cdce20
SM
873(defun ada-find-local-references (&optional pos arg)
874 "Find all references to the entity under POS.
875Calls gnatfind to find the references.
876if ARG is t, the contents of the old *gnatfind* buffer is preserved."
877 (interactive "d
878P")
879 (ada-find-references pos arg t))
880
881(defun ada-find-any-references
882 (entity &optional file line column local-only append)
eec3232e 883 "Search for references to any entity whose name is ENTITY.
93cdce20
SM
884ENTITY was first found the location given by FILE, LINE and COLUMN.
885If LOCAL-ONLY is t, then only the references in file will be listed, which
886is much faster.
887If APPEND is t, then the output of the command will be append to the existing
888buffer *gnatfind* if it exists."
797aab3c
GM
889 (interactive "sEntity name: ")
890 (ada-require-project-file)
891
4884c50b
SM
892 ;; Prepare the gnatfind command. Note that we must protect the quotes
893 ;; around operators, so that they are correctly handled and can be
894 ;; processed (gnatfind \"+\":...).
895 (let* ((quote-entity
896 (if (= (aref entity 0) ?\")
897 (if is-windows
898 (concat "\\\"" (substring entity 1 -1) "\\\"")
899 (concat "'\"" (substring entity 1 -1) "\"'"))
900 entity))
901 (switches (ada-xref-get-project-field 'gnatfind_opt))
7abe197c 902 (command (concat "gnat find " switches " "
4884c50b 903 quote-entity
797aab3c
GM
904 (if file (concat ":" (file-name-nondirectory file)))
905 (if line (concat ":" line))
93cdce20
SM
906 (if column (concat ":" column))
907 (if local-only (concat " " (file-name-nondirectory file)))
908 ))
909 old-contents)
797aab3c
GM
910
911 ;; If a project file is defined, use it
4884c50b
SM
912 (if (and ada-prj-default-project-file
913 (not (string= ada-prj-default-project-file "")))
7abe197c
JB
914 (if (string-equal (file-name-extension ada-prj-default-project-file)
915 "gpr")
916 (setq command (concat command " -P" ada-prj-default-project-file))
917 (setq command (concat command " -p" ada-prj-default-project-file))))
797aab3c 918
93cdce20
SM
919 (if (and append (get-buffer "*gnatfind*"))
920 (save-excursion
921 (set-buffer "*gnatfind*")
922 (setq old-contents (buffer-string))))
a1506d29 923
eec3232e 924 (compile-internal command "No more references" "gnatfind")
797aab3c
GM
925
926 ;; Hide the "Compilation" menu
927 (save-excursion
928 (set-buffer "*gnatfind*")
93cdce20
SM
929 (local-unset-key [menu-bar compilation-menu])
930
931 (if old-contents
932 (progn
933 (goto-char 1)
934 (insert old-contents)
935 (goto-char (point-max)))))
797aab3c
GM
936 )
937 )
938
4884c50b 939(defalias 'ada-change-prj (symbol-function 'ada-set-default-project-file))
797aab3c 940
797aab3c
GM
941;; ----- Identifier Completion --------------------------------------------
942(defun ada-complete-identifier (pos)
943 "Tries to complete the identifier around POS.
15ea3b67 944The feature is only available if the files where compiled not using the -gnatx
eec3232e 945option."
797aab3c
GM
946 (interactive "d")
947 (ada-require-project-file)
948
15ea3b67 949 ;; Initialize function-local variables and jump to the .ali buffer
797aab3c
GM
950 ;; Note that for regexp search is case insensitive too
951 (let* ((curbuf (current-buffer))
952 (identlist (ada-read-identifier pos))
953 (sofar (concat "^[0-9]+[a-zA-Z][0-9]+[ *]\\("
954 (regexp-quote (ada-name-of identlist))
955 "[a-zA-Z0-9_]*\\)"))
956 (completed nil)
15ea3b67 957 (symalist nil))
797aab3c 958
15ea3b67
GM
959 ;; Open the .ali file
960 (set-buffer (ada-get-ali-buffer (buffer-file-name)))
797aab3c
GM
961 (goto-char (point-max))
962
963 ;; build an alist of possible completions
964 (while (re-search-backward sofar nil t)
965 (setq symalist (cons (cons (match-string 1) nil) symalist)))
966
967 (setq completed (try-completion "" symalist))
968
969 ;; kills .ali buffer
970 (kill-buffer nil)
971
972 ;; deletes the incomplete identifier in the buffer
973 (set-buffer curbuf)
974 (looking-at "[a-zA-Z0-9_]+")
975 (replace-match "")
976 ;; inserts the completed symbol
977 (insert completed)
978 ))
979
980;; ----- Cross-referencing ----------------------------------------
981
982(defun ada-point-and-xref ()
c94ca9e0 983 "Jump to the declaration of the entity below the cursor."
797aab3c
GM
984 (interactive)
985 (mouse-set-point last-input-event)
986 (ada-goto-declaration (point)))
987
c94ca9e0
JB
988(defun ada-point-and-xref-body ()
989 "Jump to the body of the entity under the cursor."
990 (interactive)
991 (mouse-set-point last-input-event)
992 (ada-goto-body (point)))
993
994(defun ada-goto-body (pos &optional other-frame)
995 "Display the body of the entity around POS.
996If the entity doesn't have a body, display its declaration.
997As a side effect, the buffer for the declaration is also open."
998 (interactive "d")
999 (ada-goto-declaration pos other-frame)
1000
1001 ;; Temporarily force the display in the same buffer, since we
1002 ;; already changed previously
1003 (let ((ada-xref-other-buffer nil))
1004 (ada-goto-declaration (point) nil)))
1005
4884c50b 1006(defun ada-goto-declaration (pos &optional other-frame)
eec3232e
GM
1007 "Display the declaration of the identifier around POS.
1008The declaration is shown in another buffer if `ada-xref-other-buffer' is
4884c50b
SM
1009non-nil.
1010If OTHER-FRAME is non-nil, display the cross-reference in another frame."
797aab3c
GM
1011 (interactive "d")
1012 (ada-require-project-file)
1013 (push-mark pos)
1014 (ada-xref-push-pos (buffer-file-name) pos)
797aab3c 1015
4884c50b
SM
1016 ;; First try the standard algorithm by looking into the .ali file, but if
1017 ;; that file was too old or even did not exist, try to look in the whole
1018 ;; object path for a possible location.
1019 (let ((identlist (ada-read-identifier pos)))
1020 (condition-case nil
1021 (ada-find-in-ali identlist other-frame)
93cdce20
SM
1022 (error
1023 (let ((ali-file (ada-get-ali-file-name (ada-file-of identlist))))
1024
1025 ;; If the ALI file was up-to-date, then we probably have a predefined
1026 ;; entity, whose references are not given by GNAT
1027 (if (and (file-exists-p ali-file)
1028 (file-newer-than-file-p ali-file (ada-file-of identlist)))
1029 (message "No cross-reference found. It might be a predefined entity.")
1030
1031 ;; Else, look in every ALI file, except if the user doesn't want that
1032 (if ada-xref-search-with-egrep
1033 (ada-find-in-src-path identlist other-frame)
1034 (message "Cross-referencing information is not up-to-date. Please recompile.")
1035 )))))))
4884c50b 1036
96a483d9 1037(defun ada-goto-declaration-other-frame (pos)
eec3232e
GM
1038 "Display the declaration of the identifier around POS.
1039The declation is shown in another frame if `ada-xref-other-buffer' is non-nil."
797aab3c 1040 (interactive "d")
4884c50b 1041 (ada-goto-declaration pos t))
797aab3c 1042
15ea3b67
GM
1043(defun ada-remote (command)
1044 "Return the remote version of COMMAND, or COMMAND if remote_machine is nil."
1045 (let ((machine (ada-xref-get-project-field 'remote_machine)))
1046 (if (or (not machine) (string= machine ""))
1047 command
1048 (format "%s %s '(%s)'"
1049 remote-shell-program
1050 machine
1051 command))))
1052
15ea3b67
GM
1053(defun ada-get-absolute-dir-list (dir-list root-dir)
1054 "Returns the list of absolute directories found in dir-list.
1055If a directory is a relative directory, the value of ROOT-DIR is added in
1056front."
4884c50b 1057 (mapcar (lambda (x) (expand-file-name x root-dir)) dir-list))
15ea3b67
GM
1058
1059(defun ada-set-environment ()
1060 "Return the new value for process-environment.
1061It modifies the source path and object path with the values found in the
1062project file."
1063 (let ((include (getenv "ADA_INCLUDE_PATH"))
1064 (objects (getenv "ADA_OBJECTS_PATH"))
1065 (build-dir (ada-xref-get-project-field 'build_dir)))
1066 (if include
4884c50b 1067 (set 'include (concat path-separator include)))
15ea3b67 1068 (if objects
4884c50b 1069 (set 'objects (concat path-separator objects)))
15ea3b67
GM
1070 (cons
1071 (concat "ADA_INCLUDE_PATH="
4884c50b 1072 (mapconcat (lambda(x) (expand-file-name x build-dir))
15ea3b67 1073 (ada-xref-get-project-field 'src_dir)
4884c50b
SM
1074 path-separator)
1075 include)
15ea3b67
GM
1076 (cons
1077 (concat "ADA_OBJECTS_PATH="
4884c50b 1078 (mapconcat (lambda(x) (expand-file-name x build-dir))
15ea3b67 1079 (ada-xref-get-project-field 'obj_dir)
4884c50b
SM
1080 path-separator)
1081 objects)
15ea3b67
GM
1082 process-environment))))
1083
1084(defun ada-compile-application (&optional arg)
1085 "Compiles the application, using the command found in the project file.
1086If ARG is not nil, ask for user confirmation."
1087 (interactive "P")
797aab3c 1088 (ada-require-project-file)
15ea3b67
GM
1089 (let ((cmd (ada-xref-get-project-field 'make_cmd))
1090 (process-environment (ada-set-environment))
1091 (compilation-scroll-output t))
1092
4884c50b 1093 (setq compilation-search-path (ada-xref-get-src-dir-field))
15ea3b67
GM
1094
1095 ;; If no project file was found, ask the user
1096 (unless cmd
4884c50b 1097 (setq cmd '("") arg t))
15ea3b67 1098
4884c50b
SM
1099 ;; Make a single command from the list of commands, including the
1100 ;; commands to run it on a remote machine.
1101 (setq cmd (ada-remote (mapconcat 'identity cmd ada-command-separator)))
a1506d29 1102
4884c50b
SM
1103 (if (or ada-xref-confirm-compile arg)
1104 (setq cmd (read-from-minibuffer "enter command to compile: " cmd)))
1105
1106 ;; Insert newlines so as to separate the name of the commands to run
1107 ;; and the output of the commands. this doesn't work with cmdproxy.exe,
1108 ;; which gets confused by newline characters.
c94ca9e0 1109 (if (not (string-match ".exe" shell-file-name))
4884c50b 1110 (setq cmd (concat cmd "\n\n")))
a1506d29 1111
4884c50b 1112 (compile (ada-quote-cmd cmd))))
797aab3c 1113
15ea3b67
GM
1114(defun ada-compile-current (&optional arg prj-field)
1115 "Recompile the current file.
1116If ARG is not nil, ask for user confirmation of the command.
1117PRJ-FIELD is the name of the field to use in the project file to get the
1118command, and should be either comp_cmd (default) or check_cmd."
1119 (interactive "P")
797aab3c 1120 (ada-require-project-file)
15ea3b67
GM
1121 (let* ((field (if prj-field prj-field 'comp_cmd))
1122 (cmd (ada-xref-get-project-field field))
1123 (process-environment (ada-set-environment))
1124 (compilation-scroll-output t))
a1506d29 1125
4884c50b 1126 (setq compilation-search-path (ada-xref-get-src-dir-field))
15ea3b67 1127
4884c50b
SM
1128 (unless cmd
1129 (setq cmd '("") arg t))
a1506d29 1130
4884c50b
SM
1131 ;; Make a single command from the list of commands, including the
1132 ;; commands to run it on a remote machine.
1133 (setq cmd (ada-remote (mapconcat 'identity cmd ada-command-separator)))
a1506d29 1134
15ea3b67 1135 ;; If no project file was found, ask the user
4884c50b
SM
1136 (if (or ada-xref-confirm-compile arg)
1137 (setq cmd (read-from-minibuffer "enter command to compile: " cmd)))
1138
1139 ;; Insert newlines so as to separate the name of the commands to run
1140 ;; and the output of the commands. this doesn't work with cmdproxy.exe,
1141 ;; which gets confused by newline characters.
c94ca9e0 1142 (if (not (string-match ".exe" shell-file-name))
4884c50b 1143 (setq cmd (concat cmd "\n\n")))
a1506d29 1144
4884c50b 1145 (compile (ada-quote-cmd cmd))))
15ea3b67
GM
1146
1147(defun ada-check-current (&optional arg)
1148 "Recompile the current file.
1149If ARG is not nil, ask for user confirmation of the command."
1150 (interactive "P")
1151 (ada-compile-current arg 'check_cmd))
797aab3c 1152
15ea3b67
GM
1153(defun ada-run-application (&optional arg)
1154 "Run the application.
1155if ARG is not-nil, asks for user confirmation."
797aab3c
GM
1156 (interactive)
1157 (ada-require-project-file)
1158
15ea3b67
GM
1159 (let ((machine (ada-xref-get-project-field 'cross_prefix)))
1160 (if (and machine (not (string= machine "")))
1161 (error "This feature is not supported yet for cross environments")))
797aab3c 1162
15ea3b67 1163 (let ((command (ada-xref-get-project-field 'run_cmd)))
797aab3c 1164
15ea3b67 1165 ;; Guess the command if it wasn't specified
4884c50b
SM
1166 (if (not command)
1167 (set 'command (list (file-name-sans-extension (buffer-name)))))
797aab3c 1168
4884c50b
SM
1169 ;; Modify the command to run remotely
1170 (setq command (ada-remote (mapconcat 'identity command
1171 ada-command-separator)))
a1506d29 1172
15ea3b67
GM
1173 ;; Ask for the arguments to the command if required
1174 (if (or ada-xref-confirm-compile arg)
4884c50b
SM
1175 (setq command (read-from-minibuffer "Enter command to execute: "
1176 command)))
797aab3c
GM
1177
1178 ;; Run the command
1179 (save-excursion
1180 (set-buffer (get-buffer-create "*run*"))
15ea3b67 1181 (set 'buffer-read-only nil)
4884c50b 1182
15ea3b67 1183 (erase-buffer)
4884c50b
SM
1184 (start-process "run" (current-buffer) shell-file-name
1185 "-c" command)
1186 (comint-mode)
1187 ;; Set these two variables to their default values, since otherwise
1188 ;; the output buffer is scrolled so that only the last output line
1189 ;; is visible at the top of the buffer.
1190 (set (make-local-variable 'scroll-step) 0)
1191 (set (make-local-variable 'scroll-conservatively) 0)
797aab3c
GM
1192 )
1193 (display-buffer "*run*")
1194
1195 ;; change to buffer *run* for interactive programs
1196 (other-window 1)
1197 (switch-to-buffer "*run*")
15ea3b67 1198 ))
797aab3c 1199
4884c50b 1200(defun ada-gdb-application (&optional arg executable-name)
15ea3b67 1201 "Start the debugger on the application.
4884c50b
SM
1202EXECUTABLE-NAME, if non-nil, is debugged instead of the file specified in the
1203project file.
15ea3b67
GM
1204If ARG is non-nil, ask the user to confirm the command."
1205 (interactive "P")
797aab3c 1206 (let ((buffer (current-buffer))
4884c50b 1207 cmd pre-cmd post-cmd)
797aab3c 1208 (ada-require-project-file)
4884c50b
SM
1209 (setq cmd (if executable-name
1210 (concat ada-prj-default-debugger " " executable-name)
1211 (ada-xref-get-project-field 'debug_cmd))
1212 pre-cmd (ada-xref-get-project-field 'debug_pre_cmd)
1213 post-cmd (ada-xref-get-project-field 'debug_post_cmd))
15ea3b67
GM
1214
1215 ;; If the command was not given in the project file, start a bare gdb
1216 (if (not cmd)
1217 (set 'cmd (concat ada-prj-default-debugger
1218 " "
4884c50b
SM
1219 (or executable-name
1220 (file-name-sans-extension (buffer-file-name))))))
1221
1222 ;; For gvd, add an extra switch so that the Emacs window is completly
1223 ;; swallowed inside the Gvd one
1224 (if (and ada-tight-gvd-integration
1225 (string-match "^[^ \t]*gvd" cmd))
1226 ;; Start a new frame, so that when gvd exists we do not kill Emacs
1227 ;; We make sure that gvd swallows the new frame, not the one the
1228 ;; user has been using until now
1229 ;; The frame is made invisible initially, so that GtkPlug gets a
1230 ;; chance to fully manage it. Then it works fine with Enlightenment
1231 ;; as well
1232 (let ((frame (make-frame '((visibility . nil)))))
1233 (set 'cmd (concat
1234 cmd " --editor-window="
1235 (cdr (assoc 'outer-window-id (frame-parameters frame)))))
1236 (select-frame frame)))
1237
1238 ;; Add a -fullname switch
1239 ;; Use the remote machine
1240 (set 'cmd (ada-remote (concat cmd " -fullname ")))
1241
1242 ;; Ask for confirmation if required
15ea3b67
GM
1243 (if (or arg ada-xref-confirm-compile)
1244 (set 'cmd (read-from-minibuffer "enter command to debug: " cmd)))
1245
96a483d9 1246 (let ((old-comint-exec (symbol-function 'comint-exec)))
4884c50b
SM
1247
1248 ;; Do not add -fullname, since we can have a 'rsh' command in front.
96a483d9 1249 ;; FIXME: This is evil but luckily a nop under Emacs-21.3.50 ! -stef
4884c50b
SM
1250 (fset 'gud-gdb-massage-args (lambda (file args) args))
1251
1252 (set 'pre-cmd (mapconcat 'identity pre-cmd ada-command-separator))
1253 (if (not (equal pre-cmd ""))
1254 (setq pre-cmd (concat pre-cmd ada-command-separator)))
1255
1256 (set 'post-cmd (mapconcat 'identity post-cmd "\n"))
1257 (if post-cmd
96a483d9 1258 (set 'post-cmd (concat post-cmd "\n")))
4884c50b 1259
c94ca9e0 1260
4884c50b
SM
1261 ;; Temporarily replaces the definition of `comint-exec' so that we
1262 ;; can execute commands before running gdb.
96a483d9 1263 ;; FIXME: This is evil and not temporary !!! -stef
a1506d29 1264 (fset 'comint-exec
4884c50b
SM
1265 `(lambda (buffer name command startfile switches)
1266 (let (compilation-buffer-name-function)
1267 (save-excursion
1268 (set 'compilation-buffer-name-function
1269 (lambda(x) (buffer-name buffer)))
1270 (compile (ada-quote-cmd
1271 (concat ,pre-cmd
1272 command " "
1273 (mapconcat 'identity switches " "))))))
1274 ))
1275
1276 ;; Tight integration should force the tty mode
1277 (if (and (string-match "gvd" (comint-arguments cmd 0 0))
1278 ada-tight-gvd-integration
1279 (not (string-match "--tty" cmd)))
1280 (setq cmd (concat cmd "--tty")))
a1506d29 1281
4884c50b
SM
1282 (if (and (string-match "jdb" (comint-arguments cmd 0 0))
1283 (boundp 'jdb))
1284 (funcall (symbol-function 'jdb) cmd)
1285 (gdb cmd))
1286
c94ca9e0
JB
1287 ;; Restore the standard fset command (or for instance C-U M-x shell
1288 ;; wouldn't work anymore
1289
1290 (fset 'comint-exec old-comint-exec)
1291
4884c50b
SM
1292 ;; Send post-commands to the debugger
1293 (process-send-string (get-buffer-process (current-buffer)) post-cmd)
1294
1295 ;; Move to the end of the debugger buffer, so that it is automatically
1296 ;; scrolled from then on.
1297 (end-of-buffer)
1298
1299 ;; Display both the source window and the debugger window (the former
1300 ;; above the latter). No need to show the debugger window unless it
1301 ;; is going to have some relevant information.
1302 (if (or (not (string-match "gvd" (comint-arguments cmd 0 0)))
1303 (string-match "--tty" cmd))
1304 (split-window-vertically))
1305 (switch-to-buffer buffer)
1306 )))
797aab3c
GM
1307
1308
15ea3b67
GM
1309(defun ada-reread-prj-file (&optional filename)
1310 "Forces Emacs to read either FILENAME or the project file associated
1311with the current buffer.
1312Otherwise, this file is only read once, and never read again.
1313Since the information in the project file is shared between all buffers, this
1314automatically modifies the setup for all the Ada buffer that use this file."
797aab3c 1315 (interactive "P")
15ea3b67
GM
1316 (if filename
1317 (ada-parse-prj-file filename)
797aab3c 1318 (ada-parse-prj-file (ada-prj-find-prj-file)))
797aab3c 1319
4884c50b
SM
1320 ;; Reread the location of the standard runtime library
1321 (ada-initialize-runtime-library
c94ca9e0 1322 (or (ada-xref-get-project-field 'cross_prefix) ""))
4884c50b 1323 )
15ea3b67 1324
797aab3c
GM
1325;; ------ Private routines
1326
1327(defun ada-xref-current (file &optional ali-file-name)
eec3232e 1328 "Update the cross-references for FILE.
4884c50b
SM
1329This in fact recompiles FILE to create ALI-FILE-NAME.
1330This function returns the name of the file that was recompiled to generate
1331the cross-reference information. Note that the ali file can then be deduced by
1332replacing the file extension with .ali"
797aab3c
GM
1333 ;; kill old buffer
1334 (if (and ali-file-name
1335 (get-file-buffer ali-file-name))
1336 (kill-buffer (get-file-buffer ali-file-name)))
a1506d29 1337
4884c50b
SM
1338 (let* ((name (ada-convert-file-name file))
1339 (body-name (or (ada-get-body-name name) name)))
15ea3b67 1340
4884c50b
SM
1341 ;; Always recompile the body when we can. We thus temporarily switch to a
1342 ;; buffer than contains the body of the unit
1343 (save-excursion
1344 (let ((body-visible (find-buffer-visiting body-name))
1345 process)
1346 (if body-visible
1347 (set-buffer body-visible)
1348 (find-file body-name))
1349
1350 ;; Execute the compilation. Note that we must wait for the end of the
1351 ;; process, or the ALI file would still not be available.
1352 ;; Unfortunately, the underlying `compile' command that we use is
1353 ;; asynchronous.
1354 (ada-compile-current)
1355 (setq process (get-buffer-process "*compilation*"))
1356
1357 (while (and process
1358 (not (equal (process-status process) 'exit)))
1359 (sit-for 1))
1360
1361 ;; remove the buffer for the body if it wasn't there before
1362 (unless body-visible
1363 (kill-buffer (find-buffer-visiting body-name)))
1364 ))
1365 body-name))
15ea3b67
GM
1366
1367(defun ada-find-file-in-dir (file dir-list)
1368 "Search for FILE in DIR-LIST."
1369 (let (found)
1370 (while (and (not found) dir-list)
1371 (set 'found (concat (file-name-as-directory (car dir-list))
1372 (file-name-nondirectory file)))
a1506d29 1373
15ea3b67
GM
1374 (unless (file-exists-p found)
1375 (set 'found nil))
1376 (set 'dir-list (cdr dir-list)))
1377 found))
797aab3c
GM
1378
1379(defun ada-find-ali-file-in-dir (file)
15ea3b67
GM
1380 "Find an .ali file in obj_dir. The current buffer must be the Ada file.
1381Adds build_dir in front of the search path to conform to gnatmake's behavior,
1382and the standard runtime location at the end."
4884c50b 1383 (ada-find-file-in-dir file (ada-xref-get-obj-dir-field)))
15ea3b67
GM
1384
1385(defun ada-find-src-file-in-dir (file)
1386 "Find a source file in src_dir. The current buffer must be the Ada file.
1387Adds src_dir in front of the search path to conform to gnatmake's behavior,
1388and the standard runtime location at the end."
4884c50b 1389 (ada-find-file-in-dir file (ada-xref-get-src-dir-field)))
797aab3c
GM
1390
1391(defun ada-get-ali-file-name (file)
eec3232e
GM
1392 "Create the ali file name for the ada-file FILE.
1393The file is searched for in every directory shown in the obj_dir lines of
1394the project file."
797aab3c
GM
1395
1396 ;; This function has to handle the special case of non-standard
1397 ;; file names (i.e. not .adb or .ads)
1398 ;; The trick is the following:
1399 ;; 1- replace the extension of the current file with .ali,
1400 ;; and look for this file
1401 ;; 2- If this file is found:
1402 ;; grep the "^U" lines, and make sure we are not reading the
1403 ;; .ali file for a spec file. If we are, go to step 3.
1404 ;; 3- If the file is not found or step 2 failed:
1405 ;; find the name of the "other file", ie the body, and look
1406 ;; for its associated .ali file by subtituing the extension
4884c50b
SM
1407 ;;
1408 ;; We must also handle the case of separate packages and subprograms:
1409 ;; 4- If no ali file was found, we try to modify the file name by removing
1410 ;; everything after the last '-' or '.' character, so as to get the
1411 ;; ali file for the parent unit. If we found an ali file, we check that
1412 ;; it indeed contains the definition for the separate entity by checking
1413 ;; the 'D' lines. This is done repeatedly, in case the direct parent is
1414 ;; also a separate.
797aab3c
GM
1415
1416 (save-excursion
1417 (set-buffer (get-file-buffer file))
1418 (let ((short-ali-file-name
1419 (concat (file-name-sans-extension (file-name-nondirectory file))
1420 ".ali"))
4884c50b
SM
1421 ali-file-name
1422 is-spec)
1423
1424 ;; If we have a non-standard file name, and this is a spec, we first
1425 ;; look for the .ali file of the body, since this is the one that
1426 ;; contains the most complete information. If not found, we will do what
1427 ;; we can with the .ali file for the spec...
1428
1429 (if (not (string= (file-name-extension file) "ads"))
1430 (let ((specs ada-spec-suffixes))
1431 (while specs
1432 (if (string-match (concat (regexp-quote (car specs)) "$")
1433 file)
1434 (set 'is-spec t))
1435 (set 'specs (cdr specs)))))
1436
1437 (if is-spec
1438 (set 'ali-file-name
1439 (ada-find-ali-file-in-dir
1440 (concat (file-name-sans-extension
1441 (file-name-nondirectory
1442 (ada-other-file-name)))
1443 ".ali"))))
a1506d29 1444
4884c50b
SM
1445
1446 (setq ali-file-name
1447 (or ali-file-name
a1506d29 1448
4884c50b
SM
1449 ;; Else we take the .ali file associated with the unit
1450 (ada-find-ali-file-in-dir short-ali-file-name)
a1506d29 1451
4884c50b
SM
1452
1453 ;; else we did not find the .ali file Second chance: in case
1454 ;; the files do not have standard names (such as for instance
1455 ;; file_s.ada and file_b.ada), try to go to the other file
1456 ;; and look for its ali file
1457 (ada-find-ali-file-in-dir
1458 (concat (file-name-sans-extension
1459 (file-name-nondirectory (ada-other-file-name)))
1460 ".ali"))
1461
a1506d29 1462
4884c50b
SM
1463 ;; If we still don't have an ali file, try to get the one
1464 ;; from the parent unit, in case we have a separate entity.
1465 (let ((parent-name (file-name-sans-extension
1466 (file-name-nondirectory file))))
a1506d29 1467
4884c50b
SM
1468 (while (and (not ali-file-name)
1469 (string-match "^\\(.*\\)[.-][^.-]*" parent-name))
a1506d29 1470
4884c50b
SM
1471 (set 'parent-name (match-string 1 parent-name))
1472 (set 'ali-file-name (ada-find-ali-file-in-dir
1473 (concat parent-name ".ali")))
1474 )
1475 ali-file-name)))
a1506d29 1476
4884c50b
SM
1477 ;; If still not found, try to recompile the file
1478 (if (not ali-file-name)
1479 ;; recompile only if the user asked for this. and search the ali
1480 ;; filename again. We avoid a possible infinite recursion by
1481 ;; temporarily disabling the automatic compilation.
a1506d29 1482
4884c50b
SM
1483 (if ada-xref-create-ali
1484 (setq ali-file-name
1485 (concat (file-name-sans-extension (ada-xref-current file))
1486 ".ali"))
797aab3c 1487
4884c50b 1488 (error "Ali file not found. Recompile your file"))
a1506d29
JB
1489
1490
4884c50b
SM
1491 ;; same if the .ali file is too old and we must recompile it
1492 (if (and (file-newer-than-file-p file ali-file-name)
1493 ada-xref-create-ali)
1494 (ada-xref-current file ali-file-name)))
797aab3c 1495
4884c50b 1496 ;; Always return the correct absolute file name
797aab3c 1497 (expand-file-name ali-file-name))
4884c50b 1498 ))
797aab3c
GM
1499
1500(defun ada-get-ada-file-name (file original-file)
eec3232e
GM
1501 "Create the complete file name (+directory) for FILE.
1502The original file (where the user was) is ORIGINAL-FILE. Search in project
1503file for possible paths."
797aab3c
GM
1504
1505 (save-excursion
15ea3b67
GM
1506
1507 ;; If the buffer for original-file, use it to get the values from the
1508 ;; project file, otherwise load the file and its project file
1509 (let ((buffer (get-file-buffer original-file)))
1510 (if buffer
1511 (set-buffer buffer)
1512 (find-file original-file)
1513 (ada-require-project-file)))
a1506d29 1514
797aab3c
GM
1515 ;; we choose the first possible completion and we
1516 ;; return the absolute file name
15ea3b67 1517 (let ((filename (ada-find-src-file-in-dir file)))
797aab3c
GM
1518 (if filename
1519 (expand-file-name filename)
1520 (error (concat
1521 (file-name-nondirectory file)
1522 " not found in src_dir. Please check your project file")))
1523
1524 )))
1525
1526(defun ada-find-file-number-in-ali (file)
eec3232e 1527 "Returns the file number for FILE in the associated ali file."
797aab3c
GM
1528 (set-buffer (ada-get-ali-buffer file))
1529 (goto-char (point-min))
1530
1531 (let ((begin (re-search-forward "^D")))
1532 (beginning-of-line)
1533 (re-search-forward (concat "^D " (file-name-nondirectory file)))
1534 (count-lines begin (point))))
1535
1536(defun ada-read-identifier (pos)
4884c50b
SM
1537 "Returns the identlist around POS and switch to the .ali buffer.
1538The returned list represents the entity, and can be manipulated through the
1539macros `ada-name-of', `ada-line-of', `ada-column-of', `ada-file-of',..."
797aab3c
GM
1540
1541 ;; If at end of buffer (e.g the buffer is empty), error
1542 (if (>= (point) (point-max))
1543 (error "No identifier on point"))
a1506d29 1544
797aab3c
GM
1545 ;; goto first character of the identifier/operator (skip backward < and >
1546 ;; since they are part of multiple character operators
1547 (goto-char pos)
1548 (skip-chars-backward "a-zA-Z0-9_<>")
1549
1550 ;; check if it really is an identifier
1551 (if (ada-in-comment-p)
1552 (error "Inside comment"))
1553
1554 (let (identifier identlist)
1555 ;; Just in front of a string => we could have an operator declaration,
1556 ;; as in "+", "-", ..
1557 (if (= (char-after) ?\")
1558 (forward-char 1))
1559
1560 ;; if looking at an operator
15ea3b67
GM
1561 ;; This is only true if:
1562 ;; - the symbol is +, -, ...
1563 ;; - the symbol is made of letters, and not followed by _ or a letter
1564 (if (and (looking-at ada-operator-re)
1565 (or (not (= (char-syntax (char-after)) ?w))
1566 (not (or (= (char-syntax (char-after (match-end 0))) ?w)
1567 (= (char-after (match-end 0)) ?_)))))
797aab3c
GM
1568 (progn
1569 (if (and (= (char-before) ?\")
1570 (= (char-after (+ (length (match-string 0)) (point))) ?\"))
1571 (forward-char -1))
15ea3b67 1572 (set 'identifier (regexp-quote (concat "\"" (match-string 0) "\""))))
797aab3c
GM
1573
1574 (if (ada-in-string-p)
1575 (error "Inside string or character constant"))
1576 (if (looking-at (concat ada-keywords "[^a-zA-Z_]"))
1577 (error "No cross-reference available for reserved keyword"))
1578 (if (looking-at "[a-zA-Z0-9_]+")
1579 (set 'identifier (match-string 0))
1580 (error "No identifier around")))
a1506d29 1581
797aab3c
GM
1582 ;; Build the identlist
1583 (set 'identlist (ada-make-identlist))
1584 (ada-set-name identlist (downcase identifier))
1585 (ada-set-line identlist
93cdce20 1586 (number-to-string (count-lines 1 (point))))
797aab3c
GM
1587 (ada-set-column identlist
1588 (number-to-string (1+ (current-column))))
1589 (ada-set-file identlist (buffer-file-name))
1590 identlist
1591 ))
1592
1593(defun ada-get-all-references (identlist)
15ea3b67 1594 "Completes and returns IDENTLIST with the information extracted
eec3232e 1595from the ali file (definition file and places where it is referenced)."
a1506d29 1596
797aab3c
GM
1597 (let ((ali-buffer (ada-get-ali-buffer (ada-file-of identlist)))
1598 declaration-found)
1599 (set-buffer ali-buffer)
1600 (goto-char (point-min))
1601 (ada-set-on-declaration identlist nil)
1602
1603 ;; First attempt: we might already be on the declaration of the identifier
1604 ;; We want to look for the declaration only in a definite interval (after
1605 ;; the "^X ..." line for the current file, and before the next "^X" line
a1506d29 1606
797aab3c
GM
1607 (if (re-search-forward
1608 (concat "^X [0-9]+ " (file-name-nondirectory (ada-file-of identlist)))
1609 nil t)
1610 (let ((bound (save-excursion (re-search-forward "^X " nil t))))
1611 (set 'declaration-found
1612 (re-search-forward
1613 (concat "^" (ada-line-of identlist)
1614 "." (ada-column-of identlist)
15ea3b67 1615 "[ *]" (ada-name-of identlist)
93cdce20 1616 "[{\(<= ]?\\(.*\\)$") bound t))
797aab3c
GM
1617 (if declaration-found
1618 (ada-set-on-declaration identlist t))
1619 ))
1620
1621 ;; If declaration is still nil, then we were not on a declaration, and
1622 ;; have to fall back on other algorithms
1623
1624 (unless declaration-found
a1506d29 1625
797aab3c
GM
1626 ;; Since we alread know the number of the file, search for a direct
1627 ;; reference to it
1628 (goto-char (point-min))
1629 (set 'declaration-found t)
1630 (ada-set-ali-index
1631 identlist
1632 (number-to-string (ada-find-file-number-in-ali
1633 (ada-file-of identlist))))
1634 (unless (re-search-forward (concat (ada-ali-index-of identlist)
93cdce20 1635 "|\\([0-9]+[^0-9][0-9]+\\(\n\\.\\)? \\)*"
797aab3c 1636 (ada-line-of identlist)
c94ca9e0 1637 "[^etpzkd<>=^]"
93cdce20 1638 (ada-column-of identlist) "\\>")
797aab3c
GM
1639 nil t)
1640
1641 ;; if we did not find it, it may be because the first reference
1642 ;; is not required to have a 'unit_number|' item included.
1643 ;; Or maybe we are already on the declaration...
4884c50b
SM
1644 (unless (re-search-forward
1645 (concat
93cdce20
SM
1646 "^[0-9]+.[0-9]+[ *]"
1647 (ada-name-of identlist)
1648 "[ <{=\(]\\(.\\|\n\\.\\)*\\<"
4884c50b
SM
1649 (ada-line-of identlist)
1650 "[^0-9]"
93cdce20 1651 (ada-column-of identlist) "\\>")
4884c50b 1652 nil t)
a1506d29 1653
797aab3c
GM
1654 ;; If still not found, then either the declaration is unknown
1655 ;; or the source file has been modified since the ali file was
1656 ;; created
1657 (set 'declaration-found nil)
1658 )
1659 )
1660
1661 ;; Last check to be completly sure we have found the correct line (the
1662 ;; ali might not be up to date for instance)
1663 (if declaration-found
1664 (progn
1665 (beginning-of-line)
1666 ;; while we have a continuation line, go up one line
1667 (while (looking-at "^\\.")
1668 (previous-line 1))
1669 (unless (looking-at (concat "[0-9]+.[0-9]+[ *]"
93cdce20 1670 (ada-name-of identlist) "[ <{=\(]"))
797aab3c
GM
1671 (set 'declaration-found nil))))
1672
1673 ;; Still no success ! The ali file must be too old, and we need to
1674 ;; use a basic algorithm based on guesses. Note that this only happens
1675 ;; if the user does not want us to automatically recompile files
1676 ;; automatically
1677 (unless declaration-found
15ea3b67
GM
1678 (if (ada-xref-find-in-modified-ali identlist)
1679 (set 'declaration-found t)
797aab3c
GM
1680 ;; no more idea to find the declaration. Give up
1681 (progn
1682 (kill-buffer ali-buffer)
1683 (error (concat "No declaration of " (ada-name-of identlist)
1684 " found."))
1685 )))
1686 )
1687
a1506d29 1688
797aab3c
GM
1689 ;; Now that we have found a suitable line in the .ali file, get the
1690 ;; information available
1691 (beginning-of-line)
1692 (if declaration-found
1693 (let ((current-line (buffer-substring
1694 (point) (save-excursion (end-of-line) (point)))))
1695 (save-excursion
1696 (next-line 1)
1697 (beginning-of-line)
1698 (while (looking-at "^\\.\\(.*\\)")
1699 (set 'current-line (concat current-line (match-string 1)))
1700 (next-line 1))
1701 )
1702
1703 (if (re-search-backward "^X [0-9]+ \\([a-zA-Z0-9_.-]+\\)" nil t)
4884c50b
SM
1704
1705 ;; If we can find the file
1706 (condition-case err
1707 (ada-set-declare-file
1708 identlist
1709 (ada-get-ada-file-name (match-string 1)
1710 (ada-file-of identlist)))
a1506d29 1711
4884c50b
SM
1712 ;; Else clean up the ali file
1713 (error
1714 (kill-buffer ali-buffer)
1715 (error (error-message-string err)))
1716 ))
a1506d29 1717
797aab3c
GM
1718 (ada-set-references identlist current-line)
1719 ))
1720 ))
1721
1722(defun ada-xref-find-in-modified-ali (identlist)
1723 "Find the matching position for IDENTLIST in the current ali buffer.
1724This function is only called when the file was not up-to-date, so we need
1725to make some guesses.
eec3232e 1726This function is disabled for operators, and only works for identifiers."
797aab3c
GM
1727
1728 (unless (= (string-to-char (ada-name-of identlist)) ?\")
1729 (progn
1730 (let ((declist '()) ;;; ( (line_in_ali_file line_in_ada) ( ... ))
1731 (my-regexp (concat "[ *]"
1732 (regexp-quote (ada-name-of identlist)) " "))
1733 (line-ada "--")
1734 (col-ada "--")
1735 (line-ali 0)
1736 (len 0)
15ea3b67
GM
1737 (choice 0)
1738 (ali-buffer (current-buffer)))
797aab3c
GM
1739
1740 (goto-char (point-max))
1741 (while (re-search-backward my-regexp nil t)
1742 (save-excursion
c94ca9e0 1743 (set 'line-ali (count-lines 1 (point)))
797aab3c
GM
1744 (beginning-of-line)
1745 ;; have a look at the line and column numbers
1746 (if (looking-at "^\\([0-9]+\\).\\([0-9]+\\)[ *]")
1747 (progn
1748 (setq line-ada (match-string 1))
1749 (setq col-ada (match-string 2)))
1750 (setq line-ada "--")
1751 (setq col-ada "--")
1752 )
1753 ;; construct a list with the file names and the positions within
1754 (if (re-search-backward "^X [0-9]+ \\([a-zA-Z0-9._-]+\\)" nil t)
1755 (add-to-list
1756 'declist (list line-ali (match-string 1) line-ada col-ada))
1757 )
1758 )
1759 )
1760
1761 ;; how many possible declarations have we found ?
1762 (setq len (length declist))
1763 (cond
1764 ;; none => error
1765 ((= len 0)
1766 (kill-buffer (current-buffer))
1767 (error (concat "No declaration of "
1768 (ada-name-of identlist)
1769 " recorded in .ali file")))
a1506d29 1770
797aab3c
GM
1771 ;; one => should be the right one
1772 ((= len 1)
1773 (goto-line (caar declist)))
a1506d29 1774
797aab3c
GM
1775 ;; more than one => display choice list
1776 (t
4884c50b
SM
1777 (save-window-excursion
1778 (with-output-to-temp-buffer "*choice list*"
a1506d29 1779
4884c50b
SM
1780 (princ "Identifier is overloaded and Xref information is not up to date.\n")
1781 (princ "Possible declarations are:\n\n")
1782 (princ " no. in file at line col\n")
1783 (princ " --- --------------------- ---- ----\n")
1784 (let ((counter 0))
1785 (while (< counter len)
1786 (princ (format " %2d) %-21s %4s %4s\n"
1787 (1+ counter)
797aab3c 1788 (ada-get-ada-file-name
4884c50b 1789 (nth 1 (nth counter declist))
797aab3c 1790 (ada-file-of identlist))
4884c50b
SM
1791 (nth 2 (nth counter declist))
1792 (nth 3 (nth counter declist))
797aab3c 1793 ))
4884c50b
SM
1794 (setq counter (1+ counter))
1795 ) ; end of while
1796 ) ; end of let
1797 ) ; end of with-output-to ...
1798 (setq choice nil)
1799 (while (or
1800 (not choice)
1801 (not (integerp choice))
1802 (< choice 1)
1803 (> choice len))
1804 (setq choice
1805 (string-to-int
1806 (read-from-minibuffer "Enter No. of your choice: "))))
1807 )
15ea3b67 1808 (set-buffer ali-buffer)
797aab3c
GM
1809 (goto-line (car (nth (1- choice) declist)))
1810 ))))))
1811
1812
1813(defun ada-find-in-ali (identlist &optional other-frame)
eec3232e
GM
1814 "Look in the .ali file for the definition of the identifier in IDENTLIST.
1815If OTHER-FRAME is non nil, and `ada-xref-other-buffer' is non nil,
1816opens a new window to show the declaration."
797aab3c
GM
1817
1818 (ada-get-all-references identlist)
1819 (let ((ali-line (ada-references-of identlist))
4884c50b
SM
1820 (locations nil)
1821 (start 0)
797aab3c 1822 file line col)
4884c50b
SM
1823
1824 ;; Note: in some cases, an entity can have multiple references to the
1825 ;; bodies (this is for instance the case for a separate subprogram, that
1826 ;; has a reference both to the stub and to the real body).
1827 ;; In that case, we simply go to each one in turn.
1828
1829 ;; Get all the possible locations
1830 (string-match "^\\([0-9]+\\)[a-zA-Z+]\\([0-9]+\\)[ *]" ali-line)
1831 (set 'locations (list (list (match-string 1 ali-line) ;; line
1832 (match-string 2 ali-line) ;; column
1833 (ada-declare-file-of identlist))))
c94ca9e0
JB
1834 (while (string-match "\\([0-9]+\\)[bc]\\(<[^>]+>\\)?\\([0-9]+\\)"
1835 ali-line start)
4884c50b 1836 (setq line (match-string 1 ali-line)
c94ca9e0
JB
1837 col (match-string 3 ali-line)
1838 start (match-end 3))
4884c50b
SM
1839
1840 ;; it there was a file number in the same line
c94ca9e0 1841 (if (string-match (concat "[^{(<]\\([0-9]+\\)|\\([^|bc]+\\)?"
4884c50b
SM
1842 (match-string 0 ali-line))
1843 ali-line)
1844 (let ((file-number (match-string 1 ali-line)))
1845 (goto-char (point-min))
1846 (re-search-forward "^D \\([a-zA-Z0-9_.-]+\\)" nil t
1847 (string-to-number file-number))
1848 (set 'file (match-string 1))
1849 )
1850 ;; Else get the nearest file
1851 (set 'file (ada-declare-file-of identlist)))
a1506d29 1852
4884c50b
SM
1853 (set 'locations (append locations (list (list line col file)))))
1854
1855 ;; Add the specs at the end again, so that from the last body we go to
1856 ;; the specs
1857 (set 'locations (append locations (list (car locations))))
1858
1859 ;; Find the new location we want to go to.
1860 ;; If we are on none of the locations listed, we simply go to the specs.
1861
1862 (setq line (caar locations)
1863 col (nth 1 (car locations))
1864 file (nth 2 (car locations)))
a1506d29 1865
4884c50b
SM
1866 (while locations
1867 (if (and (string= (caar locations) (ada-line-of identlist))
1868 (string= (nth 1 (car locations)) (ada-column-of identlist))
1869 (string= (file-name-nondirectory (nth 2 (car locations)))
1870 (file-name-nondirectory (ada-file-of identlist))))
1871 (setq locations (cadr locations)
1872 line (car locations)
1873 col (nth 1 locations)
1874 file (nth 2 locations)
1875 locations nil)
1876 (set 'locations (cdr locations))))
1877
1878 ;; Find the file in the source path
1879 (set 'file (ada-get-ada-file-name file (ada-file-of identlist)))
1880
1881 ;; Kill the .ali buffer
1882 (kill-buffer (current-buffer))
797aab3c
GM
1883
1884 ;; Now go to the buffer
4884c50b
SM
1885 (ada-xref-change-buffer file
1886 (string-to-number line)
1887 (1- (string-to-number col))
1888 identlist
1889 other-frame)
797aab3c
GM
1890 ))
1891
4884c50b
SM
1892(defun ada-find-in-src-path (identlist &optional other-frame)
1893 "More general function for cross-references.
1894This function should be used when the standard algorithm that parses the
1895.ali file has failed, either because that file was too old or even did not
1896exist.
1897This function attempts to find the possible declarations for the identifier
1898anywhere in the object path.
1899This command requires the external `egrep' program to be available.
1900
1901This works well when one is using an external librarie and wants
1902to find the declaration and documentation of the subprograms one is
1903is using."
a1506d29 1904
4884c50b
SM
1905 (let (list
1906 (dirs (ada-xref-get-obj-dir-field))
1907 (regexp (concat "[ *]" (ada-name-of identlist)))
1908 line column
1909 choice
1910 file)
a1506d29 1911
4884c50b 1912 (save-excursion
a1506d29 1913
4884c50b
SM
1914 ;; Do the grep in all the directories. We do multiple shell
1915 ;; commands instead of one in case there is no .ali file in one
1916 ;; of the directory and the shell stops because of that.
a1506d29 1917
4884c50b
SM
1918 (set-buffer (get-buffer-create "*grep*"))
1919 (while dirs
1920 (insert (shell-command-to-string
1921 (concat "egrep -i -h '^X|" regexp "( |$)' "
1922 (file-name-as-directory (car dirs)) "*.ali")))
1923 (set 'dirs (cdr dirs)))
a1506d29 1924
4884c50b
SM
1925 ;; Now parse the output
1926 (set 'case-fold-search t)
1927 (goto-char (point-min))
1928 (while (re-search-forward regexp nil t)
1929 (save-excursion
1930 (beginning-of-line)
1931 (if (not (= (char-after) ?X))
1932 (progn
1933 (looking-at "\\([0-9]+\\).\\([0-9]+\\)")
1934 (setq line (match-string 1)
1935 column (match-string 2))
1936 (re-search-backward "^X [0-9]+ \\(.*\\)$")
1937 (set 'file (list (match-string 1) line column))
a1506d29 1938
4884c50b
SM
1939 ;; There could be duplicate choices, because of the structure
1940 ;; of the .ali files
1941 (unless (member file list)
1942 (set 'list (append list (list file))))))))
a1506d29 1943
4884c50b
SM
1944 ;; Current buffer is still "*grep*"
1945 (kill-buffer "*grep*")
1946 )
a1506d29 1947
4884c50b
SM
1948 ;; Now display the list of possible matches
1949 (cond
a1506d29 1950
4884c50b
SM
1951 ;; No choice found => Error
1952 ((null list)
1953 (error "No cross-reference found, please recompile your file"))
a1506d29 1954
4884c50b
SM
1955 ;; Only one choice => Do the cross-reference
1956 ((= (length list) 1)
1957 (set 'file (ada-find-src-file-in-dir (caar list)))
1958 (if file
1959 (ada-xref-change-buffer file
1960 (string-to-number (nth 1 (car list)))
1961 (string-to-number (nth 2 (car list)))
1962 identlist
1963 other-frame)
1964 (error (concat (caar list) " not found in src_dir")))
1965 (message "This is only a (good) guess at the cross-reference.")
1966 )
a1506d29 1967
4884c50b
SM
1968 ;; Else, ask the user
1969 (t
1970 (save-window-excursion
1971 (with-output-to-temp-buffer "*choice list*"
a1506d29 1972
4884c50b
SM
1973 (princ "Identifier is overloaded and Xref information is not up to date.\n")
1974 (princ "Possible declarations are:\n\n")
1975 (princ " no. in file at line col\n")
1976 (princ " --- --------------------- ---- ----\n")
1977 (let ((counter 0))
1978 (while (< counter (length list))
1979 (princ (format " %2d) %-21s %4s %4s\n"
1980 (1+ counter)
1981 (nth 0 (nth counter list))
1982 (nth 1 (nth counter list))
1983 (nth 2 (nth counter list))
1984 ))
1985 (setq counter (1+ counter))
1986 )))
1987 (setq choice nil)
1988 (while (or (not choice)
1989 (not (integerp choice))
1990 (< choice 1)
1991 (> choice (length list)))
1992 (setq choice
1993 (string-to-int
1994 (read-from-minibuffer "Enter No. of your choice: "))))
1995 )
1996 (set 'choice (1- choice))
1997 (kill-buffer "*choice list*")
1998
1999 (set 'file (ada-find-src-file-in-dir (car (nth choice list))))
2000 (if file
2001 (ada-xref-change-buffer file
2002 (string-to-number (nth 1 (nth choice list)))
2003 (string-to-number (nth 2 (nth choice list)))
2004 identlist
2005 other-frame)
2006 (error (concat (car (nth choice list)) " not found in src_dir")))
2007 (message "This is only a (good) guess at the cross-reference.")
2008 ))))
2009
797aab3c
GM
2010(defun ada-xref-change-buffer
2011 (file line column identlist &optional other-frame)
4884c50b 2012 "Select and display FILE, at LINE and COLUMN.
797aab3c 2013If we do not end on the same identifier as IDENTLIST, find the closest
eec3232e
GM
2014match. Kills the .ali buffer at the end.
2015If OTHER-FRAME is non-nil, creates a new frame to show the file."
797aab3c 2016
4884c50b 2017 (let (declaration-buffer)
797aab3c
GM
2018
2019 ;; Select and display the destination buffer
2020 (if ada-xref-other-buffer
2021 (if other-frame
2022 (find-file-other-frame file)
2023 (set 'declaration-buffer (find-file-noselect file))
2024 (set-buffer declaration-buffer)
2025 (switch-to-buffer-other-window declaration-buffer)
2026 )
2027 (find-file file)
2028 )
2029
797aab3c
GM
2030 ;; move the cursor to the correct position
2031 (push-mark)
2032 (goto-line line)
2033 (move-to-column column)
2034
2035 ;; If we are not on the identifier, the ali file was not up-to-date.
2036 ;; Try to find the nearest position where the identifier is found,
2037 ;; this is probably the right one.
2038 (unless (looking-at (ada-name-of identlist))
2039 (ada-xref-search-nearest (ada-name-of identlist)))
4884c50b 2040 ))
797aab3c
GM
2041
2042
2043(defun ada-xref-search-nearest (name)
2044 "Searches for NAME nearest to the position recorded in the Xref file.
2045It returns the position of the declaration in the buffer or nil if not found."
2046 (let ((orgpos (point))
2047 (newpos nil)
2048 (diff nil))
2049
2050 (goto-char (point-max))
2051
2052 ;; loop - look for all declarations of name in this file
2053 (while (search-backward name nil t)
2054
2055 ;; check if it really is a complete Ada identifier
2056 (if (and
2057 (not (save-excursion
2058 (goto-char (match-end 0))
2059 (looking-at "_")))
2060 (not (ada-in-string-or-comment-p))
2061 (or
2062 ;; variable declaration ?
2063 (save-excursion
2064 (skip-chars-forward "a-zA-Z_0-9" )
2065 (ada-goto-next-non-ws)
2066 (looking-at ":[^=]"))
2067 ;; procedure, function, task or package declaration ?
2068 (save-excursion
2069 (ada-goto-previous-word)
2070 (looking-at "\\<[pP][rR][oO][cC][eE][dD][uU][rR][eE]\\>\\|\\<[fF][uU][nN][cC][tT][iI][oO][nN]\\>\\|\\<[tT][yY][pP][eE]\\>\\|\\<[tT][aA][sS][kK]\\>\\|\\<[pP][aA][cC][kK][aA][gG][eE]\\>\\|\\<[bB][oO][dD][yY]\\>"))))
2071
2072 ;; check if it is nearer than the ones before if any
2073 (if (or (not diff)
2074 (< (abs (- (point) orgpos)) diff))
2075 (progn
2076 (setq newpos (point)
2077 diff (abs (- newpos orgpos))))))
2078 )
2079
2080 (if newpos
2081 (progn
2082 (message "ATTENTION: this declaration is only a (good) guess ...")
2083 (goto-char newpos))
2084 nil)))
2085
2086
2087;; Find the parent library file of the current file
2088(defun ada-goto-parent ()
eec3232e 2089 "Go to the parent library file."
797aab3c
GM
2090 (interactive)
2091 (ada-require-project-file)
2092
2093 (let ((buffer (ada-get-ali-buffer (buffer-file-name)))
2094 (unit-name nil)
2095 (body-name nil)
2096 (ali-name nil))
2097 (save-excursion
2098 (set-buffer buffer)
2099 (goto-char (point-min))
2100 (re-search-forward "^U \\([^ \t%]+\\)%[bs][ \t]+\\([^ \t]+\\)")
2101 (setq unit-name (match-string 1))
2102 (if (not (string-match "\\(.*\\)\\.[^.]+" unit-name))
2103 (progn
2104 (kill-buffer buffer)
2105 (error "No parent unit !"))
2106 (setq unit-name (match-string 1 unit-name))
2107 )
2108
2109 ;; look for the file name for the parent unit specification
2110 (goto-char (point-min))
2111 (re-search-forward (concat "^W " unit-name
2112 "%s[ \t]+\\([^ \t]+\\)[ \t]+"
2113 "\\([^ \t\n]+\\)"))
2114 (setq body-name (match-string 1))
2115 (setq ali-name (match-string 2))
2116 (kill-buffer buffer)
2117 )
2118
2119 (setq ali-name (ada-find-ali-file-in-dir ali-name))
2120
2121 (save-excursion
2122 ;; Tries to open the new ali file to find the spec file
2123 (if ali-name
2124 (progn
2125 (find-file ali-name)
2126 (goto-char (point-min))
2127 (re-search-forward (concat "^U " unit-name "%s[ \t]+"
2128 "\\([^ \t]+\\)"))
2129 (setq body-name (match-string 1))
2130 (kill-buffer (current-buffer))
2131 )
2132 )
2133 )
2134
2135 (find-file body-name)
2136 ))
2137
2138(defun ada-make-filename-from-adaname (adaname)
eec3232e
GM
2139 "Determine the filename in which ADANAME is found.
2140This is a GNAT specific function that uses gnatkrunch."
797aab3c
GM
2141 (let (krunch-buf)
2142 (setq krunch-buf (generate-new-buffer "*gkrunch*"))
2143 (save-excursion
2144 (set-buffer krunch-buf)
2145 ;; send adaname to external process `gnatkr'.
2146 (call-process "gnatkr" nil krunch-buf nil
2147 adaname ada-krunch-args)
2148 ;; fetch output of that process
2149 (setq adaname (buffer-substring
2150 (point-min)
2151 (progn
2152 (goto-char (point-min))
2153 (end-of-line)
2154 (point))))
2155 (kill-buffer krunch-buf)))
2156 adaname
2157 )
2158
797aab3c
GM
2159(defun ada-make-body-gnatstub ()
2160 "Create an Ada package body in the current buffer.
2161This function uses the `gnatstub' program to create the body.
2162This function typically is to be hooked into `ff-file-created-hooks'."
2163 (interactive)
2164
2165 (save-some-buffers nil nil)
2166
4884c50b
SM
2167 ;; If the current buffer is the body (as is the case when calling this
2168 ;; function from ff-file-created-hooks), then kill this temporary buffer
2169 (unless (interactive-p)
2170 (progn
2171 (set-buffer-modified-p nil)
2172 (kill-buffer (current-buffer))))
a1506d29 2173
797aab3c 2174
4884c50b
SM
2175 ;; Make sure the current buffer is the spec (this might not be the case
2176 ;; if for instance the user was asked for a project file)
2177
2178 (unless (buffer-file-name (car (buffer-list)))
2179 (set-buffer (cadr (buffer-list))))
2180
2181 ;; Make sure we have a project file (for parameters to gnatstub). Note that
2182 ;; this might have already been done if we have been called from the hook,
2183 ;; but this is not an expensive call)
2184 (ada-require-project-file)
797aab3c
GM
2185
2186 ;; Call the external process gnatstub
2187 (let* ((gnatstub-opts (ada-treat-cmd-string ada-gnatstub-opts))
4884c50b 2188 (filename (buffer-file-name (car (buffer-list))))
797aab3c
GM
2189 (output (concat (file-name-sans-extension filename) ".adb"))
2190 (gnatstub-cmd (concat "gnatstub " gnatstub-opts " " filename))
2191 (buffer (get-buffer-create "*gnatstub*")))
2192
2193 (save-excursion
2194 (set-buffer buffer)
2195 (compilation-minor-mode 1)
2196 (erase-buffer)
2197 (insert gnatstub-cmd)
2198 (newline)
2199 )
2200 ;; call gnatstub to create the body file
2201 (call-process shell-file-name nil buffer nil "-c" gnatstub-cmd)
2202
2203 (if (save-excursion
2204 (set-buffer buffer)
2205 (goto-char (point-min))
2206 (search-forward "command not found" nil t))
2207 (progn
2208 (message "gnatstub was not found -- using the basic algorithm")
2209 (sleep-for 2)
2210 (kill-buffer buffer)
2211 (ada-make-body))
2212
2213 ;; Else clean up the output
2214
797aab3c
GM
2215 (if (file-exists-p output)
2216 (progn
2217 (find-file output)
2218 (kill-buffer buffer))
2219
2220 ;; display the error buffer
2221 (display-buffer buffer)
2222 )
2223 )))
2224
797aab3c 2225(defun ada-xref-initialize ()
fea24571
SM
2226 "Function called by `ada-mode-hook' to initialize the ada-xref.el package.
2227For instance, it creates the gnat-specific menus, sets some hooks for
797aab3c 2228find-file...."
fea24571 2229 ;; This should really be an `add-hook'. -stef
7abe197c 2230 (setq ff-file-created-hook 'ada-make-body-gnatstub)
797aab3c 2231
797aab3c
GM
2232 ;; Completion for file names in the mini buffer should ignore .ali files
2233 (add-to-list 'completion-ignored-extensions ".ali")
c94ca9e0
JB
2234
2235 (ada-xref-update-project-menu)
797aab3c
GM
2236 )
2237
2238
2239;; ----- Add to ada-mode-hook ---------------------------------------------
2240
4884c50b
SM
2241;; Use gvd or ddd as the default debugger if it was found
2242;; On windows, do not use the --tty switch for GVD, since this is
2243;; not supported. Actually, we do not use this on Unix either, since otherwise
2244;; there is no console window left in GVD, and people have to use the
2245;; Emacs one.
2246;; This must be done before initializing the Ada menu.
2247(if (ada-find-file-in-dir "gvd" exec-path)
2248 (set 'ada-prj-default-debugger "gvd ")
2249 (if (ada-find-file-in-dir "gvd.exe" exec-path)
2250 (set 'ada-prj-default-debugger "gvd ")
2251 (if (ada-find-file-in-dir "ddd" exec-path)
2252 (set 'ada-prj-default-debugger "ddd --tty -fullname -toolbar"))))
2253
797aab3c
GM
2254(add-hook 'ada-mode-hook 'ada-xref-initialize)
2255
15ea3b67 2256;; Initializes the cross references to the runtime library
4884c50b 2257(ada-initialize-runtime-library "")
15ea3b67
GM
2258
2259;; Add these standard directories to the search path
7abe197c 2260(set 'ada-search-directories-internal
15ea3b67
GM
2261 (append (mapcar 'directory-file-name ada-xref-runtime-library-specs-path)
2262 ada-search-directories))
2263
797aab3c
GM
2264(provide 'ada-xref)
2265
ab5796a9 2266;;; arch-tag: 415a39fe-577b-4676-b3b1-6ff6db7ca24e
383d5bbb 2267;;; ada-xref.el ends here