comparison lisp/progmodes/ada-xref.el @ 30408:e3e2c9051c5f

Got rid of all byte-compiler warnings on Emacs. Add to the menu when the file is loaded, not in ada-mode-hook. Add -toolbar to the default ddd command Switches moved from ada-prj-default-comp-cmd and ada-prj-default-make-cmd to ada-prj-default-comp-opt (ada-add-ada-menu): Remove the map and name parameters Add the Ada Reference Manual to the menu (ada-check-current): rewritten as a call to ada-compile-current (ada-compile): Removed. (ada-compile-application, ada-compile-current, ada-check-current): Set the compilation-search-path so that compile.el automatically finds the sources in src_dir. Automatic scrollong of the compilation buffer. C-uC-cC-c asks for confirmation before compiling (ada-compile-current): New parameter, prj-field (ada-complete-identifier): Load the .ali file before doing processing (ada-find-ali-file-in-dir): prepend build_dir to obj_dir to conform to gnatmake's behavior. (ada-find-file-in-dir): New function (ada-find-references): Set the environment variables for gnatfind (ada-find-src-file-in-dir): New function. (ada-first-non-nil): Removed (ada-gdb-application): Add support for jdb, the java debugger. (ada-get-ada-file-name): Load the original-file first if not done yet. (ada-get-all-references): Handles the new ali syntax (parent types are found between <>). (ada-initialize-runtime-library): New function (ada-mode-hook): Always load a project file when a file is opened, so that the casing exceptions are correctly read. (ada-operator-re): Add all missing operators ("abs", "rem", "**"). (ada-parse-prj-file): Use find-file-noselect instead of find-file to open the project file, since the latter does not work with speedbar Get default values before loading the prj file, or the default executable file name is wrong. Use the absolute value of src_dir to initialize ada-search-directories and compilation-search-path,... Add the standard runtime library to the search path for find-file. (ada-prj-default-debugger): Was missing an opening '{' (ada-prj-default-bind-opt, ada-prj-default-link-opt): New variables. (ada-prj-default-gnatmake-opt): New variable (ada-prj-find-prj-file): Handles non-file buffers For non-Ada buffers, the project file is the default one Save the windows configuration before displaying the menu. (ada-prj-src-dir, ada-prj-obj-dir, ada-prj-comp-opt,...): Removed (ada-read-identifier): Fix xrefs on operators (for "mod", "and", ...) regexp-quote identifiers names to support operators +, -,... in regexps. (ada-remote): New function. (ada-run-application): Erase the output buffer before starting the run Support remote execution of the application. Use call-process, or the arguments are incorrectly parsed (ada-set-default-project-file): Reread the content of the active project file, not the one from the current buffer When a project file is set as the default project, all directories are automatically associated with it. (ada-set-environment): New function (ada-treat-cmd-string): New special variable ${current} (ada-treat-cmd-string): Revised. The substitution is now done for any ${...} substring (ada-xref-current): If no body was found, compiles the spec instead. Setup ADA_{SOURCE,OBJECTS}_PATH before running the compiler to get rid of command line length limitations. (ada-xref-get-project-field): New function (ada-xref-project-files): New variable (ada-xref-runtime-library-specs-path) (ada-xref-runtime-library-ali-path): New variables (ada-xref-set-default-prj-values): Default run command now does a cd to the build directory. New field: main_unit Provide a default file name even if the current buffer has no prj file.
author Gerd Moellmann <gerd@gnu.org>
date Mon, 24 Jul 2000 11:13:11 +0000
parents 1be4a89d81d3
children 0f1f7e931493
comparison
equal deleted inserted replaced
30407:b88ff2eabd4e 30408:e3e2c9051c5f
1 ;; @(#) ada-xref.el --- use Gnat for lookup and completion in Ada mode 1 ;; @(#) ada-xref.el --for lookup and completion in Ada mode
2 2
3 ;; Copyright (C) 1994, 1995--1998, 1999 Free Software Foundation, Inc. 3 ;; Copyright (C) 1994-1999 Free Software Foundation, Inc.
4 4
5 ;; Author: Markus Heritsch <Markus.Heritsch@studbox.uni-stuttgart.de> 5 ;; Author: Markus Heritsch <Markus.Heritsch@studbox.uni-stuttgart.de>
6 ;; Rolf Ebert <ebert@inf.enst.fr> 6 ;; Rolf Ebert <ebert@inf.enst.fr>
7 ;; Emmanuel Briot <briot@gnat.com> 7 ;; Emmanuel Briot <briot@gnat.com>
8 ;; Maintainer: Emmanuel Briot <briot@gnat.com> 8 ;; Maintainer: Emmanuel Briot <briot@gnat.com>
9 ;; Ada Core Technologies's version: $Revision: 1.75 $ 9 ;; Ada Core Technologies's version: $Revision: 1.99 $
10 ;; Keywords: languages ada xref 10 ;; Keywords: languages ada xref
11 11
12 ;; This file is not part of GNU Emacs. 12 ;; This file is not part of GNU Emacs.
13 13
14 ;; This program is free software; you can redistribute it and/or modify 14 ;; This program is free software; you can redistribute it and/or modify
60 ;; ----- Requirements ----------------------------------------------------- 60 ;; ----- Requirements -----------------------------------------------------
61 61
62 (require 'compile) 62 (require 'compile)
63 (require 'comint) 63 (require 'comint)
64 64
65 ;; ----- Dynamic byte compilation -----------------------------------------
66 (defvar byte-compile-dynamic nil)
67 (make-local-variable 'byte-compile-dynamic)
68 (setq byte-compile-dynamic t)
69
70 ;; ------ Use variables 65 ;; ------ Use variables
71 (defcustom ada-xref-other-buffer t 66 (defcustom ada-xref-other-buffer t
72 "*If nil, always display the cross-references in the same buffer. 67 "*If nil, always display the cross-references in the same buffer.
73 Otherwise create either a new buffer or a new frame." 68 Otherwise create either a new buffer or a new frame."
74 :type 'boolean :group 'ada) 69 :type 'boolean :group 'ada)
86 (defcustom ada-krunch-args "0" 81 (defcustom ada-krunch-args "0"
87 "*Maximum number of characters for filenames created by gnatkr. 82 "*Maximum number of characters for filenames created by gnatkr.
88 Set to 0, if you don't use crunched filenames. This should be a string." 83 Set to 0, if you don't use crunched filenames. This should be a string."
89 :type 'string :group 'ada) 84 :type 'string :group 'ada)
90 85
86 (defcustom ada-prj-default-comp-opt "-gnatq"
87 "Default compilation options."
88 :type 'string :group 'ada)
89
90 (defcustom ada-prj-default-bind-opt ""
91 "Default binder options."
92 :type 'string :group 'ada)
93
94 (defcustom ada-prj-default-link-opt ""
95 "Default linker options."
96 :type 'string :group 'ada)
97
98 (defcustom ada-prj-default-gnatmake-opt "-g"
99 "Default options for gnatmake."
100 :type 'string :group 'ada)
101
91 (defcustom ada-prj-default-comp-cmd 102 (defcustom ada-prj-default-comp-cmd
92 "${cross_prefix}gcc -c -g -gnatq ${comp_opt} -I${src_dir}" 103 "${cross_prefix}gcc -c ${comp_opt}"
93 "*Default command to be used to compile a single file. 104 "*Default command to be used to compile a single file.
94 Emacs will add the filename at the end of this command. 105 Emacs will add the filename at the end of this command. This is the same
95 This is the same syntax as in the project file." 106 syntax as in the project file."
96 :type 'string :group 'ada) 107 :type 'string :group 'ada)
97 108
109 (defcustom ada-prj-default-debugger "${cross_prefix}gdb"
110 "*Default name of the debugger. We recommend either `gdb',
111 `gdb --emacs_gdbtk' or `ddd --tty -fullname'."
112 :type 'string :group 'ada)
113
98 (defcustom ada-prj-default-make-cmd 114 (defcustom ada-prj-default-make-cmd
99 (concat "${cross_prefix}gnatmake ${main} -aI${src_dir} -aO${obj_dir} " 115 (concat "${cross_prefix}gnatmake -o ${main} ${main_unit} ${gnatmake_opt} "
100 "-g -gnatq -cargs ${comp_opt} " 116 "-cargs ${comp_opt} -bargs ${bind_opt} -largs ${link_opt}")
101 "-bargs ${bind_opt} -largs ${link_opt}")
102 "*Default command to be used to compile the application. 117 "*Default command to be used to compile the application.
103 This is the same syntax as in the project file." 118 This is the same syntax as in the project file."
104 :type 'string :group 'ada) 119 :type 'string :group 'ada)
105 120
106 (defcustom ada-prj-default-project-file "" 121 (defcustom ada-prj-default-project-file ""
114 This has the same syntax as in the project file (with variable substitution)." 129 This has the same syntax as in the project file (with variable substitution)."
115 :type 'string :group 'ada) 130 :type 'string :group 'ada)
116 131
117 (defcustom ada-always-ask-project nil 132 (defcustom ada-always-ask-project nil
118 "*If nil, use default values when no project file was found. 133 "*If nil, use default values when no project file was found.
119 Otherwise, ask the user for the name of the project file to use.") 134 Otherwise, ask the user for the name of the project file to use."
135 :type 'boolean :group 'ada)
120 136
121 ;; ------- Nothing to be modified by the user below this 137 ;; ------- Nothing to be modified by the user below this
122 (defvar ada-last-prj-file "" 138 (defvar ada-last-prj-file ""
123 "Name of the last project file entered by the user.") 139 "Name of the last project file entered by the user.")
124 140
125 (defvar ada-check-switch " -gnats " 141 (defvar ada-check-switch "-gnats"
126 "Switch added to the command line to check the current file.") 142 "Switch added to the command line to check the current file.")
127 143
128 (defvar ada-project-file-extension ".adp" 144 (defvar ada-project-file-extension ".adp"
129 "The extension used for project files.") 145 "The extension used for project files.")
130 146
131 (defconst is-windows (memq system-type (quote (windows-nt))) 147 (defconst is-windows (memq system-type (quote (windows-nt)))
132 "True if we are running on windows NT or windows 95.") 148 "True if we are running on windows NT or windows 95.")
149
150 (defvar ada-xref-runtime-library-specs-path '()
151 "Directories where the specs for the standard library is found.
152 This is used for cross-references.")
153
154 (defvar ada-xref-runtime-library-ali-path '()
155 "Directories where the ali for the standard library is found.
156 This is used for cross-references.")
133 157
134 (defvar ada-xref-pos-ring '() 158 (defvar ada-xref-pos-ring '()
135 "List of positions selected by the cross-references functions. 159 "List of positions selected by the cross-references functions.
136 Used to go back to these positions.") 160 Used to go back to these positions.")
137 161
138 (defconst ada-xref-pos-ring-max 16 162 (defconst ada-xref-pos-ring-max 16
139 "Number of positions kept in the list ada-xref-pos-ring.") 163 "Number of positions kept in the list ada-xref-pos-ring.")
140 164
141 (defvar ada-operator-re 165 (defvar ada-operator-re
142 "\\+\\|-\\|/\\|\\*\\|=\\|mod\\|and\\|not\\|or\\|xor\\|<=\\|<\\|>=\\|>" 166 "\\+\\|-\\|/\\|\\*\\*\\|\\*\\|=\\|&\\|abs\\|mod\\|rem\\|and\\|not\\|or\\|xor\\|<=\\|<\\|>=\\|>"
143 "Regexp to match for operators.") 167 "Regexp to match for operators.")
144 168
145 (defvar ada-xref-default-prj-file nil 169 (defvar ada-xref-default-prj-file nil
146 "Name of the default prj file, per directory. 170 "Name of the default prj file, per directory.
147 Every directory is potentially associated with a default project file. 171 Every directory is potentially associated with a default project file.
148 If it is nil, then the first prj file loaded will be the default for this 172 If it is nil, then the first prj file loaded will be the default for this
149 Emacs session.") 173 Emacs session.")
150 174
151 ;; These variables will be overwritted by buffer-local variables 175
176 (defvar ada-xref-project-files '()
177 "Associative list of project files.
178 It has the following format:
179 ((project_name . value) (project_name . value) ...)
180 As always, the values of the project file are defined through properties.")
181
152 (defvar ada-prj-prj-file nil 182 (defvar ada-prj-prj-file nil
153 "Name of the project file for the current ada buffer.") 183 "Buffer local variable that specifies the name of the project file.
154 (defvar ada-prj-src-dir nil 184 Getting the project is done by looking up the key in ada-pxref-project-file.")
155 "List of directories to look into for ada sources.") 185
156 (defvar ada-prj-obj-dir nil 186 (defun my-local-variable-if-set-p (variable &optional buffer)
157 "List of directories to look into for object and .ali files.") 187 "Returns t if VARIABLE is local in BUFFER and is non-nil."
158 (defvar ada-prj-comp-opt nil 188 (and (local-variable-p variable buffer)
159 "Switches to use on the command line for the default compile command.") 189 (save-excursion
160 (defvar ada-prj-bind-opt nil 190 (set-buffer buffer)
161 "Switches to use on the command line for the default bind command.") 191 (symbol-value variable))))
162 (defvar ada-prj-link-opt nil 192
163 "Switches to use on the command line for the default link command.") 193 (defun ada-initialize-runtime-library ()
164 (defvar ada-prj-comp-cmd nil 194 "Initializes the variables for the runtime library location."
165 "Command to use to compile the current file only.") 195 (save-excursion
166 (defvar ada-prj-make-cmd nil 196 (set 'ada-xref-runtime-library-specs-path '())
167 "Command to use to compile the whole current application.") 197 (set 'ada-xref-runtime-library-ali-path '())
168 (defvar ada-prj-run-cmd nil 198 (set-buffer (get-buffer-create "*gnatls*"))
169 "Command to use to run the current application.") 199 (widen)
170 (defvar ada-prj-debug-cmd nil 200 (erase-buffer)
171 "Command to use to run the debugger.") 201 ;; Catch any error in the following form (i.e gnatls was not found)
172 (defvar ada-prj-main nil 202 (condition-case nil
173 "Name of the main programm of the current application.") 203 ;; Even if we get an error, delete the *gnatls* buffer
174 (defvar ada-prj-remote-machine nil 204 (unwind-protect
175 "Name of the machine to log on before a compilation.") 205 (progn
176 (defvar ada-prj-cross-prefix nil 206 (call-process "gnatls" nil t nil "-v")
177 "Prefix to be added to the gnatmake, gcc, ... commands when 207 (goto-char (point-min))
178 using a cross-compilation environment. 208
179 A '-' is automatically added at the end if not already present. 209 ;; Source path
180 For instance, the compiler is called `ada-prj-cross-prefix'gnatmake.") 210
211 (search-forward "Source Search Path:")
212 (forward-line 1)
213 (while (not (looking-at "^$"))
214 (back-to-indentation)
215 (unless (looking-at "<Current_Directory>")
216 (add-to-list 'ada-xref-runtime-library-specs-path
217 (buffer-substring-no-properties
218 (point)
219 (save-excursion (end-of-line) (point)))))
220 (forward-line 1))
221
222 ;; Object path
223
224 (search-forward "Object Search Path:")
225 (forward-line 1)
226 (while (not (looking-at "^$"))
227 (back-to-indentation)
228 (unless (looking-at "<Current_Directory>")
229 (add-to-list 'ada-xref-runtime-library-ali-path
230 (buffer-substring-no-properties
231 (point)
232 (save-excursion (end-of-line) (point)))))
233 (forward-line 1))
234 )
235 (kill-buffer nil))
236 (error nil))
237 (set 'ada-xref-runtime-library-specs-path
238 (reverse ada-xref-runtime-library-specs-path))
239 (set 'ada-xref-runtime-library-ali-path
240 (reverse ada-xref-runtime-library-ali-path))
241 ))
242
243
244 (defun ada-treat-cmd-string (cmd-string)
245 "Replace meta-sequences like ${...} in CMD-STRING with the appropriate value.
246 The project file must have been loaded first.
247 As a special case, ${current} is replaced with the name of the currently
248 edited file, minus extension but with directory."
249
250 (while (string-match "\\(-[^-\$IO]*[IO]\\)?\${\\([^}]+\\)}" cmd-string)
251 (let (value)
252 (if (string= (match-string 2 cmd-string) "current")
253 (set 'value (file-name-sans-extension (buffer-file-name)))
254 (save-match-data
255 (set 'value (ada-xref-get-project-field
256 (intern (match-string 2 cmd-string))))))
257 (cond
258 ((null value)
259 (set 'cmd-string (replace-match "" t t cmd-string)))
260 ((stringp value)
261 (set 'cmd-string (replace-match value t t cmd-string)))
262 ((listp value)
263 (let ((prefix (match-string 1 cmd-string)))
264 (set 'cmd-string (replace-match
265 (mapconcat (lambda(x) (concat prefix x)) value " ")
266 t t cmd-string)))))
267 ))
268 cmd-string)
269
270 (defun ada-xref-set-default-prj-values (symbol ada-buffer)
271 "Reset the properties in SYMBOL to the default values for ADA-BUFFER."
272
273 (let ((file (buffer-file-name ada-buffer))
274 plist)
275 (save-excursion
276 (set-buffer ada-buffer)
277
278 (set 'plist
279 ;; Try hard to find a default value for filename, so that the user
280 ;; can edit his project file even if the current buffer is not an
281 ;; Ada file or not even associated with a file
282 (list 'filename (cond
283 (file
284 (ada-prj-get-prj-dir file))
285 (ada-prj-prj-file
286 ada-prj-prj-file)
287 (ada-xref-default-prj-file
288 ada-xref-default-prj-file)
289 (t
290 (error (concat "Not editing an Ada file,"
291 "and no default project "
292 "file specified!"))))
293 'build_dir (file-name-as-directory (expand-file-name "."))
294 'src_dir (list ".")
295 'obj_dir (list ".")
296 'casing (if (listp ada-case-exception-file)
297 ada-case-exception-file
298 (list ada-case-exception-file))
299 'comp_opt ada-prj-default-comp-opt
300 'bind_opt ada-prj-default-bind-opt
301 'link_opt ada-prj-default-link-opt
302 'gnatmake_opt ada-prj-default-gnatmake-opt
303 'main (if file
304 (file-name-sans-extension file)
305 "")
306 'main_unit (if file
307 (file-name-nondirectory
308 (file-name-sans-extension file))
309 "")
310 'cross_prefix ""
311 'remote_machine ""
312 'comp_cmd (concat "cd ${build_dir} && "
313 ada-prj-default-comp-cmd)
314 'check_cmd (concat ada-prj-default-comp-cmd " "
315 ada-check-switch)
316 'make_cmd (concat "cd ${build_dir} && "
317 ada-prj-default-make-cmd)
318 'run_cmd (concat "cd ${build_dir} && ${main}"
319 (if is-windows ".exe"))
320 'debug_cmd (concat ada-prj-default-debugger
321 (if is-windows " ${main}.exe"
322 " ${main}"))))
323 )
324 (set symbol plist)))
325
326 (defun ada-xref-get-project-field (field)
327 "Extract the value of FIELD from the project file of the current buffer.
328 The project file must have been loaded first.
329 A default value is returned if the file was not found."
330
331 (let ((file-name ada-prj-prj-file)
332 file value)
333
334 ;; If a default project file was set, use it if no other project
335 ;; file was specified for the buffer
336 (if (and (not file-name)
337 ada-prj-default-project-file
338 (not (string= ada-prj-default-project-file "")))
339 (set 'file-name ada-prj-default-project-file))
340
341 (set 'file (assoc file-name ada-xref-project-files))
342
343 ;; If the file was not found, use the default values
344 (if file
345 ;; Get the value from the file
346 (set 'value (plist-get (cdr file) field))
347
348 ;; Create a default nil file that contains the default values
349 (ada-xref-set-default-prj-values 'value (current-buffer))
350 (add-to-list 'ada-xref-project-files (cons nil value))
351 (set 'value (plist-get value field))
352 )
353 (if (stringp value)
354 (ada-treat-cmd-string value)
355 value))
356 )
181 357
182 ;; ----- Keybindings ------------------------------------------------------ 358 ;; ----- Keybindings ------------------------------------------------------
183 359
184 (defun ada-add-keymap () 360 (defun ada-add-keymap ()
185 "Add new key bindings when using `ada-xrel.el'." 361 "Add new key bindings when using `ada-xrel.el'."
194 (define-key ada-mode-map "\C-co" 'ff-find-other-file) 370 (define-key ada-mode-map "\C-co" 'ff-find-other-file)
195 (define-key ada-mode-map "\C-c5\C-d" 'ada-goto-declaration-other-frame) 371 (define-key ada-mode-map "\C-c5\C-d" 'ada-goto-declaration-other-frame)
196 (define-key ada-mode-map "\C-c\C-d" 'ada-goto-declaration) 372 (define-key ada-mode-map "\C-c\C-d" 'ada-goto-declaration)
197 (define-key ada-mode-map "\C-c\C-s" 'ada-xref-goto-previous-reference) 373 (define-key ada-mode-map "\C-c\C-s" 'ada-xref-goto-previous-reference)
198 (define-key ada-mode-map "\C-c\C-x" 'ada-reread-prj-file) 374 (define-key ada-mode-map "\C-c\C-x" 'ada-reread-prj-file)
199 (define-key ada-mode-map [f10] 'next-error)
200 (define-key ada-mode-map "\C-c\C-c" 'ada-compile-application) 375 (define-key ada-mode-map "\C-c\C-c" 'ada-compile-application)
201 (define-key ada-mode-map "\C-cb" 'ada-buffer-list) 376 (define-key ada-mode-map "\C-cb" 'ada-buffer-list)
202 (define-key ada-mode-map "\C-cc" 'ada-change-prj) 377 (define-key ada-mode-map "\C-cc" 'ada-change-prj)
203 (define-key ada-mode-map "\C-cd" 'ada-change-default-prj) 378 (define-key ada-mode-map "\C-cd" 'ada-change-default-prj)
204 (define-key ada-mode-map "\C-cg" 'ada-gdb-application) 379 (define-key ada-mode-map "\C-cg" 'ada-gdb-application)
208 (define-key ada-mode-map "\C-c\C-v" 'ada-check-current) 383 (define-key ada-mode-map "\C-c\C-v" 'ada-check-current)
209 ) 384 )
210 385
211 ;; ----- Menus -------------------------------------------------------------- 386 ;; ----- Menus --------------------------------------------------------------
212 (defun ada-add-ada-menu () 387 (defun ada-add-ada-menu ()
213 "Add some items to the standard Ada mode menu." 388 "Add some items to the standard Ada mode menu.
389 The items are added to the menu called NAME, which should be the same
390 name as was passed to `ada-create-menu'."
214 (interactive) 391 (interactive)
215
216 (if ada-xemacs 392 (if ada-xemacs
217 (progn 393 (let* ((menu-list '("Ada"))
218 (add-menu-button '("Ada") ["Check file" ada-check-current t] "Goto") 394 (goto-menu '("Ada" "Goto"))
219 (add-menu-button '("Ada") ["Compile file" ada-compile-current t] 395 (edit-menu '("Ada" "Edit"))
220 "Goto") 396 (help-menu '("Ada" "Help"))
221 (add-menu-button '("Ada") ["Build" ada-compile-application t] "Goto") 397 (options-menu (list "Ada" "Options")))
222 (add-menu-button '("Ada") ["Run" ada-run-application t] "Goto") 398 (funcall (symbol-function 'add-menu-button)
223 (add-menu-button '("Ada") ["Debug" ada-gdb-application t] "Goto") 399 menu-list ["Check file" ada-check-current
224 (add-menu-button '("Ada") ["--" nil t] "Goto") 400 (string= mode-name "Ada")] "Goto")
225 (add-submenu '("Ada") '("Project" 401 (funcall (symbol-function 'add-menu-button)
226 ["Associate" ada-change-prj t] 402 menu-list ["Compile file" ada-compile-current
227 ["Set Default" ada-set-default-project-file t] 403 (string= mode-name "Ada")] "Goto")
228 ["List" ada-buffer-list t]) 404 (funcall (symbol-function 'add-menu-button)
229 "Goto") 405 menu-list ["Build" ada-compile-application t] "Goto")
230 (add-menu-button '("Ada" "Goto") ["Goto Parent Unit" ada-goto-parent t] 406 (funcall (symbol-function 'add-menu-button)
231 "Next compilation error") 407 menu-list ["Run" ada-run-application t] "Goto")
232 (add-menu-button '("Ada" "Goto") ["Goto References to any entity" 408 (funcall (symbol-function 'add-menu-button)
233 ada-find-any-references t] 409 menu-list ["Debug" ada-gdb-application t] "Goto")
234 "Next compilation error") 410 (funcall (symbol-function 'add-menu-button)
235 (add-menu-button '("Ada" "Goto") ["List References" 411 menu-list ["--" nil t] "Goto")
236 ada-find-references t] 412 (funcall (symbol-function 'add-submenu)
237 "Next compilation error") 413 menu-list '("Project"
238 (add-menu-button '("Ada" "Goto") ["Goto Declaration Other Frame" 414 ["Associate" ada-change-prj t]
239 ada-goto-declaration-other-frame t] 415 ["Set Default..." ada-set-default-project-file t]
240 "Next compilation error") 416 ["List" ada-buffer-list t])
241 (add-menu-button '("Ada" "Goto") ["Goto Declaration/Body" 417 "Goto")
242 ada-goto-declaration t] 418 (funcall (symbol-function 'add-menu-button)
243 "Next compilation error") 419 goto-menu ["Goto Parent Unit" ada-goto-parent t]
244 (add-menu-button '("Ada" "Goto") ["Goto Previous Reference" 420 "Next compilation error")
245 ada-xref-goto-previous-reference t] 421 (funcall (symbol-function 'add-menu-button)
246 "Next compilation error") 422 goto-menu ["Goto References to any entity"
247 (add-menu-button '("Ada" "Goto") ["--" nil t] 423 ada-find-any-references t]
248 "Next compilation error") 424 "Next compilation error")
249 (add-menu-button '("Ada" "Edit") ["Complete Identifier" 425 (funcall (symbol-function 'add-menu-button)
250 ada-complete-identifier t] 426 goto-menu ["List References" ada-find-references t]
251 "Indent Line") 427 "Next compilation error")
252 (add-menu-button '("Ada" "Edit") ["--------" nil t] 428 (funcall (symbol-function 'add-menu-button)
253 "Indent Line") 429 goto-menu ["Goto Declaration Other Frame"
254 (add-menu-button '("Ada" "Help") ["Gnat User Guide" (info "gnat_ug")]) 430 ada-goto-declaration-other-frame t]
255 (add-menu-button '("Ada" "Help") ["Gnat Reference Manual" 431 "Next compilation error")
256 (info "gnat_rm")]) 432 (funcall (symbol-function 'add-menu-button)
257 (add-menu-button '("Ada" "Help") ["Gcc Documentation" (info "gcc")]) 433 goto-menu ["Goto Declaration/Body"
258 (add-menu-button '("Ada" "Help") ["Gdb Documentation" (info "gdb")]) 434 ada-goto-declaration t]
259 ) 435 "Next compilation error")
260 436 (funcall (symbol-function 'add-menu-button)
437 goto-menu ["Goto Previous Reference"
438 ada-xref-goto-previous-reference t]
439 "Next compilation error")
440 (funcall (symbol-function 'add-menu-button)
441 goto-menu ["--" nil t] "Next compilation error")
442 (funcall (symbol-function 'add-menu-button)
443 edit-menu ["Complete Identifier"
444 ada-complete-identifier t]
445 "Indent Line")
446 (funcall (symbol-function 'add-menu-button)
447 edit-menu ["--------" nil t] "Indent Line")
448 (funcall (symbol-function 'add-menu-button)
449 help-menu ["Gnat User Guide" (info "gnat_ug")])
450 (funcall (symbol-function 'add-menu-button)
451 help-menu ["Gnat Reference Manual" (info "gnat_rm")])
452 (funcall (symbol-function 'add-menu-button)
453 help-menu ["Gcc Documentation" (info "gcc")])
454 (funcall (symbol-function 'add-menu-button)
455 help-menu ["Gdb Documentation" (info "gdb")])
456 (funcall (symbol-function 'add-menu-button)
457 help-menu ["Ada95 Reference Manual" (info "arm95")])
458 (funcall (symbol-function 'add-menu-button)
459 options-menu
460 ["Show Cross-References in Other Buffer"
461 (setq ada-xref-other-buffer
462 (not ada-xref-other-buffer))
463 :style toggle :selected ada-xref-other-buffer])
464 (funcall (symbol-function 'add-menu-button)
465 options-menu
466 ["Automatically Recompile for Cross-References"
467 (setq ada-xref-create-ali (not ada-xref-create-ali))
468 :style toggle :selected ada-xref-create-ali])
469 (funcall (symbol-function 'add-menu-button)
470 options-menu
471 ["Confirm Commands"
472 (setq ada-xref-confirm-compile
473 (not ada-xref-confirm-compile))
474 :style toggle :selected ada-xref-confirm-compile])
475 )
476
261 ;; for Emacs 477 ;; for Emacs
262 (define-key-after (lookup-key ada-mode-map [menu-bar Ada]) [Check] 478 (let* ((menu (lookup-key ada-mode-map [menu-bar Ada]))
263 '("Check file" . ada-check-current) 'Customize) 479 (edit-menu (lookup-key ada-mode-map [menu-bar Ada Edit]))
264 (define-key-after (lookup-key ada-mode-map [menu-bar Ada]) [Compile] 480 (help-menu (lookup-key ada-mode-map [menu-bar Ada Help]))
265 '("Compile file" . ada-compile-current) 'Check) 481 (goto-menu (lookup-key ada-mode-map [menu-bar Ada Goto]))
266 (define-key-after (lookup-key ada-mode-map [menu-bar Ada]) [Build] 482 (options-menu (lookup-key ada-mode-map [menu-bar Ada Options])))
267 '("Build" . ada-compile-application) 'Compile) 483
268 (define-key-after (lookup-key ada-mode-map [menu-bar Ada]) [Run] 484 (define-key-after menu [Check] '("Check file" . ada-check-current)
269 '("Run" . ada-run-application) 'Build) 485 'Customize)
270 (define-key-after (lookup-key ada-mode-map [menu-bar Ada]) [Debug] 486 (define-key-after menu [Compile] '("Compile file" . ada-compile-current)
271 '("Debug" . ada-gdb-application) 'Run) 487 'Check)
272 (define-key-after (lookup-key ada-mode-map [menu-bar Ada]) [rem] 488 (define-key-after menu [Build] '("Build" . ada-compile-application)
273 '("--" . nil) 'Debug) 489 'Compile)
274 (define-key-after (lookup-key ada-mode-map [menu-bar Ada]) [Project] 490 (define-key-after menu [Run] '("Run" . ada-run-application) 'Build)
275 (cons "Project" (easy-menu-create-menu 491 (define-key-after menu [Debug] '("Debug" . ada-gdb-application) 'Run)
276 "Project" 492 (define-key-after menu [rem] '("--" . nil) 'Debug)
277 '(["Associate" ada-change-prj t] 493 (define-key-after menu [Project]
278 ["Set Default" ada-set-default-project-file t] 494 (cons "Project"
279 ["List" ada-buffer-list t]))) 495 (funcall (symbol-function 'easy-menu-create-menu)
280 'rem) 496 "Project"
281 497 '(["Associate..." ada-change-prj t
282 (let ((help-submenu (lookup-key ada-mode-map [menu-bar Ada Help])) 498 :included (string= mode-name "Ada")]
283 (goto-submenu (lookup-key ada-mode-map [menu-bar Ada Goto])) 499 ["Set Default..." ada-set-default-project-file t]
284 (edit-submenu (lookup-key ada-mode-map [menu-bar Ada Edit]))) 500 ["List" ada-buffer-list t])))
285 501 'rem)
286 (define-key help-submenu [Gnat_ug] 502
503 (define-key help-menu [Gnat_ug]
287 '("Gnat User Guide" . (lambda() (interactive) (info "gnat_ug")))) 504 '("Gnat User Guide" . (lambda() (interactive) (info "gnat_ug"))))
288 (define-key help-submenu [Gnat_rm] 505 (define-key help-menu [Gnat_rm]
289 '("Gnat Reference Manual" . (lambda() (interactive) (info "gnat_rm")))) 506 '("Gnat Reference Manual" . (lambda() (interactive) (info "gnat_rm"))))
290 (define-key help-submenu [Gcc] 507 (define-key help-menu [Gcc]
291 '("Gcc Documentation" . (lambda() (interactive) (info "gcc")))) 508 '("Gcc Documentation" . (lambda() (interactive) (info "gcc"))))
292 (define-key help-submenu [gdb] 509 (define-key help-menu [gdb]
293 '("Ada Aware Gdb Documentation" . 510 '("Gdb Documentation" . (lambda() (interactive) (info "gdb"))))
294 (lambda() (interactive) (info "gdb")))) 511 (define-key help-menu [gdb]
295 (define-key goto-submenu [rem] '("----" . nil)) 512 '("Ada95 Reference Manual" . (lambda() (interactive) (info "arm95"))))
296 (define-key goto-submenu [Parent] 513
297 '("Goto Parent Unit" . ada-goto-parent)) 514 (define-key goto-menu [rem] '("----" . nil))
298 (define-key goto-submenu [References-any] 515 (define-key goto-menu [Parent] '("Goto Parent Unit"
299 '("Goto References to any entity" . ada-find-any-references)) 516 . ada-goto-parent))
300 (define-key goto-submenu [References] 517 (define-key goto-menu [References-any]
301 '("List References" . ada-find-references)) 518 '("Goto References to any entity" . ada-find-any-references))
302 (define-key goto-submenu [Prev] 519 (define-key goto-menu [References]
303 '("Goto Previous Reference" . ada-xref-goto-previous-reference)) 520 '("List References" . ada-find-references))
304 (define-key goto-submenu [Decl-other] 521 (define-key goto-menu [Prev]
305 '("Goto Declaration Other Frame" . ada-goto-declaration-other-frame)) 522 '("Goto Previous Reference" . ada-xref-goto-previous-reference))
306 (define-key goto-submenu [Decl] 523 (define-key goto-menu [Decl-other]
307 '("Goto Declaration/Body" . ada-goto-declaration)) 524 '("Goto Declaration Other Frame" . ada-goto-declaration-other-frame))
308 525 (define-key goto-menu [Decl]
309 (define-key edit-submenu [rem] '("----" . nil)) 526 '("Goto Declaration/Body" . ada-goto-declaration))
310 (define-key edit-submenu [Complete] '("Complete Identifier" 527
311 . ada-complete-identifier)) 528 (define-key edit-menu [rem] '("----" . nil))
529 (define-key edit-menu [Complete] '("Complete Identifier"
530 . ada-complete-identifier))
531
532 (define-key-after options-menu [xrefrecompile]
533 '(menu-item "Automatically Recompile for Cross-References"
534 (lambda()(interactive)
535 (setq ada-xref-create-ali (not ada-xref-create-ali)))
536 :button (:toggle . ada-xref-create-ali)) t)
537 (define-key-after options-menu [xrefconfirm]
538 '(menu-item "Confirm Commands"
539 (lambda()(interactive)
540 (setq ada-xref-confirm-compile
541 (not ada-xref-confirm-compile)))
542 :button (:toggle . ada-xref-confirm-compile)) t)
543 (define-key-after options-menu [xrefother]
544 '(menu-item "Show Cross-References in Other Buffer"
545 (lambda()(interactive)
546 (setq ada-xref-other-buffer (not ada-xref-other-buffer)))
547 :button (:toggle . ada-xref-other-buffer)) t)
312 ) 548 )
313 )) 549 )
550 )
314 551
315 ;; ----- Utilities ------------------------------------------------- 552 ;; ----- Utilities -------------------------------------------------
316 553
317 (defun ada-require-project-file () 554 (defun ada-require-project-file ()
318 "If no project file is assigned to this buffer, load one." 555 "If no project file is assigned to this buffer, load one."
319 (if (not ( my-local-variable-if-set-p 'ada-prj-src-dir (current-buffer))) 556 (if (not (my-local-variable-if-set-p 'ada-prj-prj-file (current-buffer)))
320 (ada-parse-prj-file (ada-prj-find-prj-file)))) 557 (ada-reread-prj-file)))
321 558
322 (defun my-local-variable-if-set-p (variable &optional buffer)
323 "Returns t if VARIABLE is local in BUFFER and is non-nil."
324 (and (local-variable-p variable buffer)
325 (save-excursion
326 (set-buffer buffer)
327 (symbol-value variable))))
328
329 (defun ada-xref-push-pos (filename position) 559 (defun ada-xref-push-pos (filename position)
330 "Push (FILENAME, POSITION) on the position ring for cross-references." 560 "Push (FILENAME, POSITION) on the position ring for cross-references."
331 (setq ada-xref-pos-ring (cons (list position filename) ada-xref-pos-ring)) 561 (setq ada-xref-pos-ring (cons (list position filename) ada-xref-pos-ring))
332 (if (> (length ada-xref-pos-ring) ada-xref-pos-ring-max) 562 (if (> (length ada-xref-pos-ring) ada-xref-pos-ring-max)
333 (setcdr (nthcdr (1- ada-xref-pos-ring-max) ada-xref-pos-ring) nil))) 563 (setcdr (nthcdr (1- ada-xref-pos-ring-max) ada-xref-pos-ring) nil)))
347 name) 577 name)
348 578
349 (defun ada-set-default-project-file (name) 579 (defun ada-set-default-project-file (name)
350 "Set the file whose name is NAME as the default project file." 580 "Set the file whose name is NAME as the default project file."
351 (interactive "fProject file:") 581 (interactive "fProject file:")
582
583 ;; All the directories should use this file as the default from now on,
584 ;; even if they were already associated with a file.
585 (set 'ada-xref-default-prj-file nil)
586
352 (set 'ada-prj-default-project-file name) 587 (set 'ada-prj-default-project-file name)
353 (ada-reread-prj-file t) 588
589 ;; Make sure that all the buffers see the new project file, even if they
590 ;; are not Ada buffers (for instance if we want to display the current
591 ;; project file in the frame title).
592 (setq-default ada-prj-prj-file name)
593
594 (ada-reread-prj-file name)
354 ) 595 )
355 596
356 (defun ada-replace-substring (cmd-string search-for replace-with) 597 ;; ------ Handling the project file -----------------------------
357 "Replace all instances of SEARCH-FOR with REPLACE-WITH in CMD-STRING."
358 (while (string-match search-for cmd-string)
359 (setq cmd-string (replace-match replace-with t t cmd-string)))
360 cmd-string)
361
362 (defun ada-treat-cmd-string (cmd-string)
363 "Replace meta-sequences like ${...} in CMD-STRING with the appropriate value.
364 The current buffer must be the one where all local variable are defined (that
365 is the ada source)"
366 (if ( my-local-variable-if-set-p 'ada-prj-src-dir (current-buffer))
367 (if (string-match "\\(-[^-\$I]*I\\)\${src_dir}" cmd-string)
368 (progn
369 (let ((str-def (substring cmd-string (match-beginning 1)
370 (match-end 1))))
371 (setq cmd-string
372 (ada-replace-substring cmd-string
373 "\\(-[^-\$I]*I\\)\${src_dir}"
374 (mapconcat
375 (lambda (x) (concat str-def x))
376 ada-prj-src-dir " ")))))))
377 (if ( my-local-variable-if-set-p 'ada-prj-obj-dir (current-buffer))
378 (if (string-match "\\(-[^-\$O]*O\\)\${obj_dir}" cmd-string)
379 (progn
380 (let ((str-def (substring cmd-string (match-beginning 1)
381 (match-end 1))))
382 (setq cmd-string
383 (ada-replace-substring cmd-string
384 "\\(-[^-\$O]*O\\)\${obj_dir}"
385 (mapconcat
386 (lambda (x) (concat str-def x))
387 ada-prj-obj-dir
388 " ")))))))
389 (if ( my-local-variable-if-set-p 'ada-prj-remote-machine (current-buffer))
390 (setq cmd-string
391 (ada-replace-substring cmd-string "\${remote_machine}"
392 ada-prj-remote-machine)))
393 (if ( my-local-variable-if-set-p 'ada-prj-comp-opt (current-buffer))
394 (setq cmd-string
395 (ada-replace-substring cmd-string "\${comp_opt}"
396 ada-prj-comp-opt)))
397 (if ( my-local-variable-if-set-p 'ada-prj-bind-opt (current-buffer))
398 (setq cmd-string
399 (ada-replace-substring cmd-string "\${bind_opt}"
400 ada-prj-bind-opt)))
401 (if ( my-local-variable-if-set-p 'ada-prj-link-opt (current-buffer))
402 (setq cmd-string
403 (ada-replace-substring cmd-string "\${link_opt}"
404 ada-prj-link-opt)))
405 (if ( my-local-variable-if-set-p 'ada-prj-main (current-buffer))
406 (setq cmd-string
407 (ada-replace-substring cmd-string "\${main}"
408 ada-prj-main)))
409 (if ( my-local-variable-if-set-p 'ada-prj-cross-prefix (current-buffer))
410 (setq cmd-string
411 (ada-replace-substring cmd-string "\${cross_prefix}"
412 ada-prj-cross-prefix)))
413 cmd-string)
414
415 598
416 (defun ada-prj-find-prj-file (&optional no-user-question) 599 (defun ada-prj-find-prj-file (&optional no-user-question)
417 "Find the prj file associated with the current buffer. 600 "Find the prj file associated with the current buffer.
418 The rules are the following ones : 601 If NO-USER-QUESTION is non-nil, use a default file if not project file was
419 - If the buffer is already associated with a prj file, use this one 602 found, and do not ask the user.
420 - else if there's a default prj file for the same directory use it 603 If the buffer is not an Ada buffer, associate it with the default project
421 - else if a prj file with the same filename exists, use it 604 file. If none is set, return nil."
422 - else if there's only one prj file in the directory, use it 605
423 - else if there are more than one prj file, ask the user 606 (let (selected)
424 - else if there is no prj file and NO-USER-QUESTION is nil, ask the user 607
425 for the project file to use." 608 ;; If we don't have an ada buffer, or the current buffer is not
426 (let* ((current-file (buffer-file-name)) 609 ;; a real file (for instance an emerge buffer)
427 (first-choice (concat 610
428 (file-name-sans-extension current-file) 611 (if (or (not (string= mode-name "Ada"))
429 ada-project-file-extension)) 612 (not (buffer-file-name)))
430 (dir (file-name-directory current-file)) 613
431 614 ;; 1st case: not an Ada buffer
432 ;; on Emacs 20.2, directory-files does not work if 615 (if (and ada-prj-default-project-file
433 ;; parse-sexp-lookup-properties is set 616 (not (string= ada-prj-default-project-file "")))
434 (parse-sexp-lookup-properties nil) 617 (set 'selected ada-prj-default-project-file))
435 (prj-files (directory-files 618
436 dir t 619 ;; 2nd case: If the buffer already has a project file, use it
437 (concat ".*" (regexp-quote ada-project-file-extension) "$"))) 620 (if (my-local-variable-if-set-p 'ada-prj-prj-file (current-buffer))
438 (choice nil) 621 (set 'selected ada-prj-prj-file)
439 (default (assoc dir ada-xref-default-prj-file)) 622
440 ) 623 (let* ((current-file (buffer-file-name))
441 624 (first-choice (concat
442 (cond 625 (file-name-sans-extension current-file)
443 626 ada-project-file-extension))
444 ((my-local-variable-if-set-p 'ada-prj-prj-file (current-buffer)) 627 (dir (file-name-directory current-file))
445 ada-prj-prj-file) 628
446 629 ;; on Emacs 20.2, directory-files does not work if
447 (default ;; directory default project file 630 ;; parse-sexp-lookup-properties is set
448 (cdr default)) 631 (parse-sexp-lookup-properties nil)
449 632 (prj-files (directory-files
450 ;; global default project file 633 dir t
451 ((and ada-prj-default-project-file 634 (concat ".*" (regexp-quote ada-project-file-extension) "$")))
452 (not (string= ada-prj-default-project-file ""))) 635 (choice nil)
453 ada-prj-default-project-file) 636 (default (assoc dir ada-xref-default-prj-file)))
454 637
455 ((file-exists-p first-choice) 638 (cond
456 first-choice) 639
457 640 ;; 3rd case: a project file is already associated with the directory
458 ((= (length prj-files) 1) 641 (default
459 (car prj-files)) 642 (set 'selected (cdr default)))
460 643
461 ((> (length prj-files) 1) 644 ;; 4th case: the user has set a default project file for every file
462 ;; more than one possible prj file => ask the user 645 ((and ada-prj-default-project-file
463 (with-output-to-temp-buffer "*choice list*" 646 (not (string= ada-prj-default-project-file "")))
464 (princ "There are more than one possible project file. Which one should\n") 647 (set 'selected ada-prj-default-project-file))
465 (princ "I use ?\n\n") 648
466 (princ " no. file name \n") 649 ;; 5th case: there is a project file with the same name as the Ada file,
467 (princ " --- ------------------------\n") 650 ;; but not the same extension.
468 (let ((counter 1)) 651 ((file-exists-p first-choice)
469 (while (<= counter (length prj-files)) 652 (set 'selected first-choice))
470 (princ (format " %2d) %s\n" 653
471 counter 654 ;; 6th case: only one project file was found in the current directory
472 (nth (1- counter) prj-files))) 655 ((= (length prj-files) 1)
473 (setq counter (1+ counter)) 656 (set 'selected (car prj-files)))
474 ) ; end of while 657
475 ) ; end of let 658 ;; 7th case: if there are multiple files, ask the user
476 ) ; end of with-output-to ... 659 ((and (> (length prj-files) 1) (not no-user-question))
477 (setq choice nil) 660 (save-window-excursion
478 (while (or 661 (with-output-to-temp-buffer "*choice list*"
479 (not choice) 662 (princ "There are more than one possible project file. Which one should\n")
480 (not (integerp choice)) 663 (princ "be used ?\n\n")
481 (< choice 1) 664 (princ " no. file name \n")
482 (> choice (length prj-files))) 665 (princ " --- ------------------------\n")
483 (setq choice (string-to-int 666 (let ((counter 1))
484 (read-from-minibuffer "Enter No. of your choice: " 667 (while (<= counter (length prj-files))
485 )))) 668 (princ (format " %2d) %s\n"
486 (nth (1- choice) prj-files)) 669 counter
487 670 (nth (1- counter) prj-files)))
488 ((= (length prj-files) 0) 671 (setq counter (1+ counter))
489 ;; no project file found. Ask the user about it (the default value 672 ))) ; end of with-output-to ...
490 ;; is the last one the user entered. 673 (setq choice nil)
491 (if (or no-user-question (not ada-always-ask-project)) 674 (while (or
492 nil 675 (not choice)
493 (setq ada-last-prj-file 676 (not (integerp choice))
494 (read-file-name "project file:" nil ada-last-prj-file)) 677 (< choice 1)
495 (if (string= ada-last-prj-file "") nil ada-last-prj-file)) 678 (> choice (length prj-files)))
496 ) 679 (setq choice (string-to-int
497 ))) 680 (read-from-minibuffer "Enter No. of your choice: "))))
681 (set 'selected (nth (1- choice) prj-files))))
682
683 ;; 8th case: no project file was found in the directory, ask a name to the
684 ;; user, using as a default value the last one entered by the user
685 ((= (length prj-files) 0)
686 (unless (or no-user-question (not ada-always-ask-project))
687 (setq ada-last-prj-file
688 (read-file-name "project file:" nil ada-last-prj-file))
689 (unless (string= ada-last-prj-file "")
690 (set 'selected ada-last-prj-file))))
691 ))))
692 selected
693 ))
498 694
499 695
500 (defun ada-parse-prj-file (prj-file) 696 (defun ada-parse-prj-file (prj-file)
501 "Reads and parses the project file PRJ-FILE. 697 "Reads and parses the PRJ-FILE file if it was found.
502 Does nothing if PRJ-FILE was not found. 698 The current buffer should be the ada-file buffer."
503 The current buffer should be the ada-file buffer" 699 (if prj-file
504 700 (let (project src_dir obj_dir casing
505 (let ((tmp-src-dir nil) 701 (ada-buffer (current-buffer)))
506 (tmp-obj-dir nil) 702 (set 'prj-file (expand-file-name prj-file))
507 (tmp-comp-opt nil) 703
508 (tmp-bind-opt nil) 704 ;; Initialize the project with the default values
509 (tmp-link-opt nil) 705 (ada-xref-set-default-prj-values 'project (current-buffer))
510 (tmp-main nil) 706
511 (tmp-comp-cmd nil) 707 ;; Do not use find-file below, since we don't want to show this
512 (tmp-make-cmd nil) 708 ;; buffer. If the file is open through speedbar, we can't use
513 (tmp-run-cmd nil) 709 ;; find-file anyway, since the speedbar frame is special and does not
514 (tmp-debug-cmd nil) 710 ;; allow the selection of a file in it.
515 (tmp-remote-machine nil) 711
516 (tmp-cross-prefix nil) 712 (set-buffer (find-file-noselect prj-file))
517 (tmp-cd-cmd (if prj-file 713
518 (concat "cd " (file-name-directory prj-file) " && ") 714 (widen)
519 (concat "cd " (file-name-directory (buffer-file-name (current-buffer))) " && "))) 715 (goto-char (point-min))
520 (ada-buffer (current-buffer)) 716
521 ) 717 ;; Now overrides these values with the project file
522 ;; tries to find a project file in the current directory 718 (while (not (eobp))
523 (if prj-file 719 (if (looking-at "^\\([^=]+\\)=\\(.*\\)")
524 (progn 720 (cond
525 (find-file prj-file) 721 ((string= (match-string 1) "src_dir")
526 722 (add-to-list 'src_dir
527 ;; first look for the src_dir lines 723 (file-name-as-directory (match-string 2))))
528 (widen) 724 ((string= (match-string 1) "obj_dir")
529 (goto-char (point-min)) 725 (add-to-list 'obj_dir
530 (while 726 (file-name-as-directory (match-string 2))))
531 (re-search-forward "^src_dir=\\(.*\\)" nil t) 727 ((string= (match-string 1) "casing")
532 (progn 728 (set 'casing (cons (match-string 2) casing)))
533 (setq tmp-src-dir (cons 729 ((string= (match-string 1) "build_dir")
534 (file-name-as-directory 730 (set 'project
535 (match-string 1)) 731 (plist-put project 'build_dir
536 tmp-src-dir 732 (file-name-as-directory (match-string 2)))))
537 )))) 733 (t
538 ;; then for the obj_dir lines 734 (set 'project (plist-put project (intern (match-string 1))
539 (goto-char (point-min)) 735 (match-string 2))))))
540 (while (re-search-forward "^obj_dir=\\(.*\\)" nil t) 736 (forward-line 1))
541 (setq tmp-obj-dir (cons 737
542 (file-name-as-directory 738 (if src_dir (set 'project (plist-put project 'src_dir
543 (match-string 1)) 739 (reverse src_dir))))
544 tmp-obj-dir 740 (if obj_dir (set 'project (plist-put project 'obj_dir
545 ))) 741 (reverse obj_dir))))
546 742 (if casing (set 'project (plist-put project 'casing casing)))
547 ;; then for the options lines 743
548 (goto-char (point-min)) 744 ;; Memorize the newly read project file
549 (if (re-search-forward "^comp_opt=\\(.*\\)" nil t) 745 (if (assoc prj-file ada-xref-project-files)
550 (setq tmp-comp-opt (match-string 1))) 746 (setcdr (assoc prj-file ada-xref-project-files) project)
551 (goto-char (point-min)) 747 (add-to-list 'ada-xref-project-files (cons prj-file project)))
552 (if (re-search-forward "^bind_opt=\\(.*\\)" nil t) 748
553 (setq tmp-bind-opt (match-string 1))) 749 ;; Sets up the compilation-search-path so that Emacs is able to
554 (goto-char (point-min)) 750 ;; go to the source of the errors in a compilation buffer
555 (if (re-search-forward "^link_opt=\\(.*\\)" nil t) 751 (setq compilation-search-path (ada-get-absolute-dir-list
556 (setq tmp-link-opt (match-string 1))) 752 (plist-get project 'src_dir)
557 (goto-char (point-min)) 753 (plist-get project 'build_dir)))
558 (if (re-search-forward "^main=\\(.*\\)" nil t) 754
559 (setq tmp-main (match-string 1))) 755 ;; Associate each source directory in the project file with this file
560 (goto-char (point-min)) 756 (mapcar (lambda (x)
561 (if (re-search-forward "^comp_cmd=\\(.*\\)" nil t) 757 (if (not (assoc (expand-file-name x)
562 (setq tmp-comp-cmd (match-string 1))) 758 ada-xref-default-prj-file))
563 (goto-char (point-min)) 759 (setq ada-xref-default-prj-file
564 (if (re-search-forward "^remote_machine=\\(.*\\)" nil t) 760 (cons (cons (expand-file-name x) prj-file)
565 (setq tmp-remote-machine (match-string 1))) 761 ada-xref-default-prj-file))))
566 (goto-char (point-min)) 762 compilation-search-path)
567 (if (re-search-forward "^cross_prefix=\\(.*\\)" nil t) 763
568 (setq tmp-cross-prefix (match-string 1))) 764 ;; Add the directories to the search path for ff-find-other-file
569 (goto-char (point-min)) 765 ;; Do not add the '/' or '\' at the end
570 (if (re-search-forward "^make_cmd=\\(.*\\)" nil t) 766 (set (make-local-variable 'ff-search-directories)
571 (setq tmp-make-cmd (match-string 1))) 767 (append (mapcar 'directory-file-name compilation-search-path)
572 (goto-char (point-min)) 768 ada-search-directories))
573 (if (re-search-forward "^run_cmd=\\(.*\\)" nil t) 769
574 (setq tmp-run-cmd (match-string 1))) 770 ;; Kill the .ali buffer
575 (goto-char (point-min)) 771 (kill-buffer nil)
576 (if (re-search-forward "^debug_cmd=\\(.*\\)" nil t) 772 (set-buffer ada-buffer)
577 (setq tmp-debug-cmd (match-string 1))) 773
578 774 ;; Setup the project file for the current buffer
579 ;; kills the project file buffer, and go back to the ada buffer 775 (set (make-local-variable 'ada-prj-prj-file) prj-file)
580 (kill-buffer nil) 776
581 (set-buffer ada-buffer) 777 )
582 ))
583
584 ;; creates local variables (with default values if needed)
585 (set (make-local-variable 'ada-prj-prj-file) prj-file)
586
587 (set (make-local-variable 'ada-prj-src-dir)
588 (if tmp-src-dir (reverse tmp-src-dir) '("./")))
589
590 (set (make-local-variable 'ada-prj-obj-dir)
591 (if tmp-obj-dir (reverse tmp-obj-dir) '("./")))
592
593 (set (make-local-variable 'ada-prj-comp-opt)
594 (if tmp-comp-opt tmp-comp-opt ""))
595
596 (set (make-local-variable 'ada-prj-bind-opt)
597 (if tmp-bind-opt tmp-bind-opt ""))
598
599 (set (make-local-variable 'ada-prj-link-opt)
600 (if tmp-link-opt tmp-link-opt ""))
601
602 (set (make-local-variable 'ada-prj-cross-prefix)
603 (if tmp-cross-prefix
604 (if (or (string= tmp-cross-prefix "")
605 (= (aref tmp-cross-prefix (1- (length tmp-cross-prefix))) ?-))
606 tmp-cross-prefix
607 (concat tmp-cross-prefix "-"))
608 ""))
609
610 (set (make-local-variable 'ada-prj-main)
611 (if tmp-main tmp-main
612 (substring (buffer-file-name) 0 -4)))
613
614 (set (make-local-variable 'ada-prj-remote-machine)
615 (ada-treat-cmd-string
616 (if tmp-remote-machine tmp-remote-machine "")))
617
618 (set (make-local-variable 'ada-prj-comp-cmd)
619 (ada-treat-cmd-string
620 (if tmp-comp-cmd tmp-comp-cmd
621 (concat tmp-cd-cmd ada-prj-default-comp-cmd))))
622
623 (set (make-local-variable 'ada-prj-make-cmd)
624 (ada-treat-cmd-string
625 (if tmp-make-cmd tmp-make-cmd
626 (concat tmp-cd-cmd ada-prj-default-make-cmd))))
627
628 (set (make-local-variable 'ada-prj-run-cmd)
629 (ada-treat-cmd-string
630 (if tmp-run-cmd tmp-run-cmd
631 (if is-windows "${main}.exe" "${main}"))))
632
633 (set (make-local-variable 'ada-prj-debug-cmd)
634 (ada-treat-cmd-string
635 (if tmp-debug-cmd tmp-debug-cmd
636 (if is-windows
637 "${cross_prefix}gdb ${main}.exe"
638 "${cross_prefix}gdb ${main}"))))
639
640 ;; Add each directory in src_dir to the default prj list
641 (if prj-file
642 (mapcar (lambda (x)
643 (if (not (assoc (expand-file-name x)
644 ada-xref-default-prj-file))
645 (setq ada-xref-default-prj-file
646 (cons (cons (expand-file-name x)
647 prj-file)
648 ada-xref-default-prj-file))))
649 ada-prj-src-dir))
650
651 ;; Add the directories to the search path for ff-find-other-file
652 ;; Do not add the '/' or '\' at the end
653 (set (make-local-variable 'ff-search-directories)
654 (append (mapcar 'directory-file-name ada-prj-src-dir)
655 ada-search-directories))
656
657 ;; Sets up the compilation-search-path so that Emacs is able to
658 ;; go to the source of the errors in a compilation buffer
659 (setq compilation-search-path ada-prj-src-dir)
660
661 )) 778 ))
662 779
663 780
664 (defun ada-find-references (&optional pos) 781 (defun ada-find-references (&optional pos)
665 "Find all references to the entity under POS. 782 "Find all references to the entity under POS.
666 Calls gnatfind to find the references." 783 Calls gnatfind to find the references."
667 (interactive "") 784 (interactive "")
668 (unless pos 785 (unless pos
669 (set 'pos (point))) 786 (set 'pos (point)))
670 (ada-require-project-file) 787 (ada-require-project-file)
671 788
672 (let* ((identlist (ada-read-identifier pos)) 789 (let* ((identlist (ada-read-identifier pos))
673 (alifile (ada-get-ali-file-name (ada-file-of identlist)))) 790 (alifile (ada-get-ali-file-name (ada-file-of identlist)))
791 (process-environment (ada-set-environment)))
674 792
675 (set-buffer (get-file-buffer (ada-file-of identlist))) 793 (set-buffer (get-file-buffer (ada-file-of identlist)))
676 794
677 ;; if the file is more recent than the executable 795 ;; if the file is more recent than the executable
678 (if (or (buffer-modified-p (current-buffer)) 796 (if (or (buffer-modified-p (current-buffer))
767 885
768 ;; make sure we are using an Ada file 886 ;; make sure we are using an Ada file
769 (if (not (string= mode-name "Ada")) 887 (if (not (string= mode-name "Ada"))
770 (error "You must be in ada-mode to use this function")) 888 (error "You must be in ada-mode to use this function"))
771 889
772 ;; create the local variable if necessay 890 (set (make-local-variable 'ada-prj-prj-file) filename)
773 (if (not ( my-local-variable-if-set-p 'ada-prj-prj-file (current-buffer))) 891 (ada-parse-prj-file filename)
774 (make-local-variable 'ada-prj-prj-file))
775
776 ;; ask the user for the new file name
777 (setq ada-prj-prj-file filename)
778
779 ;; force Emacs to reread the prj file next-time
780 (ada-reread-prj-file)
781 ) 892 )
782 893
783 (defun ada-change-default-prj (filename) 894 (defun ada-change-default-prj (filename)
784 "Set FILENAME to be the default project file for the current directory." 895 "Set FILENAME to be the default project file for the current directory."
785 (interactive "ffile name:") 896 (interactive "ffile name:")
790 (if (assoc dir ada-xref-default-prj-file) 901 (if (assoc dir ada-xref-default-prj-file)
791 (setcdr (assoc dir ada-xref-default-prj-file) prj) 902 (setcdr (assoc dir ada-xref-default-prj-file) prj)
792 (add-to-list 'ada-xref-default-prj-file (list dir prj))) 903 (add-to-list 'ada-xref-default-prj-file (list dir prj)))
793 904
794 ;; Reparse the project file 905 ;; Reparse the project file
795 (ada-parse-prj-file ada-prj-default-project-file))) 906 (ada-parse-prj-file filename)))
796 907
797 908
798 ;; ----- Identlist manipulation ------------------------------------------- 909 ;; ----- Identlist manipulation -------------------------------------------
799 ;; An identlist is a vector that is used internally to reference an identifier 910 ;; An identlist is a vector that is used internally to reference an identifier
800 ;; To facilitate its use, we provide the following macros 911 ;; To facilitate its use, we provide the following macros
825 936
826 937
827 ;; ----- Identifier Completion -------------------------------------------- 938 ;; ----- Identifier Completion --------------------------------------------
828 (defun ada-complete-identifier (pos) 939 (defun ada-complete-identifier (pos)
829 "Tries to complete the identifier around POS. 940 "Tries to complete the identifier around POS.
830 The feature is only available if the files where not compiled using the -gnatx 941 The feature is only available if the files where compiled not using the -gnatx
831 option." 942 option."
832 (interactive "d") 943 (interactive "d")
833 (ada-require-project-file) 944 (ada-require-project-file)
834 945
835 ;; Initialize function-local variablesand jump to the .ali buffer 946 ;; Initialize function-local variables and jump to the .ali buffer
836 ;; Note that for regexp search is case insensitive too 947 ;; Note that for regexp search is case insensitive too
837 (let* ((curbuf (current-buffer)) 948 (let* ((curbuf (current-buffer))
838 (identlist (ada-read-identifier pos)) 949 (identlist (ada-read-identifier pos))
839 (sofar (concat "^[0-9]+[a-zA-Z][0-9]+[ *]\\(" 950 (sofar (concat "^[0-9]+[a-zA-Z][0-9]+[ *]\\("
840 (regexp-quote (ada-name-of identlist)) 951 (regexp-quote (ada-name-of identlist))
841 "[a-zA-Z0-9_]*\\)")) 952 "[a-zA-Z0-9_]*\\)"))
842 (completed nil) 953 (completed nil)
843 (symalist nil) 954 (symalist nil))
844 (insertpos nil)) 955
845 956 ;; Open the .ali file
846 ;; we are already in the .ali buffer 957 (set-buffer (ada-get-ali-buffer (buffer-file-name)))
847 (goto-char (point-max)) 958 (goto-char (point-max))
848 959
849 ;; build an alist of possible completions 960 ;; build an alist of possible completions
850 (while (re-search-backward sofar nil t) 961 (while (re-search-backward sofar nil t)
851 (setq symalist (cons (cons (match-string 1) nil) symalist))) 962 (setq symalist (cons (cons (match-string 1) nil) symalist)))
888 (ada-require-project-file) 999 (ada-require-project-file)
889 (push-mark pos) 1000 (push-mark pos)
890 (ada-xref-push-pos (buffer-file-name) pos) 1001 (ada-xref-push-pos (buffer-file-name) pos)
891 (ada-find-in-ali (ada-read-identifier pos) t)) 1002 (ada-find-in-ali (ada-read-identifier pos) t))
892 1003
893 (defun ada-compile (command) 1004 (defun ada-remote (command)
894 "Start COMMAND on the machine specified in the project file." 1005 "Return the remote version of COMMAND, or COMMAND if remote_machine is nil."
895 (if (and (my-local-variable-if-set-p 'ada-prj-remote-machine (current-buffer)) 1006 (let ((machine (ada-xref-get-project-field 'remote_machine)))
896 (not (string= ada-prj-remote-machine ""))) 1007 (if (or (not machine) (string= machine ""))
897 (set 'command 1008 command
898 (concat "rsh " ada-prj-remote-machine " '" 1009 (format "%s %s '(%s)'"
899 command "'"))) 1010 remote-shell-program
900 (compile command)) 1011 machine
901 1012 command))))
902 (defun ada-compile-application () 1013
903 "Compiles the application, using the command found in the project file." 1014 (defun ada-get-absolute-dir (dir root-dir)
1015 "Returns the absolute directory corresponding to DIR.
1016 If DIR is a relative directory, the value of ROOT-DIR is added in front."
1017 (if (= (string-to-char dir) ?/)
1018 dir
1019 (concat root-dir dir)))
1020
1021 (defun ada-get-absolute-dir-list (dir-list root-dir)
1022 "Returns the list of absolute directories found in dir-list.
1023 If a directory is a relative directory, the value of ROOT-DIR is added in
1024 front."
1025 (mapcar (lambda (x) (ada-get-absolute-dir x root-dir)) dir-list))
1026
1027 (defun ada-set-environment ()
1028 "Return the new value for process-environment.
1029 It modifies the source path and object path with the values found in the
1030 project file."
1031 (let ((include (getenv "ADA_INCLUDE_PATH"))
1032 (objects (getenv "ADA_OBJECTS_PATH"))
1033 (build-dir (ada-xref-get-project-field 'build_dir)))
1034 (if include
1035 (set 'include (concat include path-separator)))
1036 (if objects
1037 (set 'objects (concat objects path-separator)))
1038 (cons
1039 (concat "ADA_INCLUDE_PATH="
1040 include
1041 (mapconcat (lambda(x) (ada-get-absolute-dir x build-dir))
1042 (ada-xref-get-project-field 'src_dir)
1043 path-separator))
1044 (cons
1045 (concat "ADA_OBJECTS_PATH="
1046 objects
1047 (mapconcat (lambda(x) (ada-get-absolute-dir x build-dir))
1048 (ada-xref-get-project-field 'obj_dir)
1049 path-separator))
1050 process-environment))))
1051
1052 (defun ada-compile-application (&optional arg)
1053 "Compiles the application, using the command found in the project file.
1054 If ARG is not nil, ask for user confirmation."
1055 (interactive "P")
1056 (ada-require-project-file)
1057 (let ((cmd (ada-xref-get-project-field 'make_cmd))
1058 (process-environment (ada-set-environment))
1059 (compilation-scroll-output t))
1060
1061 (set 'compilation-search-path
1062 (ada-get-absolute-dir-list (ada-xref-get-project-field 'src_dir)
1063 (ada-xref-get-project-field 'build_dir)))
1064
1065 ;; If no project file was found, ask the user
1066 (unless cmd
1067 (setq cmd "" arg t))
1068
1069 (compile (ada-remote
1070 (if (or ada-xref-confirm-compile arg)
1071 (read-from-minibuffer "enter command to compile: " cmd)
1072 cmd)))
1073 ))
1074
1075 (defun ada-compile-current (&optional arg prj-field)
1076 "Recompile the current file.
1077 If ARG is not nil, ask for user confirmation of the command.
1078 PRJ-FIELD is the name of the field to use in the project file to get the
1079 command, and should be either comp_cmd (default) or check_cmd."
1080 (interactive "P")
1081 (ada-require-project-file)
1082 (let* ((field (if prj-field prj-field 'comp_cmd))
1083 (cmd (ada-xref-get-project-field field))
1084 (process-environment (ada-set-environment))
1085 (compilation-scroll-output t))
1086
1087 (set 'compilation-search-path
1088 (ada-get-absolute-dir-list (ada-xref-get-project-field 'src_dir)
1089 (ada-xref-get-project-field 'build_dir)))
1090
1091 ;; If no project file was found, ask the user
1092 (if cmd
1093 (set 'cmd (concat cmd " " (ada-convert-file-name (buffer-file-name))))
1094 (setq cmd "" arg t))
1095
1096 (compile (ada-remote
1097 (if (or ada-xref-confirm-compile arg)
1098 (read-from-minibuffer "enter command to compile: " cmd)
1099 cmd)))))
1100
1101 (defun ada-check-current (&optional arg)
1102 "Recompile the current file.
1103 If ARG is not nil, ask for user confirmation of the command."
1104 (interactive "P")
1105 (ada-compile-current arg 'check_cmd))
1106
1107 (defun ada-run-application (&optional arg)
1108 "Run the application.
1109 if ARG is not-nil, asks for user confirmation."
904 (interactive) 1110 (interactive)
905 (ada-require-project-file) 1111 (ada-require-project-file)
906 1112
907 ;; prompt for command to execute 1113 (let ((machine (ada-xref-get-project-field 'cross_prefix)))
908 (ada-compile 1114 (if (and machine (not (string= machine "")))
909 (if ada-xref-confirm-compile 1115 (error "This feature is not supported yet for cross environments")))
910 (read-from-minibuffer "enter command to compile: " 1116
911 ada-prj-make-cmd) 1117 (let ((command (ada-xref-get-project-field 'run_cmd)))
912 ada-prj-make-cmd)) 1118
913 ) 1119 ;; Guess the command if it wasn't specified
914 1120 (if (or (not command) (string= command ""))
915 (defun ada-compile-current () 1121 (set 'command (file-name-sans-extension (buffer-name))))
916 "Recompile the current file." 1122
917 (interactive) 1123 ;; Ask for the arguments to the command if required
918 (ada-require-project-file) 1124 (if (or ada-xref-confirm-compile arg)
919 1125 (set 'command (read-from-minibuffer "Enter command to execute: " command)))
920 ;; prompt for command to execute 1126
921 (ada-compile 1127 ;; Modify the command to run remotely
922 (if ada-xref-confirm-compile 1128 (setq command (ada-remote command))
923 (read-from-minibuffer "enter command to compile: "
924 (concat
925 ada-prj-comp-cmd " " (ada-convert-file-name (buffer-file-name))))
926 (concat ada-prj-comp-cmd " " (ada-convert-file-name (buffer-file-name)))))
927 )
928
929 (defun ada-check-current ()
930 "Recompile the current file."
931 (interactive)
932 (ada-require-project-file)
933
934 ;; prompt for command to execute
935 (let ((command (concat ada-prj-comp-cmd ada-check-switch
936 (ada-convert-file-name (buffer-file-name)))))
937 (compile
938 (if ada-xref-confirm-compile
939 (read-from-minibuffer "enter command to compile: " command)
940 command))))
941
942
943 (defun ada-run-application ()
944 "Run the application."
945 (interactive)
946 (ada-require-project-file)
947
948 (if (and (my-local-variable-if-set-p 'ada-prj-cross-prefix (current-buffer))
949 (not (string= ada-prj-cross-prefix "")))
950 (error "This feature is not supported yet for cross-compilation environments"))
951
952 (let ((command ada-prj-run-cmd)
953 (buffer (current-buffer)))
954 ;; Search the command name if necessary
955 (if (not (my-local-variable-if-set-p 'ada-prj-run-cmd (current-buffer)))
956 (setq command (file-name-sans-extension (buffer-name)))
957 )
958
959 ;; Ask for the arguments to the command
960 (setq command
961 (read-from-minibuffer "Enter command to execute: "
962 command))
963 1129
964 ;; Run the command 1130 ;; Run the command
965 (save-excursion 1131 (save-excursion
966 (set-buffer (get-buffer-create "*run*")) 1132 (set-buffer (get-buffer-create "*run*"))
967 (goto-char (point-max)) 1133 (set 'buffer-read-only nil)
1134 (erase-buffer)
1135 (goto-char (point-min))
968 (insert "\nRunning " command "\n\n") 1136 (insert "\nRunning " command "\n\n")
969 (make-comint "run" 1137 (start-process "run" (current-buffer) shell-file-name "-c" command)
970 (comint-arguments command 0 0)
971 nil
972 (comint-arguments command 1 nil))
973 ) 1138 )
974 (display-buffer "*run*") 1139 (display-buffer "*run*")
975 1140
976 ;; change to buffer *run* for interactive programs 1141 ;; change to buffer *run* for interactive programs
977 (other-window 1) 1142 (other-window 1)
978 (switch-to-buffer "*run*") 1143 (switch-to-buffer "*run*")
979 ) 1144 ))
980 ) 1145
981 1146
982 1147 (defun ada-gdb-application (&optional arg)
983 (defun ada-gdb-application () 1148 "Start the debugger on the application.
984 "Start the debugger on the application." 1149 If ARG is non-nil, ask the user to confirm the command."
985 (interactive) 1150 (interactive "P")
986
987 (require 'gud)
988 (let ((buffer (current-buffer)) 1151 (let ((buffer (current-buffer))
989 gdb-buffer) 1152 gdb-buffer
1153 cmd)
990 (ada-require-project-file) 1154 (ada-require-project-file)
991 1155 (set 'cmd (ada-xref-get-project-field 'debug_cmd))
992 (if (and (my-local-variable-if-set-p 'ada-prj-cross-prefix buffer) 1156 (let ((machine (ada-xref-get-project-field 'remote_machine)))
993 (not (string= ada-prj-cross-prefix ""))) 1157 (if (and machine (not (string= machine "")))
994 (error "This feature is not supported yet for cross-compilation environments")) 1158 (error "This feature is not supported yet for remote environments")))
995 1159
996 ;; If the command to use was given in the project file 1160 ;; If the command was not given in the project file, start a bare gdb
997 (if (my-local-variable-if-set-p 'ada-prj-debug-cmd buffer) 1161 (if (not cmd)
998 (gdb ada-prj-debug-cmd) 1162 (set 'cmd (concat ada-prj-default-debugger
999 ;; Else the user will have to enter the command himself 1163 " "
1000 (gdb "") 1164 (file-name-sans-extension (buffer-file-name)))))
1001 ) 1165 (if (or arg ada-xref-confirm-compile)
1002 1166 (set 'cmd (read-from-minibuffer "enter command to debug: " cmd)))
1003 (set 'gdb-buffer (current-buffer)) 1167
1168 ;; Set the variable gud-last-last-frame so that glide-debug can find
1169 ;; the name of the Ada file, and thus of the project file if needed.
1170 (if ada-prj-prj-file
1171 (set 'gud-last-last-frame (cons ada-prj-prj-file 1)))
1172
1173 (if (and (string-match "jdb" (comint-arguments cmd 0 0))
1174 (boundp 'jdb))
1175 (funcall (symbol-function 'jdb) cmd)
1176 (gdb cmd))
1177
1178 (set 'gdb-buffer (symbol-value 'gud-comint-buffer))
1004 1179
1005 ;; Switch back to the source buffer 1180 ;; Switch back to the source buffer
1006 ;; and Activate the debug part in the contextual menu 1181 ;; and Activate the debug part in the contextual menu
1007 (switch-to-buffer buffer) 1182 (switch-to-buffer buffer)
1008 1183
1009 (if (functionp 'gud-make-debug-menu) 1184 (if (functionp 'gud-make-debug-menu)
1010 (gud-make-debug-menu)) 1185 (funcall (symbol-function 'gud-make-debug-menu)))
1011 1186
1012 ;; Warning: on Emacs >= 20.3.8, same-window-regexps includes gud-*, 1187 ;; Warning: on Emacs >= 20.3.8, same-window-regexps includes gud-*,
1013 ;; so the following call to display buffer will select the 1188 ;; so the following call to display buffer will select the
1014 ;; buffer instead of displaying it in another window 1189 ;; buffer instead of displaying it in another window
1015 ;; This is why the second argument to display-buffer is 't' 1190 ;; This is why the second argument to display-buffer is 't'
1016 (display-buffer gdb-buffer t) 1191 (display-buffer gdb-buffer t)
1017 )) 1192 ))
1018 1193
1019 1194
1020 (defun ada-reread-prj-file (&optional for-all-buffer) 1195 (defun ada-reread-prj-file (&optional filename)
1021 "Forces Emacs to read the project file again. 1196 "Forces Emacs to read either FILENAME or the project file associated
1022 Otherwise, this file is only read once, and never read again 1197 with the current buffer.
1023 If FOR-ALL-BUFFER is non-nil, or the function was called with \C-u prefix, 1198 Otherwise, this file is only read once, and never read again.
1024 then do this for every opened buffer." 1199 Since the information in the project file is shared between all buffers, this
1200 automatically modifies the setup for all the Ada buffer that use this file."
1025 (interactive "P") 1201 (interactive "P")
1026 (if for-all-buffer 1202 (if filename
1027 1203 (ada-parse-prj-file filename)
1028 ;; do this for every buffer
1029 (mapcar (lambda (x)
1030 (save-excursion
1031 (set-buffer x)
1032 ;; if we have the ada-mode and there is a real file
1033 ;; associated with the buffer
1034 (if (and (string= mode-name "Ada")
1035 (buffer-file-name))
1036 (progn
1037 (kill-local-variable 'ada-prj-src-dir)
1038 (kill-local-variable 'ada-prj-obj-dir)
1039 (ada-parse-prj-file (ada-prj-find-prj-file))))
1040 ))
1041 (buffer-list))
1042
1043 ;; else do this just for the current buffer
1044 (kill-local-variable 'ada-prj-src-dir)
1045 (kill-local-variable 'ada-prj-obj-dir)
1046 (ada-parse-prj-file (ada-prj-find-prj-file))) 1204 (ada-parse-prj-file (ada-prj-find-prj-file)))
1047 ) 1205 )
1206
1048 1207
1049 ;; ------ Private routines 1208 ;; ------ Private routines
1050 1209
1051 (defun ada-xref-current (file &optional ali-file-name) 1210 (defun ada-xref-current (file &optional ali-file-name)
1052 "Update the cross-references for FILE. 1211 "Update the cross-references for FILE.
1053 This in fact recompiles FILE to create ALI-FILE-NAME." 1212 This in fact recompiles FILE to create ALI-FILE-NAME."
1054 ;; kill old buffer 1213 ;; kill old buffer
1055 (if (and ali-file-name 1214 (if (and ali-file-name
1056 (get-file-buffer ali-file-name)) 1215 (get-file-buffer ali-file-name))
1057 (kill-buffer (get-file-buffer ali-file-name))) 1216 (kill-buffer (get-file-buffer ali-file-name)))
1058 ;; prompt for command to execute 1217 ;; read the project file
1059 (setq compile-command (concat ada-prj-comp-cmd 1218 (ada-require-project-file)
1060 " " 1219 (let* ((cmd (ada-xref-get-project-field 'comp_cmd))
1061 file)) 1220 (process-environment (ada-set-environment))
1062 (compile 1221 (compilation-scroll-output t)
1063 (if ada-xref-confirm-compile 1222 (name (ada-convert-file-name (buffer-file-name)))
1064 (read-from-minibuffer "enter command to execute gcc: " 1223 (body-name (ada-get-body-name name)))
1065 compile-command) 1224
1066 compile-command)) 1225 ;; Always recompile the body when we can
1067 ) 1226 (set 'body-name (or body-name name))
1068 1227
1069 (defun ada-first-non-nil (list) 1228 ;; prompt for command to execute
1070 "Returns the first non-nil element of the LIST" 1229 (set 'cmd (concat cmd " " body-name))
1071 (cond 1230 (compile (ada-remote
1072 ((not list) nil) 1231 (if ada-xref-confirm-compile
1073 ((car list) (car list)) 1232 (read-from-minibuffer "enter command to compile: " cmd)
1074 (t (ada-first-non-nil (cdr list))) 1233 cmd)))))
1075 )) 1234
1076 1235 (defun ada-find-file-in-dir (file dir-list)
1236 "Search for FILE in DIR-LIST."
1237 (let (found)
1238 (while (and (not found) dir-list)
1239 (set 'found (concat (file-name-as-directory (car dir-list))
1240 (file-name-nondirectory file)))
1241
1242 (unless (file-exists-p found)
1243 (set 'found nil))
1244 (set 'dir-list (cdr dir-list)))
1245 found))
1077 1246
1078 (defun ada-find-ali-file-in-dir (file) 1247 (defun ada-find-ali-file-in-dir (file)
1079 "Search for FILE in obj_dir. 1248 "Find an .ali file in obj_dir. The current buffer must be the Ada file.
1080 The current buffer must be the Ada file." 1249 Adds build_dir in front of the search path to conform to gnatmake's behavior,
1081 (ada-first-non-nil 1250 and the standard runtime location at the end."
1082 (mapcar (lambda (x) 1251 (ada-find-file-in-dir file
1083 (if (file-exists-p (concat (file-name-directory x) 1252 (append
1084 file)) 1253
1085 (concat (file-name-directory x) file) 1254 ;; Add ${build_dir} in front of the path
1086 nil)) 1255 (list (ada-xref-get-project-field 'build_dir))
1087 ada-prj-obj-dir)) 1256
1088 ) 1257 (ada-get-absolute-dir-list
1258 (ada-xref-get-project-field 'obj_dir)
1259 (ada-xref-get-project-field 'build_dir))
1260
1261 ;; Add the standard runtime at the end
1262 ada-xref-runtime-library-ali-path)))
1263
1264 (defun ada-find-src-file-in-dir (file)
1265 "Find a source file in src_dir. The current buffer must be the Ada file.
1266 Adds src_dir in front of the search path to conform to gnatmake's behavior,
1267 and the standard runtime location at the end."
1268 (ada-find-file-in-dir file
1269 (append
1270
1271 ;; Add ${build_dir} in front of the path
1272 (list (ada-xref-get-project-field 'build_dir))
1273
1274 (ada-get-absolute-dir-list
1275 (ada-xref-get-project-field 'src_dir)
1276 (ada-xref-get-project-field 'build_dir))
1277
1278 ;; Add the standard runtime at the end
1279 ada-xref-runtime-library-specs-path)))
1280
1089 1281
1090 (defun ada-get-ali-file-name (file) 1282 (defun ada-get-ali-file-name (file)
1091 "Create the ali file name for the ada-file FILE. 1283 "Create the ali file name for the ada-file FILE.
1092 The file is searched for in every directory shown in the obj_dir lines of 1284 The file is searched for in every directory shown in the obj_dir lines of
1093 the project file." 1285 the project file."
1107 (save-excursion 1299 (save-excursion
1108 (set-buffer (get-file-buffer file)) 1300 (set-buffer (get-file-buffer file))
1109 (let ((short-ali-file-name 1301 (let ((short-ali-file-name
1110 (concat (file-name-sans-extension (file-name-nondirectory file)) 1302 (concat (file-name-sans-extension (file-name-nondirectory file))
1111 ".ali")) 1303 ".ali"))
1112 (ali-file-name "")) 1304 ali-file-name)
1113 ;; First step 1305 ;; First step
1114 ;; we take the first possible completion 1306 ;; we take the first possible completion
1115 (setq ali-file-name (ada-find-ali-file-in-dir short-ali-file-name)) 1307 (setq ali-file-name (ada-find-ali-file-in-dir short-ali-file-name))
1116 1308
1117 ;; If we have found the .ali file, but the source file was a spec 1309 ;; If we have found the .ali file, but the source file was a spec
1118 ;; with a non-standard name, search the .ali file for the body if any, 1310 ;; with a non-standard name, search the .ali file for the body if any,
1119 ;; since the xref information is more complete in that one 1311 ;; since the xref information is more complete in that one
1120 (unless ali-file-name 1312 (unless ali-file-name
1121 (if (not (string= (file-name-extension file) ".ads")) 1313 (if (not (string= (file-name-extension file) "ads"))
1122 (let ((is-spec nil) 1314 (let ((is-spec nil)
1123 (specs ada-spec-suffixes) 1315 (specs ada-spec-suffixes)
1124 body-ali) 1316 body-ali)
1125 (while specs 1317 (while specs
1126 (if (string-match (concat (regexp-quote (car specs)) "$") 1318 (if (string-match (concat (regexp-quote (car specs)) "$")
1170 "Create the complete file name (+directory) for FILE. 1362 "Create the complete file name (+directory) for FILE.
1171 The original file (where the user was) is ORIGINAL-FILE. Search in project 1363 The original file (where the user was) is ORIGINAL-FILE. Search in project
1172 file for possible paths." 1364 file for possible paths."
1173 1365
1174 (save-excursion 1366 (save-excursion
1175 (set-buffer (get-file-buffer original-file)) 1367
1368 ;; If the buffer for original-file, use it to get the values from the
1369 ;; project file, otherwise load the file and its project file
1370 (let ((buffer (get-file-buffer original-file)))
1371 (if buffer
1372 (set-buffer buffer)
1373 (find-file original-file)
1374 (ada-require-project-file)))
1375
1176 ;; we choose the first possible completion and we 1376 ;; we choose the first possible completion and we
1177 ;; return the absolute file name 1377 ;; return the absolute file name
1178 (let ((filename 1378 (let ((filename (ada-find-src-file-in-dir file)))
1179 (ada-first-non-nil (mapcar (lambda (x)
1180 (if (file-exists-p (concat (file-name-directory x)
1181 (file-name-nondirectory file)))
1182 (concat (file-name-directory x)
1183 (file-name-nondirectory file))
1184 nil))
1185 ada-prj-src-dir))))
1186
1187 (if filename 1379 (if filename
1188 (expand-file-name filename) 1380 (expand-file-name filename)
1189 (error (concat 1381 (error (concat
1190 (file-name-nondirectory file) 1382 (file-name-nondirectory file)
1191 " not found in src_dir. Please check your project file"))) 1383 " not found in src_dir. Please check your project file")))
1230 ;; as in "+", "-", .. 1422 ;; as in "+", "-", ..
1231 (if (= (char-after) ?\") 1423 (if (= (char-after) ?\")
1232 (forward-char 1)) 1424 (forward-char 1))
1233 1425
1234 ;; if looking at an operator 1426 ;; if looking at an operator
1235 (if (looking-at ada-operator-re) 1427 ;; This is only true if:
1428 ;; - the symbol is +, -, ...
1429 ;; - the symbol is made of letters, and not followed by _ or a letter
1430 (if (and (looking-at ada-operator-re)
1431 (or (not (= (char-syntax (char-after)) ?w))
1432 (not (or (= (char-syntax (char-after (match-end 0))) ?w)
1433 (= (char-after (match-end 0)) ?_)))))
1236 (progn 1434 (progn
1237 (if (and (= (char-before) ?\") 1435 (if (and (= (char-before) ?\")
1238 (= (char-after (+ (length (match-string 0)) (point))) ?\")) 1436 (= (char-after (+ (length (match-string 0)) (point))) ?\"))
1239 (forward-char -1)) 1437 (forward-char -1))
1240 (set 'identifier (concat "\"" (match-string 0) "\""))) 1438 (set 'identifier (regexp-quote (concat "\"" (match-string 0) "\""))))
1241 1439
1242 (if (ada-in-string-p) 1440 (if (ada-in-string-p)
1243 (error "Inside string or character constant")) 1441 (error "Inside string or character constant"))
1244 (if (looking-at (concat ada-keywords "[^a-zA-Z_]")) 1442 (if (looking-at (concat ada-keywords "[^a-zA-Z_]"))
1245 (error "No cross-reference available for reserved keyword")) 1443 (error "No cross-reference available for reserved keyword"))
1257 (ada-set-file identlist (buffer-file-name)) 1455 (ada-set-file identlist (buffer-file-name))
1258 identlist 1456 identlist
1259 )) 1457 ))
1260 1458
1261 (defun ada-get-all-references (identlist) 1459 (defun ada-get-all-references (identlist)
1262 "Completes and returns the IDENTLIST with the information extracted 1460 "Completes and returns IDENTLIST with the information extracted
1263 from the ali file (definition file and places where it is referenced)." 1461 from the ali file (definition file and places where it is referenced)."
1264 1462
1265 (let ((ali-buffer (ada-get-ali-buffer (ada-file-of identlist))) 1463 (let ((ali-buffer (ada-get-ali-buffer (ada-file-of identlist)))
1266 declaration-found) 1464 declaration-found)
1267 (set-buffer ali-buffer) 1465 (set-buffer ali-buffer)
1278 (let ((bound (save-excursion (re-search-forward "^X " nil t)))) 1476 (let ((bound (save-excursion (re-search-forward "^X " nil t))))
1279 (set 'declaration-found 1477 (set 'declaration-found
1280 (re-search-forward 1478 (re-search-forward
1281 (concat "^" (ada-line-of identlist) 1479 (concat "^" (ada-line-of identlist)
1282 "." (ada-column-of identlist) 1480 "." (ada-column-of identlist)
1283 "[ *]" (regexp-quote (ada-name-of identlist)) 1481 "[ *]" (ada-name-of identlist)
1284 " \\(.*\\)$") bound t)) 1482 " \\(.*\\)$") bound t))
1285 (if declaration-found 1483 (if declaration-found
1286 (ada-set-on-declaration identlist t)) 1484 (ada-set-on-declaration identlist t))
1287 )) 1485 ))
1288 1486
1329 (beginning-of-line) 1527 (beginning-of-line)
1330 ;; while we have a continuation line, go up one line 1528 ;; while we have a continuation line, go up one line
1331 (while (looking-at "^\\.") 1529 (while (looking-at "^\\.")
1332 (previous-line 1)) 1530 (previous-line 1))
1333 (unless (looking-at (concat "[0-9]+.[0-9]+[ *]" 1531 (unless (looking-at (concat "[0-9]+.[0-9]+[ *]"
1334 (ada-name-of identlist) " ")) 1532 (ada-name-of identlist) "[ <]"))
1335 (set 'declaration-found nil)))) 1533 (set 'declaration-found nil))))
1336 1534
1337 ;; Still no success ! The ali file must be too old, and we need to 1535 ;; Still no success ! The ali file must be too old, and we need to
1338 ;; use a basic algorithm based on guesses. Note that this only happens 1536 ;; use a basic algorithm based on guesses. Note that this only happens
1339 ;; if the user does not want us to automatically recompile files 1537 ;; if the user does not want us to automatically recompile files
1340 ;; automatically 1538 ;; automatically
1341 (unless declaration-found 1539 (unless declaration-found
1342 (unless (ada-xref-find-in-modified-ali identlist) 1540 (if (ada-xref-find-in-modified-ali identlist)
1541 (set 'declaration-found t)
1343 ;; no more idea to find the declaration. Give up 1542 ;; no more idea to find the declaration. Give up
1344 (progn 1543 (progn
1345 (kill-buffer ali-buffer) 1544 (kill-buffer ali-buffer)
1346 (error (concat "No declaration of " (ada-name-of identlist) 1545 (error (concat "No declaration of " (ada-name-of identlist)
1347 " found.")) 1546 " found."))
1386 (regexp-quote (ada-name-of identlist)) " ")) 1585 (regexp-quote (ada-name-of identlist)) " "))
1387 (line-ada "--") 1586 (line-ada "--")
1388 (col-ada "--") 1587 (col-ada "--")
1389 (line-ali 0) 1588 (line-ali 0)
1390 (len 0) 1589 (len 0)
1391 (choice 0)) 1590 (choice 0)
1591 (ali-buffer (current-buffer)))
1392 1592
1393 (goto-char (point-max)) 1593 (goto-char (point-max))
1394 (while (re-search-backward my-regexp nil t) 1594 (while (re-search-backward my-regexp nil t)
1395 (save-excursion 1595 (save-excursion
1396 (set 'line-ali (count-lines (point-min) (point))) 1596 (set 'line-ali (count-lines (point-min) (point)))
1453 (not (integerp choice)) 1653 (not (integerp choice))
1454 (< choice 1) 1654 (< choice 1)
1455 (> choice len)) 1655 (> choice len))
1456 (setq choice (string-to-int 1656 (setq choice (string-to-int
1457 (read-from-minibuffer "Enter No. of your choice: ")))) 1657 (read-from-minibuffer "Enter No. of your choice: "))))
1658 (set-buffer ali-buffer)
1458 (goto-line (car (nth (1- choice) declist))) 1659 (goto-line (car (nth (1- choice) declist)))
1459 )))))) 1660 ))))))
1460 1661
1461 1662
1462 (defun ada-find-in-ali (identlist &optional other-frame) 1663 (defun ada-find-in-ali (identlist &optional other-frame)
1481 (re-search-forward "^D \\([a-zA-Z0-9_.-]+\\)" nil t 1682 (re-search-forward "^D \\([a-zA-Z0-9_.-]+\\)" nil t
1482 (string-to-number file-number)) 1683 (string-to-number file-number))
1483 (set 'file (match-string 1)) 1684 (set 'file (match-string 1))
1484 ) 1685 )
1485 ;; Else get the nearest file 1686 ;; Else get the nearest file
1486 (re-search-backward "^X [0-9]+ \\([a-zA-Z0-9_.-]+\\)" nil t) 1687 (set 'file (ada-declare-file-of identlist))
1487 (set 'file (match-string 1))
1488 ) 1688 )
1489 ) 1689 )
1490 (error "No body found")) 1690 (error "No body found"))
1491 1691
1492 ;; Else we were not on the declaration, find the place for it 1692 ;; Else we were not on the declaration, find the place for it
1533 (find-file file) 1733 (find-file file)
1534 ) 1734 )
1535 1735
1536 ;; If the new buffer is not already associated with a project file, do it 1736 ;; If the new buffer is not already associated with a project file, do it
1537 (unless (my-local-variable-if-set-p 'ada-prj-prj-file (current-buffer)) 1737 (unless (my-local-variable-if-set-p 'ada-prj-prj-file (current-buffer))
1538 (progn 1738 (set (make-local-variable 'ada-prj-prj-file) prj-file))
1539 (make-local-variable 'ada-prj-prj-file)
1540 (set 'ada-prj-prj-file prj-file)))
1541 1739
1542 ;; move the cursor to the correct position 1740 ;; move the cursor to the correct position
1543 (push-mark) 1741 (push-mark)
1544 (goto-line line) 1742 (goto-line line)
1545 (move-to-column column) 1743 (move-to-column column)
1667 (point)))) 1865 (point))))
1668 (kill-buffer krunch-buf))) 1866 (kill-buffer krunch-buf)))
1669 adaname 1867 adaname
1670 ) 1868 )
1671 1869
1672
1673 (defun ada-make-body-gnatstub () 1870 (defun ada-make-body-gnatstub ()
1674 "Create an Ada package body in the current buffer. 1871 "Create an Ada package body in the current buffer.
1675 This function uses the `gnatstub' program to create the body. 1872 This function uses the `gnatstub' program to create the body.
1676 This function typically is to be hooked into `ff-file-created-hooks'." 1873 This function typically is to be hooked into `ff-file-created-hooks'."
1677 (interactive) 1874 (interactive)
1728 1925
1729 (defun ada-xref-initialize () 1926 (defun ada-xref-initialize ()
1730 "Function called by ada-mode-hook to initialize the ada-xref.el package. 1927 "Function called by ada-mode-hook to initialize the ada-xref.el package.
1731 For instance, it creates the gnat-specific menus, set some hooks for 1928 For instance, it creates the gnat-specific menus, set some hooks for
1732 find-file...." 1929 find-file...."
1733 (ada-add-ada-menu)
1734 (make-local-hook 'ff-file-created-hooks) 1930 (make-local-hook 'ff-file-created-hooks)
1735 (setq ff-file-created-hooks 'ada-make-body-gnatstub) 1931 (setq ff-file-created-hooks 'ada-make-body-gnatstub)
1736 1932
1737 ;; Read the project file and update the search path 1933 ;; Read the project file and update the search path
1738 ;; before looking for the other file 1934 ;; before looking for the other file
1746 1942
1747 ;; ----- Add to ada-mode-hook --------------------------------------------- 1943 ;; ----- Add to ada-mode-hook ---------------------------------------------
1748 1944
1749 ;; Set the keymap once and for all, so that the keys set by the user in his 1945 ;; Set the keymap once and for all, so that the keys set by the user in his
1750 ;; config file are not overwritten every time we open a new file. 1946 ;; config file are not overwritten every time we open a new file.
1947 (ada-add-ada-menu)
1751 (ada-add-keymap) 1948 (ada-add-keymap)
1752 1949
1753 (add-hook 'ada-mode-hook 'ada-xref-initialize) 1950 (add-hook 'ada-mode-hook 'ada-xref-initialize)
1754 1951
1952 ;; Use ddd as the default debugger if it was found
1953 (if (ada-find-file-in-dir "ddd" exec-path)
1954 (set 'ada-prj-default-debugger "ddd --tty -fullname -toolbar"))
1955
1956 ;; Initializes the cross references to the runtime library
1957 (ada-initialize-runtime-library)
1958
1959 ;; Add these standard directories to the search path
1960 (set 'ada-search-directories
1961 (append (mapcar 'directory-file-name ada-xref-runtime-library-specs-path)
1962 ada-search-directories))
1963
1964 ;; Make sure that the files are always associated with a project file. Since
1965 ;; the project file has some fields that are used for the editor (like the
1966 ;; casing exceptions), it has to be read before the user edits a file).
1967 (add-hook 'ada-mode-hook
1968 (lambda()
1969 (let ((file (ada-prj-find-prj-file t)))
1970 (if file (ada-reread-prj-file file)))))
1971
1755 (provide 'ada-xref) 1972 (provide 'ada-xref)
1756 1973
1757 ;;; ada-xref.el ends here 1974 ;;; ada-xref.el ends here