(tramp-find-file-exists-command, tramp-find-shell): Follow error conventions.
[bpt/emacs.git] / lisp / progmodes / ada-mode.el
CommitLineData
3afbc435 1;;; ada-mode.el --- major-mode for editing Ada sources
972579f9 2
58e7eb2a 3;; Copyright (C) 1994, 95, 97, 98, 99, 2000, 2001, 2002, 03, 2004
2be7dabc 4;; Free Software Foundation, Inc.
972579f9 5
7749c1a8
GM
6;; Author: Rolf Ebert <ebert@inf.enst.fr>
7;; Markus Heritsch <Markus.Heritsch@studbox.uni-stuttgart.de>
8;; Emmanuel Briot <briot@gnat.com>
9;; Maintainer: Emmanuel Briot <briot@gnat.com>
f7a80909 10;; Ada Core Technologies's version: Revision: 1.188
7749c1a8 11;; Keywords: languages ada
d03b8a2d 12
3afbc435 13;; This file is part of GNU Emacs.
972579f9 14
2be7dabc 15;; GNU Emacs is free software; you can redistribute it and/or modify
972579f9
RS
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,
972579f9
RS
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.
7749c1a8
GM
29
30;;; Commentary:
31;;; This mode is a major mode for editing Ada83 and Ada95 source code.
4cc7e498 32;;; This is a major rewrite of the file packaged with Emacs-20. The
f7a80909 33;;; ada-mode is composed of four lisp files, ada-mode.el, ada-xref.el,
7749c1a8 34;;; ada-prj.el and ada-stmt.el. Only this file (ada-mode.el) is
655880d2 35;;; completely independent from the GNU Ada compiler Gnat, distributed
7749c1a8 36;;; by Ada Core Technologies. All the other files rely heavily on
5dab0769 37;;; features provided only by Gnat.
972579f9 38;;;
7749c1a8
GM
39;;; Note: this mode will not work with Emacs 19. If you are on a VMS
40;;; system, where the latest version of Emacs is 19.28, you will need
41;;; another file, called ada-vms.el, that provides some required
42;;; functions.
43
44;;; Usage:
45;;; Emacs should enter Ada mode automatically when you load an Ada file.
46;;; By default, the valid extensions for Ada files are .ads, .adb or .ada
47;;; If the ada-mode does not start automatically, then simply type the
48;;; following command :
49;;; M-x ada-mode
50;;;
51;;; By default, ada-mode is configured to take full advantage of the GNAT
52;;; compiler (the menus will include the cross-referencing features,...).
53;;; If you are using another compiler, you might want to set the following
54;;; variable in your .emacs (Note: do not set this in the ada-mode-hook, it
55;;; won't work) :
56;;; (setq ada-which-compiler 'generic)
57;;;
58;;; This mode requires find-file.el to be present on your system.
972579f9 59
7749c1a8 60;;; History:
3ca7b46f
KH
61;;; The first Ada mode for GNU Emacs was written by V. Broman in
62;;; 1985. He based his work on the already existing Modula-2 mode.
63;;; This was distributed as ada.el in versions of Emacs prior to 19.29.
972579f9
RS
64;;;
65;;; Lynn Slater wrote an extensive Ada mode in 1989. It consisted of
66;;; several files with support for dired commands and other nice
67;;; things. It is currently available from the PAL
68;;; (wuarchive.wustl.edu:/languages/ada) as ada-mode-1.06a.tar.Z.
69;;;
70;;; The probably very first Ada mode (called electric-ada.el) was
71;;; written by Steven D. Litvintchouk and Steven M. Rosen for the
72;;; Gosling Emacs. L. Slater based his development on ada.el and
73;;; electric-ada.el.
74;;;
7749c1a8
GM
75;;; A complete rewrite by M. Heritsch and R. Ebert has been done.
76;;; Some ideas from the Ada mode mailing list have been
972579f9
RS
77;;; added. Some of the functionality of L. Slater's mode has not
78;;; (yet) been recoded in this new mode. Perhaps you prefer sticking
79;;; to his version.
972579f9 80;;;
7749c1a8
GM
81;;; A complete rewrite for Emacs-20 / Gnat-3.11 has been done by Ada Core
82;;; Technologies. Please send bugs to briot@gnat.com
83
84;;; Credits:
85;;; Many thanks to John McCabe <john@assen.demon.co.uk> for sending so
86;;; many patches included in this package.
87;;; Christian Egli <Christian.Egli@hcsd.hac.com>:
88;;; ada-imenu-generic-expression
89;;; Many thanks also to the following persons that have contributed one day
90;;; to the ada-mode
91;;; Philippe Waroquiers (PW) <philippe@cfmu.eurocontrol.be> in particular,
92;;; woodruff@stc.llnl.gov (John Woodruff)
93;;; jj@ddci.dk (Jesper Joergensen)
94;;; gse@ocsystems.com (Scott Evans)
95;;; comar@gnat.com (Cyrille Comar)
96;;; stephen.leake@gsfc.nasa.gov (Stephen Leake)
4607c7f4 97;;; robin-reply@reagans.org
f139ce87 98;;; and others for their valuable hints.
972579f9 99
7749c1a8 100;;; Code:
4cc7e498 101;;; Note: Every function in this package is compiler-independent.
7749c1a8 102;;; The names start with ada-
655880d2 103;;; The variables that the user can edit can all be modified through
7749c1a8
GM
104;;; the customize mode. They are sorted in alphabetical order in this
105;;; file.
106
4607c7f4
SM
107;;; Supported packages.
108;;; This package supports a number of other Emacs modes. These other modes
109;;; should be loaded before the ada-mode, which will then setup some variables
110;;; to improve the support for Ada code.
111;;; Here is the list of these modes:
112;;; `which-function-mode': Display the name of the subprogram the cursor is
113;;; in in the mode line.
114;;; `outline-mode': Provides the capability to collapse or expand the code
115;;; for specific language constructs, for instance if you want to hide the
116;;; code corresponding to a subprogram
117;;; `align': This mode is now provided with Emacs 21, but can also be
118;;; installed manually for older versions of Emacs. It provides the
119;;; capability to automatically realign the selected region (for instance
120;;; all ':=', ':' and '--' will be aligned on top of each other.
121;;; `imenu': Provides a menu with the list of entities defined in the current
122;;; buffer, and an easy way to jump to any of them
123;;; `speedbar': Provides a separate file browser, and the capability for each
124;;; file to see the list of entities defined in it and to jump to them
125;;; easily
126;;; `abbrev-mode': Provides the capability to define abbreviations, which
127;;; are automatically expanded when you type them. See the Emacs manual.
128
6f9a2614
JB
129(eval-when-compile
130 (require 'ispell nil t)
131 (require 'find-file nil t)
132 (require 'align nil t)
133 (require 'which-func nil t)
134 (require 'compile nil t))
7749c1a8
GM
135
136;; this function is needed at compile time
137(eval-and-compile
655880d2
GM
138 (defun ada-check-emacs-version (major minor &optional is-xemacs)
139 "Returns t if Emacs's version is greater or equal to MAJOR.MINOR.
140If IS-XEMACS is non-nil, check for XEmacs instead of Emacs."
141 (let ((xemacs-running (or (string-match "Lucid" emacs-version)
4cc7e498 142 (string-match "XEmacs" emacs-version))))
655880d2 143 (and (or (and is-xemacs xemacs-running)
4cc7e498
GM
144 (not (or is-xemacs xemacs-running)))
145 (or (> emacs-major-version major)
146 (and (= emacs-major-version major)
147 (>= emacs-minor-version minor)))))))
148
7749c1a8 149
7749c1a8 150;; This call should not be made in the release that is done for the
7aeff5ab 151;; official Emacs, since it does nothing useful for the latest version
f7a80909
JB
152;;(if (not (ada-check-emacs-version 21 1))
153;; (require 'ada-support))
52748d95 154
7749c1a8
GM
155(defvar ada-mode-hook nil
156 "*List of functions to call when Ada mode is invoked.
f7a80909 157This hook is automatically executed after the `ada-mode' is
7749c1a8
GM
158fully loaded.
159This is a good place to add Ada environment specific bindings.")
52748d95
RS
160
161(defgroup ada nil
655880d2 162 "Major mode for editing Ada source in Emacs."
52748d95
RS
163 :group 'languages)
164
7749c1a8
GM
165(defcustom ada-auto-case t
166 "*Non-nil means automatically change case of preceding word while typing.
167Casing is done according to `ada-case-keyword', `ada-case-identifier'
168and `ada-case-attribute'."
169 :type 'boolean :group 'ada)
972579f9 170
7749c1a8
GM
171(defcustom ada-broken-decl-indent 0
172 "*Number of columns to indent a broken declaration.
173
174An example is :
175 declare
176 A,
177 >>>>>B : Integer; -- from ada-broken-decl-indent"
178 :type 'integer :group 'ada)
972579f9 179
52748d95 180(defcustom ada-broken-indent 2
7749c1a8 181 "*Number of columns to indent the continuation of a broken line.
972579f9 182
7749c1a8
GM
183An example is :
184 My_Var : My_Type := (Field1 =>
185 >>>>>>>>>Value); -- from ada-broken-indent"
186 :type 'integer :group 'ada)
972579f9 187
80d50f88
SM
188(defcustom ada-continuation-indent ada-broken-indent
189 "*Number of columns to indent the continuation of broken lines in
190parenthesis.
191
192An example is :
193 Func (Param1,
194 >>>>>Param2);"
195 :type 'integer :group 'ada)
196
7749c1a8
GM
197(defcustom ada-case-attribute 'ada-capitalize-word
198 "*Function to call to adjust the case of Ada attributes.
4cc7e498
GM
199It may be `downcase-word', `upcase-word', `ada-loose-case-word',
200`ada-capitalize-word' or `ada-no-auto-case'."
7749c1a8
GM
201 :type '(choice (const downcase-word)
202 (const upcase-word)
203 (const ada-capitalize-word)
4cc7e498
GM
204 (const ada-loose-case-word)
205 (const ada-no-auto-case))
52748d95 206 :group 'ada)
972579f9 207
4607c7f4
SM
208(defcustom ada-case-exception-file
209 (list (convert-standard-filename' "~/.emacs_case_exceptions"))
4cc7e498
GM
210 "*List of special casing exceptions dictionaries for identifiers.
211The first file is the one where new exceptions will be saved by Emacs
212when you call `ada-create-case-exception'.
213
214These files should contain one word per line, that gives the casing
4607c7f4
SM
215to be used for that word in Ada files. If the line starts with the
216character *, then the exception will be used for substrings that either
217start at the beginning of a word or after a _ character, and end either
218at the end of the word or at a _ character. Each line can be terminated by
4cc7e498
GM
219a comment."
220 :type '(repeat (file))
221 :group 'ada)
972579f9 222
7749c1a8 223(defcustom ada-case-keyword 'downcase-word
655880d2 224 "*Function to call to adjust the case of an Ada keywords.
7749c1a8
GM
225It may be `downcase-word', `upcase-word', `ada-loose-case-word' or
226`ada-capitalize-word'."
227 :type '(choice (const downcase-word)
228 (const upcase-word)
229 (const ada-capitalize-word)
4cc7e498
GM
230 (const ada-loose-case-word)
231 (const ada-no-auto-case))
52748d95 232 :group 'ada)
972579f9 233
7749c1a8
GM
234(defcustom ada-case-identifier 'ada-loose-case-word
235 "*Function to call to adjust the case of an Ada identifier.
236It may be `downcase-word', `upcase-word', `ada-loose-case-word' or
237`ada-capitalize-word'."
238 :type '(choice (const downcase-word)
239 (const upcase-word)
240 (const ada-capitalize-word)
4cc7e498
GM
241 (const ada-loose-case-word)
242 (const ada-no-auto-case))
52748d95 243 :group 'ada)
972579f9 244
7749c1a8 245(defcustom ada-clean-buffer-before-saving t
655880d2 246 "*Non-nil means remove trailing spaces and untabify the buffer before saving."
7749c1a8 247 :type 'boolean :group 'ada)
972579f9 248
7749c1a8
GM
249(defcustom ada-indent 3
250 "*Size of Ada indentation.
972579f9 251
7749c1a8
GM
252An example is :
253procedure Foo is
254begin
255>>>>>>>>>>null; -- from ada-indent"
256 :type 'integer :group 'ada)
972579f9 257
7749c1a8
GM
258(defcustom ada-indent-after-return t
259 "*Non-nil means automatically indent after RET or LFD."
260 :type 'boolean :group 'ada)
972579f9 261
4cc7e498
GM
262(defcustom ada-indent-align-comments t
263 "*Non-nil means align comments on previous line comments, if any.
264If nil, indentation is calculated as usual.
265Note that indentation is calculated only if `ada-indent-comment-as-code' is t.
266
267For instance:
268 A := 1; -- A multi-line comment
269 -- aligned if ada-indent-align-comments is t"
270 :type 'boolean :group 'ada)
271
7749c1a8 272(defcustom ada-indent-comment-as-code t
4cc7e498 273 "*Non-nil means indent comment lines as code.
f0529b5b 274nil means do not auto-indent comments."
7749c1a8 275 :type 'boolean :group 'ada)
972579f9 276
4607c7f4
SM
277(defcustom ada-indent-handle-comment-special nil
278 "*Non-nil if comment lines should be handled specially inside
279parenthesis.
280By default, if the line that contains the open parenthesis has some
281text following it, then the following lines will be indented in the
282same column as this text. This will not be true if the first line is
283a comment and `ada-indent-handle-comment-special' is t.
284
285type A is
286 ( Value_1, -- common behavior, when not a comment
287 Value_2);
288
289type A is
290 ( -- `ada-indent-handle-comment-special' is nil
291 Value_1,
292 Value_2);
293
294type A is
295 ( -- `ada-indent-handle-comment-special' is non-nil
296 Value_1,
297 Value_2);"
298 :type 'boolean :group 'ada)
a1506d29 299
7749c1a8
GM
300(defcustom ada-indent-is-separate t
301 "*Non-nil means indent 'is separate' or 'is abstract' if on a single line."
302 :type 'boolean :group 'ada)
972579f9 303
7749c1a8
GM
304(defcustom ada-indent-record-rel-type 3
305 "*Indentation for 'record' relative to 'type' or 'use'.
52748d95 306
7749c1a8
GM
307An example is:
308 type A is
309 >>>>>>>>>>>record -- from ada-indent-record-rel-type"
310 :type 'integer :group 'ada)
52748d95 311
4cc7e498
GM
312(defcustom ada-indent-renames ada-broken-indent
313 "*Indentation for renames relative to the matching function statement.
314If ada-indent-return is null or negative, the indentation is done relative to
315the open parenthesis (if there is no parenthesis, ada-broken-indent is used).
316
317An example is:
318 function A (B : Integer)
319 return C; -- from ada-indent-return
320 >>>renames Foo; -- from ada-indent-renames"
321 :type 'integer :group 'ada)
322
7749c1a8
GM
323(defcustom ada-indent-return 0
324 "*Indentation for 'return' relative to the matching 'function' statement.
325If ada-indent-return is null or negative, the indentation is done relative to
655880d2 326the open parenthesis (if there is no parenthesis, ada-broken-indent is used).
52748d95 327
7749c1a8
GM
328An example is:
329 function A (B : Integer)
330 >>>>>return C; -- from ada-indent-return"
331 :type 'integer :group 'ada)
52748d95 332
7749c1a8
GM
333(defcustom ada-indent-to-open-paren t
334 "*Non-nil means indent according to the innermost open parenthesis."
335 :type 'boolean :group 'ada)
52748d95 336
5ebcaf36 337(defcustom ada-fill-comment-prefix "-- "
7749c1a8 338 "*Text inserted in the first columns when filling a comment paragraph.
10bcf543
RS
339Note: if you modify this variable, you will have to invoke `ada-mode'
340again to take account of the new value."
7749c1a8 341 :type 'string :group 'ada)
52748d95 342
7749c1a8
GM
343(defcustom ada-fill-comment-postfix " --"
344 "*Text inserted at the end of each line when filling a comment paragraph.
345with `ada-fill-comment-paragraph-postfix'."
346 :type 'string :group 'ada)
52748d95 347
7749c1a8
GM
348(defcustom ada-label-indent -4
349 "*Number of columns to indent a label.
52748d95 350
7749c1a8
GM
351An example is:
352procedure Foo is
353begin
80d50f88
SM
354>>>>>>>>>>>>Label: -- from ada-label-indent
355
356This is also used for <<..>> labels"
7749c1a8 357 :type 'integer :group 'ada)
52748d95
RS
358
359(defcustom ada-language-version 'ada95
360 "*Do we program in `ada83' or `ada95'?"
7749c1a8 361 :type '(choice (const ada83) (const ada95)) :group 'ada)
52748d95 362
7749c1a8 363(defcustom ada-move-to-declaration nil
655880d2 364 "*Non-nil means `ada-move-to-start' moves point to the subprogram declaration,
7749c1a8
GM
365not to 'begin'."
366 :type 'boolean :group 'ada)
972579f9 367
7749c1a8
GM
368(defcustom ada-popup-key '[down-mouse-3]
369 "*Key used for binding the contextual menu.
4cc7e498 370If nil, no contextual menu is available."
7c5fd355 371 :type '(restricted-sexp :match-alternatives (stringp vectorp))
50a8310e 372 :group 'ada)
cadd3658 373
7749c1a8 374(defcustom ada-search-directories
f7a80909
JB
375 (append '(".")
376 (split-string (or (getenv "ADA_INCLUDE_PATH") "") ":")
377 '("/usr/adainclude" "/usr/local/adainclude"
378 "/opt/gnu/adainclude"))
655880d2 379 "*List of directories to search for Ada files.
6f9a2614
JB
380See the description for the `ff-search-directories' variable. This variable
381is the initial value of this variable, and is copied and modified in
382`ada-search-directories-internal'."
7749c1a8
GM
383 :type '(repeat (choice :tag "Directory"
384 (const :tag "default" nil)
385 (directory :format "%v")))
52748d95 386 :group 'ada)
cadd3658 387
6f9a2614
JB
388(defvar ada-search-directories-internal ada-search-directories
389 "Internal version of `ada-search-directories'.
390Its value is the concatenation of the search path as read in the project file
391and the standard runtime location, and the value of the user-defined
392ada-search-directories.")
393
7749c1a8 394(defcustom ada-stmt-end-indent 0
655880d2 395 "*Number of columns to indent the end of a statement on a separate line.
cadd3658 396
7749c1a8
GM
397An example is:
398 if A = B
399 >>>>>>>>>>>then -- from ada-stmt-end-indent"
400 :type 'integer :group 'ada)
cadd3658 401
7749c1a8 402(defcustom ada-tab-policy 'indent-auto
655880d2 403 "*Control the behavior of the TAB key.
7749c1a8
GM
404Must be one of :
405`indent-rigidly' : always adds ada-indent blanks at the beginning of the line.
406`indent-auto' : use indentation functions in this file.
407`always-tab' : do indent-relative."
408 :type '(choice (const indent-auto)
409 (const indent-rigidly)
410 (const always-tab))
52748d95 411 :group 'ada)
972579f9 412
4cc7e498
GM
413(defcustom ada-use-indent ada-broken-indent
414 "*Indentation for the lines in a 'use' statement.
415
416An example is:
417 use Ada.Text_IO,
418 >>>>>Ada.Numerics; -- from ada-use-indent"
419 :type 'integer :group 'ada)
420
7749c1a8
GM
421(defcustom ada-when-indent 3
422 "*Indentation for 'when' relative to 'exception' or 'case'.
423
424An example is:
425 case A is
655880d2 426 >>>>>>>>when B => -- from ada-when-indent"
7749c1a8
GM
427 :type 'integer :group 'ada)
428
4cc7e498
GM
429(defcustom ada-with-indent ada-broken-indent
430 "*Indentation for the lines in a 'with' statement.
431
432An example is:
433 with Ada.Text_IO,
434 >>>>>Ada.Numerics; -- from ada-with-indent"
435 :type 'integer :group 'ada)
436
7749c1a8 437(defcustom ada-which-compiler 'gnat
655880d2
GM
438 "*Name of the compiler to use.
439This will determine what features are made available through the ada-mode.
440The possible choices are :
7749c1a8
GM
441`gnat': Use Ada Core Technologies' Gnat compiler. Add some cross-referencing
442 features
443`generic': Use a generic compiler"
444 :type '(choice (const gnat)
445 (const generic))
52748d95 446 :group 'ada)
972579f9 447
972579f9
RS
448
449;;; ---- end of user configurable variables
450\f
451
7749c1a8 452(defvar ada-body-suffixes '(".adb")
655880d2
GM
453 "List of possible suffixes for Ada body files.
454The extensions should include a `.' if needed.")
7749c1a8
GM
455
456(defvar ada-spec-suffixes '(".ads")
655880d2
GM
457 "List of possible suffixes for Ada spec files.
458The extensions should include a `.' if needed.")
7749c1a8 459
88127f30 460(defvar ada-mode-menu (make-sparse-keymap "Ada")
655880d2 461 "Menu for ada-mode.")
972579f9 462
7749c1a8 463(defvar ada-mode-map (make-sparse-keymap)
cadd3658 464 "Local keymap used for Ada mode.")
972579f9 465
4cc7e498
GM
466(defvar ada-mode-abbrev-table nil
467 "Local abbrev table for Ada mode.")
468
972579f9
RS
469(defvar ada-mode-syntax-table nil
470 "Syntax table to be used for editing Ada source code.")
471
f139ce87
KH
472(defvar ada-mode-symbol-syntax-table nil
473 "Syntax table for Ada, where `_' is a word constituent.")
474
7749c1a8
GM
475(eval-when-compile
476 (defconst ada-83-string-keywords
477 '("abort" "abs" "accept" "access" "all" "and" "array" "at" "begin"
478 "body" "case" "constant" "declare" "delay" "delta" "digits" "do"
479 "else" "elsif" "end" "entry" "exception" "exit" "for" "function"
480 "generic" "goto" "if" "in" "is" "limited" "loop" "mod" "new"
481 "not" "null" "of" "or" "others" "out" "package" "pragma" "private"
482 "procedure" "raise" "range" "record" "rem" "renames" "return"
483 "reverse" "select" "separate" "subtype" "task" "terminate" "then"
484 "type" "use" "when" "while" "with" "xor")
655880d2
GM
485 "List of Ada keywords.
486This variable is used to define `ada-83-keywords' and `ada-95-keywords'"))
7749c1a8
GM
487
488(defvar ada-ret-binding nil
489 "Variable to save key binding of RET when casing is activated.")
490
491(defvar ada-case-exception '()
655880d2 492 "Alist of words (entities) that have special casing.")
7749c1a8 493
4607c7f4
SM
494(defvar ada-case-exception-substring '()
495 "Alist of substrings (entities) that have special casing.
496The substrings are detected for word constituant when the word
497is not itself in ada-case-exception, and only for substrings that
498either are at the beginning or end of the word, or start after '_'.")
499
7749c1a8
GM
500(defvar ada-lfd-binding nil
501 "Variable to save key binding of LFD when casing is activated.")
502
503(defvar ada-other-file-alist nil
504 "Variable used by find-file to find the name of the other package.
655880d2 505See `ff-other-file-alist'.")
7749c1a8 506
4607c7f4
SM
507(defvar ada-align-list
508 '(("[^:]\\(\\s-*\\):[^:]" 1 t)
509 ("[^=]\\(\\s-+\\)=[^=]" 1 t)
510 ("\\(\\s-*\\)use\\s-" 1)
511 ("\\(\\s-*\\)--" 1))
512 "Ada support for align.el <= 2.2
513This variable provides regular expressions on which to align different lines.
514See `align-mode-alist' for more information.")
515
516(defvar ada-align-modes
517 '((ada-declaration
518 (regexp . "[^:]\\(\\s-*\\):[^:]")
519 (valid . (lambda() (not (ada-in-comment-p))))
520 (modes . '(ada-mode)))
521 (ada-assignment
522 (regexp . "[^=]\\(\\s-+\\)=[^=]")
523 (valid . (lambda() (not (ada-in-comment-p))))
524 (modes . '(ada-mode)))
525 (ada-comment
526 (regexp . "\\(\\s-*\\)--")
527 (modes . '(ada-mode)))
528 (ada-use
529 (regexp . "\\(\\s-*\\)use\\s-")
530 (valid . (lambda() (not (ada-in-comment-p))))
531 (modes . '(ada-mode)))
532 )
533 "Ada support for align.el >= 2.8
534This variable defines several rules to use to align different lines.")
535
536(defconst ada-align-region-separate
537 (concat
538 "^\\s-*\\($\\|\\("
539 "begin\\|"
540 "declare\\|"
541 "else\\|"
542 "end\\|"
543 "exception\\|"
544 "for\\|"
545 "function\\|"
546 "generic\\|"
547 "if\\|"
548 "is\\|"
549 "procedure\\|"
550 "record\\|"
551 "return\\|"
552 "type\\|"
553 "when"
554 "\\)\\>\\)")
555 "see the variable `align-region-separate' for more information.")
556
7749c1a8
GM
557;;; ---- Below are the regexp used in this package for parsing
558
972579f9 559(defconst ada-83-keywords
7749c1a8
GM
560 (eval-when-compile
561 (concat "\\<" (regexp-opt ada-83-string-keywords t) "\\>"))
cadd3658 562 "Regular expression for looking at Ada83 keywords.")
972579f9 563
f139ce87 564(defconst ada-95-keywords
7749c1a8
GM
565 (eval-when-compile
566 (concat "\\<" (regexp-opt
567 (append
568 '("abstract" "aliased" "protected" "requeue"
569 "tagged" "until")
570 ada-83-string-keywords) t) "\\>"))
cadd3658 571 "Regular expression for looking at Ada95 keywords.")
972579f9 572
f139ce87 573(defvar ada-keywords ada-95-keywords
5e1cecee 574 "Regular expression for looking at Ada keywords.")
972579f9 575
7749c1a8
GM
576(defconst ada-ident-re
577 "\\(\\sw\\|[_.]\\)+"
276c1210 578 "Regexp matching Ada (qualified) identifiers.")
f139ce87 579
4607c7f4
SM
580;; "with" needs to be included in the regexp, so that we can insert new lines
581;; after the declaration of the parameter for a generic.
972579f9 582(defvar ada-procedure-start-regexp
4607c7f4
SM
583 (concat
584 "^[ \t]*\\(with[ \t]+\\)?\\(procedure\\|function\\|task\\)[ \t\n]+"
585
586 ;; subprogram name: operator ("[+/=*]")
587 "\\("
588 "\\(\"[^\"]+\"\\)"
589
590 ;; subprogram name: name
591 "\\|"
592 "\\(\\(\\sw\\|[_.]\\)+\\)"
593 "\\)")
972579f9
RS
594 "Regexp used to find Ada procedures/functions.")
595
596(defvar ada-package-start-regexp
597 "^[ \t]*\\(package\\)"
655880d2 598 "Regexp used to find Ada packages.")
972579f9
RS
599
600
601;;; ---- regexps for indentation functions
602
603(defvar ada-block-start-re
7749c1a8
GM
604 (eval-when-compile
605 (concat "\\<\\(" (regexp-opt '("begin" "declare" "else"
606 "exception" "generic" "loop" "or"
607 "private" "select" ))
608 "\\|\\(\\(limited\\|abstract\\|tagged\\)[ \t\n]+\\)*record\\)\\>"))
5e1cecee 609 "Regexp for keywords starting Ada blocks.")
972579f9
RS
610
611(defvar ada-end-stmt-re
7749c1a8
GM
612 (eval-when-compile
613 (concat "\\("
614 ";" "\\|"
615 "=>[ \t]*$" "\\|"
616 "^[ \t]*separate[ \t]*(\\(\\sw\\|[_.]\\)+)" "\\|"
4cc7e498
GM
617 "\\<" (regexp-opt '("begin" "declare" "is" "do" "else" "generic"
618 "loop" "private" "record" "select"
619 "then abort" "then") t) "\\>" "\\|"
7749c1a8
GM
620 "^[ \t]*" (regexp-opt '("function" "package" "procedure")
621 t) "\\>\\(\\sw\\|[ \t_.]\\)+\\<is\\>" "\\|"
622 "^[ \t]*exception\\>"
623 "\\)") )
972579f9 624 "Regexp of possible ends for a non-broken statement.
5e1cecee 625A new statement starts after these.")
972579f9 626
7749c1a8
GM
627(defvar ada-matching-start-re
628 (eval-when-compile
629 (concat "\\<"
630 (regexp-opt
631 '("end" "loop" "select" "begin" "case" "do"
632 "if" "task" "package" "record" "protected") t)
633 "\\>"))
655880d2 634 "Regexp used in ada-goto-matching-start.")
7749c1a8
GM
635
636(defvar ada-matching-decl-start-re
637 (eval-when-compile
638 (concat "\\<"
639 (regexp-opt
4cc7e498 640 '("is" "separate" "end" "declare" "if" "new" "begin" "generic" "when") t)
7749c1a8 641 "\\>"))
655880d2 642 "Regexp used in ada-goto-matching-decl-start.")
7749c1a8 643
972579f9
RS
644(defvar ada-loop-start-re
645 "\\<\\(for\\|while\\|loop\\)\\>"
646 "Regexp for the start of a loop.")
647
648(defvar ada-subprog-start-re
7749c1a8
GM
649 (eval-when-compile
650 (concat "\\<" (regexp-opt '("accept" "entry" "function" "package" "procedure"
651 "protected" "task") t) "\\>"))
972579f9
RS
652 "Regexp for the start of a subprogram.")
653
cadd3658 654(defvar ada-named-block-re
7749c1a8 655 "[ \t]*\\(\\sw\\|_\\)+[ \t]*:[^=]"
cadd3658
RS
656 "Regexp of the name of a block or loop.")
657
655880d2
GM
658(defvar ada-contextual-menu-on-identifier nil
659 "Set to true when the right mouse button was clicked on an identifier.")
660
4cc7e498
GM
661(defvar ada-contextual-menu-last-point nil
662 "Position of point just before displaying the menu.
663This is a list (point buffer).
664Since `ada-popup-menu' moves the point where the user clicked, the region
665is modified. Therefore no command from the menu knows what the user selected
666before displaying the contextual menu.
667To get the original region, restore the point to this position before
668calling `region-end' and `region-beginning'.
669Modify this variable if you want to restore the point to another position.")
670
f7a80909
JB
671(easy-menu-define ada-contextual-menu nil
672 "Menu to use when the user presses the right mouse button.
4cc7e498
GM
673The variable `ada-contextual-menu-on-identifier' will be set to t before
674displaying the menu if point was on an identifier."
f7a80909
JB
675 '("Ada"
676 ["Goto Declaration/Body" ada-point-and-xref
677 :included ada-contextual-menu-on-identifier]
678 ["Goto Body" ada-point-and-xref-body
679 :included ada-contextual-menu-on-identifier]
680 ["Goto Previous Reference" ada-xref-goto-previous-reference]
681 ["List References" ada-find-references
682 :included ada-contextual-menu-on-identifier]
683 ["List Local References" ada-find-local-references
684 :included ada-contextual-menu-on-identifier]
685 ["-" nil nil]
686 ["Other File" ff-find-other-file]
687 ["Goto Parent Unit" ada-goto-parent]))
7749c1a8 688
972579f9 689\f
7749c1a8
GM
690;;------------------------------------------------------------------
691;; Support for imenu (see imenu.el)
692;;------------------------------------------------------------------
693
4607c7f4
SM
694(defconst ada-imenu-comment-re "\\([ \t]*--.*\\)?")
695
4cc7e498 696(defconst ada-imenu-subprogram-menu-re
4607c7f4
SM
697 (concat "^[ \t]*\\(procedure\\|function\\)[ \t\n]+"
698 "\\(\\(\\sw\\|_\\)+\\)[ \t\n]*\\([ \t\n]\\|([^)]+)"
699 ada-imenu-comment-re
700 "\\)[ \t\n]*"
701 "\\(return[ \t\n]+\\(\\sw\\|[_.]\\)+[ \t\n]*\\)?is[ \t\n]"))
4cc7e498 702
74480345 703(defvar ada-imenu-generic-expression
7749c1a8 704 (list
4cc7e498 705 (list nil ada-imenu-subprogram-menu-re 2)
7749c1a8
GM
706 (list "*Specs*"
707 (concat
708 "^[ \t]*\\(procedure\\|function\\)[ \t\n]+\\(\\(\\sw\\|_\\)+\\)"
709 "\\("
4607c7f4
SM
710 "\\(" ada-imenu-comment-re "[ \t\n]+\\|[ \t\n]*([^)]+)"
711 ada-imenu-comment-re "\\)";; parameter list or simple space
7749c1a8
GM
712 "\\([ \t\n]*return[ \t\n]+\\(\\sw\\|[_.]\\)+[ \t\n]*\\)?"
713 "\\)?;") 2)
4607c7f4 714 '("*Tasks*" "^[ \t]*task[ \t]+\\(type[ \t]+\\)?\\(\\(body[ \t]+\\)?\\(\\sw\\|_\\)+\\)" 2)
7749c1a8 715 '("*Type Defs*" "^[ \t]*\\(sub\\)?type[ \t]+\\(\\(\\sw\\|_\\)+\\)" 2)
4607c7f4
SM
716 '("*Protected*"
717 "^[ \t]*protected[ \t]+\\(type[ \t]+\\)?\\(\\(body[ \t]+\\)?\\(\\sw\\|_\\)+\\)" 2)
7749c1a8 718 '("*Packages*" "^[ \t]*package[ \t]+\\(\\(body[ \t]+\\)?\\(\\sw\\|[_.]\\)+\\)" 1))
655880d2 719 "Imenu generic expression for Ada mode.
4607c7f4
SM
720See `imenu-generic-expression'. This variable will create several submenus for
721each type of entity that can be found in an Ada file.")
4cc7e498 722
74480345 723\f
7749c1a8 724;;------------------------------------------------------------
655880d2 725;; Support for compile.el
7749c1a8
GM
726;;------------------------------------------------------------
727
728(defun ada-compile-mouse-goto-error ()
4cc7e498 729 "Mouse interface for ada-compile-goto-error."
7749c1a8
GM
730 (interactive)
731 (mouse-set-point last-input-event)
732 (ada-compile-goto-error (point))
733 )
734
735(defun ada-compile-goto-error (pos)
655880d2
GM
736 "Replaces `compile-goto-error' from compile.el.
737If POS is on a file and line location, go to this position. It adds to
738compile.el the capacity to go to a reference in an error message.
7749c1a8 739For instance, on this line:
655880d2
GM
740 foo.adb:61:11: [...] in call to size declared at foo.ads:11
741both file locations can be clicked on and jumped to."
7749c1a8
GM
742 (interactive "d")
743 (goto-char pos)
744
745 (skip-chars-backward "-a-zA-Z0-9_:./\\")
746 (cond
747 ;; special case: looking at a filename:line not at the beginning of a line
748 ((and (not (bolp))
4cc7e498
GM
749 (looking-at
750 "\\([-_.a-zA-Z0-9]+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?"))
751 (let ((line (match-string 2))
f7a80909 752 file
7749c1a8
GM
753 (error-pos (point-marker))
754 source)
755 (save-excursion
756 (save-restriction
757 (widen)
4cc7e498 758 ;; Use funcall so as to prevent byte-compiler warnings
f7a80909
JB
759 ;; `ada-find-file' is not defined if ada-xref wasn't loaded. But
760 ;; if we can find it, we should use it instead of
761 ;; `compilation-find-file', since the latter doesn't know anything
762 ;; about source path.
763
764 (if (functionp 'ada-find-file)
765 (setq file (funcall (symbol-function 'ada-find-file)
766 (match-string 1)))
767 (setq file (funcall (symbol-function 'compilation-find-file)
768 (point-marker) (match-string 1)
769 "./")))
770 (set-buffer file)
771
7749c1a8
GM
772 (if (stringp line)
773 (goto-line (string-to-number line)))
36144b26 774 (setq source (point-marker))))
4cc7e498
GM
775 (funcall (symbol-function 'compilation-goto-locus)
776 (cons source error-pos))
7749c1a8
GM
777 ))
778
779 ;; otherwise, default behavior
780 (t
4cc7e498 781 (funcall (symbol-function 'compile-goto-error)))
7749c1a8
GM
782 )
783 (recenter))
784
4cc7e498 785\f
655880d2
GM
786;;-------------------------------------------------------------------------
787;; Grammar related function
788;; The functions below work with the syntax class of the characters in an Ada
789;; buffer. Two syntax tables are created, depending on whether we want '_'
790;; to be considered as part of a word or not.
791;; Some characters may have multiple meanings depending on the context:
792;; - ' is either the beginning of a constant character or an attribute
793;; - # is either part of a based litteral or a gnatprep statement.
794;; - " starts a string, but not if inside a constant character.
795;; - ( and ) should be ignored if inside a constant character.
796;; Thus their syntax property is changed automatically, and we can still use
797;; the standard Emacs functions for sexp (see `ada-in-string-p')
798;;
799;; On Emacs, this is done through the `syntax-table' text property. The
800;; modification is done automatically each time the user as typed a new
801;; character. This is already done in `font-lock-mode' (in
802;; `font-lock-syntactic-keywords', so we take advantage of the existing
803;; mechanism. If font-lock-mode is not activated, we do it by hand in
804;; `ada-after-change-function', thanks to `ada-deactivate-properties' and
805;; `ada-initialize-properties'.
806;;
807;; on XEmacs, the `syntax-table' property does not exist and we have to use a
808;; slow advice to `parse-partial-sexp' to do the same thing.
809;; When executing parse-partial-sexp, we simply modify the strings before and
810;; after, so that the special constants '"', '(' and ')' do not interact
811;; with parse-partial-sexp.
812;; Note: this code is slow and needs to be rewritten as soon as something
813;; better is available on XEmacs.
814;;-------------------------------------------------------------------------
972579f9
RS
815
816(defun ada-create-syntax-table ()
655880d2
GM
817 "Create the two syntax tables use in the Ada mode.
818The standard table declares `_' as a symbol constituent, the second one
819declares it as a word constituent."
7749c1a8 820 (interactive)
36144b26 821 (setq ada-mode-syntax-table (make-syntax-table))
972579f9
RS
822 (set-syntax-table ada-mode-syntax-table)
823
cadd3658
RS
824 ;; define string brackets (`%' is alternative string bracket, but
825 ;; almost never used as such and throws font-lock and indentation
826 ;; off the track.)
827 (modify-syntax-entry ?% "$" ada-mode-syntax-table)
972579f9
RS
828 (modify-syntax-entry ?\" "\"" ada-mode-syntax-table)
829
972579f9
RS
830 (modify-syntax-entry ?: "." ada-mode-syntax-table)
831 (modify-syntax-entry ?\; "." ada-mode-syntax-table)
832 (modify-syntax-entry ?& "." ada-mode-syntax-table)
833 (modify-syntax-entry ?\| "." ada-mode-syntax-table)
834 (modify-syntax-entry ?+ "." ada-mode-syntax-table)
835 (modify-syntax-entry ?* "." ada-mode-syntax-table)
836 (modify-syntax-entry ?/ "." ada-mode-syntax-table)
837 (modify-syntax-entry ?= "." ada-mode-syntax-table)
838 (modify-syntax-entry ?< "." ada-mode-syntax-table)
839 (modify-syntax-entry ?> "." ada-mode-syntax-table)
840 (modify-syntax-entry ?$ "." ada-mode-syntax-table)
841 (modify-syntax-entry ?\[ "." ada-mode-syntax-table)
842 (modify-syntax-entry ?\] "." ada-mode-syntax-table)
843 (modify-syntax-entry ?\{ "." ada-mode-syntax-table)
844 (modify-syntax-entry ?\} "." ada-mode-syntax-table)
845 (modify-syntax-entry ?. "." ada-mode-syntax-table)
846 (modify-syntax-entry ?\\ "." ada-mode-syntax-table)
847 (modify-syntax-entry ?\' "." ada-mode-syntax-table)
848
849 ;; a single hyphen is punctuation, but a double hyphen starts a comment
850 (modify-syntax-entry ?- ". 12" ada-mode-syntax-table)
851
655880d2
GM
852 ;; See the comment above on grammar related function for the special
853 ;; setup for '#'.
6f9a2614 854 (if (featurep 'xemacs)
7749c1a8
GM
855 (modify-syntax-entry ?# "<" ada-mode-syntax-table)
856 (modify-syntax-entry ?# "$" ada-mode-syntax-table))
857
972579f9
RS
858 ;; and \f and \n end a comment
859 (modify-syntax-entry ?\f "> " ada-mode-syntax-table)
860 (modify-syntax-entry ?\n "> " ada-mode-syntax-table)
861
cadd3658 862 ;; define what belongs in Ada symbols
972579f9
RS
863 (modify-syntax-entry ?_ "_" ada-mode-syntax-table)
864
865 ;; define parentheses to match
866 (modify-syntax-entry ?\( "()" ada-mode-syntax-table)
867 (modify-syntax-entry ?\) ")(" ada-mode-syntax-table)
f139ce87 868
36144b26 869 (setq ada-mode-symbol-syntax-table (copy-syntax-table ada-mode-syntax-table))
f139ce87 870 (modify-syntax-entry ?_ "w" ada-mode-symbol-syntax-table)
972579f9
RS
871 )
872
655880d2
GM
873;; Support of special characters in XEmacs (see the comments at the beginning
874;; of the section on Grammar related functions).
7749c1a8 875
6f9a2614 876(if (featurep 'xemacs)
7749c1a8 877 (defadvice parse-partial-sexp (around parse-partial-sexp-protect-constants)
655880d2 878 "Handles special character constants and gnatprep statements."
7749c1a8
GM
879 (let (change)
880 (if (< to from)
881 (let ((tmp from))
882 (setq from to to tmp)))
883 (save-excursion
884 (goto-char from)
885 (while (re-search-forward "'\\([(\")#]\\)'" to t)
36144b26 886 (setq change (cons (list (match-beginning 1)
7749c1a8
GM
887 1
888 (match-string 1))
889 change))
890 (replace-match "'A'"))
891 (goto-char from)
892 (while (re-search-forward "\\(#[0-9a-fA-F]*#\\)" to t)
36144b26 893 (setq change (cons (list (match-beginning 1)
7749c1a8
GM
894 (length (match-string 1))
895 (match-string 1))
896 change))
4cc7e498 897 (replace-match (make-string (length (match-string 1)) ?@))))
7749c1a8
GM
898 ad-do-it
899 (save-excursion
900 (while change
901 (goto-char (caar change))
902 (delete-char (cadar change))
903 (insert (caddar change))
36144b26 904 (setq change (cdr change)))))))
7749c1a8 905
7749c1a8 906(defun ada-deactivate-properties ()
655880d2
GM
907 "Deactivate ada-mode's properties handling.
908This would be a duplicate of font-lock if both are used at the same time."
7749c1a8
GM
909 (remove-hook 'after-change-functions 'ada-after-change-function t))
910
911(defun ada-initialize-properties ()
912 "Initialize some special text properties in the whole buffer.
655880d2
GM
913In particular, character constants are said to be strings, #...# are treated
914as numbers instead of gnatprep comments."
7749c1a8
GM
915 (save-excursion
916 (save-restriction
917 (widen)
918 (goto-char (point-min))
919 (while (re-search-forward "'.'" nil t)
920 (add-text-properties (match-beginning 0) (match-end 0)
921 '(syntax-table ("'" . ?\"))))
922 (goto-char (point-min))
923 (while (re-search-forward "^[ \t]*#" nil t)
924 (add-text-properties (match-beginning 0) (match-end 0)
925 '(syntax-table (11 . 10))))
926 (set-buffer-modified-p nil)
927
928 ;; Setting this only if font-lock is not set won't work
929 ;; if the user activates or deactivates font-lock-mode,
930 ;; but will make things faster most of the time
7749c1a8
GM
931 (add-hook 'after-change-functions 'ada-after-change-function nil t)
932 )))
933
934(defun ada-after-change-function (beg end old-len)
655880d2
GM
935 "Called when the region between BEG and END was changed in the buffer.
936OLD-LEN indicates what the length of the replaced text was."
7749c1a8
GM
937 (let ((inhibit-point-motion-hooks t)
938 (eol (point)))
939 (save-excursion
940 (save-match-data
941 (beginning-of-line)
942 (remove-text-properties (point) eol '(syntax-table nil))
943 (while (re-search-forward "'.'" eol t)
944 (add-text-properties (match-beginning 0) (match-end 0)
945 '(syntax-table ("'" . ?\"))))
946 (beginning-of-line)
947 (if (looking-at "^[ \t]*#")
948 (add-text-properties (match-beginning 0) (match-end 0)
f7a80909 949 '(syntax-table (11 . 10))))))))
7749c1a8 950
4cc7e498
GM
951;;------------------------------------------------------------------
952;; Testing the grammatical context
953;;------------------------------------------------------------------
954
955(defsubst ada-in-comment-p (&optional parse-result)
956 "Returns t if inside a comment."
957 (nth 4 (or parse-result
958 (parse-partial-sexp
f7a2f2c6 959 (line-beginning-position) (point)))))
4cc7e498
GM
960
961(defsubst ada-in-string-p (&optional parse-result)
962 "Returns t if point is inside a string.
963If parse-result is non-nil, use is instead of calling parse-partial-sexp."
964 (nth 3 (or parse-result
965 (parse-partial-sexp
f7a2f2c6 966 (line-beginning-position) (point)))))
4cc7e498
GM
967
968(defsubst ada-in-string-or-comment-p (&optional parse-result)
969 "Returns t if inside a comment or string."
36144b26 970 (setq parse-result (or parse-result
4cc7e498 971 (parse-partial-sexp
f7a2f2c6 972 (line-beginning-position) (point))))
4cc7e498
GM
973 (or (ada-in-string-p parse-result) (ada-in-comment-p parse-result)))
974
7749c1a8 975
655880d2
GM
976;;------------------------------------------------------------------
977;; Contextual menus
4cc7e498
GM
978;; The Ada-mode comes with contextual menus, bound by default to the right
979;; mouse button.
655880d2
GM
980;; Add items to this menu by modifying `ada-contextual-menu'. Note that the
981;; variable `ada-contextual-menu-on-identifier' is set automatically to t
982;; if the mouse button was pressed on an identifier.
983;;------------------------------------------------------------------
7749c1a8 984
4cc7e498
GM
985(defun ada-call-from-contextual-menu (function)
986 "Execute FUNCTION when called from the contextual menu.
987It forces Emacs to change the cursor position."
988 (interactive)
989 (funcall function)
990 (setq ada-contextual-menu-last-point
991 (list (point) (current-buffer))))
992
7749c1a8 993(defun ada-popup-menu (position)
655880d2 994 "Pops up a contextual menu, depending on where the user clicked.
4cc7e498
GM
995POSITION is the location the mouse was clicked on.
996Sets `ada-contextual-menu-last-point' to the current position before
997displaying the menu. When a function from the menu is called, the point is
998where the mouse button was clicked."
7749c1a8 999 (interactive "e")
4cc7e498
GM
1000
1001 ;; declare this as a local variable, so that the function called
1002 ;; in the contextual menu does not hide the region in
1003 ;; transient-mark-mode.
1004 (let ((deactivate-mark nil))
36144b26 1005 (setq ada-contextual-menu-last-point
4cc7e498 1006 (list (point) (current-buffer)))
655880d2 1007 (mouse-set-point last-input-event)
4cc7e498 1008
655880d2 1009 (setq ada-contextual-menu-on-identifier
4cc7e498
GM
1010 (and (char-after)
1011 (or (= (char-syntax (char-after)) ?w)
1012 (= (char-after) ?_))
1013 (not (ada-in-string-or-comment-p))
1014 (save-excursion (skip-syntax-forward "w")
1015 (not (ada-after-keyword-p)))
1016 ))
f7a80909
JB
1017 (if (fboundp 'popup-menu)
1018 (funcall (symbol-function 'popup-menu) ada-contextual-menu)
1019 (let (choice)
1020 (setq choice (x-popup-menu position ada-contextual-menu))
1021 (if choice
1022 (funcall (lookup-key ada-contextual-menu (vector (car choice)))))))
1023
4cc7e498
GM
1024 (set-buffer (cadr ada-contextual-menu-last-point))
1025 (goto-char (car ada-contextual-menu-last-point))
1026 ))
1027
7749c1a8 1028
655880d2
GM
1029;;------------------------------------------------------------------
1030;; Misc functions
1031;;------------------------------------------------------------------
7749c1a8
GM
1032
1033;;;###autoload
1034(defun ada-add-extensions (spec body)
655880d2
GM
1035 "Define SPEC and BODY as being valid extensions for Ada files.
1036Going from body to spec with `ff-find-other-file' used these
1037extensions.
1038SPEC and BODY are two regular expressions that must match against the file
1039name"
7749c1a8 1040 (let* ((reg (concat (regexp-quote body) "$"))
4cc7e498 1041 (tmp (assoc reg ada-other-file-alist)))
7749c1a8 1042 (if tmp
4cc7e498 1043 (setcdr tmp (list (cons spec (cadr tmp))))
7749c1a8 1044 (add-to-list 'ada-other-file-alist (list reg (list spec)))))
4cc7e498 1045
7749c1a8 1046 (let* ((reg (concat (regexp-quote spec) "$"))
4cc7e498 1047 (tmp (assoc reg ada-other-file-alist)))
7749c1a8 1048 (if tmp
4cc7e498 1049 (setcdr tmp (list (cons body (cadr tmp))))
7749c1a8
GM
1050 (add-to-list 'ada-other-file-alist (list reg (list body)))))
1051
1997815f
AS
1052 (add-to-list 'auto-mode-alist
1053 (cons (concat (regexp-quote spec) "\\'") 'ada-mode))
1054 (add-to-list 'auto-mode-alist
1055 (cons (concat (regexp-quote body) "\\'") 'ada-mode))
7749c1a8
GM
1056
1057 (add-to-list 'ada-spec-suffixes spec)
1058 (add-to-list 'ada-body-suffixes body)
1059
1060 ;; Support for speedbar (Specifies that we want to see these files in
1061 ;; speedbar)
f7a80909 1062 (if (fboundp 'speedbar-add-supported-extension)
7749c1a8 1063 (progn
4cc7e498
GM
1064 (funcall (symbol-function 'speedbar-add-supported-extension)
1065 spec)
1066 (funcall (symbol-function 'speedbar-add-supported-extension)
1067 body)))
7749c1a8
GM
1068 )
1069
1070
a681b2a1 1071;;;###autoload
972579f9 1072(defun ada-mode ()
cadd3658 1073 "Ada mode is the major mode for editing Ada code.
972579f9
RS
1074
1075Bindings are as follows: (Note: 'LFD' is control-j.)
4607c7f4 1076\\{ada-mode-map}
972579f9
RS
1077
1078 Indent line '\\[ada-tab]'
1079 Indent line, insert newline and indent the new line. '\\[newline-and-indent]'
1080
1081 Re-format the parameter-list point is in '\\[ada-format-paramlist]'
1082 Indent all lines in region '\\[ada-indent-region]'
972579f9
RS
1083
1084 Adjust case of identifiers and keywords in region '\\[ada-adjust-case-region]'
1085 Adjust case of identifiers and keywords in buffer '\\[ada-adjust-case-buffer]'
1086
7749c1a8 1087 Fill comment paragraph, justify and append postfix '\\[fill-paragraph]'
972579f9 1088
cadd3658 1089 Next func/proc/task '\\[ada-next-procedure]' Previous func/proc/task '\\[ada-previous-procedure]'
f139ce87 1090 Next package '\\[ada-next-package]' Previous package '\\[ada-previous-package]'
972579f9
RS
1091
1092 Goto matching start of current 'end ...;' '\\[ada-move-to-start]'
1093 Goto end of current block '\\[ada-move-to-end]'
1094
1095Comments are handled using standard GNU Emacs conventions, including:
1096 Start a comment '\\[indent-for-comment]'
1097 Comment region '\\[comment-region]'
1098 Uncomment region '\\[ada-uncomment-region]'
1099 Continue comment on next line '\\[indent-new-comment-line]'
1100
1101If you use imenu.el:
1102 Display index-menu of functions & procedures '\\[imenu]'
1103
1104If you use find-file.el:
1105 Switch to other file (Body <-> Spec) '\\[ff-find-other-file]'
1106 or '\\[ff-mouse-find-other-file]
1107 Switch to other file in other window '\\[ada-ff-other-window]'
1108 or '\\[ff-mouse-find-other-file-other-window]
7749c1a8 1109 If you use this function in a spec and no body is available, it gets created with body stubs.
972579f9
RS
1110
1111If you use ada-xref.el:
1112 Goto declaration: '\\[ada-point-and-xref]' on the identifier
1113 or '\\[ada-goto-declaration]' with point on the identifier
4cc7e498 1114 Complete identifier: '\\[ada-complete-identifier]'."
972579f9
RS
1115
1116 (interactive)
1117 (kill-all-local-variables)
1118
64a0475c 1119 (set (make-local-variable 'require-final-newline) mode-require-final-newline)
972579f9 1120
7749c1a8
GM
1121 ;; Set the paragraph delimiters so that one can select a whole block
1122 ;; simply with M-h
1123 (set (make-local-variable 'paragraph-start) "[ \t\n\f]*$")
1124 (set (make-local-variable 'paragraph-separate) "[ \t\n\f]*$")
972579f9
RS
1125
1126 ;; comment end must be set because it may hold a wrong value if
1127 ;; this buffer had been in another mode before. RE
7749c1a8
GM
1128 (set (make-local-variable 'comment-end) "")
1129
1130 ;; used by autofill and indent-new-comment-line
1131 (set (make-local-variable 'comment-start-skip) "---*[ \t]*")
1132
1133 ;; used by autofill to break a comment line and continue it on another line.
1134 ;; The reason we need this one is that the default behavior does not work
1135 ;; correctly with the definition of paragraph-start above when the comment
655880d2 1136 ;; is right after a multi-line subprogram declaration (the comments are
7749c1a8
GM
1137 ;; aligned under the latest parameter, not under the declaration start).
1138 (set (make-local-variable 'comment-line-break-function)
1139 (lambda (&optional soft) (let ((fill-prefix nil))
4cc7e498
GM
1140 (indent-new-comment-line soft))))
1141
7749c1a8
GM
1142 (set (make-local-variable 'indent-line-function)
1143 'ada-indent-current-function)
1144
1145 (set (make-local-variable 'comment-column) 40)
1146
1147 ;; Emacs 20.3 defines a comment-padding to insert spaces between
1148 ;; the comment and the text. We do not want any, this is already
1149 ;; included in comment-start
6f9a2614 1150 (unless (featurep 'xemacs)
4607c7f4
SM
1151 (progn
1152 (if (ada-check-emacs-version 20 3)
1153 (progn
1154 (set (make-local-variable 'parse-sexp-ignore-comments) t)
1155 (set (make-local-variable 'comment-padding) 0)))
1156 (set (make-local-variable 'parse-sexp-lookup-properties) t)
1157 ))
7749c1a8 1158
4607c7f4
SM
1159 (set 'case-fold-search t)
1160 (if (boundp 'imenu-case-fold-search)
1161 (set 'imenu-case-fold-search t))
7749c1a8
GM
1162
1163 (set (make-local-variable 'fill-paragraph-function)
1164 'ada-fill-comment-paragraph)
1165
1166 (set (make-local-variable 'imenu-generic-expression)
1167 ada-imenu-generic-expression)
1168
1169 ;; Support for compile.el
1170 ;; We just substitute our own functions to go to the error.
1171 (add-hook 'compilation-mode-hook
db72f2a6 1172 (lambda()
5dab0769
SM
1173 (set (make-local-variable 'compile-auto-highlight) 40)
1174 ;; FIXME: This has global impact! -stef
4cc7e498
GM
1175 (define-key compilation-minor-mode-map [mouse-2]
1176 'ada-compile-mouse-goto-error)
1177 (define-key compilation-minor-mode-map "\C-c\C-c"
1178 'ada-compile-goto-error)
1179 (define-key compilation-minor-mode-map "\C-m"
5dab0769 1180 'ada-compile-goto-error)))
7749c1a8 1181
4607c7f4
SM
1182 ;; font-lock support :
1183 ;; We need to set some properties for XEmacs, and define some variables
1184 ;; for Emacs
1185
6f9a2614 1186 (if (featurep 'xemacs)
4607c7f4
SM
1187 ;; XEmacs
1188 (put 'ada-mode 'font-lock-defaults
1189 '(ada-font-lock-keywords
1190 nil t ((?\_ . "w") (?# . ".")) beginning-of-line))
1191 ;; Emacs
1192 (set (make-local-variable 'font-lock-defaults)
1193 '(ada-font-lock-keywords
1194 nil t
1195 ((?\_ . "w") (?# . "."))
1196 beginning-of-line
1197 (font-lock-syntactic-keywords . ada-font-lock-syntactic-keywords)))
1198 )
4cc7e498 1199
7749c1a8 1200 ;; Set up support for find-file.el.
5dab0769 1201 (set (make-local-variable 'ff-other-file-alist)
7749c1a8 1202 'ada-other-file-alist)
5dab0769 1203 (set (make-local-variable 'ff-search-directories)
6f9a2614
JB
1204 'ada-search-directories-internal)
1205 (setq ff-post-load-hook 'ada-set-point-accordingly
1206 ff-file-created-hook 'ada-make-body)
1207 (add-hook 'ff-pre-load-hook 'ada-which-function-are-we-in)
4cc7e498 1208
7749c1a8
GM
1209 ;; Some special constructs for find-file.el
1210 ;; We do not need to add the construction for 'with', which is in the
1211 ;; standard find-file.el
7749c1a8 1212 (make-local-variable 'ff-special-constructs)
4cc7e498
GM
1213
1214 ;; Go to the parent package :
7749c1a8 1215 (add-to-list 'ff-special-constructs
4cc7e498
GM
1216 (cons (eval-when-compile
1217 (concat "^\\(private[ \t]\\)?[ \t]*package[ \t]+"
1218 "\\(body[ \t]+\\)?"
1219 "\\(\\(\\sw\\|[_.]\\)+\\)\\.\\(\\sw\\|_\\)+[ \t\n]+is"))
1220 (lambda ()
6f9a2614
JB
1221 (if (fboundp 'ff-get-file)
1222 (if (boundp 'fname)
1223 (set 'fname (ff-get-file
1224 ada-search-directories-internal
1225 (ada-make-filename-from-adaname
1226 (match-string 3))
1227 ada-spec-suffixes)))))))
7749c1a8
GM
1228 ;; Another special construct for find-file.el : when in a separate clause,
1229 ;; go to the correct package.
1230 (add-to-list 'ff-special-constructs
4cc7e498
GM
1231 (cons "^separate[ \t\n]*(\\(\\(\\sw\\|[_.]\\)+\\))"
1232 (lambda ()
6f9a2614
JB
1233 (if (fboundp 'ff-get-file)
1234 (if (boundp 'fname)
1235 (setq fname (ff-get-file
1236 ada-search-directories-internal
1237 (ada-make-filename-from-adaname
1238 (match-string 1))
1239 ada-spec-suffixes)))))))
1240
7749c1a8
GM
1241 ;; Another special construct, that redefines the one in find-file.el. The
1242 ;; old one can handle only one possible type of extension for Ada files
4cc7e498
GM
1243 ;; remove from the list the standard "with..." that is put by find-file.el,
1244 ;; since it uses the old ada-spec-suffix variable
1245 ;; This one needs to replace the standard one defined in find-file.el (with
1246 ;; Emacs <= 20.4), since that one uses the old variable ada-spec-suffix
1247 (let ((old-construct
1248 (assoc "^with[ \t]+\\([a-zA-Z0-9_\\.]+\\)" ff-special-constructs))
1249 (new-cdr
1250 (lambda ()
6f9a2614
JB
1251 (if (fboundp 'ff-get-file)
1252 (if (boundp 'fname)
1253 (set 'fname (ff-get-file
1254 ada-search-directories-internal
1255 (ada-make-filename-from-adaname
1256 (match-string 1))
1257 ada-spec-suffixes)))))))
4cc7e498
GM
1258 (if old-construct
1259 (setcdr old-construct new-cdr)
1260 (add-to-list 'ff-special-constructs
1261 (cons "^with[ \t]+\\([a-zA-Z0-9_\\.]+\\)"
1262 new-cdr))))
1263
7749c1a8
GM
1264 ;; Support for outline-minor-mode
1265 (set (make-local-variable 'outline-regexp)
4cc7e498 1266 "\\([ \t]*\\(procedure\\|function\\|package\\|if\\|while\\|for\\|declare\\|case\\|end\\|begin\\|loop\\)\\|--\\)")
7749c1a8
GM
1267 (set (make-local-variable 'outline-level) 'ada-outline-level)
1268
1269 ;; Support for imenu : We want a sorted index
36144b26 1270 (setq imenu-sort-function 'imenu--sort-by-name)
7749c1a8 1271
4607c7f4
SM
1272 ;; Support for ispell : Check only comments
1273 (set (make-local-variable 'ispell-check-comments) 'exclusive)
1274
1275 ;; Support for align.el <= 2.2, if present
1276 ;; align.el is distributed with Emacs 21, but not with earlier versions.
1277 (if (boundp 'align-mode-alist)
1278 (add-to-list 'align-mode-alist '(ada-mode . ada-align-list)))
1279
1280 ;; Support for align.el >= 2.8, if present
1281 (if (boundp 'align-dq-string-modes)
1282 (progn
1283 (add-to-list 'align-dq-string-modes 'ada-mode)
1284 (add-to-list 'align-open-comment-modes 'ada-mode)
4607c7f4
SM
1285 (set (make-variable-buffer-local 'align-region-separate)
1286 ada-align-region-separate)
4607c7f4 1287
80d50f88
SM
1288 ;; Exclude comments alone on line from alignment.
1289 (add-to-list 'align-exclude-rules-list
1290 '(ada-solo-comment
1291 (regexp . "^\\(\\s-*\\)--")
1292 (modes . '(ada-mode))))
1293 (add-to-list 'align-exclude-rules-list
1294 '(ada-solo-use
1295 (regexp . "^\\(\\s-*\\)\\<use\\>")
1296 (modes . '(ada-mode))))
1297
1298 (setq ada-align-modes nil)
a1506d29 1299
80d50f88
SM
1300 (add-to-list 'ada-align-modes
1301 '(ada-declaration-assign
1302 (regexp . "[^:]\\(\\s-*\\):[^:]")
1303 (valid . (lambda() (not (ada-in-comment-p))))
1304 (repeat . t)
1305 (modes . '(ada-mode))))
1306 (add-to-list 'ada-align-modes
1307 '(ada-associate
1308 (regexp . "[^=]\\(\\s-*\\)=>")
1309 (valid . (lambda() (not (ada-in-comment-p))))
1310 (modes . '(ada-mode))))
1311 (add-to-list 'ada-align-modes
1312 '(ada-comment
1313 (regexp . "\\(\\s-*\\)--")
1314 (modes . '(ada-mode))))
1315 (add-to-list 'ada-align-modes
1316 '(ada-use
1317 (regexp . "\\(\\s-*\\)\\<use\\s-")
1318 (valid . (lambda() (not (ada-in-comment-p))))
1319 (modes . '(ada-mode))))
1320 (add-to-list 'ada-align-modes
1321 '(ada-at
1322 (regexp . "\\(\\s-+\\)at\\>")
1323 (modes . '(ada-mode))))
4cc7e498 1324
a1506d29 1325
80d50f88
SM
1326 (setq align-mode-rules-list ada-align-modes)
1327 ))
a1506d29 1328
7749c1a8
GM
1329 ;; Set up the contextual menu
1330 (if ada-popup-key
1331 (define-key ada-mode-map ada-popup-key 'ada-popup-menu))
1332
4cc7e498
GM
1333 ;; Support for Abbreviations (the user still need to "M-x abbrev-mode"
1334 (define-abbrev-table 'ada-mode-abbrev-table ())
36144b26 1335 (setq local-abbrev-table ada-mode-abbrev-table)
4cc7e498 1336
80d50f88
SM
1337 ;; Support for which-function mode
1338 ;; which-function-mode does not work with nested subprograms, since it is
1339 ;; based only on the regexps generated by imenu, and thus can only detect the
1340 ;; beginning of subprograms, not the end.
1341 ;; Fix is: redefine a new function ada-which-function, and call it when the
1342 ;; major-mode is ada-mode.
a1506d29 1343
2389f143
RS
1344 (make-local-variable 'which-func-functions)
1345 (setq which-func-functions '(ada-which-function))
80d50f88 1346
7749c1a8 1347 ;; Support for indent-new-comment-line (Especially for XEmacs)
36144b26 1348 (setq comment-multi-line nil)
7749c1a8 1349
4607c7f4
SM
1350 (setq major-mode 'ada-mode
1351 mode-name "Ada")
972579f9 1352
972579f9
RS
1353 (use-local-map ada-mode-map)
1354
5dab0769 1355 (easy-menu-add ada-mode-menu ada-mode-map)
4cc7e498 1356
7749c1a8 1357 (set-syntax-table ada-mode-syntax-table)
972579f9
RS
1358
1359 (if ada-clean-buffer-before-saving
1360 (progn
7749c1a8 1361 ;; remove all spaces at the end of lines in the whole buffer.
80d50f88 1362 (add-hook 'local-write-file-hooks 'delete-trailing-whitespace)
7749c1a8
GM
1363 ;; convert all tabs to the correct number of spaces.
1364 (add-hook 'local-write-file-hooks
db72f2a6 1365 (lambda () (untabify (point-min) (point-max))))))
972579f9 1366
4d9db685
RS
1367 (set (make-local-variable 'skeleton-further-elements)
1368 '((< '(backward-delete-char-untabify
1369 (min ada-indent (current-column))))))
1370 (add-hook 'skeleton-end-hook 'ada-adjust-case-skeleton nil t)
1371
9a969196 1372 (run-mode-hooks 'ada-mode-hook)
972579f9 1373
4607c7f4
SM
1374 ;; To be run after the hook, in case the user modified
1375 ;; ada-fill-comment-prefix
1376 (make-local-variable 'comment-start)
1377 (if ada-fill-comment-prefix
1378 (set 'comment-start ada-fill-comment-prefix)
1379 (set 'comment-start "-- "))
a1506d29 1380
7749c1a8
GM
1381 ;; Run this after the hook to give the users a chance to activate
1382 ;; font-lock-mode
972579f9 1383
6f9a2614 1384 (unless (featurep 'xemacs)
4607c7f4
SM
1385 (progn
1386 (ada-initialize-properties)
4607c7f4 1387 (add-hook 'font-lock-mode-hook 'ada-deactivate-properties nil t)))
972579f9
RS
1388
1389 ;; the following has to be done after running the ada-mode-hook
1390 ;; because users might want to set the values of these variable
1391 ;; inside the hook (MH)
1392
1393 (cond ((eq ada-language-version 'ada83)
36144b26 1394 (setq ada-keywords ada-83-keywords))
f139ce87 1395 ((eq ada-language-version 'ada95)
36144b26 1396 (setq ada-keywords ada-95-keywords)))
972579f9
RS
1397
1398 (if ada-auto-case
1399 (ada-activate-keys-for-case)))
1400
4d9db685
RS
1401(defun ada-adjust-case-skeleton ()
1402 "Adjust the case of the text inserted by a skeleton."
1403 (save-excursion
1404 (let ((aa-end (point)))
1405 (ada-adjust-case-region
1406 (progn (goto-char (symbol-value 'beg)) (forward-word -1) (point))
1407 (goto-char aa-end)))))
4607c7f4
SM
1408
1409;; transient-mark-mode and mark-active are not defined in XEmacs
1410(defun ada-region-selected ()
1411 "t if a region has been selected by the user and is still active."
6f9a2614
JB
1412 (or (and (featurep 'xemacs) (funcall (symbol-function 'region-active-p)))
1413 (and (not (featurep 'xemacs))
4607c7f4
SM
1414 (symbol-value 'transient-mark-mode)
1415 (symbol-value 'mark-active))))
1416
972579f9 1417\f
655880d2
GM
1418;;-----------------------------------------------------------------
1419;; auto-casing
1420;; Since Ada is case-insensitive, the Ada-mode provides an extensive set of
1421;; functions to auto-case identifiers, keywords, ...
1422;; The basic rules for autocasing are defined through the variables
1423;; `ada-case-attribute', `ada-case-keyword' and `ada-case-identifier'. These
1424;; are references to the functions that will do the actual casing.
1425;;
1426;; However, in most cases, the user will want to define some exceptions to
1427;; these casing rules. This is done through a list of files, that contain
1428;; one word per line. These files are stored in `ada-case-exception-file'.
4cc7e498 1429;; For backward compatibility, this variable can also be a string.
655880d2 1430;;-----------------------------------------------------------------
cadd3658 1431
4607c7f4
SM
1432(defun ada-save-exceptions-to-file (file-name)
1433 "Save the exception lists `ada-case-exception' and
1434`ada-case-exception-substring' to the file FILE-NAME."
a1506d29 1435
4607c7f4
SM
1436 ;; Save the list in the file
1437 (find-file (expand-file-name file-name))
1438 (erase-buffer)
1439 (mapcar (lambda (x) (insert (car x) "\n"))
1440 (sort (copy-sequence ada-case-exception)
1441 (lambda(a b) (string< (car a) (car b)))))
1442 (mapcar (lambda (x) (insert "*" (car x) "\n"))
1443 (sort (copy-sequence ada-case-exception-substring)
1444 (lambda(a b) (string< (car a) (car b)))))
1445 (save-buffer)
1446 (kill-buffer nil)
1447 )
a1506d29 1448
7749c1a8 1449(defun ada-create-case-exception (&optional word)
655880d2
GM
1450 "Defines WORD as an exception for the casing system.
1451If WORD is not given, then the current word in the buffer is used instead.
1452The new words is added to the first file in `ada-case-exception-file'.
1453The standard casing rules will no longer apply to this word."
972579f9 1454 (interactive)
7749c1a8 1455 (let ((previous-syntax-table (syntax-table))
4cc7e498
GM
1456 file-name
1457 )
1458
1459 (cond ((stringp ada-case-exception-file)
36144b26 1460 (setq file-name ada-case-exception-file))
4cc7e498 1461 ((listp ada-case-exception-file)
36144b26 1462 (setq file-name (car ada-case-exception-file)))
4cc7e498 1463 (t
4607c7f4
SM
1464 (error (concat "No exception file specified. "
1465 "See variable ada-case-exception-file."))))
4cc7e498 1466
7749c1a8
GM
1467 (set-syntax-table ada-mode-symbol-syntax-table)
1468 (unless word
1469 (save-excursion
4cc7e498 1470 (skip-syntax-backward "w")
36144b26 1471 (setq word (buffer-substring-no-properties
4cc7e498 1472 (point) (save-excursion (forward-word 1) (point))))))
4607c7f4 1473 (set-syntax-table previous-syntax-table)
7749c1a8
GM
1474
1475 ;; Reread the exceptions file, in case it was modified by some other,
4607c7f4 1476 (ada-case-read-exceptions-from-file file-name)
4cc7e498 1477
7749c1a8
GM
1478 ;; If the word is already in the list, even with a different casing
1479 ;; we simply want to replace it.
7749c1a8 1480 (if (and (not (equal ada-case-exception '()))
c2fb6415
RS
1481 (assoc-string word ada-case-exception t))
1482 (setcar (assoc-string word ada-case-exception t) word)
7749c1a8
GM
1483 (add-to-list 'ada-case-exception (cons word t))
1484 )
972579f9 1485
4607c7f4 1486 (ada-save-exceptions-to-file file-name)
7749c1a8 1487 ))
4cc7e498 1488
4607c7f4
SM
1489(defun ada-create-case-exception-substring (&optional word)
1490 "Defines the substring WORD as an exception for the casing system.
1491If WORD is not given, then the current word in the buffer is used instead,
1492or the selected region if any is active.
1493The new words is added to the first file in `ada-case-exception-file'.
1494When auto-casing a word, this substring will be special-cased, unless the
1495word itself has a special casing."
1496 (interactive)
1497 (let ((file-name
1498 (cond ((stringp ada-case-exception-file)
1499 ada-case-exception-file)
1500 ((listp ada-case-exception-file)
1501 (car ada-case-exception-file))
1502 (t
1503 (error (concat "No exception file specified. "
1504 "See variable ada-case-exception-file."))))))
1505
1506 ;; Find the substring to define as an exception. Order is: the parameter,
1507 ;; if any, or the selected region, or the word under the cursor
1508 (cond
1509 (word nil)
1510
1511 ((ada-region-selected)
1512 (setq word (buffer-substring-no-properties
1513 (region-beginning) (region-end))))
1514
1515 (t
1516 (let ((underscore-syntax (char-syntax ?_)))
1517 (unwind-protect
1518 (progn
1519 (modify-syntax-entry ?_ "." (syntax-table))
1520 (save-excursion
1521 (skip-syntax-backward "w")
1522 (set 'word (buffer-substring-no-properties
1523 (point)
1524 (save-excursion (forward-word 1) (point))))))
1525 (modify-syntax-entry ?_ (make-string 1 underscore-syntax)
1526 (syntax-table))))))
1527
1528 ;; Reread the exceptions file, in case it was modified by some other,
1529 (ada-case-read-exceptions-from-file file-name)
1530
1531 ;; If the word is already in the list, even with a different casing
1532 ;; we simply want to replace it.
1533 (if (and (not (equal ada-case-exception-substring '()))
c2fb6415
RS
1534 (assoc-string word ada-case-exception-substring t))
1535 (setcar (assoc-string word ada-case-exception-substring t) word)
4607c7f4
SM
1536 (add-to-list 'ada-case-exception-substring (cons word t))
1537 )
1538
1539 (ada-save-exceptions-to-file file-name)
1540
1541 (message (concat "Defining " word " as a casing exception"))))
1542
4cc7e498
GM
1543(defun ada-case-read-exceptions-from-file (file-name)
1544 "Read the content of the casing exception file FILE-NAME."
1545 (if (file-readable-p (expand-file-name file-name))
7749c1a8 1546 (let ((buffer (current-buffer)))
4cc7e498
GM
1547 (find-file (expand-file-name file-name))
1548 (set-syntax-table ada-mode-symbol-syntax-table)
7749c1a8
GM
1549 (widen)
1550 (goto-char (point-min))
1551 (while (not (eobp))
4cc7e498
GM
1552
1553 ;; If the item is already in the list, even with an other casing,
1554 ;; do not add it again. This way, the user can easily decide which
1555 ;; priority should be applied to each casing exception
1556 (let ((word (buffer-substring-no-properties
1557 (point) (save-excursion (forward-word 1) (point)))))
4607c7f4
SM
1558
1559 ;; Handling a substring ?
1560 (if (char-equal (string-to-char word) ?*)
1561 (progn
1562 (setq word (substring word 1))
c2fb6415 1563 (unless (assoc-string word ada-case-exception-substring t)
4607c7f4 1564 (add-to-list 'ada-case-exception-substring (cons word t))))
c2fb6415 1565 (unless (assoc-string word ada-case-exception t)
4607c7f4 1566 (add-to-list 'ada-case-exception (cons word t)))))
4cc7e498 1567
7749c1a8
GM
1568 (forward-line 1))
1569 (kill-buffer nil)
4cc7e498
GM
1570 (set-buffer buffer)))
1571 )
1572
1573(defun ada-case-read-exceptions ()
1574 "Read all the casing exception files from `ada-case-exception-file'."
1575 (interactive)
1576
1577 ;; Reinitialize the casing exception list
4607c7f4
SM
1578 (setq ada-case-exception '()
1579 ada-case-exception-substring '())
4cc7e498
GM
1580
1581 (cond ((stringp ada-case-exception-file)
1582 (ada-case-read-exceptions-from-file ada-case-exception-file))
1583
1584 ((listp ada-case-exception-file)
1585 (mapcar 'ada-case-read-exceptions-from-file
1586 ada-case-exception-file))))
7749c1a8 1587
4607c7f4
SM
1588(defun ada-adjust-case-substring ()
1589 "Adjust case of substrings in the previous word."
1590 (interactive)
1591 (let ((substrings ada-case-exception-substring)
1592 (max (point))
1593 (case-fold-search t)
1594 (underscore-syntax (char-syntax ?_))
1595 re)
1596
1597 (save-excursion
1598 (forward-word -1)
a1506d29 1599
4607c7f4
SM
1600 (unwind-protect
1601 (progn
1602 (modify-syntax-entry ?_ "." (syntax-table))
a1506d29 1603
4607c7f4
SM
1604 (while substrings
1605 (setq re (concat "\\b" (regexp-quote (caar substrings)) "\\b"))
a1506d29 1606
4607c7f4
SM
1607 (save-excursion
1608 (while (re-search-forward re max t)
f7a80909 1609 (replace-match (caar substrings) t)))
4607c7f4
SM
1610 (setq substrings (cdr substrings))
1611 )
1612 )
1613 (modify-syntax-entry ?_ (make-string 1 underscore-syntax) (syntax-table)))
1614 )))
1615
7749c1a8 1616(defun ada-adjust-case-identifier ()
655880d2
GM
1617 "Adjust case of the previous identifier.
1618The auto-casing is done according to the value of `ada-case-identifier' and
1619the exceptions defined in `ada-case-exception-file'."
4cc7e498 1620 (interactive)
7749c1a8
GM
1621 (if (or (equal ada-case-exception '())
1622 (equal (char-after) ?_))
4607c7f4
SM
1623 (progn
1624 (funcall ada-case-identifier -1)
1625 (ada-adjust-case-substring))
972579f9 1626
7749c1a8
GM
1627 (progn
1628 (let ((end (point))
1629 (start (save-excursion (skip-syntax-backward "w")
4cc7e498 1630 (point)))
7749c1a8
GM
1631 match)
1632 ;; If we have an exception, replace the word by the correct casing
c2fb6415
RS
1633 (if (setq match (assoc-string (buffer-substring start end)
1634 ada-case-exception t))
972579f9 1635
7749c1a8
GM
1636 (progn
1637 (delete-region start end)
1638 (insert (car match)))
972579f9 1639
655880d2 1640 ;; Else simply re-case the word
4607c7f4
SM
1641 (funcall ada-case-identifier -1)
1642 (ada-adjust-case-substring))))))
972579f9
RS
1643
1644(defun ada-after-keyword-p ()
4cc7e498 1645 "Returns t if cursor is after a keyword that is not an attribute."
972579f9
RS
1646 (save-excursion
1647 (forward-word -1)
4cc7e498
GM
1648 (and (not (and (char-before)
1649 (or (= (char-before) ?_)
1650 (= (char-before) ?'))));; unless we have a _ or '
7749c1a8 1651 (looking-at (concat ada-keywords "[^_]")))))
972579f9
RS
1652
1653(defun ada-adjust-case (&optional force-identifier)
5e1cecee 1654 "Adjust the case of the word before the just typed character.
655880d2 1655If FORCE-IDENTIFIER is non-nil then also adjust keyword as identifier."
4607c7f4
SM
1656 (if (not (bobp))
1657 (progn
1658 (forward-char -1)
1659 (if (and (not (bobp))
1660 ;; or if at the end of a character constant
1661 (not (and (eq (following-char) ?')
1662 (eq (char-before (1- (point))) ?')))
1663 ;; or if the previous character was not part of a word
1664 (eq (char-syntax (char-before)) ?w)
1665 ;; if in a string or a comment
1666 (not (ada-in-string-or-comment-p))
1667 )
1668 (if (save-excursion
1669 (forward-word -1)
1670 (or (= (point) (point-min))
1671 (backward-char 1))
1672 (= (following-char) ?'))
1673 (funcall ada-case-attribute -1)
1674 (if (and
1675 (not force-identifier) ; (MH)
1676 (ada-after-keyword-p))
1677 (funcall ada-case-keyword -1)
1678 (ada-adjust-case-identifier))))
1679 (forward-char 1)
1680 ))
7749c1a8 1681 )
972579f9
RS
1682
1683(defun ada-adjust-case-interactive (arg)
655880d2
GM
1684 "Adjust the case of the previous word, and process the character just typed.
1685ARG is the prefix the user entered with \C-u."
972579f9 1686 (interactive "P")
972579f9 1687
4cc7e498
GM
1688 (if ada-auto-case
1689 (let ((lastk last-command-char)
1690 (previous-syntax-table (syntax-table)))
1691
1692 (unwind-protect
1693 (progn
1694 (set-syntax-table ada-mode-symbol-syntax-table)
1695 (cond ((or (eq lastk ?\n)
1696 (eq lastk ?\r))
1697 ;; horrible kludge
1698 (insert " ")
1699 (ada-adjust-case)
1700 ;; horrible dekludge
1701 (delete-backward-char 1)
1702 ;; some special keys and their bindings
1703 (cond
1704 ((eq lastk ?\n)
1705 (funcall ada-lfd-binding))
1706 ((eq lastk ?\r)
1707 (funcall ada-ret-binding))))
1708 ((eq lastk ?\C-i) (ada-tab))
1709 ;; Else just insert the character
1710 ((self-insert-command (prefix-numeric-value arg))))
1711 ;; if there is a keyword in front of the underscore
1712 ;; then it should be part of an identifier (MH)
1713 (if (eq lastk ?_)
1714 (ada-adjust-case t)
1715 (ada-adjust-case))
1716 )
1717 ;; Restore the syntax table
1718 (set-syntax-table previous-syntax-table))
1719 )
1720
1721 ;; Else, no auto-casing
1722 (cond
1723 ((eq last-command-char ?\n)
1724 (funcall ada-lfd-binding))
1725 ((eq last-command-char ?\r)
1726 (funcall ada-ret-binding))
1727 (t
1728 (self-insert-command (prefix-numeric-value arg))))
1729 ))
972579f9
RS
1730
1731(defun ada-activate-keys-for-case ()
655880d2 1732 "Modifies the key bindings for all the keys that should readjust the casing."
7749c1a8 1733 (interactive)
4cc7e498
GM
1734 ;; Save original key-bindings to allow swapping ret/lfd
1735 ;; when casing is activated.
1736 ;; The 'or ...' is there to be sure that the value will not
1737 ;; be changed again when Ada mode is called more than once
36144b26
SM
1738 (or ada-ret-binding (setq ada-ret-binding (key-binding "\C-M")))
1739 (or ada-lfd-binding (setq ada-lfd-binding (key-binding "\C-j")))
4cc7e498
GM
1740
1741 ;; Call case modifying function after certain keys.
972579f9
RS
1742 (mapcar (function (lambda(key) (define-key
1743 ada-mode-map
1744 (char-to-string key)
1745 'ada-adjust-case-interactive)))
4cc7e498
GM
1746 '( ?` ?_ ?# ?% ?& ?* ?( ?) ?- ?= ?+
1747 ?| ?\; ?: ?' ?\" ?< ?, ?. ?> ?/ ?\n 32 ?\r )))
972579f9 1748
972579f9 1749(defun ada-loose-case-word (&optional arg)
655880d2
GM
1750 "Upcase first letter and letters following `_' in the following word.
1751No other letter is modified.
1752ARG is ignored, and is there for compatibility with `capitalize-word' only."
7749c1a8 1753 (interactive)
4cc7e498
GM
1754 (save-excursion
1755 (let ((end (save-excursion (skip-syntax-forward "w") (point)))
1756 (first t))
1757 (skip-syntax-backward "w")
1758 (while (and (or first (search-forward "_" end t))
1759 (< (point) end))
1760 (and first
36144b26 1761 (setq first nil))
4cc7e498
GM
1762 (insert-char (upcase (following-char)) 1)
1763 (delete-char 1)))))
1764
1765(defun ada-no-auto-case (&optional arg)
1766 "Does nothing.
1767This function can be used for the auto-casing variables in the ada-mode, to
1768adapt to unusal auto-casing schemes. Since it does nothing, you can for
1769instance use it for `ada-case-identifier' if you don't want any special
1770auto-casing for identifiers, whereas keywords have to be lower-cased.
1771See also `ada-auto-case' to disable auto casing altogether."
1772 )
972579f9 1773
7749c1a8 1774(defun ada-capitalize-word (&optional arg)
655880d2
GM
1775 "Upcase first letter and letters following '_', lower case other letters.
1776ARG is ignored, and is there for compatibility with `capitalize-word' only."
7749c1a8 1777 (interactive)
4cc7e498
GM
1778 (let ((end (save-excursion (skip-syntax-forward "w") (point)))
1779 (begin (save-excursion (skip-syntax-backward "w") (point))))
7749c1a8 1780 (modify-syntax-entry ?_ "_")
4cc7e498 1781 (capitalize-region begin end)
7749c1a8 1782 (modify-syntax-entry ?_ "w")))
972579f9 1783
972579f9 1784(defun ada-adjust-case-region (from to)
655880d2 1785 "Adjusts the case of all words in the region between FROM and TO.
5e1cecee 1786Attention: This function might take very long for big regions !"
972579f9
RS
1787 (interactive "*r")
1788 (let ((begin nil)
1789 (end nil)
1790 (keywordp nil)
7749c1a8
GM
1791 (attribp nil)
1792 (previous-syntax-table (syntax-table)))
1793 (message "Adjusting case ...")
f139ce87 1794 (unwind-protect
7749c1a8
GM
1795 (save-excursion
1796 (set-syntax-table ada-mode-symbol-syntax-table)
1797 (goto-char to)
1798 ;;
1799 ;; loop: look for all identifiers, keywords, and attributes
1800 ;;
1801 (while (re-search-backward "\\<\\(\\sw+\\)\\>" from t)
36144b26
SM
1802 (setq end (match-end 1))
1803 (setq attribp
7749c1a8
GM
1804 (and (> (point) from)
1805 (save-excursion
1806 (forward-char -1)
36144b26 1807 (setq attribp (looking-at "'.[^']")))))
7749c1a8
GM
1808 (or
1809 ;; do nothing if it is a string or comment
1810 (ada-in-string-or-comment-p)
1811 (progn
1812 ;;
1813 ;; get the identifier or keyword or attribute
1814 ;;
36144b26
SM
1815 (setq begin (point))
1816 (setq keywordp (looking-at ada-keywords))
7749c1a8
GM
1817 (goto-char end)
1818 ;;
1819 ;; casing according to user-option
1820 ;;
1821 (if attribp
1822 (funcall ada-case-attribute -1)
1823 (if keywordp
1824 (funcall ada-case-keyword -1)
1825 (ada-adjust-case-identifier)))
1826 (goto-char begin))))
1827 (message "Adjusting case ... Done"))
1828 (set-syntax-table previous-syntax-table))))
972579f9 1829
972579f9 1830(defun ada-adjust-case-buffer ()
5e1cecee 1831 "Adjusts the case of all words in the whole buffer.
972579f9 1832ATTENTION: This function might take very long for big buffers !"
f139ce87 1833 (interactive "*")
972579f9
RS
1834 (ada-adjust-case-region (point-min) (point-max)))
1835
1836\f
655880d2
GM
1837;;--------------------------------------------------------------
1838;; Format Parameter Lists
1839;; Some special algorithms are provided to indent the parameter lists in
1840;; subprogram declarations. This is done in two steps:
1841;; - First parses the parameter list. The returned list has the following
1842;; format:
1843;; ( (<Param_Name> in? out? access? <Type_Name> <Default_Expression>)
1844;; ... )
1845;; This is done in `ada-scan-paramlist'.
1846;; - Delete and recreate the parameter list in function
4cc7e498
GM
1847;; `ada-insert-paramlist'.
1848;; Both steps are called from `ada-format-paramlist'.
655880d2
GM
1849;; Note: Comments inside the parameter list are lost.
1850;; The syntax has to be correct, or the reformating will fail.
1851;;--------------------------------------------------------------
972579f9 1852
655880d2
GM
1853(defun ada-format-paramlist ()
1854 "Reformats the parameter list point is in."
972579f9
RS
1855 (interactive)
1856 (let ((begin nil)
1857 (end nil)
1858 (delend nil)
7749c1a8
GM
1859 (paramlist nil)
1860 (previous-syntax-table (syntax-table)))
f139ce87 1861 (unwind-protect
7749c1a8
GM
1862 (progn
1863 (set-syntax-table ada-mode-symbol-syntax-table)
f139ce87 1864
7749c1a8
GM
1865 ;; check if really inside parameter list
1866 (or (ada-in-paramlist-p)
1867 (error "not in parameter list"))
655880d2 1868
7749c1a8 1869 ;; find start of current parameter-list
7749c1a8 1870 (ada-search-ignore-string-comment
276c1210 1871 (concat ada-subprog-start-re "\\|\\<body\\>" ) t nil)
7749c1a8
GM
1872 (down-list 1)
1873 (backward-char 1)
36144b26 1874 (setq begin (point))
f139ce87 1875
7749c1a8 1876 ;; find end of parameter-list
7749c1a8 1877 (forward-sexp 1)
36144b26 1878 (setq delend (point))
7749c1a8 1879 (delete-char -1)
4cc7e498 1880 (insert "\n")
f139ce87 1881
7749c1a8 1882 ;; find end of last parameter-declaration
7749c1a8 1883 (forward-comment -1000)
36144b26 1884 (setq end (point))
f139ce87 1885
7749c1a8 1886 ;; build a list of all elements of the parameter-list
36144b26 1887 (setq paramlist (ada-scan-paramlist (1+ begin) end))
f139ce87 1888
7749c1a8 1889 ;; delete the original parameter-list
4cc7e498 1890 (delete-region begin delend)
f139ce87 1891
7749c1a8 1892 ;; insert the new parameter-list
7749c1a8
GM
1893 (goto-char begin)
1894 (ada-insert-paramlist paramlist))
f139ce87 1895
f139ce87 1896 ;; restore syntax-table
7749c1a8 1897 (set-syntax-table previous-syntax-table)
f139ce87 1898 )))
972579f9 1899
972579f9 1900(defun ada-scan-paramlist (begin end)
655880d2
GM
1901 "Scan the parameter list found in between BEGIN and END.
1902Returns the equivalent internal parameter list."
972579f9
RS
1903 (let ((paramlist (list))
1904 (param (list))
1905 (notend t)
1906 (apos nil)
1907 (epos nil)
1908 (semipos nil)
1909 (match-cons nil))
1910
1911 (goto-char begin)
655880d2 1912
972579f9 1913 ;; loop until end of last parameter
972579f9
RS
1914 (while notend
1915
972579f9 1916 ;; find first character of parameter-declaration
972579f9 1917 (ada-goto-next-non-ws)
36144b26 1918 (setq apos (point))
972579f9 1919
972579f9 1920 ;; find last character of parameter-declaration
36144b26 1921 (if (setq match-cons
7749c1a8 1922 (ada-search-ignore-string-comment "[ \t\n]*;" nil end t))
972579f9 1923 (progn
36144b26
SM
1924 (setq epos (car match-cons))
1925 (setq semipos (cdr match-cons)))
1926 (setq epos end))
972579f9 1927
972579f9 1928 ;; read name(s) of parameter(s)
972579f9 1929 (goto-char apos)
7749c1a8 1930 (looking-at "\\(\\(\\sw\\|[_, \t\n]\\)*\\(\\sw\\|_\\)\\)[ \t\n]*:[^=]")
972579f9 1931
36144b26 1932 (setq param (list (match-string 1)))
7749c1a8 1933 (ada-search-ignore-string-comment ":" nil epos t 'search-forward)
972579f9 1934
972579f9 1935 ;; look for 'in'
36144b26
SM
1936 (setq apos (point))
1937 (setq param
7749c1a8
GM
1938 (append param
1939 (list
1940 (consp
1941 (ada-search-ignore-string-comment
1942 "in" nil epos t 'word-search-forward)))))
972579f9 1943
972579f9 1944 ;; look for 'out'
972579f9 1945 (goto-char apos)
36144b26 1946 (setq param
7749c1a8
GM
1947 (append param
1948 (list
1949 (consp
1950 (ada-search-ignore-string-comment
1951 "out" nil epos t 'word-search-forward)))))
972579f9 1952
5e1cecee 1953 ;; look for 'access'
972579f9 1954 (goto-char apos)
36144b26 1955 (setq param
7749c1a8
GM
1956 (append param
1957 (list
1958 (consp
1959 (ada-search-ignore-string-comment
1960 "access" nil epos t 'word-search-forward)))))
972579f9 1961
5e1cecee 1962 ;; skip 'in'/'out'/'access'
972579f9
RS
1963 (goto-char apos)
1964 (ada-goto-next-non-ws)
5e1cecee 1965 (while (looking-at "\\<\\(in\\|out\\|access\\)\\>")
972579f9
RS
1966 (forward-word 1)
1967 (ada-goto-next-non-ws))
1968
7749c1a8 1969 ;; read type of parameter
4cc7e498
GM
1970 ;; We accept spaces in the name, since some software like Rose
1971 ;; generates something like: "A : B 'Class"
1972 (looking-at "\\<\\(\\sw\\|[_.' \t]\\)+\\>")
36144b26 1973 (setq param
7749c1a8
GM
1974 (append param
1975 (list (match-string 0))))
972579f9 1976
972579f9 1977 ;; read default-expression, if there is one
36144b26
SM
1978 (goto-char (setq apos (match-end 0)))
1979 (setq param
7749c1a8
GM
1980 (append param
1981 (list
36144b26 1982 (if (setq match-cons
7749c1a8
GM
1983 (ada-search-ignore-string-comment
1984 ":=" nil epos t 'search-forward))
1985 (buffer-substring (car match-cons) epos)
1986 nil))))
655880d2 1987
972579f9 1988 ;; add this parameter-declaration to the list
36144b26 1989 (setq paramlist (append paramlist (list param)))
972579f9 1990
972579f9 1991 ;; check if it was the last parameter
972579f9 1992 (if (eq epos end)
36144b26 1993 (setq notend nil)
972579f9 1994 (goto-char semipos))
655880d2 1995 )
972579f9
RS
1996 (reverse paramlist)))
1997
972579f9 1998(defun ada-insert-paramlist (paramlist)
655880d2 1999 "Inserts a formatted PARAMLIST in the buffer."
972579f9
RS
2000 (let ((i (length paramlist))
2001 (parlen 0)
2002 (typlen 0)
972579f9
RS
2003 (inp nil)
2004 (outp nil)
5e1cecee 2005 (accessp nil)
972579f9 2006 (column nil)
972579f9
RS
2007 (firstcol nil))
2008
972579f9 2009 ;; loop until last parameter
972579f9 2010 (while (not (zerop i))
36144b26 2011 (setq i (1- i))
972579f9 2012
972579f9 2013 ;; get max length of parameter-name
36144b26 2014 (setq parlen (max parlen (length (nth 0 (nth i paramlist)))))
972579f9 2015
972579f9 2016 ;; get max length of type-name
36144b26 2017 (setq typlen (max typlen (length (nth 4 (nth i paramlist)))))
972579f9 2018
972579f9 2019 ;; is there any 'in' ?
36144b26 2020 (setq inp (or inp (nth 1 (nth i paramlist))))
972579f9 2021
972579f9 2022 ;; is there any 'out' ?
36144b26 2023 (setq outp (or outp (nth 2 (nth i paramlist))))
972579f9 2024
5e1cecee 2025 ;; is there any 'access' ?
36144b26 2026 (setq accessp (or accessp (nth 3 (nth i paramlist))))
655880d2 2027 )
972579f9 2028
972579f9 2029 ;; does paramlist already start on a separate line ?
972579f9
RS
2030 (if (save-excursion
2031 (re-search-backward "^.\\|[^ \t]" nil t)
2032 (looking-at "^."))
2033 ;; yes => re-indent it
7749c1a8
GM
2034 (progn
2035 (ada-indent-current)
2036 (save-excursion
2037 (if (looking-at "\\(is\\|return\\)")
2038 (replace-match " \\1"))))
655880d2 2039
7749c1a8 2040 ;; no => insert it where we are after removing any whitespace
7749c1a8
GM
2041 (fixup-whitespace)
2042 (save-excursion
2043 (cond
2044 ((looking-at "[ \t]*\\(\n\\|;\\)")
2045 (replace-match "\\1"))
2046 ((looking-at "[ \t]*\\(is\\|return\\)")
2047 (replace-match " \\1"))))
2048 (insert " "))
972579f9
RS
2049
2050 (insert "(")
7749c1a8 2051 (ada-indent-current)
972579f9 2052
36144b26
SM
2053 (setq firstcol (current-column))
2054 (setq i (length paramlist))
972579f9 2055
972579f9 2056 ;; loop until last parameter
972579f9 2057 (while (not (zerop i))
36144b26
SM
2058 (setq i (1- i))
2059 (setq column firstcol)
972579f9 2060
972579f9 2061 ;; insert parameter-name, space and colon
972579f9
RS
2062 (insert (nth 0 (nth i paramlist)))
2063 (indent-to (+ column parlen 1))
2064 (insert ": ")
36144b26 2065 (setq column (current-column))
972579f9 2066
972579f9 2067 ;; insert 'in' or space
972579f9
RS
2068 (if (nth 1 (nth i paramlist))
2069 (insert "in ")
2070 (if (and
2071 (or inp
5e1cecee 2072 accessp)
972579f9
RS
2073 (not (nth 3 (nth i paramlist))))
2074 (insert " ")))
2075
972579f9 2076 ;; insert 'out' or space
972579f9
RS
2077 (if (nth 2 (nth i paramlist))
2078 (insert "out ")
2079 (if (and
2080 (or outp
5e1cecee 2081 accessp)
972579f9
RS
2082 (not (nth 3 (nth i paramlist))))
2083 (insert " ")))
2084
5e1cecee 2085 ;; insert 'access'
972579f9 2086 (if (nth 3 (nth i paramlist))
5e1cecee 2087 (insert "access "))
972579f9 2088
36144b26 2089 (setq column (current-column))
972579f9 2090
972579f9 2091 ;; insert type-name and, if necessary, space and default-expression
972579f9
RS
2092 (insert (nth 4 (nth i paramlist)))
2093 (if (nth 5 (nth i paramlist))
2094 (progn
2095 (indent-to (+ column typlen 1))
2096 (insert (nth 5 (nth i paramlist)))))
2097
972579f9 2098 ;; check if it was the last parameter
7749c1a8
GM
2099 (if (zerop i)
2100 (insert ")")
2101 ;; no => insert ';' and newline and indent
2102 (insert ";")
2103 (newline)
2104 (indent-to firstcol))
655880d2 2105 )
972579f9 2106
7749c1a8 2107 ;; if anything follows, except semicolon, newline, is or return
972579f9 2108 ;; put it in a new line and indent it
7749c1a8
GM
2109 (unless (looking-at "[ \t]*\\(;\\|\n\\|is\\|return\\)")
2110 (ada-indent-newline-indent))
972579f9
RS
2111 ))
2112
972579f9
RS
2113
2114\f
655880d2
GM
2115;;;----------------------------------------------------------------
2116;; Indentation Engine
2117;; All indentations are indicated as a two-element string:
2118;; - position of reference in the buffer
2119;; - offset to indent from this position (can also be a symbol or a list
2120;; that are evaluated)
2121;; Thus the total indentation for a line is the column number of the reference
2122;; position plus whatever value the evaluation of the second element provides.
2123;; This mechanism is used so that the ada-mode can "explain" how the
2124;; indentation was calculated, by showing which variables were used.
2125;;
2126;; The indentation itself is done in only one pass: first we try to guess in
2127;; what context we are by looking at the following keyword or punctuation
2128;; sign. If nothing remarkable is found, just try to guess the indentation
2129;; based on previous lines.
2130;;
2131;; The relevant functions for indentation are:
2132;; - `ada-indent-region': Re-indent a region of text
2133;; - `ada-justified-indent-current': Re-indent the current line and shows the
2134;; calculation that were done
2135;; - `ada-indent-current': Re-indent the current line
2136;; - `ada-get-current-indent': Calculate the indentation for the current line,
2137;; based on the context (see above).
2138;; - `ada-get-indent-*': Calculate the indentation in a specific context.
4cc7e498
GM
2139;; For efficiency, these functions do not check they are in the correct
2140;; context.
655880d2 2141;;;----------------------------------------------------------------
972579f9 2142
972579f9 2143(defun ada-indent-region (beg end)
4cc7e498 2144 "Indent the region between BEG end END."
972579f9
RS
2145 (interactive "*r")
2146 (goto-char beg)
f139ce87 2147 (let ((block-done 0)
7749c1a8 2148 (lines-remaining (count-lines beg end))
4cc7e498 2149 (msg (format "%%4d out of %4d lines remaining ..."
7749c1a8 2150 (count-lines beg end)))
f139ce87
KH
2151 (endmark (copy-marker end)))
2152 ;; catch errors while indenting
7749c1a8
GM
2153 (while (< (point) endmark)
2154 (if (> block-done 39)
4cc7e498
GM
2155 (progn
2156 (setq lines-remaining (- lines-remaining block-done)
2157 block-done 0)
2158 (message msg lines-remaining)))
2159 (if (= (char-after) ?\n) nil
7749c1a8
GM
2160 (ada-indent-current))
2161 (forward-line 1)
4cc7e498 2162 (setq block-done (1+ block-done)))
f139ce87 2163 (message "indenting ... done")))
972579f9 2164
972579f9
RS
2165(defun ada-indent-newline-indent ()
2166 "Indents the current line, inserts a newline and then indents the new line."
2167 (interactive "*")
cadd3658
RS
2168 (ada-indent-current)
2169 (newline)
2170 (ada-indent-current))
972579f9 2171
7749c1a8 2172(defun ada-indent-newline-indent-conditional ()
655880d2
GM
2173 "Insert a newline and indent it.
2174The original line is indented first if `ada-indent-after-return' is non-nil.
2175This function is intended to be bound to the \C-m and \C-j keys."
7749c1a8
GM
2176 (interactive "*")
2177 (if ada-indent-after-return (ada-indent-current))
2178 (newline)
2179 (ada-indent-current))
2180
2181(defun ada-justified-indent-current ()
655880d2 2182 "Indent the current line and explains how the calculation was done."
7749c1a8
GM
2183 (interactive)
2184
2185 (let ((cur-indent (ada-indent-current)))
2186
4607c7f4
SM
2187 (let ((line (save-excursion
2188 (goto-char (car cur-indent))
80d50f88 2189 (count-lines 1 (point)))))
4607c7f4
SM
2190
2191 (if (equal (cdr cur-indent) '(0))
2192 (message (concat "same indentation as line " (number-to-string line)))
2193 (message (mapconcat (lambda(x)
2194 (cond
2195 ((symbolp x)
2196 (symbol-name x))
2197 ((numberp x)
2198 (number-to-string x))
2199 ((listp x)
2200 (concat "- " (symbol-name (cadr x))))
2201 ))
2202 (cdr cur-indent)
2203 " + "))))
7749c1a8
GM
2204 (save-excursion
2205 (goto-char (car cur-indent))
2206 (sit-for 1))))
972579f9 2207
4cc7e498
GM
2208(defun ada-batch-reformat ()
2209 "Re-indent and re-case all the files found on the command line.
2210This function should be used from the Unix/Windows command line, with a
2211command like:
2212 emacs -batch -l ada-mode -f ada-batch-reformat file1 file2 ..."
2213
2214 (while command-line-args-left
2215 (let ((source (car command-line-args-left)))
2216 (message (concat "formating " source))
2217 (find-file source)
2218 (ada-indent-region (point-min) (point-max))
2219 (ada-adjust-case-buffer)
2220 (write-file source))
36144b26 2221 (setq command-line-args-left (cdr command-line-args-left)))
4cc7e498
GM
2222 (message "Done")
2223 (kill-emacs 0))
2224
2225(defsubst ada-goto-previous-word ()
2226 "Moves point to the beginning of the previous word of Ada code.
2227Returns the new position of point or nil if not found."
2228 (ada-goto-next-word t))
2229
972579f9 2230(defun ada-indent-current ()
655880d2
GM
2231 "Indent current line as Ada code.
2232Returns the calculation that was done, including the reference point and the
2233offset."
972579f9 2234 (interactive)
7749c1a8 2235 (let ((previous-syntax-table (syntax-table))
4cc7e498
GM
2236 (orgpoint (point-marker))
2237 cur-indent tmp-indent
2238 prev-indent)
972579f9 2239
7749c1a8
GM
2240 (unwind-protect
2241 (progn
4cc7e498 2242 (set-syntax-table ada-mode-symbol-syntax-table)
f139ce87 2243
4cc7e498
GM
2244 ;; This need to be done here so that the advice is not always
2245 ;; activated (this might interact badly with other modes)
6f9a2614 2246 (if (featurep 'xemacs)
4cc7e498
GM
2247 (ad-activate 'parse-partial-sexp t))
2248
2249 (save-excursion
36144b26 2250 (setq cur-indent
4cc7e498
GM
2251
2252 ;; Not First line in the buffer ?
2253 (if (save-excursion (zerop (forward-line -1)))
2254 (progn
2255 (back-to-indentation)
2256 (ada-get-current-indent))
2257
2258 ;; first line in the buffer
2259 (list (point-min) 0))))
2260
2261 ;; Evaluate the list to get the column to indent to
2262 ;; prev-indent contains the column to indent to
2263 (if cur-indent
2264 (setq prev-indent (save-excursion (goto-char (car cur-indent))
2265 (current-column))
2266 tmp-indent (cdr cur-indent))
2267 (setq prev-indent 0 tmp-indent '()))
eaae8106 2268
4cc7e498
GM
2269 (while (not (null tmp-indent))
2270 (cond
2271 ((numberp (car tmp-indent))
36144b26 2272 (setq prev-indent (+ prev-indent (car tmp-indent))))
4cc7e498 2273 (t
36144b26 2274 (setq prev-indent (+ prev-indent (eval (car tmp-indent)))))
4cc7e498 2275 )
36144b26 2276 (setq tmp-indent (cdr tmp-indent)))
4cc7e498
GM
2277
2278 ;; only re-indent if indentation is different then the current
2279 (if (= (save-excursion (back-to-indentation) (current-column)) prev-indent)
2280 nil
2281 (beginning-of-line)
2282 (delete-horizontal-space)
2283 (indent-to prev-indent))
2284 ;;
2285 ;; restore position of point
2286 ;;
2287 (goto-char orgpoint)
2288 (if (< (current-column) (current-indentation))
2289 (back-to-indentation)))
2290
2291 ;; restore syntax-table
2292 (set-syntax-table previous-syntax-table)
6f9a2614 2293 (if (featurep 'xemacs)
4cc7e498
GM
2294 (ad-deactivate 'parse-partial-sexp))
2295 )
655880d2 2296
7749c1a8
GM
2297 cur-indent
2298 ))
972579f9 2299
7749c1a8 2300(defun ada-get-current-indent ()
4cc7e498 2301 "Return the indentation to use for the current line."
7749c1a8 2302 (let (column
4cc7e498
GM
2303 pos
2304 match-cons
2305 result
2306 (orgpoint (save-excursion
2307 (beginning-of-line)
2308 (forward-comment -10000)
2309 (forward-line 1)
2310 (point))))
2311
36144b26 2312 (setq result
972579f9 2313 (cond
7749c1a8 2314
4cc7e498 2315 ;;-----------------------------
972579f9 2316 ;; in open parenthesis, but not in parameter-list
4cc7e498 2317 ;;-----------------------------
eaae8106 2318
4cc7e498
GM
2319 ((and ada-indent-to-open-paren
2320 (not (ada-in-paramlist-p))
36144b26 2321 (setq column (ada-in-open-paren-p)))
eaae8106 2322
972579f9 2323 ;; check if we have something like this (Table_Component_Type =>
7749c1a8 2324 ;; Source_File_Record)
972579f9 2325 (save-excursion
4607c7f4
SM
2326
2327 ;; Align the closing parenthesis on the opening one
2328 (if (= (following-char) ?\))
2329 (save-excursion
2330 (goto-char column)
2331 (skip-chars-backward " \t")
2332 (list (1- (point)) 0))
a1506d29 2333
4607c7f4
SM
2334 (if (and (skip-chars-backward " \t")
2335 (= (char-before) ?\n)
2336 (not (forward-comment -10000))
2337 (= (char-before) ?>))
2338 ;; ??? Could use a different variable
2339 (list column 'ada-broken-indent)
2340
80d50f88
SM
2341 ;; We want all continuation lines to be indented the same
2342 ;; (ada-broken-line from the opening parenthesis. However, in
2343 ;; parameter list, each new parameter should be indented at the
2344 ;; column as the opening parenthesis.
2345
2346 ;; A special case to handle nested boolean expressions, as in
2347 ;; ((B
2348 ;; and then C) -- indented by ada-broken-indent
2349 ;; or else D) -- indenting this line.
2350 ;; ??? This is really a hack, we should have a proper way to go to
2351 ;; ??? the beginning of the statement
a1506d29 2352
80d50f88
SM
2353 (if (= (char-before) ?\))
2354 (backward-sexp))
a1506d29 2355
80d50f88
SM
2356 (if (memq (char-before) '(?, ?\; ?\( ?\)))
2357 (list column 0)
2358 (list column 'ada-continuation-indent)
2359 )))))
972579f9 2360
4cc7e498
GM
2361 ;;---------------------------
2362 ;; at end of buffer
2363 ;;---------------------------
972579f9 2364
4cc7e498
GM
2365 ((not (char-after))
2366 (ada-indent-on-previous-lines nil orgpoint orgpoint))
eaae8106 2367
4cc7e498
GM
2368 ;;---------------------------
2369 ;; starting with e
2370 ;;---------------------------
eaae8106 2371
4607c7f4 2372 ((= (downcase (char-after)) ?e)
4cc7e498 2373 (cond
972579f9 2374
4cc7e498 2375 ;; ------- end ------
eaae8106 2376
4cc7e498
GM
2377 ((looking-at "end\\>")
2378 (let ((label 0)
2379 limit)
2380 (save-excursion
2381 (ada-goto-matching-start 1)
eaae8106 2382
4cc7e498
GM
2383 ;;
2384 ;; found 'loop' => skip back to 'while' or 'for'
2385 ;; if 'loop' is not on a separate line
2386 ;; Stop the search for 'while' and 'for' when a ';' is encountered.
2387 ;;
2388 (if (save-excursion
2389 (beginning-of-line)
2390 (looking-at ".+\\<loop\\>"))
2391 (progn
2392 (save-excursion
36144b26 2393 (setq limit (car (ada-search-ignore-string-comment ";" t))))
4cc7e498
GM
2394 (if (save-excursion
2395 (and
36144b26 2396 (setq match-cons
4cc7e498
GM
2397 (ada-search-ignore-string-comment ada-loop-start-re t limit))
2398 (not (looking-at "\\<loop\\>"))))
2399 (progn
2400 (goto-char (car match-cons))
2401 (save-excursion
2402 (beginning-of-line)
2403 (if (looking-at ada-named-block-re)
36144b26 2404 (setq label (- ada-label-indent))))))))
a1506d29 2405
4607c7f4
SM
2406 ;; found 'record' =>
2407 ;; if the keyword is found at the beginning of a line (or just
2408 ;; after limited, we indent on it, otherwise we indent on the
2409 ;; beginning of the type declaration)
2410 ;; type A is (B : Integer;
2411 ;; C : Integer) is record
2412 ;; end record; -- This is badly indented otherwise
2413 (if (looking-at "record")
2414 (if (save-excursion
2415 (beginning-of-line)
2416 (looking-at "^[ \t]*\\(record\\|limited record\\)"))
2417 (list (save-excursion (back-to-indentation) (point)) 0)
2418 (list (save-excursion
2419 (car (ada-search-ignore-string-comment "\\<type\\>" t)))
2420 0))
2421
2422 ;; Else keep the same indentation as the beginning statement
2423 (list (+ (save-excursion (back-to-indentation) (point)) label) 0)))))
4cc7e498
GM
2424
2425 ;; ------ exception ----
eaae8106 2426
4cc7e498
GM
2427 ((looking-at "exception\\>")
2428 (save-excursion
2429 (ada-goto-matching-start 1)
2430 (list (save-excursion (back-to-indentation) (point)) 0)))
2431
2432 ;; else
eaae8106 2433
4cc7e498
GM
2434 ((looking-at "else\\>")
2435 (if (save-excursion (ada-goto-previous-word)
2436 (looking-at "\\<or\\>"))
2437 (ada-indent-on-previous-lines nil orgpoint orgpoint)
2438 (save-excursion
2439 (ada-goto-matching-start 1 nil t)
2440 (list (progn (back-to-indentation) (point)) 0))))
2441
2442 ;; elsif
a1506d29 2443
4cc7e498
GM
2444 ((looking-at "elsif\\>")
2445 (save-excursion
2446 (ada-goto-matching-start 1 nil t)
2447 (list (progn (back-to-indentation) (point)) 0)))
2448
2449 ))
2450
2451 ;;---------------------------
2452 ;; starting with w (when)
2453 ;;---------------------------
a1506d29 2454
4607c7f4 2455 ((and (= (downcase (char-after)) ?w)
4cc7e498 2456 (looking-at "when\\>"))
972579f9 2457 (save-excursion
4cc7e498
GM
2458 (ada-goto-matching-start 1)
2459 (list (save-excursion (back-to-indentation) (point))
2460 'ada-when-indent)))
2461
2462 ;;---------------------------
2463 ;; starting with t (then)
2464 ;;---------------------------
2465
4607c7f4 2466 ((and (= (downcase (char-after)) ?t)
4cc7e498 2467 (looking-at "then\\>"))
7749c1a8 2468 (if (save-excursion (ada-goto-previous-word)
4cc7e498 2469 (looking-at "and\\>"))
7749c1a8 2470 (ada-indent-on-previous-lines nil orgpoint orgpoint)
4cc7e498
GM
2471 (save-excursion
2472 ;; Select has been added for the statement: "select ... then abort"
2473 (ada-search-ignore-string-comment
2474 "\\<\\(elsif\\|if\\|select\\)\\>" t nil)
2475 (list (progn (back-to-indentation) (point))
2476 'ada-stmt-end-indent))))
2477
2478 ;;---------------------------
2479 ;; starting with l (loop)
2480 ;;---------------------------
a1506d29 2481
4607c7f4 2482 ((and (= (downcase (char-after)) ?l)
4cc7e498 2483 (looking-at "loop\\>"))
36144b26 2484 (setq pos (point))
972579f9
RS
2485 (save-excursion
2486 (goto-char (match-end 0))
2487 (ada-goto-stmt-start)
7749c1a8 2488 (if (looking-at "\\<\\(loop\\|if\\)\\>")
4cc7e498
GM
2489 (ada-indent-on-previous-lines nil orgpoint orgpoint)
2490 (unless (looking-at ada-loop-start-re)
2491 (ada-search-ignore-string-comment ada-loop-start-re
2492 nil pos))
2493 (if (looking-at "\\<loop\\>")
2494 (ada-indent-on-previous-lines nil orgpoint orgpoint)
2495 (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent)))))
2496
4607c7f4
SM
2497 ;;----------------------------
2498 ;; starting with l (limited) or r (record)
2499 ;;----------------------------
a1506d29 2500
4607c7f4
SM
2501 ((or (and (= (downcase (char-after)) ?l)
2502 (looking-at "limited\\>"))
2503 (and (= (downcase (char-after)) ?r)
2504 (looking-at "record\\>")))
2505
2506 (save-excursion
2507 (ada-search-ignore-string-comment
2508 "\\<\\(type\\|use\\)\\>" t nil)
2509 (if (looking-at "\\<use\\>")
2510 (ada-search-ignore-string-comment "for" t nil nil
2511 'word-search-backward))
2512 (list (progn (back-to-indentation) (point))
2513 'ada-indent-record-rel-type)))
2514
4cc7e498
GM
2515 ;;---------------------------
2516 ;; starting with b (begin)
2517 ;;---------------------------
2518
4607c7f4 2519 ((and (= (downcase (char-after)) ?b)
4cc7e498 2520 (looking-at "begin\\>"))
972579f9
RS
2521 (save-excursion
2522 (if (ada-goto-matching-decl-start t)
4cc7e498
GM
2523 (list (progn (back-to-indentation) (point)) 0)
2524 (ada-indent-on-previous-lines nil orgpoint orgpoint))))
2525
2526 ;;---------------------------
2527 ;; starting with i (is)
2528 ;;---------------------------
2529
4607c7f4 2530 ((and (= (downcase (char-after)) ?i)
4cc7e498 2531 (looking-at "is\\>"))
eaae8106 2532
7749c1a8 2533 (if (and ada-indent-is-separate
4cc7e498
GM
2534 (save-excursion
2535 (goto-char (match-end 0))
2536 (ada-goto-next-non-ws (save-excursion (end-of-line)
2537 (point)))
2538 (looking-at "\\<abstract\\>\\|\\<separate\\>")))
972579f9
RS
2539 (save-excursion
2540 (ada-goto-stmt-start)
4cc7e498 2541 (list (progn (back-to-indentation) (point)) 'ada-indent))
972579f9
RS
2542 (save-excursion
2543 (ada-goto-stmt-start)
80d50f88
SM
2544 (if (looking-at "\\<package\\|procedure\\|function\\>")
2545 (list (progn (back-to-indentation) (point)) 0)
2546 (list (progn (back-to-indentation) (point)) 'ada-indent)))))
4cc7e498
GM
2547
2548 ;;---------------------------
4607c7f4 2549 ;; starting with r (return, renames)
4cc7e498
GM
2550 ;;---------------------------
2551
4607c7f4
SM
2552 ((and (= (downcase (char-after)) ?r)
2553 (looking-at "re\\(turn\\|names\\)\\>"))
a1506d29 2554
4607c7f4
SM
2555 (save-excursion
2556 (let ((var 'ada-indent-return))
2557 ;; If looking at a renames, skip the 'return' statement too
2558 (if (looking-at "renames")
2559 (let (pos)
2560 (save-excursion
2561 (set 'pos (ada-search-ignore-string-comment ";\\|return\\>" t)))
2562 (if (and pos
2563 (= (downcase (char-after (car pos))) ?r))
2564 (goto-char (car pos)))
2565 (set 'var 'ada-indent-renames)))
a1506d29 2566
4607c7f4
SM
2567 (forward-comment -1000)
2568 (if (= (char-before) ?\))
2569 (forward-sexp -1)
2570 (forward-word -1))
a1506d29 2571
4607c7f4
SM
2572 ;; If there is a parameter list, and we have a function declaration
2573 ;; or a access to subprogram declaration
2574 (let ((num-back 1))
2575 (if (and (= (following-char) ?\()
2576 (save-excursion
2577 (or (progn
2578 (backward-word 1)
2579 (looking-at "\\(function\\|procedure\\)\\>"))
2580 (progn
2581 (backward-word 1)
2582 (set 'num-back 2)
2583 (looking-at "\\(function\\|procedure\\)\\>")))))
a1506d29 2584
4607c7f4
SM
2585 ;; The indentation depends of the value of ada-indent-return
2586 (if (<= (eval var) 0)
2587 (list (point) (list '- var))
2588 (list (progn (backward-word num-back) (point))
2589 var))
a1506d29 2590
4607c7f4
SM
2591 ;; Else there is no parameter list, but we have a function
2592 ;; Only do something special if the user want to indent
2593 ;; relative to the "function" keyword
2594 (if (and (> (eval var) 0)
2595 (save-excursion (forward-word -1)
2596 (looking-at "function\\>")))
2597 (list (progn (forward-word -1) (point)) var)
a1506d29 2598
4607c7f4
SM
2599 ;; Else...
2600 (ada-indent-on-previous-lines nil orgpoint orgpoint)))))))
a1506d29 2601
4cc7e498
GM
2602 ;;--------------------------------
2603 ;; starting with 'o' or 'p'
2604 ;; 'or' as statement-start
2605 ;; 'private' as statement-start
2606 ;;--------------------------------
2607
4607c7f4
SM
2608 ((and (or (= (downcase (char-after)) ?o)
2609 (= (downcase (char-after)) ?p))
4cc7e498
GM
2610 (or (ada-looking-at-semi-or)
2611 (ada-looking-at-semi-private)))
972579f9 2612 (save-excursion
4607c7f4
SM
2613 ;; ??? Wasn't this done already in ada-looking-at-semi-or ?
2614 (ada-goto-matching-start 1)
2615 (list (progn (back-to-indentation) (point)) 0)))
7749c1a8 2616
4cc7e498
GM
2617 ;;--------------------------------
2618 ;; starting with 'd' (do)
2619 ;;--------------------------------
2620
4607c7f4 2621 ((and (= (downcase (char-after)) ?d)
4cc7e498 2622 (looking-at "do\\>"))
972579f9
RS
2623 (save-excursion
2624 (ada-goto-stmt-start)
4cc7e498
GM
2625 (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent)))
2626
2627 ;;--------------------------------
2628 ;; starting with '-' (comment)
2629 ;;--------------------------------
2630
2631 ((= (char-after) ?-)
2632 (if ada-indent-comment-as-code
2633
2634 ;; Indent comments on previous line comments if required
2635 ;; We must use a search-forward (even if the code is more complex),
2636 ;; since we want to find the beginning of the comment.
2637 (let (pos)
eaae8106 2638
4cc7e498
GM
2639 (if (and ada-indent-align-comments
2640 (save-excursion
2641 (forward-line -1)
2642 (beginning-of-line)
2643 (while (and (not pos)
2644 (search-forward "--"
2645 (save-excursion
2646 (end-of-line) (point))
2647 t))
2648 (unless (ada-in-string-p)
36144b26 2649 (setq pos (point))))
4cc7e498
GM
2650 pos))
2651 (list (- pos 2) 0)
eaae8106 2652
4cc7e498
GM
2653 ;; Else always on previous line
2654 (ada-indent-on-previous-lines nil orgpoint orgpoint)))
2655
2656 ;; Else same indentation as the previous line
2657 (list (save-excursion (back-to-indentation) (point)) 0)))
2658
2659 ;;--------------------------------
2660 ;; starting with '#' (preprocessor line)
2661 ;;--------------------------------
2662
2663 ((and (= (char-after) ?#)
2664 (equal ada-which-compiler 'gnat)
2665 (looking-at "#[ \t]*\\(if\\|els\\(e\\|if\\)\\|end[ \t]*if\\)"))
2666 (list (save-excursion (beginning-of-line) (point)) 0))
2667
2668 ;;--------------------------------
2669 ;; starting with ')' (end of a parameter list)
2670 ;;--------------------------------
2671
2672 ((and (not (eobp)) (= (char-after) ?\)))
2673 (save-excursion
2674 (forward-char 1)
2675 (backward-sexp 1)
2676 (list (point) 0)))
2677
2678 ;;---------------------------------
2679 ;; new/abstract/separate
2680 ;;---------------------------------
eaae8106 2681
4cc7e498
GM
2682 ((looking-at "\\(new\\|abstract\\|separate\\)\\>")
2683 (ada-indent-on-previous-lines nil orgpoint orgpoint))
2684
2685 ;;---------------------------------
972579f9 2686 ;; package/function/procedure
4cc7e498
GM
2687 ;;---------------------------------
2688
4607c7f4 2689 ((and (or (= (downcase (char-after)) ?p) (= (downcase (char-after)) ?f))
4cc7e498 2690 (looking-at "\\<\\(package\\|function\\|procedure\\)\\>"))
972579f9 2691 (save-excursion
4cc7e498
GM
2692 ;; Go up until we find either a generic section, or the end of the
2693 ;; previous subprogram/package
2694 (let (found)
2695 (while (and (not found)
2696 (ada-search-ignore-string-comment
2697 "\\<\\(generic\\|end\\|begin\\|package\\|procedure\\|function\\)\\>" t))
eaae8106 2698
4cc7e498
GM
2699 ;; avoid "with procedure"... in generic parts
2700 (save-excursion
2701 (forward-word -1)
36144b26 2702 (setq found (not (looking-at "with"))))))
eaae8106 2703
4cc7e498 2704 (if (looking-at "generic")
7749c1a8
GM
2705 (list (progn (back-to-indentation) (point)) 0)
2706 (ada-indent-on-previous-lines nil orgpoint orgpoint))))
eaae8106 2707
4cc7e498 2708 ;;---------------------------------
972579f9 2709 ;; label
4cc7e498 2710 ;;---------------------------------
eaae8106 2711
4cc7e498 2712 ((looking-at "\\(\\sw\\|_\\)+[ \t\n]*:[^=]")
972579f9 2713 (if (ada-in-decl-p)
4cc7e498
GM
2714 (ada-indent-on-previous-lines nil orgpoint orgpoint)
2715 (append (ada-indent-on-previous-lines nil orgpoint orgpoint)
2716 '(ada-label-indent))))
2717
2718 ))
2719
2720 ;;---------------------------------
2721 ;; Other syntaxes
2722 ;;---------------------------------
2723 (or result (ada-indent-on-previous-lines nil orgpoint orgpoint))))
7749c1a8
GM
2724
2725(defun ada-indent-on-previous-lines (&optional nomove orgpoint initial-pos)
655880d2
GM
2726 "Calculate the indentation for the new line after ORGPOINT.
2727The result list is based on the previous lines in the buffer.
2728If NOMOVE is nil, moves point to the beginning of the current statement.
2729if INITIAL-POS is non-nil, moves point to INITIAL-POS before calculation."
7749c1a8
GM
2730 (if initial-pos
2731 (goto-char initial-pos))
4cc7e498
GM
2732 (let ((oldpoint (point)))
2733
7749c1a8 2734 ;; Is inside a parameter-list ?
972579f9 2735 (if (ada-in-paramlist-p)
4cc7e498 2736 (ada-get-indent-paramlist)
972579f9 2737
7749c1a8 2738 ;; move to beginning of current statement
7749c1a8
GM
2739 (unless nomove
2740 (ada-goto-stmt-start))
972579f9 2741
4cc7e498
GM
2742 ;; no beginning found => don't change indentation
2743 (if (and (eq oldpoint (point))
2744 (not nomove))
2745 (ada-get-indent-nochange)
7749c1a8 2746
4cc7e498
GM
2747 (cond
2748 ;;
2749 ((and
2750 ada-indent-to-open-paren
2751 (ada-in-open-paren-p))
2752 (ada-get-indent-open-paren))
2753 ;;
2754 ((looking-at "end\\>")
2755 (ada-get-indent-end orgpoint))
2756 ;;
2757 ((looking-at ada-loop-start-re)
2758 (ada-get-indent-loop orgpoint))
2759 ;;
2760 ((looking-at ada-subprog-start-re)
2761 (ada-get-indent-subprog orgpoint))
2762 ;;
2763 ((looking-at ada-block-start-re)
2764 (ada-get-indent-block-start orgpoint))
2765 ;;
2766 ((looking-at "\\(sub\\)?type\\>")
2767 (ada-get-indent-type orgpoint))
2768 ;;
2769 ;; "then" has to be included in the case of "select...then abort"
2770 ;; statements, since (goto-stmt-start) at the beginning of
2771 ;; the current function would leave the cursor on that position
2772 ((looking-at "\\(\\(els\\)?if\\>\\)\\|then abort\\\>")
2773 (ada-get-indent-if orgpoint))
2774 ;;
2775 ((looking-at "case\\>")
2776 (ada-get-indent-case orgpoint))
2777 ;;
2778 ((looking-at "when\\>")
2779 (ada-get-indent-when orgpoint))
2780 ;;
2781 ((looking-at "\\(\\sw\\|_\\)+[ \t\n]*:[^=]")
2782 (ada-get-indent-label orgpoint))
2783 ;;
2784 ((looking-at "separate\\>")
2785 (ada-get-indent-nochange))
80d50f88
SM
2786
2787 ;; A label
2788 ((looking-at "<<")
2789 (list (+ (save-excursion (back-to-indentation) (point))
2790 (- ada-label-indent))))
a1506d29 2791
4cc7e498
GM
2792 ;;
2793 ((looking-at "with\\>\\|use\\>")
2794 ;; Are we still in that statement, or are we in fact looking at
2795 ;; the previous one ?
2796 (if (save-excursion (search-forward ";" oldpoint t))
2797 (list (progn (back-to-indentation) (point)) 0)
2798 (list (point) (if (looking-at "with")
2799 'ada-with-indent
2800 'ada-use-indent))))
2801 ;;
2802 (t
2803 (ada-get-indent-noindent orgpoint)))))
2804 ))
972579f9 2805
655880d2
GM
2806(defun ada-get-indent-open-paren ()
2807 "Calculates the indentation when point is behind an unclosed parenthesis."
7749c1a8 2808 (list (ada-in-open-paren-p) 0))
972579f9 2809
655880d2
GM
2810(defun ada-get-indent-nochange ()
2811 "Return the current indentation of the previous line."
972579f9
RS
2812 (save-excursion
2813 (forward-line -1)
655880d2
GM
2814 (back-to-indentation)
2815 (list (point) 0)))
972579f9 2816
655880d2
GM
2817(defun ada-get-indent-paramlist ()
2818 "Calculates the indentation when point is inside a parameter list."
972579f9
RS
2819 (save-excursion
2820 (ada-search-ignore-string-comment "[^ \t\n]" t nil t)
2821 (cond
972579f9 2822 ;; in front of the first parameter
7749c1a8 2823 ((= (char-after) ?\()
972579f9 2824 (goto-char (match-end 0))
7749c1a8 2825 (list (point) 0))
655880d2 2826
972579f9 2827 ;; in front of another parameter
7749c1a8 2828 ((= (char-after) ?\;)
972579f9
RS
2829 (goto-char (cdr (ada-search-ignore-string-comment "(\\|;" t nil t)))
2830 (ada-goto-next-non-ws)
7749c1a8 2831 (list (point) 0))
655880d2 2832
4607c7f4
SM
2833 ;; After an affectation (default parameter value in subprogram
2834 ;; declaration)
2835 ((and (= (following-char) ?=) (= (preceding-char) ?:))
2836 (back-to-indentation)
2837 (list (point) 'ada-broken-indent))
2838
972579f9 2839 ;; inside a parameter declaration
972579f9
RS
2840 (t
2841 (goto-char (cdr (ada-search-ignore-string-comment "(\\|;" t nil t)))
2842 (ada-goto-next-non-ws)
4607c7f4 2843 (list (point) 0)))))
972579f9 2844
655880d2
GM
2845(defun ada-get-indent-end (orgpoint)
2846 "Calculates the indentation when point is just before an end_statement.
2847ORGPOINT is the limit position used in the calculation."
972579f9
RS
2848 (let ((defun-name nil)
2849 (indent nil))
4cc7e498 2850
972579f9 2851 ;; is the line already terminated by ';' ?
972579f9 2852 (if (save-excursion
655880d2 2853 (ada-search-ignore-string-comment ";" nil orgpoint nil
4cc7e498
GM
2854 'search-forward))
2855
972579f9 2856 ;; yes, look what's following 'end'
972579f9
RS
2857 (progn
2858 (forward-word 1)
2859 (ada-goto-next-non-ws)
2860 (cond
4cc7e498
GM
2861 ((looking-at "\\<\\(loop\\|select\\|if\\|case\\)\\>")
2862 (save-excursion (ada-check-matching-start (match-string 0)))
2863 (list (save-excursion (back-to-indentation) (point)) 0))
2864
972579f9
RS
2865 ;;
2866 ;; loop/select/if/case/record/select
2867 ;;
7749c1a8 2868 ((looking-at "\\<record\\>")
972579f9 2869 (save-excursion
7749c1a8 2870 (ada-check-matching-start (match-string 0))
4cc7e498
GM
2871 ;; we are now looking at the matching "record" statement
2872 (forward-word 1)
2873 (ada-goto-stmt-start)
2874 ;; now on the matching type declaration, or use clause
2875 (unless (looking-at "\\(for\\|type\\)\\>")
2876 (ada-search-ignore-string-comment "\\<type\\>" t))
2877 (list (progn (back-to-indentation) (point)) 0)))
972579f9
RS
2878 ;;
2879 ;; a named block end
2880 ;;
f139ce87 2881 ((looking-at ada-ident-re)
36144b26 2882 (setq defun-name (match-string 0))
4cc7e498
GM
2883 (save-excursion
2884 (ada-goto-matching-start 0)
2885 (ada-check-defun-name defun-name))
2886 (list (progn (back-to-indentation) (point)) 0))
972579f9
RS
2887 ;;
2888 ;; a block-end without name
2889 ;;
7749c1a8 2890 ((= (char-after) ?\;)
4cc7e498
GM
2891 (save-excursion
2892 (ada-goto-matching-start 0)
2893 (if (looking-at "\\<begin\\>")
2894 (progn
36144b26 2895 (setq indent (list (point) 0))
4cc7e498
GM
2896 (if (ada-goto-matching-decl-start t)
2897 (list (progn (back-to-indentation) (point)) 0)
4607c7f4
SM
2898 indent))
2899 (list (progn (back-to-indentation) (point)) 0)
2900 )))
972579f9
RS
2901 ;;
2902 ;; anything else - should maybe signal an error ?
2903 ;;
2904 (t
4cc7e498
GM
2905 (list (save-excursion (back-to-indentation) (point))
2906 'ada-broken-indent))))
972579f9 2907
655880d2 2908 (list (save-excursion (back-to-indentation) (point))
4cc7e498 2909 'ada-broken-indent))))
972579f9
RS
2910
2911(defun ada-get-indent-case (orgpoint)
655880d2
GM
2912 "Calculates the indentation when point is just before a case statement.
2913ORGPOINT is the limit position used in the calculation."
7749c1a8 2914 (let ((match-cons nil)
972579f9
RS
2915 (opos (point)))
2916 (cond
2917 ;;
2918 ;; case..is..when..=>
2919 ;;
2920 ((save-excursion
36144b26 2921 (setq match-cons (and
cadd3658
RS
2922 ;; the `=>' must be after the keyword `is'.
2923 (ada-search-ignore-string-comment
7749c1a8 2924 "is" nil orgpoint nil 'word-search-forward)
cadd3658
RS
2925 (ada-search-ignore-string-comment
2926 "[ \t\n]+=>" nil orgpoint))))
972579f9
RS
2927 (save-excursion
2928 (goto-char (car match-cons))
7749c1a8
GM
2929 (unless (ada-search-ignore-string-comment "when" t opos)
2930 (error "missing 'when' between 'case' and '=>'"))
4cc7e498 2931 (list (save-excursion (back-to-indentation) (point)) 'ada-indent)))
972579f9
RS
2932 ;;
2933 ;; case..is..when
2934 ;;
2935 ((save-excursion
36144b26 2936 (setq match-cons (ada-search-ignore-string-comment
7749c1a8 2937 "when" nil orgpoint nil 'word-search-forward)))
972579f9 2938 (goto-char (cdr match-cons))
7749c1a8 2939 (list (save-excursion (back-to-indentation) (point)) 'ada-broken-indent))
972579f9
RS
2940 ;;
2941 ;; case..is
2942 ;;
2943 ((save-excursion
36144b26 2944 (setq match-cons (ada-search-ignore-string-comment
7749c1a8
GM
2945 "is" nil orgpoint nil 'word-search-forward)))
2946 (list (save-excursion (back-to-indentation) (point)) 'ada-when-indent))
972579f9
RS
2947 ;;
2948 ;; incomplete case
2949 ;;
2950 (t
655880d2 2951 (list (save-excursion (back-to-indentation) (point))
4cc7e498 2952 'ada-broken-indent)))))
972579f9
RS
2953
2954(defun ada-get-indent-when (orgpoint)
4cc7e498 2955 "Calculates the indentation when point is just before a when statement.
655880d2 2956ORGPOINT is the limit position used in the calculation."
7749c1a8 2957 (let ((cur-indent (save-excursion (back-to-indentation) (point))))
655880d2 2958 (if (ada-search-ignore-string-comment "[ \t\n]*=>" nil orgpoint)
4cc7e498 2959 (list cur-indent 'ada-indent)
7749c1a8 2960 (list cur-indent 'ada-broken-indent))))
972579f9 2961
972579f9 2962(defun ada-get-indent-if (orgpoint)
655880d2
GM
2963 "Calculates the indentation when point is just before an if statement.
2964ORGPOINT is the limit position used in the calculation."
7749c1a8 2965 (let ((cur-indent (save-excursion (back-to-indentation) (point)))
972579f9
RS
2966 (match-cons nil))
2967 ;;
7749c1a8 2968 ;; Move to the correct then (ignore all "and then")
972579f9 2969 ;;
36144b26 2970 (while (and (setq match-cons (ada-search-ignore-string-comment
7749c1a8
GM
2971 "\\<\\(then\\|and[ \t]*then\\)\\>"
2972 nil orgpoint))
4607c7f4 2973 (= (downcase (char-after (car match-cons))) ?a)))
7749c1a8
GM
2974 ;; If "then" was found (we are looking at it)
2975 (if match-cons
972579f9
RS
2976 (progn
2977 ;;
2978 ;; 'then' first in separate line ?
7749c1a8 2979 ;; => indent according to 'then',
4cc7e498 2980 ;; => else indent according to 'if'
972579f9
RS
2981 ;;
2982 (if (save-excursion
2983 (back-to-indentation)
2984 (looking-at "\\<then\\>"))
36144b26 2985 (setq cur-indent (save-excursion (back-to-indentation) (point))))
4cc7e498 2986 ;; skip 'then'
972579f9 2987 (forward-word 1)
4cc7e498 2988 (list cur-indent 'ada-indent))
972579f9 2989
7749c1a8 2990 (list cur-indent 'ada-broken-indent))))
972579f9 2991
972579f9 2992(defun ada-get-indent-block-start (orgpoint)
655880d2
GM
2993 "Calculates the indentation when point is at the start of a block.
2994ORGPOINT is the limit position used in the calculation."
7749c1a8 2995 (let ((pos nil))
972579f9
RS
2996 (cond
2997 ((save-excursion
2998 (forward-word 1)
36144b26 2999 (setq pos (ada-goto-next-non-ws orgpoint)))
972579f9
RS
3000 (goto-char pos)
3001 (save-excursion
7749c1a8 3002 (ada-indent-on-previous-lines t orgpoint)))
655880d2 3003
4607c7f4
SM
3004 ;; Special case for record types, for instance for:
3005 ;; type A is (B : Integer;
3006 ;; C : Integer) is record
3007 ;; null; -- This is badly indented otherwise
3008 ((looking-at "record")
3009
3010 ;; If record is at the beginning of the line, indent from there
3011 (if (save-excursion
3012 (beginning-of-line)
3013 (looking-at "^[ \t]*\\(record\\|limited record\\)"))
3014 (list (save-excursion (back-to-indentation) (point)) 'ada-indent)
3015
3016 ;; else indent relative to the type command
3017 (list (save-excursion
3018 (car (ada-search-ignore-string-comment "\\<type\\>" t)))
3019 'ada-indent)))
3020
972579f9 3021 ;; nothing follows the block-start
972579f9 3022 (t
7749c1a8 3023 (list (save-excursion (back-to-indentation) (point)) 'ada-indent)))))
972579f9 3024
972579f9 3025(defun ada-get-indent-subprog (orgpoint)
655880d2
GM
3026 "Calculates the indentation when point is just before a subprogram.
3027ORGPOINT is the limit position used in the calculation."
972579f9 3028 (let ((match-cons nil)
7749c1a8
GM
3029 (cur-indent (save-excursion (back-to-indentation) (point)))
3030 (foundis nil))
972579f9
RS
3031 ;;
3032 ;; is there an 'is' in front of point ?
3033 ;;
3034 (if (save-excursion
36144b26 3035 (setq match-cons
7749c1a8
GM
3036 (ada-search-ignore-string-comment
3037 "\\<\\(is\\|do\\)\\>" nil orgpoint)))
972579f9
RS
3038 ;;
3039 ;; yes, then skip to its end
3040 ;;
3041 (progn
36144b26 3042 (setq foundis t)
972579f9
RS
3043 (goto-char (cdr match-cons)))
3044 ;;
3045 ;; no, then goto next non-ws, if there is one in front of point
3046 ;;
3047 (progn
7749c1a8 3048 (unless (ada-goto-next-non-ws orgpoint)
972579f9
RS
3049 (goto-char orgpoint))))
3050
3051 (cond
3052 ;;
3053 ;; nothing follows 'is'
3054 ;;
3055 ((and
3056 foundis
3057 (save-excursion
3058 (not (ada-search-ignore-string-comment
3059 "[^ \t\n]" nil orgpoint t))))
7749c1a8 3060 (list cur-indent 'ada-indent))
972579f9
RS
3061 ;;
3062 ;; is abstract/separate/new ...
3063 ;;
3064 ((and
3065 foundis
3066 (save-excursion
36144b26 3067 (setq match-cons
7749c1a8
GM
3068 (ada-search-ignore-string-comment
3069 "\\<\\(separate\\|new\\|abstract\\)\\>"
3070 nil orgpoint))))
972579f9 3071 (goto-char (car match-cons))
276c1210 3072 (ada-search-ignore-string-comment ada-subprog-start-re t)
972579f9
RS
3073 (ada-get-indent-noindent orgpoint))
3074 ;;
3075 ;; something follows 'is'
3076 ;;
3077 ((and
3078 foundis
36144b26 3079 (save-excursion (setq match-cons (ada-goto-next-non-ws orgpoint)))
7749c1a8
GM
3080 (goto-char match-cons)
3081 (ada-indent-on-previous-lines t orgpoint)))
972579f9
RS
3082 ;;
3083 ;; no 'is' but ';'
3084 ;;
3085 ((save-excursion
4cc7e498 3086 (ada-search-ignore-string-comment ";" nil orgpoint nil 'search-forward))
7749c1a8 3087 (list cur-indent 0))
972579f9
RS
3088 ;;
3089 ;; no 'is' or ';'
3090 ;;
3091 (t
7749c1a8 3092 (list cur-indent 'ada-broken-indent)))))
972579f9 3093
972579f9 3094(defun ada-get-indent-noindent (orgpoint)
655880d2
GM
3095 "Calculates the indentation when point is just before a 'noindent stmt'.
3096ORGPOINT is the limit position used in the calculation."
cadd3658
RS
3097 (let ((label 0))
3098 (save-excursion
3099 (beginning-of-line)
972579f9 3100
7749c1a8
GM
3101 (cond
3102
4cc7e498 3103 ;; This one is called when indenting a line preceded by a multi-line
7749c1a8
GM
3104 ;; subprogram declaration (in that case, we are at this point inside
3105 ;; the parameter declaration list)
3106 ((ada-in-paramlist-p)
3107 (ada-previous-procedure)
4cc7e498 3108 (list (save-excursion (back-to-indentation) (point)) 0))
7749c1a8 3109
655880d2 3110 ;; This one is called when indenting the second line of a multi-line
7749c1a8
GM
3111 ;; declaration section, in a declare block or a record declaration
3112 ((looking-at "[ \t]*\\(\\sw\\|_\\)*[ \t]*,[ \t]*$")
4cc7e498
GM
3113 (list (save-excursion (back-to-indentation) (point))
3114 'ada-broken-decl-indent))
7749c1a8
GM
3115
3116 ;; This one is called in every over case when indenting a line at the
3117 ;; top level
3118 (t
3119 (if (looking-at ada-named-block-re)
36144b26 3120 (setq label (- ada-label-indent))
7749c1a8 3121
4cc7e498
GM
3122 (let (p)
3123
3124 ;; "with private" or "null record" cases
3125 (if (or (save-excursion
3126 (and (ada-search-ignore-string-comment "\\<private\\>" nil orgpoint)
36144b26 3127 (setq p (point))
4cc7e498
GM
3128 (save-excursion (forward-char -7);; skip back "private"
3129 (ada-goto-previous-word)
3130 (looking-at "with"))))
3131 (save-excursion
3132 (and (ada-search-ignore-string-comment "\\<record\\>" nil orgpoint)
36144b26 3133 (setq p (point))
4cc7e498
GM
3134 (save-excursion (forward-char -6);; skip back "record"
3135 (ada-goto-previous-word)
3136 (looking-at "null")))))
3137 (progn
3138 (goto-char p)
3139 (re-search-backward "\\<\\(type\\|subtype\\)\\>" nil t)
3140 (list (save-excursion (back-to-indentation) (point)) 0)))))
7749c1a8 3141 (if (save-excursion
4cc7e498
GM
3142 (ada-search-ignore-string-comment ";" nil orgpoint nil
3143 'search-forward))
3144 (list (+ (save-excursion (back-to-indentation) (point)) label) 0)
3145 (list (+ (save-excursion (back-to-indentation) (point)) label)
3146 'ada-broken-indent)))))))
972579f9
RS
3147
3148(defun ada-get-indent-label (orgpoint)
655880d2
GM
3149 "Calculates the indentation when before a label or variable declaration.
3150ORGPOINT is the limit position used in the calculation."
972579f9 3151 (let ((match-cons nil)
7749c1a8
GM
3152 (cur-indent (save-excursion (back-to-indentation) (point))))
3153 (ada-search-ignore-string-comment ":" nil)
972579f9 3154 (cond
972579f9 3155 ;; loop label
972579f9 3156 ((save-excursion
36144b26 3157 (setq match-cons (ada-search-ignore-string-comment
4cc7e498 3158 ada-loop-start-re nil orgpoint)))
972579f9
RS
3159 (goto-char (car match-cons))
3160 (ada-get-indent-loop orgpoint))
7749c1a8 3161
972579f9 3162 ;; declare label
972579f9 3163 ((save-excursion
36144b26 3164 (setq match-cons (ada-search-ignore-string-comment
4cc7e498 3165 "\\<declare\\|begin\\>" nil orgpoint)))
7749c1a8
GM
3166 (goto-char (car match-cons))
3167 (list (save-excursion (back-to-indentation) (point)) 'ada-indent))
3168
3169 ;; variable declaration
3170 ((ada-in-decl-p)
3171 (if (save-excursion
3172 (ada-search-ignore-string-comment ";" nil orgpoint))
3173 (list cur-indent 0)
4cc7e498 3174 (list cur-indent 'ada-broken-indent)))
7749c1a8 3175
972579f9 3176 ;; nothing follows colon
972579f9 3177 (t
7749c1a8 3178 (list cur-indent '(- ada-label-indent))))))
972579f9
RS
3179
3180(defun ada-get-indent-loop (orgpoint)
655880d2
GM
3181 "Calculates the indentation when just before a loop or a for ... use.
3182ORGPOINT is the limit position used in the calculation."
972579f9 3183 (let ((match-cons nil)
cadd3658 3184 (pos (point))
7749c1a8 3185
4cc7e498 3186 ;; If looking at a named block, skip the label
cadd3658
RS
3187 (label (save-excursion
3188 (beginning-of-line)
3189 (if (looking-at ada-named-block-re)
3190 (- ada-label-indent)
3191 0))))
7749c1a8 3192
972579f9
RS
3193 (cond
3194
3195 ;;
3196 ;; statement complete
3197 ;;
3198 ((save-excursion
655880d2 3199 (ada-search-ignore-string-comment ";" nil orgpoint nil
4cc7e498 3200 'search-forward))
7749c1a8 3201 (list (+ (save-excursion (back-to-indentation) (point)) label) 0))
972579f9
RS
3202 ;;
3203 ;; simple loop
3204 ;;
3205 ((looking-at "loop\\>")
36144b26 3206 (setq pos (ada-get-indent-block-start orgpoint))
7749c1a8 3207 (if (equal label 0)
4cc7e498
GM
3208 pos
3209 (list (+ (car pos) label) (cdr pos))))
972579f9
RS
3210
3211 ;;
3212 ;; 'for'- loop (or also a for ... use statement)
3213 ;;
3214 ((looking-at "for\\>")
3215 (cond
3216 ;;
3217 ;; for ... use
3218 ;;
3219 ((save-excursion
3220 (and
3221 (goto-char (match-end 0))
7749c1a8
GM
3222 (ada-goto-next-non-ws orgpoint)
3223 (forward-word 1)
3224 (if (= (char-after) ?') (forward-word 1) t)
3225 (ada-goto-next-non-ws orgpoint)
972579f9
RS
3226 (looking-at "\\<use\\>")
3227 ;;
3228 ;; check if there is a 'record' before point
3229 ;;
3230 (progn
36144b26 3231 (setq match-cons (ada-search-ignore-string-comment
7749c1a8 3232 "record" nil orgpoint nil 'word-search-forward))
972579f9
RS
3233 t)))
3234 (if match-cons
f7a80909
JB
3235 (progn
3236 (goto-char (car match-cons))
3237 (list (save-excursion (back-to-indentation) (point)) 'ada-indent))
3238 (list (save-excursion (back-to-indentation) (point)) 'ada-broken-indent))
3239 )
3240
972579f9
RS
3241 ;;
3242 ;; for..loop
3243 ;;
3244 ((save-excursion
36144b26 3245 (setq match-cons (ada-search-ignore-string-comment
7749c1a8 3246 "loop" nil orgpoint nil 'word-search-forward)))
972579f9
RS
3247 (goto-char (car match-cons))
3248 ;;
3249 ;; indent according to 'loop', if it's first in the line;
3250 ;; otherwise to 'for'
3251 ;;
7749c1a8
GM
3252 (unless (save-excursion
3253 (back-to-indentation)
3254 (looking-at "\\<loop\\>"))
3255 (goto-char pos))
4cc7e498
GM
3256 (list (+ (save-excursion (back-to-indentation) (point)) label)
3257 'ada-indent))
972579f9
RS
3258 ;;
3259 ;; for-statement is broken
3260 ;;
3261 (t
4cc7e498
GM
3262 (list (+ (save-excursion (back-to-indentation) (point)) label)
3263 'ada-broken-indent))))
972579f9
RS
3264
3265 ;;
3266 ;; 'while'-loop
3267 ;;
3268 ((looking-at "while\\>")
3269 ;;
3270 ;; while..loop ?
3271 ;;
3272 (if (save-excursion
36144b26 3273 (setq match-cons (ada-search-ignore-string-comment
7749c1a8 3274 "loop" nil orgpoint nil 'word-search-forward)))
972579f9
RS
3275
3276 (progn
3277 (goto-char (car match-cons))
3278 ;;
3279 ;; indent according to 'loop', if it's first in the line;
3280 ;; otherwise to 'while'.
3281 ;;
7749c1a8
GM
3282 (unless (save-excursion
3283 (back-to-indentation)
3284 (looking-at "\\<loop\\>"))
3285 (goto-char pos))
4cc7e498
GM
3286 (list (+ (save-excursion (back-to-indentation) (point)) label)
3287 'ada-indent))
972579f9 3288
4cc7e498
GM
3289 (list (+ (save-excursion (back-to-indentation) (point)) label)
3290 'ada-broken-indent))))))
972579f9
RS
3291
3292(defun ada-get-indent-type (orgpoint)
655880d2
GM
3293 "Calculates the indentation when before a type statement.
3294ORGPOINT is the limit position used in the calculation."
972579f9
RS
3295 (let ((match-dat nil))
3296 (cond
3297 ;;
3298 ;; complete record declaration
3299 ;;
3300 ((save-excursion
3301 (and
36144b26 3302 (setq match-dat (ada-search-ignore-string-comment
7749c1a8 3303 "end" nil orgpoint nil 'word-search-forward))
972579f9
RS
3304 (ada-goto-next-non-ws)
3305 (looking-at "\\<record\\>")
3306 (forward-word 1)
3307 (ada-goto-next-non-ws)
7749c1a8 3308 (= (char-after) ?\;)))
972579f9 3309 (goto-char (car match-dat))
7749c1a8 3310 (list (save-excursion (back-to-indentation) (point)) 0))
972579f9
RS
3311 ;;
3312 ;; record type
3313 ;;
3314 ((save-excursion
36144b26 3315 (setq match-dat (ada-search-ignore-string-comment
7749c1a8 3316 "record" nil orgpoint nil 'word-search-forward)))
972579f9 3317 (goto-char (car match-dat))
7749c1a8 3318 (list (save-excursion (back-to-indentation) (point)) 'ada-indent))
972579f9
RS
3319 ;;
3320 ;; complete type declaration
3321 ;;
3322 ((save-excursion
655880d2 3323 (ada-search-ignore-string-comment ";" nil orgpoint nil
4cc7e498 3324 'search-forward))
7749c1a8 3325 (list (save-excursion (back-to-indentation) (point)) 0))
972579f9 3326 ;;
f139ce87 3327 ;; "type ... is", but not "type ... is ...", which is broken
972579f9
RS
3328 ;;
3329 ((save-excursion
7749c1a8 3330 (and
655880d2 3331 (ada-search-ignore-string-comment "is" nil orgpoint nil
4cc7e498 3332 'word-search-forward)
7749c1a8
GM
3333 (not (ada-goto-next-non-ws orgpoint))))
3334 (list (save-excursion (back-to-indentation) (point)) 'ada-broken-indent))
972579f9
RS
3335 ;;
3336 ;; broken statement
3337 ;;
3338 (t
655880d2 3339 (list (save-excursion (back-to-indentation) (point))
4cc7e498 3340 'ada-broken-indent)))))
972579f9
RS
3341
3342\f
655880d2
GM
3343;; -----------------------------------------------------------
3344;; -- searching and matching
3345;; -----------------------------------------------------------
3346
3347(defun ada-goto-stmt-start ()
3348 "Moves point to the beginning of the statement that point is in or after.
3349Returns the new position of point.
3350As a special case, if we are looking at a closing parenthesis, skip to the
3351open parenthesis."
972579f9
RS
3352 (let ((match-dat nil)
3353 (orgpoint (point)))
3354
36144b26 3355 (setq match-dat (ada-search-prev-end-stmt))
972579f9 3356 (if match-dat
eaae8106 3357
4cc7e498
GM
3358 ;;
3359 ;; found a previous end-statement => check if anything follows
3360 ;;
3361 (unless (looking-at "declare")
3362 (progn
3363 (unless (save-excursion
3364 (goto-char (cdr match-dat))
3365 (ada-goto-next-non-ws orgpoint))
3366 ;;
3367 ;; nothing follows => it's the end-statement directly in
3368 ;; front of point => search again
3369 ;;
36144b26 3370 (setq match-dat (ada-search-prev-end-stmt)))
4cc7e498
GM
3371 ;;
3372 ;; if found the correct end-statement => goto next non-ws
3373 ;;
3374 (if match-dat
3375 (goto-char (cdr match-dat)))
3376 (ada-goto-next-non-ws)
3377 ))
eaae8106 3378
972579f9
RS
3379 ;;
3380 ;; no previous end-statement => we are at the beginning of the
3381 ;; accessible part of the buffer
3382 ;;
3383 (progn
4cc7e498
GM
3384 (goto-char (point-min))
3385 ;;
3386 ;; skip to the very first statement, if there is one
3387 ;;
3388 (unless (ada-goto-next-non-ws orgpoint)
3389 (goto-char orgpoint))))
972579f9
RS
3390 (point)))
3391
3392
655880d2
GM
3393(defun ada-search-prev-end-stmt ()
3394 "Moves point to previous end-statement.
3395Returns a cons cell whose car is the beginning and whose cdr the end of the
3396match."
972579f9 3397 (let ((match-dat nil)
4cc7e498 3398 (found nil))
7749c1a8 3399
972579f9 3400 ;; search until found or beginning-of-buffer
972579f9
RS
3401 (while
3402 (and
3403 (not found)
36144b26 3404 (setq match-dat (ada-search-ignore-string-comment
655880d2 3405 ada-end-stmt-re t)))
972579f9
RS
3406
3407 (goto-char (car match-dat))
7749c1a8 3408 (unless (ada-in-open-paren-p)
80d50f88 3409 (cond
a1506d29 3410
80d50f88
SM
3411 ((and (looking-at
3412 "\\<\\(record\\|loop\\|select\\|else\\|then\\)\\>")
3413 (save-excursion
3414 (ada-goto-previous-word)
3415 (looking-at "\\<\\(end\\|or\\|and\\)\\>[ \t]*[^;]")))
3416 (forward-word -1))
3417
3418 ((looking-at "is")
3419 (setq found
3420 (and (save-excursion (ada-goto-previous-word)
3421 (ada-goto-previous-word)
3422 (not (looking-at "subtype")))
a1506d29 3423
80d50f88
SM
3424 (save-excursion (goto-char (cdr match-dat))
3425 (ada-goto-next-non-ws)
3426 ;; words that can go after an 'is'
3427 (not (looking-at
3428 (eval-when-compile
3429 (concat "\\<"
3430 (regexp-opt
3431 '("separate" "access" "array"
3432 "abstract" "new") t)
3433 "\\>\\|("))))))))
a1506d29 3434
80d50f88
SM
3435 (t
3436 (setq found t))
3437 )))
972579f9
RS
3438
3439 (if found
3440 match-dat
3441 nil)))
3442
3443
3444(defun ada-goto-next-non-ws (&optional limit)
655880d2
GM
3445 "Skips white spaces, newlines and comments to next non-ws character.
3446Stop the search at LIMIT.
7749c1a8
GM
3447Do not call this function from within a string."
3448 (unless limit
36144b26 3449 (setq limit (point-max)))
7749c1a8
GM
3450 (while (and (<= (point) limit)
3451 (progn (forward-comment 10000)
3452 (if (and (not (eobp))
3453 (save-excursion (forward-char 1)
3454 (ada-in-string-p)))
3455 (progn (forward-sexp 1) t)))))
3456 (if (< (point) limit)
3457 (point)
3458 nil)
3459 )
972579f9
RS
3460
3461
3462(defun ada-goto-stmt-end (&optional limit)
655880d2
GM
3463 "Moves point to the end of the statement that point is in or before.
3464Returns the new position of point or nil if not found.
3465Stop the search at LIMIT."
972579f9
RS
3466 (if (ada-search-ignore-string-comment ada-end-stmt-re nil limit)
3467 (point)
3468 nil))
3469
3470
cadd3658 3471(defun ada-goto-next-word (&optional backward)
655880d2
GM
3472 "Moves point to the beginning of the next word of Ada code.
3473If BACKWARD is non-nil, jump to the beginning of the previous word.
3474Returns the new position of point or nil if not found."
972579f9 3475 (let ((match-cons nil)
7749c1a8
GM
3476 (orgpoint (point))
3477 (old-syntax (char-to-string (char-syntax ?_))))
3478 (modify-syntax-entry ?_ "w")
3479 (unless backward
4cc7e498 3480 (skip-syntax-forward "w"))
36144b26 3481 (if (setq match-cons
7749c1a8
GM
3482 (if backward
3483 (ada-search-ignore-string-comment "\\w" t nil t)
3484 (ada-search-ignore-string-comment "\\w" nil nil t)))
972579f9
RS
3485 ;;
3486 ;; move to the beginning of the word found
3487 ;;
3488 (progn
cadd3658 3489 (goto-char (car match-cons))
7749c1a8 3490 (skip-syntax-backward "w")
972579f9
RS
3491 (point))
3492 ;;
3493 ;; if not found, restore old position of point
3494 ;;
7749c1a8
GM
3495 (goto-char orgpoint)
3496 'nil)
3497 (modify-syntax-entry ?_ old-syntax))
3498 )
972579f9
RS
3499
3500
3501(defun ada-check-matching-start (keyword)
655880d2
GM
3502 "Signals an error if matching block start is not KEYWORD.
3503Moves point to the matching block start."
972579f9 3504 (ada-goto-matching-start 0)
7749c1a8
GM
3505 (unless (looking-at (concat "\\<" keyword "\\>"))
3506 (error "matching start is not '%s'" keyword)))
972579f9
RS
3507
3508
3509(defun ada-check-defun-name (defun-name)
655880d2
GM
3510 "Checks if the name of the matching defun really is DEFUN-NAME.
3511Assumes point to be already positioned by 'ada-goto-matching-start'.
3512Moves point to the beginning of the declaration."
972579f9 3513
cadd3658 3514 ;; named block without a `declare'
cadd3658
RS
3515 (if (save-excursion
3516 (ada-goto-previous-word)
3517 (looking-at (concat "\\<" defun-name "\\> *:")))
7749c1a8 3518 t ; do nothing
972579f9 3519 ;;
cadd3658 3520 ;; 'accept' or 'package' ?
972579f9 3521 ;;
4cc7e498 3522 (unless (looking-at ada-subprog-start-re)
7749c1a8 3523 (ada-goto-matching-decl-start))
cadd3658
RS
3524 ;;
3525 ;; 'begin' of 'procedure'/'function'/'task' or 'declare'
3526 ;;
3527 (save-excursion
972579f9 3528 ;;
cadd3658 3529 ;; a named 'declare'-block ?
972579f9 3530 ;;
cadd3658
RS
3531 (if (looking-at "\\<declare\\>")
3532 (ada-goto-stmt-start)
972579f9 3533 ;;
cadd3658 3534 ;; no, => 'procedure'/'function'/'task'/'protected'
972579f9 3535 ;;
cadd3658
RS
3536 (progn
3537 (forward-word 2)
3538 (backward-word 1)
3539 ;;
3540 ;; skip 'body' 'type'
3541 ;;
3542 (if (looking-at "\\<\\(body\\|type\\)\\>")
3543 (forward-word 1))
3544 (forward-sexp 1)
3545 (backward-sexp 1)))
3546 ;;
3547 ;; should be looking-at the correct name
3548 ;;
7749c1a8
GM
3549 (unless (looking-at (concat "\\<" defun-name "\\>"))
3550 (error "matching defun has different name: %s"
3551 (buffer-substring (point)
3552 (progn (forward-sexp 1) (point))))))))
972579f9 3553
4cc7e498 3554(defun ada-goto-matching-decl-start (&optional noerror recursive)
655880d2
GM
3555 "Moves point to the matching declaration start of the current 'begin'.
3556If NOERROR is non-nil, it only returns nil if no match was found."
972579f9 3557 (let ((nest-count 1)
4607c7f4
SM
3558
3559 ;; first should be set to t if we should stop at the first
3560 ;; "begin" we encounter.
4cc7e498 3561 (first (not recursive))
7749c1a8 3562 (count-generic nil)
6f9a2614 3563 (stop-at-when nil)
7749c1a8
GM
3564 )
3565
4cc7e498
GM
3566 ;; Ignore "when" most of the time, except if we are looking at the
3567 ;; beginning of a block (structure: case .. is
3568 ;; when ... =>
3569 ;; begin ...
3570 ;; exception ... )
3571 (if (looking-at "begin")
36144b26 3572 (setq stop-at-when t))
4cc7e498 3573
7749c1a8
GM
3574 (if (or
3575 (looking-at "\\<\\(package\\|procedure\\|function\\)\\>")
3576 (save-excursion
655880d2 3577 (ada-search-ignore-string-comment
4cc7e498 3578 "\\<\\(package\\|procedure\\|function\\|generic\\)\\>" t)
7749c1a8 3579 (looking-at "generic")))
36144b26 3580 (setq count-generic t))
7749c1a8 3581
972579f9 3582 ;; search backward for interesting keywords
972579f9
RS
3583 (while (and
3584 (not (zerop nest-count))
7749c1a8 3585 (ada-search-ignore-string-comment ada-matching-decl-start-re t))
972579f9
RS
3586 ;;
3587 ;; calculate nest-depth
3588 ;;
3589 (cond
3590 ;;
3591 ((looking-at "end")
3592 (ada-goto-matching-start 1 noerror)
7749c1a8 3593
4cc7e498
GM
3594 ;; In some case, two begin..end block can follow each other closely,
3595 ;; which we have to detect, as in
3596 ;; procedure P is
3597 ;; procedure Q is
3598 ;; begin
3599 ;; end;
7749c1a8 3600 ;; begin -- here we should go to procedure, not begin
4cc7e498
GM
3601 ;; end
3602
3603 (if (looking-at "begin")
3604 (let ((loop-again t))
3605 (save-excursion
3606 (while loop-again
3607 ;; If begin was just there as the beginning of a block
3608 ;; (with no declare) then do nothing, otherwise just
3609 ;; register that we have to find the statement that
3610 ;; required the begin
3611
3612 (ada-search-ignore-string-comment
3613 "\\<\\(declare\\|begin\\|end\\|procedure\\|function\\|task\\|package\\)\\>"
3614 t)
3615
3616 (if (looking-at "end")
4607c7f4
SM
3617 (ada-goto-matching-start 1 noerror t)
3618 ;; (ada-goto-matching-decl-start noerror t)
4cc7e498 3619
36144b26 3620 (setq loop-again nil)
4cc7e498 3621 (unless (looking-at "begin")
36144b26 3622 (setq nest-count (1+ nest-count))))
4cc7e498
GM
3623 ))
3624 )))
7749c1a8
GM
3625 ;;
3626 ((looking-at "generic")
3627 (if count-generic
3628 (progn
36144b26
SM
3629 (setq first nil)
3630 (setq nest-count (1- nest-count)))))
972579f9 3631 ;;
4cc7e498
GM
3632 ((looking-at "if")
3633 (save-excursion
3634 (forward-word -1)
3635 (unless (looking-at "\\<end[ \t\n]*if\\>")
3636 (progn
36144b26
SM
3637 (setq nest-count (1- nest-count))
3638 (setq first nil)))))
eaae8106 3639
4cc7e498
GM
3640 ;;
3641 ((looking-at "declare\\|generic")
36144b26 3642 (setq nest-count (1- nest-count))
4607c7f4 3643 (setq first t))
972579f9
RS
3644 ;;
3645 ((looking-at "is")
276c1210
RS
3646 ;; check if it is only a type definition, but not a protected
3647 ;; type definition, which should be handled like a procedure.
7749c1a8 3648 (if (or (looking-at "is[ \t]+<>")
cadd3658 3649 (save-excursion
7749c1a8
GM
3650 (forward-comment -10000)
3651 (forward-char -1)
3652
3653 ;; Detect if we have a closing parenthesis (Could be
3654 ;; either the end of subprogram parameters or (<>)
3655 ;; in a type definition
3656 (if (= (char-after) ?\))
cadd3658
RS
3657 (progn
3658 (forward-char 1)
3659 (backward-sexp 1)
7749c1a8 3660 (forward-comment -10000)
cadd3658 3661 ))
7749c1a8 3662 (skip-chars-backward "a-zA-Z0-9_.'")
cadd3658 3663 (ada-goto-previous-word)
7749c1a8 3664 (and
f7a80909 3665 (looking-at "\\<\\(sub\\)?type\\|case\\>")
cadd3658
RS
3666 (save-match-data
3667 (ada-goto-previous-word)
3668 (not (looking-at "\\<protected\\>"))))
7749c1a8 3669 )) ; end of `or'
972579f9
RS
3670 (goto-char (match-beginning 0))
3671 (progn
36144b26
SM
3672 (setq nest-count (1- nest-count))
3673 (setq first nil))))
972579f9
RS
3674
3675 ;;
3676 ((looking-at "new")
3677 (if (save-excursion
3678 (ada-goto-previous-word)
3679 (looking-at "is"))
3680 (goto-char (match-beginning 0))))
3681 ;;
3682 ((and first
3683 (looking-at "begin"))
36144b26 3684 (setq nest-count 0))
4cc7e498
GM
3685 ;;
3686 ((looking-at "when")
4607c7f4
SM
3687 (save-excursion
3688 (forward-word -1)
3689 (unless (looking-at "\\<exit[ \t\n]*when\\>")
3690 (progn
3691 (if stop-at-when
3692 (setq nest-count (1- nest-count)))
f7a80909 3693 ))))
4607c7f4
SM
3694 ;;
3695 ((looking-at "begin")
3696 (setq first nil))
972579f9
RS
3697 ;;
3698 (t
36144b26
SM
3699 (setq nest-count (1+ nest-count))
3700 (setq first nil)))
972579f9 3701
7749c1a8 3702 );; end of loop
972579f9
RS
3703
3704 ;; check if declaration-start is really found
7749c1a8
GM
3705 (if (and
3706 (zerop nest-count)
7749c1a8
GM
3707 (if (looking-at "is")
3708 (ada-search-ignore-string-comment ada-subprog-start-re t)
3709 (looking-at "declare\\|generic")))
3710 t
3711 (if noerror nil
3712 (error "no matching proc/func/task/declare/package/protected")))
3713 ))
972579f9
RS
3714
3715(defun ada-goto-matching-start (&optional nest-level noerror gotothen)
655880d2
GM
3716 "Moves point to the beginning of a block-start.
3717Which block depends on the value of NEST-LEVEL, which defaults to zero. If
3718NOERROR is non-nil, it only returns nil if no matching start was found.
3719If GOTOTHEN is non-nil, point moves to the 'then' following 'if'."
972579f9
RS
3720 (let ((nest-count (if nest-level nest-level 0))
3721 (found nil)
3722 (pos nil))
3723
3724 ;;
3725 ;; search backward for interesting keywords
3726 ;;
3727 (while (and
3728 (not found)
7749c1a8
GM
3729 (ada-search-ignore-string-comment ada-matching-start-re t))
3730
3731 (unless (and (looking-at "\\<record\\>")
3732 (save-excursion
3733 (forward-word -1)
3734 (looking-at "\\<null\\>")))
3735 (progn
3736 ;;
3737 ;; calculate nest-depth
3738 ;;
3739 (cond
3740 ;; found block end => increase nest depth
3741 ((looking-at "end")
36144b26 3742 (setq nest-count (1+ nest-count)))
7749c1a8
GM
3743
3744 ;; found loop/select/record/case/if => check if it starts or
3745 ;; ends a block
3746 ((looking-at "loop\\|select\\|record\\|case\\|if")
36144b26 3747 (setq pos (point))
7749c1a8
GM
3748 (save-excursion
3749 ;;
3750 ;; check if keyword follows 'end'
3751 ;;
3752 (ada-goto-previous-word)
3753 (if (looking-at "\\<end\\>[ \t]*[^;]")
3754 ;; it ends a block => increase nest depth
4607c7f4
SM
3755 (setq nest-count (1+ nest-count)
3756 pos (point))
a1506d29 3757
7749c1a8 3758 ;; it starts a block => decrease nest depth
36144b26 3759 (setq nest-count (1- nest-count))))
7749c1a8
GM
3760 (goto-char pos))
3761
3762 ;; found package start => check if it really is a block
3763 ((looking-at "package")
3764 (save-excursion
3765 ;; ignore if this is just a renames statement
3766 (let ((current (point))
3767 (pos (ada-search-ignore-string-comment
3768 "\\<\\(is\\|renames\\|;\\)\\>" nil)))
3769 (if pos
3770 (goto-char (car pos))
3771 (error (concat
655880d2 3772 "No matching 'is' or 'renames' for 'package' at"
4cc7e498 3773 " line "
80d50f88 3774 (number-to-string (count-lines 1 (1+ current)))))))
7749c1a8
GM
3775 (unless (looking-at "renames")
3776 (progn
3777 (forward-word 1)
3778 (ada-goto-next-non-ws)
3779 ;; ignore it if it is only a declaration with 'new'
4607c7f4
SM
3780 ;; We could have package Foo is new ....
3781 ;; or package Foo is separate;
3782 ;; or package Foo is begin null; end Foo
3783 ;; for elaboration code (elaboration)
3784 (if (not (looking-at "\\<\\(new\\|separate\\|begin\\)\\>"))
36144b26 3785 (setq nest-count (1- nest-count)))))))
7749c1a8
GM
3786 ;; found task start => check if it has a body
3787 ((looking-at "task")
3788 (save-excursion
3789 (forward-word 1)
3790 (ada-goto-next-non-ws)
3791 (cond
3792 ((looking-at "\\<body\\>"))
3793 ((looking-at "\\<type\\>")
3794 ;; In that case, do nothing if there is a "is"
3795 (forward-word 2);; skip "type"
3796 (ada-goto-next-non-ws);; skip type name
3797
4cc7e498
GM
3798 ;; Do nothing if we are simply looking at a simple
3799 ;; "task type name;" statement with no block
3800 (unless (looking-at ";")
3801 (progn
3802 ;; Skip the parameters
3803 (if (looking-at "(")
3804 (ada-search-ignore-string-comment ")" nil))
3805 (let ((tmp (ada-search-ignore-string-comment
3806 "\\<\\(is\\|;\\)\\>" nil)))
3807 (if tmp
3808 (progn
3809 (goto-char (car tmp))
3810 (if (looking-at "is")
36144b26 3811 (setq nest-count (1- nest-count)))))))))
7749c1a8 3812 (t
4cc7e498
GM
3813 ;; Check if that task declaration had a block attached to
3814 ;; it (i.e do nothing if we have just "task name;")
3815 (unless (progn (forward-word 1)
3816 (looking-at "[ \t]*;"))
36144b26 3817 (setq nest-count (1- nest-count)))))))
7749c1a8
GM
3818 ;; all the other block starts
3819 (t
36144b26 3820 (setq nest-count (1- nest-count)))) ; end of 'cond'
972579f9 3821
7749c1a8 3822 ;; match is found, if nest-depth is zero
972579f9 3823 ;;
36144b26 3824 (setq found (zerop nest-count))))) ; end of loop
972579f9 3825
4607c7f4
SM
3826 (if (bobp)
3827 (point)
3828 (if found
3829 ;;
3830 ;; match found => is there anything else to do ?
3831 ;;
3832 (progn
3833 (cond
3834 ;;
3835 ;; found 'if' => skip to 'then', if it's on a separate line
3836 ;; and GOTOTHEN is non-nil
3837 ;;
3838 ((and
3839 gotothen
3840 (looking-at "if")
3841 (save-excursion
3842 (ada-search-ignore-string-comment "then" nil nil nil
3843 'word-search-forward)
3844 (back-to-indentation)
3845 (looking-at "\\<then\\>")))
3846 (goto-char (match-beginning 0)))
a1506d29 3847
4607c7f4
SM
3848 ;;
3849 ;; found 'do' => skip back to 'accept'
3850 ;;
3851 ((looking-at "do")
3852 (unless (ada-search-ignore-string-comment
3853 "accept" t nil nil
3854 'word-search-backward)
3855 (error "missing 'accept' in front of 'do'"))))
3856 (point))
a1506d29 3857
4607c7f4
SM
3858 (if noerror
3859 nil
3860 (error "no matching start"))))))
972579f9
RS
3861
3862
3863(defun ada-goto-matching-end (&optional nest-level noerror)
655880d2
GM
3864 "Moves point to the end of a block.
3865Which block depends on the value of NEST-LEVEL, which defaults to zero.
3866If NOERROR is non-nil, it only returns nil if found no matching start."
4607c7f4
SM
3867 (let ((nest-count (or nest-level 0))
3868 (regex (eval-when-compile
3869 (concat "\\<"
3870 (regexp-opt '("end" "loop" "select" "begin" "case"
3871 "if" "task" "package" "record" "do"
3872 "procedure" "function") t)
3873 "\\>")))
f7a80909
JB
3874 found
3875 pos
4607c7f4
SM
3876
3877 ;; First is used for subprograms: they are generally handled
3878 ;; recursively, but of course we do not want to do that the
3879 ;; first time (see comment below about subprograms)
3880 (first (not (looking-at "declare"))))
3881
3882 ;; If we are already looking at one of the keywords, this shouldn't count
3883 ;; in the nesting loop below, so we just make sure we don't count it.
3884 ;; "declare" is a special case because we need to look after the "begin"
3885 ;; keyword
f7a80909 3886 (if (looking-at "\\<if\\|loop\\|case\\|begin\\>")
4607c7f4 3887 (forward-char 1))
972579f9
RS
3888
3889 ;;
3890 ;; search forward for interesting keywords
3891 ;;
3892 (while (and
3893 (not found)
4607c7f4 3894 (ada-search-ignore-string-comment regex nil))
972579f9
RS
3895
3896 ;;
3897 ;; calculate nest-depth
3898 ;;
3899 (backward-word 1)
3900 (cond
4607c7f4
SM
3901 ;; procedures and functions need to be processed recursively, in
3902 ;; case they are defined in a declare/begin block, as in:
3903 ;; declare -- NL 0 (nested level)
3904 ;; A : Boolean;
3905 ;; procedure B (C : D) is
3906 ;; begin -- NL 1
3907 ;; null;
3908 ;; end B; -- NL 0, and we would exit
3909 ;; begin
3910 ;; end; -- we should exit here
3911 ;; processing them recursively avoids the need for any special
3912 ;; handling.
3913 ;; Nothing should be done if we have only the specs or a
3914 ;; generic instantion.
a1506d29 3915
4607c7f4
SM
3916 ((and (looking-at "\\<procedure\\|function\\>"))
3917 (if first
3918 (forward-word 1)
f7a80909
JB
3919
3920 (setq pos (point))
4607c7f4 3921 (ada-search-ignore-string-comment "is\\|;")
f7a80909
JB
3922 (if (= (char-before) ?s)
3923 (progn
3924 (ada-goto-next-non-ws)
3925 (unless (looking-at "\\<new\\>")
3926 (progn
3927 (goto-char pos)
3928 (ada-goto-matching-end 0 t)))))))
a1506d29 3929
972579f9
RS
3930 ;; found block end => decrease nest depth
3931 ((looking-at "\\<end\\>")
4607c7f4
SM
3932 (setq nest-count (1- nest-count)
3933 found (<= nest-count 0))
3934 ;; skip the following keyword
3935 (if (progn
3936 (skip-chars-forward "end")
3937 (ada-goto-next-non-ws)
3938 (looking-at "\\<\\(loop\\|select\\|record\\|case\\|if\\)\\>"))
3939 (forward-word 1)))
a1506d29 3940
4607c7f4
SM
3941 ;; found package start => check if it really starts a block, and is not
3942 ;; in fact a generic instantiation for instance
972579f9 3943 ((looking-at "\\<package\\>")
655880d2 3944 (ada-search-ignore-string-comment "is" nil nil nil
4cc7e498 3945 'word-search-forward)
972579f9
RS
3946 (ada-goto-next-non-ws)
3947 ;; ignore and skip it if it is only a 'new' package
7749c1a8
GM
3948 (if (looking-at "\\<new\\>")
3949 (goto-char (match-end 0))
4607c7f4
SM
3950 (setq nest-count (1+ nest-count)
3951 found (<= nest-count 0))))
a1506d29 3952
972579f9
RS
3953 ;; all the other block starts
3954 (t
f7a80909
JB
3955 (if (not first)
3956 (setq nest-count (1+ nest-count)))
3957 (setq found (<= nest-count 0))
7749c1a8 3958 (forward-word 1))) ; end of 'cond'
972579f9 3959
4607c7f4 3960 (setq first nil))
972579f9 3961
7749c1a8
GM
3962 (if found
3963 t
3964 (if noerror
3965 nil
3966 (error "no matching end")))
3967 ))
972579f9
RS
3968
3969
3970(defun ada-search-ignore-string-comment
4cc7e498 3971 (search-re &optional backward limit paramlists search-func)
655880d2
GM
3972 "Regexp-search for SEARCH-RE, ignoring comments, strings.
3973If PARAMLISTS is nil, ignore parameter lists. Returns a cons cell of
3974begin and end of match data or nil, if not found.
3975The search is done using SEARCH-FUNC, which should search backward if
3976BACKWARD is non-nil, forward otherwise. SEARCH-FUNC can be optimized in case
3977we are searching for a constant string.
3978The search stops at pos LIMIT.
3979Point is moved at the beginning of the search-re."
7749c1a8
GM
3980 (let (found
3981 begin
3982 end
3983 parse-result
3984 (previous-syntax-table (syntax-table)))
3985
3986 (unless search-func
36144b26 3987 (setq search-func (if backward 're-search-backward 're-search-forward)))
972579f9
RS
3988
3989 ;;
3990 ;; search until found or end-of-buffer
7749c1a8 3991 ;; We have to test that we do not look further than limit
972579f9 3992 ;;
7749c1a8 3993 (set-syntax-table ada-mode-symbol-syntax-table)
972579f9 3994 (while (and (not found)
7749c1a8
GM
3995 (or (not limit)
3996 (or (and backward (<= limit (point)))
3997 (>= limit (point))))
972579f9 3998 (funcall search-func search-re limit 1))
36144b26
SM
3999 (setq begin (match-beginning 0))
4000 (setq end (match-end 0))
7749c1a8 4001
36144b26 4002 (setq parse-result (parse-partial-sexp
7749c1a8
GM
4003 (save-excursion (beginning-of-line) (point))
4004 (point)))
972579f9
RS
4005
4006 (cond
4007 ;;
7749c1a8 4008 ;; If inside a string, skip it (and the following comments)
972579f9 4009 ;;
7749c1a8 4010 ((ada-in-string-p parse-result)
6f9a2614 4011 (if (featurep 'xemacs)
7749c1a8
GM
4012 (search-backward "\"" nil t)
4013 (goto-char (nth 8 parse-result)))
4014 (unless backward (forward-sexp 1)))
972579f9 4015 ;;
7749c1a8
GM
4016 ;; If inside a comment, skip it (and the following comments)
4017 ;; There is a special code for comments at the end of the file
972579f9 4018 ;;
7749c1a8 4019 ((ada-in-comment-p parse-result)
6f9a2614 4020 (if (featurep 'xemacs)
4cc7e498
GM
4021 (progn
4022 (forward-line 1)
4023 (beginning-of-line)
4024 (forward-comment -1))
7749c1a8
GM
4025 (goto-char (nth 8 parse-result)))
4026 (unless backward
4027 ;; at the end of the file, it is not possible to skip a comment
4028 ;; so we just go at the end of the line
4029 (if (forward-comment 1)
4030 (progn
4031 (forward-comment 1000)
4032 (beginning-of-line))
4033 (end-of-line))))
972579f9 4034 ;;
7749c1a8 4035 ;; directly in front of a comment => skip it, if searching forward
972579f9 4036 ;;
7749c1a8
GM
4037 ((and (= (char-after begin) ?-) (= (char-after (1+ begin)) ?-))
4038 (unless backward (progn (forward-char -1) (forward-comment 1000))))
4039
972579f9
RS
4040 ;;
4041 ;; found a parameter-list but should ignore it => skip it
4042 ;;
7749c1a8 4043 ((and (not paramlists) (ada-in-paramlist-p))
972579f9 4044 (if backward
7749c1a8
GM
4045 (search-backward "(" nil t)
4046 (search-forward ")" nil t)))
972579f9
RS
4047 ;;
4048 ;; found what we were looking for
4049 ;;
4050 (t
36144b26 4051 (setq found t)))) ; end of loop
972579f9 4052
7749c1a8 4053 (set-syntax-table previous-syntax-table)
972579f9
RS
4054
4055 (if found
7749c1a8 4056 (cons begin end)
972579f9
RS
4057 nil)))
4058
655880d2
GM
4059;; -------------------------------------------------------
4060;; -- Testing the position of the cursor
4061;; -------------------------------------------------------
972579f9
RS
4062
4063(defun ada-in-decl-p ()
655880d2
GM
4064 "Returns t if point is inside a declarative part.
4065Assumes point to be at the end of a statement."
4066 (or (ada-in-paramlist-p)
4067 (save-excursion
4cc7e498 4068 (ada-goto-matching-decl-start t))))
972579f9
RS
4069
4070
4071(defun ada-looking-at-semi-or ()
655880d2 4072 "Returns t if looking-at an 'or' following a semicolon."
972579f9
RS
4073 (save-excursion
4074 (and (looking-at "\\<or\\>")
4075 (progn
4076 (forward-word 1)
4077 (ada-goto-stmt-start)
4078 (looking-at "\\<or\\>")))))
4079
4080
4081(defun ada-looking-at-semi-private ()
4cc7e498 4082 "Returns t if looking at the start of a private section in a package.
7749c1a8 4083Returns nil if the private is part of the package name, as in
655880d2 4084'private package A is...' (this can only happen at top level)."
972579f9
RS
4085 (save-excursion
4086 (and (looking-at "\\<private\\>")
7749c1a8 4087 (not (looking-at "\\<private[ \t]*\\(package\\|generic\\)"))
7749c1a8 4088
4cc7e498
GM
4089 ;; Make sure this is the start of a private section (ie after
4090 ;; a semicolon or just after the package declaration, but not
4091 ;; after a 'type ... is private' or 'is new ... with private'
4607c7f4
SM
4092 ;;
4093 ;; Note that a 'private' statement at the beginning of the buffer
4094 ;; does not indicate a private section, since this is instead a
4095 ;; 'private procedure ...'
eaae8106 4096 (progn (forward-comment -1000)
4607c7f4
SM
4097 (and (not (bobp))
4098 (or (= (char-before) ?\;)
4099 (and (forward-word -3)
4100 (looking-at "\\<package\\>"))))))))
7749c1a8 4101
972579f9
RS
4102
4103(defun ada-in-paramlist-p ()
655880d2 4104 "Returns t if point is inside a parameter-list."
972579f9
RS
4105 (save-excursion
4106 (and
4cc7e498 4107 (ada-search-ignore-string-comment "(\\|)" t nil t)
972579f9 4108 ;; inside parentheses ?
7749c1a8 4109 (= (char-after) ?\()
4cc7e498
GM
4110
4111 ;; We could be looking at two things here:
4112 ;; operator definition: function "." (
4113 ;; subprogram definition: procedure .... (
4114 ;; Let's skip back over the first one
4115 (progn
4607c7f4 4116 (skip-chars-backward " \t\n")
4cc7e498
GM
4117 (if (= (char-before) ?\")
4118 (backward-char 3)
4119 (backward-word 1))
4120 t)
4121
4122 ;; and now over the second one
4123 (backward-word 1)
4124
7749c1a8
GM
4125 ;; We should ignore the case when the reserved keyword is in a
4126 ;; comment (for instance, when we have:
4127 ;; -- .... package
4128 ;; Test (A)
4129 ;; we should return nil
4130
4131 (not (ada-in-string-or-comment-p))
4cc7e498 4132
7749c1a8
GM
4133 ;; right keyword two words before parenthesis ?
4134 ;; Type is in this list because of discriminants
4135 (looking-at (eval-when-compile
4136 (concat "\\<\\("
4137 "procedure\\|function\\|body\\|"
4138 "task\\|entry\\|accept\\|"
4139 "access[ \t]+procedure\\|"
4140 "access[ \t]+function\\|"
4cc7e498 4141 "pragma\\|"
7749c1a8 4142 "type\\)\\>"))))))
972579f9 4143
4cc7e498
GM
4144(defun ada-search-ignore-complex-boolean (regexp backwardp)
4145 "Like `ada-search-ignore-string-comment', except that it also ignores
4146boolean expressions 'and then' and 'or else'."
4147 (let (result)
36144b26 4148 (while (and (setq result (ada-search-ignore-string-comment regexp backwardp))
4cc7e498
GM
4149 (save-excursion (forward-word -1)
4150 (looking-at "and then\\|or else"))))
4151 result))
4152
972579f9 4153(defun ada-in-open-paren-p ()
655880d2
GM
4154 "Returns the position of the first non-ws behind the last unclosed
4155parenthesis, or nil."
7749c1a8
GM
4156 (save-excursion
4157 (let ((parse (parse-partial-sexp
4cc7e498
GM
4158 (point)
4159 (or (car (ada-search-ignore-complex-boolean
4160 "\\<\\(;\\|is\\|then\\|loop\\|begin\\|else\\)\\>"
4161 t))
4162 (point-min)))))
4163
7749c1a8
GM
4164 (if (nth 1 parse)
4165 (progn
4166 (goto-char (1+ (nth 1 parse)))
4607c7f4
SM
4167
4168 ;; Skip blanks, if they are not followed by a comment
4169 ;; See:
4170 ;; type A is ( Value_0,
4171 ;; Value_1);
4172 ;; type B is ( -- comment
4173 ;; Value_2);
a1506d29 4174
4607c7f4
SM
4175 (if (or (not ada-indent-handle-comment-special)
4176 (not (looking-at "[ \t]+--")))
4177 (skip-chars-forward " \t"))
4178
4cc7e498 4179 (point))))))
972579f9
RS
4180
4181\f
4cc7e498
GM
4182;; -----------------------------------------------------------
4183;; -- Behavior Of TAB Key
4184;; -----------------------------------------------------------
655880d2 4185
972579f9 4186(defun ada-tab ()
7749c1a8 4187 "Do indenting or tabbing according to `ada-tab-policy'.
7749c1a8 4188In Transient Mark mode, if the mark is active, operate on the contents
655880d2 4189of the region. Otherwise, operates only on the current line."
972579f9 4190 (interactive)
7749c1a8
GM
4191 (cond ((eq ada-tab-policy 'indent-rigidly) (ada-tab-hard))
4192 ((eq ada-tab-policy 'indent-auto)
4607c7f4 4193 (if (ada-region-selected)
7749c1a8
GM
4194 (ada-indent-region (region-beginning) (region-end))
4195 (ada-indent-current)))
972579f9
RS
4196 ((eq ada-tab-policy 'always-tab) (error "not implemented"))
4197 ))
4198
972579f9
RS
4199(defun ada-untab (arg)
4200 "Delete leading indenting according to `ada-tab-policy'."
4201 (interactive "P")
4202 (cond ((eq ada-tab-policy 'indent-rigidly) (ada-untab-hard))
972579f9
RS
4203 ((eq ada-tab-policy 'indent-auto) (error "not implemented"))
4204 ((eq ada-tab-policy 'always-tab) (error "not implemented"))
4205 ))
4206
972579f9 4207(defun ada-indent-current-function ()
cadd3658 4208 "Ada mode version of the indent-line-function."
972579f9
RS
4209 (interactive "*")
4210 (let ((starting-point (point-marker)))
7749c1a8 4211 (beginning-of-line)
972579f9
RS
4212 (ada-tab)
4213 (if (< (point) starting-point)
4214 (goto-char starting-point))
4215 (set-marker starting-point nil)
4216 ))
4217
972579f9
RS
4218(defun ada-tab-hard ()
4219 "Indent current line to next tab stop."
4220 (interactive)
4221 (save-excursion
4222 (beginning-of-line)
4223 (insert-char ? ada-indent))
4224 (if (save-excursion (= (point) (progn (beginning-of-line) (point))))
4225 (forward-char ada-indent)))
4226
972579f9
RS
4227(defun ada-untab-hard ()
4228 "indent current line to previous tab stop."
4229 (interactive)
4230 (let ((bol (save-excursion (progn (beginning-of-line) (point))))
7749c1a8 4231 (eol (save-excursion (progn (end-of-line) (point)))))
972579f9
RS
4232 (indent-rigidly bol eol (- 0 ada-indent))))
4233
4234
972579f9 4235\f
655880d2
GM
4236;; ------------------------------------------------------------
4237;; -- Miscellaneous
4238;; ------------------------------------------------------------
972579f9 4239
4607c7f4
SM
4240;; Not needed any more for Emacs 21.2, but still needed for backward
4241;; compatibility
4242(defun ada-remove-trailing-spaces ()
4243 "Remove trailing spaces in the whole buffer."
4244 (interactive)
4245 (save-match-data
4246 (save-excursion
4247 (save-restriction
4248 (widen)
4249 (goto-char (point-min))
4250 (while (re-search-forward "[ \t]+$" (point-max) t)
4251 (replace-match "" nil nil))))))
4252
cadd3658
RS
4253(defun ada-gnat-style ()
4254 "Clean up comments, `(' and `,' for GNAT style checking switch."
4255 (interactive)
4256 (save-excursion
4607c7f4
SM
4257
4258 ;; The \n is required, or the line after an empty comment line is
4259 ;; simply ignored.
cadd3658 4260 (goto-char (point-min))
4607c7f4
SM
4261 (while (re-search-forward "--[ \t]*\\([^-\n]\\)" nil t)
4262 (replace-match "-- \\1")
4263 (forward-line 1)
4264 (beginning-of-line))
a1506d29 4265
cadd3658
RS
4266 (goto-char (point-min))
4267 (while (re-search-forward "\\>(" nil t)
4607c7f4
SM
4268 (if (not (ada-in-string-or-comment-p))
4269 (replace-match " (")))
4270 (goto-char (point-min))
4271 (while (re-search-forward ";--" nil t)
4272 (forward-char -1)
4273 (if (not (ada-in-string-or-comment-p))
4274 (replace-match "; --")))
cadd3658 4275 (goto-char (point-min))
4cc7e498 4276 (while (re-search-forward "([ \t]+" nil t)
4607c7f4
SM
4277 (if (not (ada-in-string-or-comment-p))
4278 (replace-match "(")))
4cc7e498
GM
4279 (goto-char (point-min))
4280 (while (re-search-forward ")[ \t]+)" nil t)
4607c7f4
SM
4281 (if (not (ada-in-string-or-comment-p))
4282 (replace-match "))")))
4cc7e498
GM
4283 (goto-char (point-min))
4284 (while (re-search-forward "\\>:" nil t)
4607c7f4
SM
4285 (if (not (ada-in-string-or-comment-p))
4286 (replace-match " :")))
4287
4288 ;; Make sure there is a space after a ','.
4289 ;; Always go back to the beginning of the match, since otherwise
4290 ;; a statement like ('F','D','E') is incorrectly modified.
4cc7e498 4291 (goto-char (point-min))
4607c7f4
SM
4292 (while (re-search-forward ",[ \t]*\\(.\\)" nil t)
4293 (if (not (save-excursion
4294 (goto-char (match-beginning 0))
4295 (ada-in-string-or-comment-p)))
4296 (replace-match ", \\1")))
4297
4298 ;; Operators should be surrounded by spaces.
4cc7e498 4299 (goto-char (point-min))
4607c7f4
SM
4300 (while (re-search-forward
4301 "[ \t]*\\(/=\\|\\*\\*\\|:=\\|\\.\\.\\|[-:+*/]\\)[ \t]*"
4302 nil t)
4303 (goto-char (match-beginning 1))
4304 (if (or (looking-at "--")
4305 (ada-in-string-or-comment-p))
4cc7e498 4306 (progn
4607c7f4
SM
4307 (forward-line 1)
4308 (beginning-of-line))
4309 (cond
4310 ((string= (match-string 1) "/=")
4311 (replace-match " /= "))
4312 ((string= (match-string 1) "..")
4313 (replace-match " .. "))
4314 ((string= (match-string 1) "**")
4315 (replace-match " ** "))
4316 ((string= (match-string 1) ":=")
4317 (replace-match " := "))
4318 (t
4319 (replace-match " \\1 ")))
4320 (forward-char 1)))
cadd3658
RS
4321 ))
4322
4323
972579f9 4324\f
655880d2 4325;; -------------------------------------------------------------
4cc7e498 4326;; -- Moving To Procedures/Packages/Statements
655880d2
GM
4327;; -------------------------------------------------------------
4328
4cc7e498
GM
4329(defun ada-move-to-start ()
4330 "Moves point to the matching start of the current Ada structure."
4331 (interactive)
4332 (let ((pos (point))
4333 (previous-syntax-table (syntax-table)))
4334 (unwind-protect
4335 (progn
4336 (set-syntax-table ada-mode-symbol-syntax-table)
4337
4cc7e498
GM
4338 (save-excursion
4339 ;;
4340 ;; do nothing if in string or comment or not on 'end ...;'
4341 ;; or if an error occurs during processing
4342 ;;
4343 (or
4344 (ada-in-string-or-comment-p)
4345 (and (progn
4346 (or (looking-at "[ \t]*\\<end\\>")
4347 (backward-word 1))
4348 (or (looking-at "[ \t]*\\<end\\>")
4349 (backward-word 1))
4350 (or (looking-at "[ \t]*\\<end\\>")
4351 (error "not on end ...;")))
4352 (ada-goto-matching-start 1)
36144b26 4353 (setq pos (point))
4cc7e498
GM
4354
4355 ;;
4356 ;; on 'begin' => go on, according to user option
4357 ;;
4358 ada-move-to-declaration
4359 (looking-at "\\<begin\\>")
4360 (ada-goto-matching-decl-start)
36144b26 4361 (setq pos (point))))
4cc7e498
GM
4362
4363 ) ; end of save-excursion
4364
4365 ;; now really move to the found position
4607c7f4 4366 (goto-char pos))
4cc7e498
GM
4367
4368 ;; restore syntax-table
4369 (set-syntax-table previous-syntax-table))))
4370
4371(defun ada-move-to-end ()
4372 "Moves point to the matching end of the block around point.
4373Moves to 'begin' if in a declarative part."
4374 (interactive)
4375 (let ((pos (point))
4607c7f4 4376 decl-start
4cc7e498
GM
4377 (previous-syntax-table (syntax-table)))
4378 (unwind-protect
4379 (progn
4380 (set-syntax-table ada-mode-symbol-syntax-table)
4381
4cc7e498
GM
4382 (save-excursion
4383
4cc7e498 4384 (cond
80d50f88 4385 ;; Go to the beginning of the current word, and check if we are
4cc7e498 4386 ;; directly on 'begin'
4607c7f4 4387 ((save-excursion
80d50f88 4388 (skip-syntax-backward "w")
4607c7f4 4389 (looking-at "\\<begin\\>"))
f7a80909
JB
4390 (ada-goto-matching-end 1)
4391 )
a1506d29 4392
4607c7f4
SM
4393 ;; on first line of subprogram body
4394 ;; Do nothing for specs or generic instantion, since these are
4395 ;; handled as the general case (find the enclosing block)
4396 ;; We also need to make sure that we ignore nested subprograms
4397 ((save-excursion
4398 (and (skip-syntax-backward "w")
4399 (looking-at "\\<function\\>\\|\\<procedure\\>" )
4400 (ada-search-ignore-string-comment "is\\|;")
4401 (not (= (char-before) ?\;))
4402 ))
4403 (skip-syntax-backward "w")
4404 (ada-goto-matching-end 0 t))
a1506d29 4405
4cc7e498
GM
4406 ;; on first line of task declaration
4407 ((save-excursion
4408 (and (ada-goto-stmt-start)
4409 (looking-at "\\<task\\>" )
4410 (forward-word 1)
4411 (ada-goto-next-non-ws)
4412 (looking-at "\\<body\\>")))
4413 (ada-search-ignore-string-comment "begin" nil nil nil
4414 'word-search-forward))
4415 ;; accept block start
4416 ((save-excursion
4417 (and (ada-goto-stmt-start)
4418 (looking-at "\\<accept\\>" )))
4419 (ada-goto-matching-end 0))
4420 ;; package start
4421 ((save-excursion
4607c7f4
SM
4422 (setq decl-start (and (ada-goto-matching-decl-start t) (point)))
4423 (and decl-start (looking-at "\\<package\\>")))
4cc7e498 4424 (ada-goto-matching-end 1))
80d50f88
SM
4425
4426 ;; On a "declare" keyword
4427 ((save-excursion
4428 (skip-syntax-backward "w")
4429 (looking-at "\\<declare\\>"))
4430 (ada-goto-matching-end 0 t))
a1506d29 4431
4cc7e498 4432 ;; inside a 'begin' ... 'end' block
4607c7f4
SM
4433 (decl-start
4434 (goto-char decl-start)
4435 (ada-goto-matching-end 0 t))
a1506d29 4436
4cc7e498
GM
4437 ;; (hopefully ;-) everything else
4438 (t
4439 (ada-goto-matching-end 1)))
36144b26 4440 (setq pos (point))
4cc7e498
GM
4441 )
4442
4443 ;; now really move to the position found
4607c7f4 4444 (goto-char pos))
4cc7e498
GM
4445
4446 ;; restore syntax-table
4447 (set-syntax-table previous-syntax-table))))
4448
972579f9
RS
4449(defun ada-next-procedure ()
4450 "Moves point to next procedure."
4451 (interactive)
4452 (end-of-line)
4453 (if (re-search-forward ada-procedure-start-regexp nil t)
4607c7f4 4454 (goto-char (match-beginning 2))
972579f9
RS
4455 (error "No more functions/procedures/tasks")))
4456
4457(defun ada-previous-procedure ()
4458 "Moves point to previous procedure."
4459 (interactive)
4460 (beginning-of-line)
4461 (if (re-search-backward ada-procedure-start-regexp nil t)
4607c7f4 4462 (goto-char (match-beginning 2))
972579f9
RS
4463 (error "No more functions/procedures/tasks")))
4464
4465(defun ada-next-package ()
4466 "Moves point to next package."
4467 (interactive)
4468 (end-of-line)
4469 (if (re-search-forward ada-package-start-regexp nil t)
4470 (goto-char (match-beginning 1))
4471 (error "No more packages")))
4472
4473(defun ada-previous-package ()
4474 "Moves point to previous package."
4475 (interactive)
4476 (beginning-of-line)
4477 (if (re-search-backward ada-package-start-regexp nil t)
4478 (goto-char (match-beginning 1))
4479 (error "No more packages")))
4480
4481\f
655880d2
GM
4482;; ------------------------------------------------------------
4483;; -- Define keymap and menus for Ada
4484;; -------------------------------------------------------------
972579f9 4485
7749c1a8 4486(defun ada-create-keymap ()
655880d2 4487 "Create the keymap associated with the Ada mode."
7749c1a8
GM
4488
4489 ;; Indentation and Formatting
4490 (define-key ada-mode-map "\C-j" 'ada-indent-newline-indent-conditional)
4491 (define-key ada-mode-map "\C-m" 'ada-indent-newline-indent-conditional)
4492 (define-key ada-mode-map "\t" 'ada-tab)
4493 (define-key ada-mode-map "\C-c\t" 'ada-justified-indent-current)
4494 (define-key ada-mode-map "\C-c\C-l" 'ada-indent-region)
6f9a2614 4495 (if (featurep 'xemacs)
4607c7f4
SM
4496 (define-key ada-mode-map '(shift tab) 'ada-untab)
4497 (define-key ada-mode-map [(shift tab)] 'ada-untab))
7749c1a8
GM
4498 (define-key ada-mode-map "\C-c\C-f" 'ada-format-paramlist)
4499 ;; We don't want to make meta-characters case-specific.
4500
4501 ;; Movement
4502 (define-key ada-mode-map "\M-\C-e" 'ada-next-procedure)
4503 (define-key ada-mode-map "\M-\C-a" 'ada-previous-procedure)
4504 (define-key ada-mode-map "\C-c\C-a" 'ada-move-to-start)
4505 (define-key ada-mode-map "\C-c\C-e" 'ada-move-to-end)
4506
4507 ;; Compilation
4508 (unless (lookup-key ada-mode-map "\C-c\C-c")
4509 (define-key ada-mode-map "\C-c\C-c" 'compile))
4510
4511 ;; Casing
4512 (define-key ada-mode-map "\C-c\C-b" 'ada-adjust-case-buffer)
4513 (define-key ada-mode-map "\C-c\C-t" 'ada-case-read-exceptions)
4514 (define-key ada-mode-map "\C-c\C-y" 'ada-create-case-exception)
4607c7f4 4515 (define-key ada-mode-map "\C-c\C-\M-y" 'ada-create-case-exception-substring)
7749c1a8 4516
4cc7e498
GM
4517 ;; On XEmacs, you can easily specify whether DEL should deletes
4518 ;; one character forward or one character backward. Take this into
4519 ;; account
4520 (if (boundp 'delete-key-deletes-forward)
4521 (define-key ada-mode-map [backspace] 'backward-delete-char-untabify)
4522 (define-key ada-mode-map "\177" 'backward-delete-char-untabify))
7749c1a8
GM
4523
4524 ;; Make body
4525 (define-key ada-mode-map "\C-c\C-n" 'ada-make-subprogram-body)
4526
655880d2 4527 ;; Use predefined function of Emacs19 for comments (RE)
7749c1a8
GM
4528 (define-key ada-mode-map "\C-c;" 'comment-region)
4529 (define-key ada-mode-map "\C-c:" 'ada-uncomment-region)
f7a80909
JB
4530
4531 ;; The following keys are bound to functions defined in ada-xref.el or
4532 ;; ada-prj,el., However, RMS rightly thinks that the code should be shared,
4533 ;; and activated only if the right compiler is used
6f9a2614 4534 (if (featurep 'xemacs)
f7a80909
JB
4535 (progn
4536 (define-key ada-mode-map '(shift button3) 'ada-point-and-xref)
4537 (define-key ada-mode-map '(control tab) 'ada-complete-identifier))
4538 (define-key ada-mode-map [C-tab] 'ada-complete-identifier)
4539 (define-key ada-mode-map [S-mouse-3] 'ada-point-and-xref))
4540
4541 (define-key ada-mode-map "\C-co" 'ff-find-other-file)
4542 (define-key ada-mode-map "\C-c5\C-d" 'ada-goto-declaration-other-frame)
4543 (define-key ada-mode-map "\C-c\C-d" 'ada-goto-declaration)
4544 (define-key ada-mode-map "\C-c\C-s" 'ada-xref-goto-previous-reference)
4545 (define-key ada-mode-map "\C-c\C-c" 'ada-compile-application)
4546 (define-key ada-mode-map "\C-cc" 'ada-change-prj)
4547 (define-key ada-mode-map "\C-cd" 'ada-set-default-project-file)
4548 (define-key ada-mode-map "\C-cg" 'ada-gdb-application)
4549 (define-key ada-mode-map "\C-cr" 'ada-run-application)
4550 (define-key ada-mode-map "\C-c\C-o" 'ada-goto-parent)
4551 (define-key ada-mode-map "\C-c\C-r" 'ada-find-references)
4552 (define-key ada-mode-map "\C-cl" 'ada-find-local-references)
4553 (define-key ada-mode-map "\C-c\C-v" 'ada-check-current)
4554 (define-key ada-mode-map "\C-cf" 'ada-find-file)
4555
4556 (define-key ada-mode-map "\C-cu" 'ada-prj-edit)
4557
4558 ;; The templates, defined in ada-stmt.el
4559
4560 (let ((map (make-sparse-keymap)))
4561 (define-key map "h" 'ada-header)
4562 (define-key map "\C-a" 'ada-array)
4563 (define-key map "b" 'ada-exception-block)
4564 (define-key map "d" 'ada-declare-block)
4565 (define-key map "c" 'ada-case)
4566 (define-key map "\C-e" 'ada-elsif)
4567 (define-key map "e" 'ada-else)
4568 (define-key map "\C-k" 'ada-package-spec)
4569 (define-key map "k" 'ada-package-body)
4570 (define-key map "\C-p" 'ada-procedure-spec)
4571 (define-key map "p" 'ada-subprogram-body)
4572 (define-key map "\C-f" 'ada-function-spec)
4573 (define-key map "f" 'ada-for-loop)
4574 (define-key map "i" 'ada-if)
4575 (define-key map "l" 'ada-loop)
4576 (define-key map "\C-r" 'ada-record)
4577 (define-key map "\C-s" 'ada-subtype)
4578 (define-key map "S" 'ada-tabsize)
4579 (define-key map "\C-t" 'ada-task-spec)
4580 (define-key map "t" 'ada-task-body)
4581 (define-key map "\C-y" 'ada-type)
4582 (define-key map "\C-v" 'ada-private)
4583 (define-key map "u" 'ada-use)
4584 (define-key map "\C-u" 'ada-with)
4585 (define-key map "\C-w" 'ada-when)
4586 (define-key map "w" 'ada-while-loop)
4587 (define-key map "\C-x" 'ada-exception)
4588 (define-key map "x" 'ada-exit)
4589 (define-key ada-mode-map "\C-ct" map))
7749c1a8 4590 )
972579f9 4591
655880d2 4592
7749c1a8 4593(defun ada-create-menu ()
f7a80909
JB
4594 "Create the ada menu as shown in the menu bar."
4595 (let ((m '("Ada"
4596 ("Help"
4597 ["Ada Mode" (info "ada-mode") t]
4598 ["GNAT User's Guide" (info "gnat_ugn")
4599 (eq ada-which-compiler 'gnat)]
4600 ["GNAT Reference Manual" (info "gnat_rm")
4601 (eq ada-which-compiler 'gnat)]
4602 ["Gcc Documentation" (info "gcc")
4603 (eq ada-which-compiler 'gnat)]
4604 ["Gdb Documentation" (info "gdb")
4605 (eq ada-which-compiler 'gnat)]
4606 ["Ada95 Reference Manual" (info "arm95")
4607 (eq ada-which-compiler 'gnat)])
4608 ("Options" :included (eq major-mode 'ada-mode)
4609 ["Auto Casing" (setq ada-auto-case (not ada-auto-case))
4610 :style toggle :selected ada-auto-case]
4611 ["Auto Indent After Return"
4612 (setq ada-indent-after-return (not ada-indent-after-return))
4613 :style toggle :selected ada-indent-after-return]
4614 ["Automatically Recompile For Cross-references"
4615 (setq ada-xref-create-ali (not ada-xref-create-ali))
4616 :style toggle :selected ada-xref-create-ali
4617 :included (eq ada-which-compiler 'gnat)]
4618 ["Confirm Commands"
4619 (setq ada-xref-confirm-compile (not ada-xref-confirm-compile))
4620 :style toggle :selected ada-xref-confirm-compile
4621 :included (eq ada-which-compiler 'gnat)]
4622 ["Show Cross-references In Other Buffer"
4623 (setq ada-xref-other-buffer (not ada-xref-other-buffer))
4624 :style toggle :selected ada-xref-other-buffer
4625 :included (eq ada-which-compiler 'gnat)]
4626 ["Tight Integration With GNU Visual Debugger"
4627 (setq ada-tight-gvd-integration (not ada-tight-gvd-integration))
4628 :style toggle :selected ada-tight-gvd-integration
4629 :included (string-match "gvd" ada-prj-default-debugger)])
4630 ["Customize" (customize-group 'ada)
4631 :included (fboundp 'customize-group)]
4632 ["Check file" ada-check-current (eq ada-which-compiler 'gnat)]
4633 ["Compile file" ada-compile-current (eq ada-which-compiler 'gnat)]
4634 ["Build" ada-compile-application
4635 (eq ada-which-compiler 'gnat)]
4636 ["Run" ada-run-application t]
4637 ["Debug" ada-gdb-application (eq ada-which-compiler 'gnat)]
4638 ["------" nil nil]
4639 ("Project"
4640 :included (eq ada-which-compiler 'gnat)
4641 ["Load..." ada-set-default-project-file t]
4642 ["New..." ada-prj-new t]
4643 ["Edit..." ada-prj-edit t])
4644 ("Goto" :included (eq major-mode 'ada-mode)
4645 ["Goto Declaration/Body" ada-goto-declaration
4646 (eq ada-which-compiler 'gnat)]
4647 ["Goto Body" ada-goto-body
4648 (eq ada-which-compiler 'gnat)]
4649 ["Goto Declaration Other Frame"
4650 ada-goto-declaration-other-frame
4651 (eq ada-which-compiler 'gnat)]
4652 ["Goto Previous Reference" ada-xref-goto-previous-reference
4653 (eq ada-which-compiler 'gnat)]
4654 ["List Local References" ada-find-local-references
4655 (eq ada-which-compiler 'gnat)]
4656 ["List References" ada-find-references
4657 (eq ada-which-compiler 'gnat)]
4658 ["Goto Reference To Any Entity" ada-find-any-references
4659 (eq ada-which-compiler 'gnat)]
4660 ["Goto Parent Unit" ada-goto-parent
4661 (eq ada-which-compiler 'gnat)]
4662 ["--" nil nil]
4663 ["Next compilation error" next-error t]
4664 ["Previous Package" ada-previous-package t]
4665 ["Next Package" ada-next-package t]
4666 ["Previous Procedure" ada-previous-procedure t]
6f9a2614
JB
4667 ["Next Procedure" ada-next-procedure t]
4668 ["Goto Start Of Statement" ada-move-to-start t]
f7a80909
JB
4669 ["Goto End Of Statement" ada-move-to-end t]
4670 ["-" nil nil]
4671 ["Other File" ff-find-other-file t]
4672 ["Other File Other Window" ada-ff-other-window t])
4673 ("Edit" :included (eq major-mode 'ada-mode)
4674 ["Search File On Source Path" ada-find-file t]
4675 ["------" nil nil]
4676 ["Complete Identifier" ada-complete-identifier t]
4677 ["-----" nil nil]
4678 ["Indent Line" ada-indent-current-function t]
4679 ["Justify Current Indentation" ada-justified-indent-current t]
4680 ["Indent Lines in Selection" ada-indent-region t]
4681 ["Indent Lines in File"
4682 (ada-indent-region (point-min) (point-max)) t]
4683 ["Format Parameter List" ada-format-paramlist t]
4684 ["-" nil nil]
4685 ["Comment Selection" comment-region t]
4686 ["Uncomment Selection" ada-uncomment-region t]
4687 ["--" nil nil]
4688 ["Fill Comment Paragraph" fill-paragraph t]
4689 ["Fill Comment Paragraph Justify"
4690 ada-fill-comment-paragraph-justify t]
4691 ["Fill Comment Paragraph Postfix"
4692 ada-fill-comment-paragraph-postfix t]
4693 ["---" nil nil]
4694 ["Adjust Case Selection" ada-adjust-case-region t]
4695 ["Adjust Case in File" ada-adjust-case-buffer t]
6f9a2614
JB
4696 ["Create Case Exception" ada-create-case-exception t]
4697 ["Create Case Exception Substring"
f7a80909
JB
4698 ada-create-case-exception-substring t]
4699 ["Reload Case Exceptions" ada-case-read-exceptions t]
4700 ["----" nil nil]
4701 ["Make body for subprogram" ada-make-subprogram-body t]
4702 ["-----" nil nil]
4703 ["Narrow to subprogram" ada-narrow-to-defun t])
4704 ("Templates"
4705 :included (eq major-mode 'ada-mode)
4706 ["Header" ada-header t]
4707 ["-" nil nil]
4708 ["Package Body" ada-package-body t]
4709 ["Package Spec" ada-package-spec t]
4710 ["Function Spec" ada-function-spec t]
4711 ["Procedure Spec" ada-procedure-spec t]
4712 ["Proc/func Body" ada-subprogram-body t]
4713 ["Task Body" ada-task-body t]
4714 ["Task Spec" ada-task-spec t]
4715 ["Declare Block" ada-declare-block t]
4716 ["Exception Block" ada-exception-block t]
4717 ["--" nil nil]
4718 ["Entry" ada-entry t]
4719 ["Entry family" ada-entry-family t]
4720 ["Select" ada-select t]
4721 ["Accept" ada-accept t]
4722 ["Or accept" ada-or-accep t]
4723 ["Or delay" ada-or-delay t]
4724 ["Or terminate" ada-or-terminate t]
4725 ["---" nil nil]
4726 ["Type" ada-type t]
4727 ["Private" ada-private t]
4728 ["Subtype" ada-subtype t]
4729 ["Record" ada-record t]
4730 ["Array" ada-array t]
4731 ["----" nil nil]
4732 ["If" ada-if t]
4733 ["Else" ada-else t]
4734 ["Elsif" ada-elsif t]
4735 ["Case" ada-case t]
4736 ["-----" nil nil]
4737 ["While Loop" ada-while-loop t]
4738 ["For Loop" ada-for-loop t]
4739 ["Loop" ada-loop t]
4740 ["------" nil nil]
4741 ["Exception" ada-exception t]
4742 ["Exit" ada-exit t]
4743 ["When" ada-when t])
4744 )))
4745
4cc7e498 4746 (easy-menu-define ada-mode-menu ada-mode-map "Menu keymap for Ada mode" m)
6f9a2614
JB
4747 (if (featurep 'xemacs)
4748 (progn
4749 (define-key ada-mode-map [menu-bar] ada-mode-menu)
4750 (set 'mode-popup-menu (cons "Ada mode" ada-mode-menu))))))
972579f9
RS
4751
4752\f
655880d2
GM
4753;; -------------------------------------------------------
4754;; Commenting/Uncommenting code
4cc7e498 4755;; The following two calls are provided to enhance the standard
7749c1a8 4756;; comment-region function, which only allows uncommenting if the
655880d2 4757;; comment is at the beginning of a line. If the line have been re-indented,
7749c1a8
GM
4758;; we are unable to use comment-region, which makes no sense.
4759;;
655880d2
GM
4760;; In addition, we provide an interface to the standard comment handling
4761;; function for justifying the comments.
4762;; -------------------------------------------------------
4763
80d50f88 4764(defadvice comment-region (before ada-uncomment-anywhere disable)
7749c1a8 4765 (if (and arg
4607c7f4
SM
4766 (listp arg) ;; a prefix with \C-u is of the form '(4), whereas
4767 ;; \C-u 2 sets arg to '2' (fixed by S.Leake)
7749c1a8
GM
4768 (string= mode-name "Ada"))
4769 (save-excursion
4770 (let ((cs (concat "^[ \t]*" (regexp-quote comment-start))))
4771 (goto-char beg)
4772 (while (re-search-forward cs end t)
4773 (replace-match comment-start))
4774 ))))
972579f9 4775
7749c1a8 4776(defun ada-uncomment-region (beg end &optional arg)
655880d2 4777 "Delete `comment-start' at the beginning of a line in the region."
7749c1a8 4778 (interactive "r\nP")
4cc7e498
GM
4779
4780 ;; This advice is not needed anymore with Emacs21. However, for older
4781 ;; versions, as well as for XEmacs, we still need to enable it.
6f9a2614 4782 (if (or (<= emacs-major-version 20) (featurep 'xemacs))
4cc7e498
GM
4783 (progn
4784 (ad-activate 'comment-region)
4607c7f4 4785 (comment-region beg end (- (or arg 2)))
4cc7e498 4786 (ad-deactivate 'comment-region))
80d50f88
SM
4787 (comment-region beg end (list (- (or arg 2))))
4788 (ada-indent-region beg end)))
7749c1a8
GM
4789
4790(defun ada-fill-comment-paragraph-justify ()
4791 "Fills current comment paragraph and justifies each line as well."
4792 (interactive)
4793 (ada-fill-comment-paragraph 'full))
4794
4795(defun ada-fill-comment-paragraph-postfix ()
4796 "Fills current comment paragraph and justifies each line as well.
655880d2 4797Adds `ada-fill-comment-postfix' at the end of each line."
7749c1a8
GM
4798 (interactive)
4799 (ada-fill-comment-paragraph 'full t))
972579f9 4800
7749c1a8
GM
4801(defun ada-fill-comment-paragraph (&optional justify postfix)
4802 "Fills the current comment paragraph.
4803If JUSTIFY is non-nil, each line is justified as well.
4804If POSTFIX and JUSTIFY are non-nil, `ada-fill-comment-postfix' is appended
4805to each filled and justified line.
4806The paragraph is indented on the first line."
972579f9 4807 (interactive "P")
7749c1a8
GM
4808
4809 ;; check if inside comment or just in front a comment
4810 (if (and (not (ada-in-comment-p))
4811 (not (looking-at "[ \t]*--")))
4812 (error "not inside comment"))
4813
80d50f88
SM
4814 (let* (indent from to
4815 (opos (point-marker))
7749c1a8 4816
4cc7e498
GM
4817 ;; Sets this variable to nil, otherwise it prevents
4818 ;; fill-region-as-paragraph to work on Emacs <= 20.2
4819 (parse-sexp-lookup-properties nil)
4820
7749c1a8
GM
4821 fill-prefix
4822 (fill-column (current-fill-column)))
4823
4824 ;; Find end of paragraph
4825 (back-to-indentation)
80d50f88 4826 (while (and (not (eobp)) (looking-at ".*--[ \t]*[^ \t\n]"))
7749c1a8 4827 (forward-line 1)
4cc7e498
GM
4828
4829 ;; If we were at the last line in the buffer, create a dummy empty
4830 ;; line at the end of the buffer.
4607c7f4 4831 (if (eobp)
4cc7e498
GM
4832 (insert "\n")
4833 (back-to-indentation)))
7749c1a8 4834 (beginning-of-line)
36144b26 4835 (setq to (point-marker))
7749c1a8
GM
4836 (goto-char opos)
4837
4838 ;; Find beginning of paragraph
4607c7f4 4839 (back-to-indentation)
80d50f88 4840 (while (and (not (bobp)) (looking-at ".*--[ \t]*[^ \t\n]"))
4607c7f4
SM
4841 (forward-line -1)
4842 (back-to-indentation))
4843
80d50f88 4844 ;; We want one line above the first one, unless we are at the beginning
4607c7f4
SM
4845 ;; of the buffer
4846 (unless (bobp)
10bcf543 4847 (forward-line 1))
4607c7f4 4848 (beginning-of-line)
36144b26 4849 (setq from (point-marker))
7749c1a8
GM
4850
4851 ;; Calculate the indentation we will need for the paragraph
4852 (back-to-indentation)
36144b26 4853 (setq indent (current-column))
7749c1a8
GM
4854 ;; unindent the first line of the paragraph
4855 (delete-region from (point))
4856
4857 ;; Remove the old postfixes
4858 (goto-char from)
4cc7e498 4859 (while (re-search-forward "--\n" to t)
7749c1a8
GM
4860 (replace-match "\n"))
4861
4862 (goto-char (1- to))
36144b26 4863 (setq to (point-marker))
7749c1a8
GM
4864
4865 ;; Indent and justify the paragraph
36144b26 4866 (setq fill-prefix ada-fill-comment-prefix)
7749c1a8
GM
4867 (set-left-margin from to indent)
4868 (if postfix
36144b26 4869 (setq fill-column (- fill-column (length ada-fill-comment-postfix))))
7749c1a8
GM
4870
4871 (fill-region-as-paragraph from to justify)
4872
4873 ;; Add the postfixes if required
4874 (if postfix
4875 (save-restriction
4876 (goto-char from)
4877 (narrow-to-region from to)
4878 (while (not (eobp))
4879 (end-of-line)
4880 (insert-char ? (- fill-column (current-column)))
4881 (insert ada-fill-comment-postfix)
4882 (forward-line))
4883 ))
4884
4885 ;; In Emacs <= 20.2 and XEmacs <=20.4, there is a bug, and a newline is
4886 ;; inserted at the end. Delete it
6f9a2614 4887 (if (or (featurep 'xemacs)
7749c1a8
GM
4888 (<= emacs-major-version 19)
4889 (and (= emacs-major-version 20)
4890 (<= emacs-minor-version 2)))
4891 (progn
4892 (goto-char to)
4893 (end-of-line)
4894 (delete-char 1)))
4895
4896 (goto-char opos)))
972579f9 4897
4cc7e498 4898
655880d2
GM
4899;; ---------------------------------------------------
4900;; support for find-file.el
4901;; These functions are used by find-file to guess the file names from
4902;; unit names, and to find the other file (spec or body) from the current
4903;; file (body or spec).
4904;; It is also used to find in which function we are, so as to put the
4905;; cursor at the correct position.
4906;; Standard Ada does not force any relation between unit names and file names,
4907;; so some of these functions can only be a good approximation. However, they
4908;; are also overriden in `ada-xref'.el when we know that the user is using
4909;; GNAT.
4910;; ---------------------------------------------------
4911
4912;; Overriden when we work with GNAT, to use gnatkrunch
972579f9 4913(defun ada-make-filename-from-adaname (adaname)
655880d2
GM
4914 "Determine the filename in which ADANAME is found.
4915This is a generic function, independent from any compiler."
7749c1a8 4916 (while (string-match "\\." adaname)
36144b26 4917 (setq adaname (replace-match "-" t t adaname)))
4cc7e498 4918 (downcase adaname)
972579f9
RS
4919 )
4920
7749c1a8 4921(defun ada-other-file-name ()
4cc7e498
GM
4922 "Return the name of the other file.
4923The name returned is the body if current-buffer is the spec, or the spec
4924otherwise."
4925
4926 (let ((is-spec nil)
4927 (is-body nil)
4928 (suffixes ada-spec-suffixes)
4929 (name (buffer-file-name)))
4930
4931 ;; Guess whether we have a spec or a body, and get the basename of the
4932 ;; file. Since the extension may not start with '.', we can not use
4933 ;; file-name-extension
4934 (while (and (not is-spec)
4935 suffixes)
4936 (if (string-match (concat "\\(.*\\)" (car suffixes) "$") name)
4937 (setq is-spec t
4938 name (match-string 1 name)))
36144b26 4939 (setq suffixes (cdr suffixes)))
4cc7e498
GM
4940
4941 (if (not is-spec)
4942 (progn
36144b26 4943 (setq suffixes ada-body-suffixes)
4cc7e498
GM
4944 (while (and (not is-body)
4945 suffixes)
4946 (if (string-match (concat "\\(.*\\)" (car suffixes) "$") name)
4947 (setq is-body t
4948 name (match-string 1 name)))
36144b26 4949 (setq suffixes (cdr suffixes)))))
eaae8106 4950
4cc7e498
GM
4951 ;; If this wasn't in either list, return name itself
4952 (if (not (or is-spec is-body))
4953 name
eaae8106 4954
4cc7e498
GM
4955 ;; Else find the other possible names
4956 (if is-spec
36144b26
SM
4957 (setq suffixes ada-body-suffixes)
4958 (setq suffixes ada-spec-suffixes))
4959 (setq is-spec name)
4cc7e498
GM
4960
4961 (while suffixes
4607c7f4
SM
4962
4963 ;; If we are using project file, search for the other file in all
4964 ;; the possible src directories.
a1506d29 4965
6f9a2614 4966 (if (fboundp 'ada-find-src-file-in-dir)
4607c7f4
SM
4967 (let ((other
4968 (ada-find-src-file-in-dir
4969 (file-name-nondirectory (concat name (car suffixes))))))
4970 (if other
4971 (set 'is-spec other)))
4972
4973 ;; Else search in the current directory
4974 (if (file-exists-p (concat name (car suffixes)))
4975 (setq is-spec (concat name (car suffixes)))))
36144b26 4976 (setq suffixes (cdr suffixes)))
4cc7e498
GM
4977
4978 is-spec)))
f139ce87 4979
f139ce87 4980(defun ada-which-function-are-we-in ()
655880d2
GM
4981 "Return the name of the function whose definition/declaration point is in.
4982Redefines the function `ff-which-function-are-we-in'."
36144b26 4983 (setq ff-function-name nil)
f139ce87 4984 (save-excursion
4cc7e498 4985 (end-of-line);; make sure we get the complete name
7749c1a8
GM
4986 (if (or (re-search-backward ada-procedure-start-regexp nil t)
4987 (re-search-backward ada-package-start-regexp nil t))
36144b26 4988 (setq ff-function-name (match-string 0)))
7749c1a8 4989 ))
f139ce87 4990
4cc7e498
GM
4991
4992(defvar ada-last-which-function-line -1
4993 "Last on which ada-which-function was called")
4994(defvar ada-last-which-function-subprog 0
4995 "Last subprogram name returned by ada-which-function")
4996(make-variable-buffer-local 'ada-last-which-function-subprog)
4997(make-variable-buffer-local 'ada-last-which-function-line)
4998
4999
5000(defun ada-which-function ()
5001 "Returns the name of the function whose body the point is in.
5002This function works even in the case of nested subprograms, whereas the
80d50f88 5003standard Emacs function `which-function' does not.
4cc7e498
GM
5004Since the search can be long, the results are cached."
5005
80d50f88 5006 (let ((line (count-lines 1 (point)))
4cc7e498
GM
5007 (pos (point))
5008 end-pos
4607c7f4 5009 func-name indent
4cc7e498
GM
5010 found)
5011
5012 ;; If this is the same line as before, simply return the same result
5013 (if (= line ada-last-which-function-line)
5014 ada-last-which-function-subprog
5015
5016 (save-excursion
5017 ;; In case the current line is also the beginning of the body
5018 (end-of-line)
4cc7e498 5019
4607c7f4
SM
5020 ;; Are we looking at "function Foo\n (paramlist)"
5021 (skip-chars-forward " \t\n(")
a1506d29 5022
4607c7f4 5023 (condition-case nil
80d50f88 5024 (up-list 1)
4607c7f4
SM
5025 (error nil))
5026
5027 (skip-chars-forward " \t\n")
5028 (if (looking-at "return")
5029 (progn
5030 (forward-word 1)
5031 (skip-chars-forward " \t\n")
5032 (skip-chars-forward "a-zA-Z0-9_'")))
a1506d29 5033
4cc7e498
GM
5034 ;; Can't simply do forward-word, in case the "is" is not on the
5035 ;; same line as the closing parenthesis
5036 (skip-chars-forward "is \t\n")
5037
5038 ;; No look for the closest subprogram body that has not ended yet.
4607c7f4
SM
5039 ;; Not that we expect all the bodies to be finished by "end <name>",
5040 ;; or a simple "end;" indented in the same column as the start of
5041 ;; the subprogram. The goal is to be as efficient as possible.
4cc7e498
GM
5042
5043 (while (and (not found)
5044 (re-search-backward ada-imenu-subprogram-menu-re nil t))
4607c7f4
SM
5045
5046 ;; Get the function name, but not the properties, or this changes
5047 ;; the face in the modeline on Emacs 21
5048 (setq func-name (match-string-no-properties 2))
4cc7e498
GM
5049 (if (and (not (ada-in-comment-p))
5050 (not (save-excursion
5051 (goto-char (match-end 0))
5052 (looking-at "[ \t\n]*new"))))
5053 (save-excursion
4607c7f4
SM
5054 (back-to-indentation)
5055 (setq indent (current-column))
4cc7e498 5056 (if (ada-search-ignore-string-comment
4607c7f4
SM
5057 (concat "end[ \t]+" func-name "[ \t]*;\\|^"
5058 (make-string indent ? ) "end;"))
36144b26
SM
5059 (setq end-pos (point))
5060 (setq end-pos (point-max)))
4cc7e498 5061 (if (>= end-pos pos)
36144b26 5062 (setq found func-name))))
4cc7e498
GM
5063 )
5064 (setq ada-last-which-function-line line
5065 ada-last-which-function-subprog found)
5066 found))))
5067
5068(defun ada-ff-other-window ()
5069 "Find other file in other window using `ff-find-other-file'."
5070 (interactive)
5071 (and (fboundp 'ff-find-other-file)
5072 (ff-find-other-file t)))
5073
7749c1a8 5074(defun ada-set-point-accordingly ()
655880d2
GM
5075 "Move to the function declaration that was set by
5076`ff-which-function-are-we-in'."
7749c1a8
GM
5077 (if ff-function-name
5078 (progn
5079 (goto-char (point-min))
655880d2 5080 (unless (ada-search-ignore-string-comment
4cc7e498 5081 (concat ff-function-name "\\b") nil)
7749c1a8 5082 (goto-char (point-min))))))
f139ce87 5083
4cc7e498
GM
5084(defun ada-get-body-name (&optional spec-name)
5085 "Returns the file name for the body of SPEC-NAME.
5086If SPEC-NAME is nil, returns the body for the current package.
5087Returns nil if no body was found."
5088 (interactive)
5089
36144b26 5090 (unless spec-name (setq spec-name (buffer-file-name)))
4cc7e498 5091
4607c7f4
SM
5092 ;; Remove the spec extension. We can not simply remove the file extension,
5093 ;; but we need to take into account the specific non-GNAT extensions that the
5094 ;; user might have specified.
5095
5096 (let ((suffixes ada-spec-suffixes)
5097 end)
5098 (while suffixes
5099 (setq end (- (length spec-name) (length (car suffixes))))
5100 (if (string-equal (car suffixes) (substring spec-name end))
5101 (setq spec-name (substring spec-name 0 end)))
5102 (setq suffixes (cdr suffixes))))
5103
4cc7e498 5104 ;; If find-file.el was available, use its functions
6f9a2614
JB
5105 (if (fboundp 'ff-get-file-name)
5106 (ff-get-file-name ada-search-directories-internal
4cc7e498
GM
5107 (ada-make-filename-from-adaname
5108 (file-name-nondirectory
5109 (file-name-sans-extension spec-name)))
5110 ada-body-suffixes)
5111 ;; Else emulate it very simply
5112 (concat (ada-make-filename-from-adaname
5113 (file-name-nondirectory
5114 (file-name-sans-extension spec-name)))
5115 ".adb")))
5116
655880d2
GM
5117\f
5118;; ---------------------------------------------------
5119;; support for font-lock.el
cadd3658
RS
5120;; Strings are a real pain in Ada because a single quote character is
5121;; overloaded as a string quote and type/instance delimiter. By default, a
5122;; single quote is given punctuation syntax in `ada-mode-syntax-table'.
5123;; So, for Font Lock mode purposes, we mark single quotes as having string
655880d2
GM
5124;; syntax when the gods that created Ada determine them to be.
5125;;
5126;; This only works in Emacs. See the comments before the grammar functions
5127;; at the beginning of this file for how this is done with XEmacs.
5128;; ----------------------------------------------------
cadd3658
RS
5129
5130(defconst ada-font-lock-syntactic-keywords
5131 ;; Mark single quotes as having string quote syntax in 'c' instances.
655880d2
GM
5132 ;; As a special case, ''' will not be highlighted, but if we do not
5133 ;; set this special case, then the rest of the buffer is highlighted as
7749c1a8
GM
5134 ;; a string
5135 ;; This sets the properties of the characters, so that ada-in-string-p
5136 ;; correctly handles '"' too...
4607c7f4 5137 '(("[^a-zA-Z0-9)]\\('\\)[^'\n]\\('\\)" (1 (7 . ?')) (2 (7 . ?')))
7749c1a8 5138 ("^[ \t]*\\(#\\(if\\|else\\|elsif\\|end\\)\\)" (1 (11 . ?\n)))
972579f9 5139 ))
972579f9 5140
7749c1a8
GM
5141(defvar ada-font-lock-keywords
5142 (eval-when-compile
5143 (list
5144 ;;
5145 ;; handle "type T is access function return S;"
5146 (list "\\<\\(function[ \t]+return\\)\\>" '(1 font-lock-keyword-face) )
cadd3658 5147
7749c1a8
GM
5148 ;; preprocessor line
5149 (list "^[ \t]*\\(#.*\n\\)" '(1 font-lock-type-face t))
cadd3658 5150
7749c1a8
GM
5151 ;;
5152 ;; accept, entry, function, package (body), protected (body|type),
5153 ;; pragma, procedure, task (body) plus name.
5154 (list (concat
5155 "\\<\\("
5156 "accept\\|"
5157 "entry\\|"
5158 "function\\|"
5159 "package[ \t]+body\\|"
5160 "package\\|"
5161 "pragma\\|"
5162 "procedure\\|"
5163 "protected[ \t]+body\\|"
5164 "protected[ \t]+type\\|"
5165 "protected\\|"
5166 "task[ \t]+body\\|"
5167 "task[ \t]+type\\|"
5168 "task"
5169 "\\)\\>[ \t]*"
5170 "\\(\\sw+\\(\\.\\sw*\\)*\\)?")
5171 '(1 font-lock-keyword-face) '(2 font-lock-function-name-face nil t))
5172 ;;
5173 ;; Optional keywords followed by a type name.
5174 (list (concat ; ":[ \t]*"
4607c7f4 5175 "\\<\\(access[ \t]+all\\|access[ \t]+constant\\|access\\|constant\\|in[ \t]+reverse\\|\\|in[ \t]+out\\|in\\|out\\)\\>"
7749c1a8
GM
5176 "[ \t]*"
5177 "\\(\\sw+\\(\\.\\sw*\\)*\\)?")
5178 '(1 font-lock-keyword-face nil t) '(2 font-lock-type-face nil t))
cadd3658 5179
7749c1a8
GM
5180 ;;
5181 ;; Main keywords, except those treated specially below.
5182 (concat "\\<"
5183 (regexp-opt
5184 '("abort" "abs" "abstract" "accept" "access" "aliased" "all"
5185 "and" "array" "at" "begin" "case" "declare" "delay" "delta"
5186 "digits" "do" "else" "elsif" "entry" "exception" "exit" "for"
5187 "generic" "if" "in" "is" "limited" "loop" "mod" "not"
5188 "null" "or" "others" "private" "protected" "raise"
5189 "range" "record" "rem" "renames" "requeue" "return" "reverse"
5190 "select" "separate" "tagged" "task" "terminate" "then" "until"
f7a80909 5191 "when" "while" "with" "xor") t)
7749c1a8
GM
5192 "\\>")
5193 ;;
5194 ;; Anything following end and not already fontified is a body name.
5195 '("\\<\\(end\\)\\>\\([ \t]+\\)?\\(\\(\\sw\\|[_.]\\)+\\)?"
5196 (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t))
5197 ;;
5198 ;; Keywords followed by a type or function name.
5199 (list (concat "\\<\\("
5200 "new\\|of\\|subtype\\|type"
5201 "\\)\\>[ \t]*\\(\\sw+\\(\\.\\sw*\\)*\\)?[ \t]*\\((\\)?")
5202 '(1 font-lock-keyword-face)
5203 '(2 (if (match-beginning 4)
5204 font-lock-function-name-face
5205 font-lock-type-face) nil t))
5206 ;;
5207 ;; Keywords followed by a (comma separated list of) reference.
4607c7f4
SM
5208 ;; Note that font-lock only works on single lines, thus we can not
5209 ;; correctly highlight a with_clause that spans multiple lines.
5210 (list (concat "\\<\\(goto\\|raise\\|use\\|with\\)"
5211 "[ \t]+\\([a-zA-Z0-9_., \t]+\\)\\W")
7749c1a8 5212 '(1 font-lock-keyword-face) '(2 font-lock-reference-face nil t))
f7a80909 5213
7749c1a8
GM
5214 ;;
5215 ;; Goto tags.
5216 '("<<\\(\\sw+\\)>>" 1 font-lock-reference-face)
4607c7f4
SM
5217
5218 ;; Highlight based-numbers (R. Reagan <robin-reply@reagans.org>)
5219 (list "\\([0-9]+#[0-9a-fA-F_]+#\\)" '(1 font-lock-constant-face t))
5220
5221 ;; Ada unnamed numerical constants
5222 (list "\\W\\([-+]?[0-9._]+\\)\\>" '(1 font-lock-constant-face))
a1506d29 5223
7749c1a8
GM
5224 ))
5225 "Default expressions to highlight in Ada mode.")
5226
4cc7e498 5227
655880d2
GM
5228;; ---------------------------------------------------------
5229;; Support for outline.el
5230;; ---------------------------------------------------------
cadd3658 5231
cadd3658 5232(defun ada-outline-level ()
655880d2 5233 "This is so that `current-column` DTRT in otherwise-hidden text"
7749c1a8 5234 ;; patch from Dave Love <fx@gnu.org>
b073b657
DL
5235 (let (buffer-invisibility-spec)
5236 (save-excursion
7749c1a8 5237 (back-to-indentation)
b073b657 5238 (current-column))))
972579f9 5239
f7a80909
JB
5240;; ---------------------------------------------------------
5241;; Support for narrow-to-region
5242;; ---------------------------------------------------------
5243
5244(defun ada-narrow-to-defun (&optional arg)
5245 "make text outside current subprogram invisible.
5246The subprogram visible is the one that contains or follow point.
5247Optional ARG is ignored.
5248Use `M-x widen' to go back to the full visibility for the buffer"
5249
5250 (interactive)
5251 (save-excursion
5252 (let (end)
5253 (widen)
5254 (forward-line 1)
5255 (ada-previous-procedure)
5256
5257 (save-excursion
5258 (beginning-of-line)
5259 (setq end (point)))
5260
5261 (ada-move-to-end)
5262 (end-of-line)
5263 (narrow-to-region end (point))
5264 (message
5265 "Use M-x widen to get back to full visibility in the buffer"))))
5266
655880d2
GM
5267;; ---------------------------------------------------------
5268;; Automatic generation of code
5269;; The Ada-mode has a set of function to automatically generate a subprogram
5270;; or package body from its spec.
5271;; These function only use a primary and basic algorithm, this could use a
5272;; lot of improvement.
5273;; When the user is using GNAT, we rather use gnatstub to generate an accurate
5274;; body.
5275;; ----------------------------------------------------------
972579f9 5276
f139ce87 5277(defun ada-gen-treat-proc (match)
655880d2
GM
5278 "Make dummy body of a procedure/function specification.
5279MATCH is a cons cell containing the start and end location of the last search
5280for ada-procedure-start-regexp."
f139ce87 5281 (goto-char (car match))
7749c1a8 5282 (let (func-found procname functype)
f139ce87 5283 (cond
7749c1a8 5284 ((or (looking-at "^[ \t]*procedure")
36144b26 5285 (setq func-found (looking-at "^[ \t]*function")))
f139ce87 5286 ;; treat it as a proc/func
7749c1a8 5287 (forward-word 2)
f139ce87 5288 (forward-word -1)
36144b26 5289 (setq procname (buffer-substring (point) (cdr match))) ; store proc name
7749c1a8
GM
5290
5291 ;; goto end of procname
5292 (goto-char (cdr match))
5293
5294 ;; skip over parameterlist
5295 (unless (looking-at "[ \t\n]*\\(;\\|return\\)")
5296 (forward-sexp))
5297
5298 ;; if function, skip over 'return' and result type.
f139ce87 5299 (if func-found
7749c1a8
GM
5300 (progn
5301 (forward-word 1)
5302 (skip-chars-forward " \t\n")
36144b26 5303 (setq functype (buffer-substring (point)
7749c1a8
GM
5304 (progn
5305 (skip-chars-forward
5306 "a-zA-Z0-9_\.")
5307 (point))))))
5308 ;; look for next non WS
5309 (cond
5310 ((looking-at "[ \t]*;")
5311 (delete-region (match-beginning 0) (match-end 0));; delete the ';'
5312 (ada-indent-newline-indent)
5313 (insert "is")
5314 (ada-indent-newline-indent)
5315 (if func-found
5316 (progn
5317 (insert "Result : " functype ";")
5318 (ada-indent-newline-indent)))
5319 (insert "begin")
5320 (ada-indent-newline-indent)
5321 (if func-found
5322 (insert "return Result;")
5323 (insert "null;"))
5324 (ada-indent-newline-indent)
5325 (insert "end " procname ";")
5326 (ada-indent-newline-indent)
5327 )
5328 ;; else
5329 ((looking-at "[ \t\n]*is")
5330 ;; do nothing
5331 )
5332 ((looking-at "[ \t\n]*rename")
5333 ;; do nothing
5334 )
5335 (t
5336 (message "unknown syntax"))))
f139ce87 5337 (t
7749c1a8
GM
5338 (if (looking-at "^[ \t]*task")
5339 (progn
5340 (message "Task conversion is not yet implemented")
5341 (forward-word 2)
5342 (if (looking-at "[ \t]*;")
5343 (forward-line)
5344 (ada-move-to-end))
5345 ))))))
f139ce87
KH
5346
5347(defun ada-make-body ()
5348 "Create an Ada package body in the current buffer.
5349The potential old buffer contents is deleted first, then we copy the
5350spec buffer in here and modify it to make it a body.
f139ce87
KH
5351This function typically is to be hooked into `ff-file-created-hooks'."
5352 (interactive)
5353 (delete-region (point-min) (point-max))
5354 (insert-buffer (car (cdr (buffer-list))))
5355 (ada-mode)
5356
7749c1a8 5357 (let (found ada-procedure-or-package-start-regexp)
36144b26 5358 (if (setq found
7749c1a8
GM
5359 (ada-search-ignore-string-comment ada-package-start-regexp nil))
5360 (progn (goto-char (cdr found))
5361 (insert " body")
5362 )
972579f9 5363 (error "No package"))
f139ce87 5364
36144b26 5365 (setq ada-procedure-or-package-start-regexp
7749c1a8
GM
5366 (concat ada-procedure-start-regexp
5367 "\\|"
5368 ada-package-start-regexp))
972579f9 5369
36144b26 5370 (while (setq found
7749c1a8
GM
5371 (ada-search-ignore-string-comment
5372 ada-procedure-or-package-start-regexp nil))
5373 (progn
5374 (goto-char (car found))
5375 (if (looking-at ada-package-start-regexp)
5376 (progn (goto-char (cdr found))
5377 (insert " body"))
5378 (ada-gen-treat-proc found))))))
5379
4cc7e498 5380
7749c1a8 5381(defun ada-make-subprogram-body ()
655880d2 5382 "Make one dummy subprogram body from spec surrounding point."
7749c1a8
GM
5383 (interactive)
5384 (let* ((found (re-search-backward ada-procedure-start-regexp nil t))
4cc7e498
GM
5385 (spec (match-beginning 0))
5386 body-file)
7749c1a8
GM
5387 (if found
5388 (progn
5389 (goto-char spec)
5390 (if (and (re-search-forward "(\\|;" nil t)
5391 (= (char-before) ?\())
5392 (progn
5393 (ada-search-ignore-string-comment ")" nil)
5394 (ada-search-ignore-string-comment ";" nil)))
36144b26 5395 (setq spec (buffer-substring spec (point)))
7749c1a8 5396
4cc7e498 5397 ;; If find-file.el was available, use its functions
36144b26 5398 (setq body-file (ada-get-body-name))
4cc7e498
GM
5399 (if body-file
5400 (find-file body-file)
f7a80909 5401 (error "No body found for the package. Create it first."))
4cc7e498 5402
7749c1a8
GM
5403 (save-restriction
5404 (widen)
5405 (goto-char (point-max))
5406 (forward-comment -10000)
5407 (re-search-backward "\\<end\\>" nil t)
5408 ;; Move to the beginning of the elaboration part, if any
5409 (re-search-backward "^begin" nil t)
5410 (newline)
5411 (forward-char -1)
5412 (insert spec)
5413 (re-search-backward ada-procedure-start-regexp nil t)
5414 (ada-gen-treat-proc (cons (match-beginning 0) (match-end 0)))
5415 ))
5416 (error "Not in subprogram spec"))))
5417
655880d2
GM
5418;; --------------------------------------------------------
5419;; Global initializations
5420;; --------------------------------------------------------
5421
7749c1a8
GM
5422;; Create the keymap once and for all. If we do that in ada-mode,
5423;; the keys changed in the user's .emacs have to be modified
5424;; every time
5425(ada-create-keymap)
5426(ada-create-menu)
5427
5428;; Create the syntax tables, but do not activate them
5429(ada-create-syntax-table)
5430
5431;; Add the default extensions (and set up speedbar)
5432(ada-add-extensions ".ads" ".adb")
5433;; This two files are generated by GNAT when running with -gnatD
5434(if (equal ada-which-compiler 'gnat)
5435 (ada-add-extensions ".ads.dg" ".adb.dg"))
5436
5437;; Read the special cases for exceptions
5438(ada-case-read-exceptions)
5439
f7a80909 5440;; Setup auto-loading of the other ada-mode files.
7749c1a8
GM
5441(if (equal ada-which-compiler 'gnat)
5442 (progn
f7a80909
JB
5443 (autoload 'ada-change-prj "ada-xref" nil t)
5444 (autoload 'ada-check-current "ada-xref" nil t)
5445 (autoload 'ada-compile-application "ada-xref" nil t)
5446 (autoload 'ada-compile-current "ada-xref" nil t)
5447 (autoload 'ada-complete-identifier "ada-xref" nil t)
5448 (autoload 'ada-find-file "ada-xref" nil t)
5449 (autoload 'ada-find-any-references "ada-xref" nil t)
5450 (autoload 'ada-find-src-file-in-dir "ada-xref" nil t)
5451 (autoload 'ada-find-local-references "ada-xref" nil t)
5452 (autoload 'ada-find-references "ada-xref" nil t)
5453 (autoload 'ada-gdb-application "ada-xref" nil t)
5454 (autoload 'ada-goto-declaration "ada-xref" nil t)
5455 (autoload 'ada-goto-declaration-other-frame "ada-xref" nil t)
5456 (autoload 'ada-goto-parent "ada-xref" nil t)
5457 (autoload 'ada-make-body-gnatstub "ada-xref" nil t)
5458 (autoload 'ada-point-and-xref "ada-xref" nil t)
5459 (autoload 'ada-reread-prj-file "ada-xref" nil t)
5460 (autoload 'ada-run-application "ada-xref" nil t)
5461 (autoload 'ada-set-default-project-file "ada-xref" nil nil)
5462 (autoload 'ada-set-default-project-file "ada-xref" nil t)
5463 (autoload 'ada-xref-goto-previous-reference "ada-xref" nil t)
5464
5465 (autoload 'ada-customize "ada-prj" nil t)
5466 (autoload 'ada-prj-edit "ada-prj" nil t)
5467 (autoload 'ada-prj-new "ada-prj" nil t)
5468 (autoload 'ada-prj-save "ada-prj" nil t)
7749c1a8 5469 ))
f7a80909
JB
5470
5471(autoload 'ada-array "ada-stmt" nil t)
5472(autoload 'ada-case "ada-stmt" nil t)
5473(autoload 'ada-declare-block "ada-stmt" nil t)
5474(autoload 'ada-else "ada-stmt" nil t)
5475(autoload 'ada-elsif "ada-stmt" nil t)
5476(autoload 'ada-exception "ada-stmt" nil t)
5477(autoload 'ada-exception-block "ada-stmt" nil t)
5478(autoload 'ada-exit "ada-stmt" nil t)
5479(autoload 'ada-for-loop "ada-stmt" nil t)
5480(autoload 'ada-function-spec "ada-stmt" nil t)
5481(autoload 'ada-header "ada-stmt" nil t)
5482(autoload 'ada-if "ada-stmt" nil t)
5483(autoload 'ada-loop "ada-stmt" nil t)
5484(autoload 'ada-package-body "ada-stmt" nil t)
5485(autoload 'ada-package-spec "ada-stmt" nil t)
5486(autoload 'ada-private "ada-stmt" nil t)
5487(autoload 'ada-procedure-spec "ada-stmt" nil t)
5488(autoload 'ada-record "ada-stmt" nil t)
5489(autoload 'ada-subprogram-body "ada-stmt" nil t)
5490(autoload 'ada-subtype "ada-stmt" nil t)
5491(autoload 'ada-tabsize "ada-stmt" nil t)
5492(autoload 'ada-task-body "ada-stmt" nil t)
5493(autoload 'ada-task-spec "ada-stmt" nil t)
5494(autoload 'ada-type "ada-stmt" nil t)
5495(autoload 'ada-use "ada-stmt" nil t)
5496(autoload 'ada-when "ada-stmt" nil t)
5497(autoload 'ada-while-loop "ada-stmt" nil t)
5498(autoload 'ada-with "ada-stmt" nil t)
972579f9 5499
7749c1a8 5500;;; provide ourselves
972579f9
RS
5501(provide 'ada-mode)
5502
ab5796a9 5503;;; arch-tag: 1b7d45ec-1698-43b5-8d4a-e479ea023270
a681b2a1 5504;;; ada-mode.el ends here