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