Don't call c-parse-state when c++-template-syntax-table is active.
[bpt/emacs.git] / lisp / progmodes / simula.el
CommitLineData
a26389d1
ER
1;;; simula.el --- SIMULA 87 code editing commands for Emacs
2
ba318903 3;; Copyright (C) 1992, 1994, 1996, 2001-2014 Free Software Foundation,
ab422c4d 4;; Inc.
58142744 5
62507a6a
GM
6;; Author: Hans Henrik Eriksen <hhe@ifi.uio.no>
7;; Maintainer: simula-mode@ifi.uio.no
8;; (above email addresses invalid as of April 2008)
f961a17c
ER
9;; Adapted-By: ESR
10;; Keywords: languages
11
a26389d1
ER
12;; This file is part of GNU Emacs.
13
b1fc2b50 14;; GNU Emacs is free software: you can redistribute it and/or modify
a26389d1 15;; it under the terms of the GNU General Public License as published by
b1fc2b50
GM
16;; the Free Software Foundation, either version 3 of the License, or
17;; (at your option) any later version.
a26389d1
ER
18
19;; GNU Emacs is distributed in the hope that it will be useful,
20;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22;; GNU General Public License for more details.
23
24;; You should have received a copy of the GNU General Public License
b1fc2b50 25;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
a26389d1 26
f961a17c
ER
27;;; Commentary:
28
d9ecc911
ER
29;; A major mode for editing the Simula language. It knows about Simula
30;; syntax and standard indentation commands. It also provides convenient
31;; abbrevs for Simula keywords.
32;;
33;; Hans Henrik Eriksen (the author) may be reached at:
a26389d1
ER
34;; Institutt for informatikk,
35;; Universitetet i Oslo
a26389d1 36
f961a17c 37;;; Code:
a26389d1 38
8ca3cd44 39\f
5636765c
SE
40(defgroup simula nil
41 "Major mode for editing Simula code."
8ec3bce0 42 :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
5636765c
SE
43 :prefix "simula-"
44 :group 'languages)
45
8ca3cd44
RS
46(defconst simula-tab-always-indent-default nil
47 "Non-nil means TAB in SIMULA mode should always reindent the current line.
48Otherwise TAB indents only when point is within
49the run of whitespace at the beginning of the line.")
a26389d1 50
5636765c 51(defcustom simula-tab-always-indent simula-tab-always-indent-default
fb7ada5f 52 "Non-nil means TAB in SIMULA mode should always reindent the current line.
3005d32e 53Otherwise TAB indents only when point is within
5636765c
SE
54the run of whitespace at the beginning of the line."
55 :type 'boolean
56 :group 'simula)
a26389d1 57
8ca3cd44
RS
58(defconst simula-indent-level-default 3
59 "Indentation of SIMULA statements with respect to containing block.")
60
5636765c 61(defcustom simula-indent-level simula-indent-level-default
fb7ada5f 62 "Indentation of SIMULA statements with respect to containing block."
5636765c
SE
63 :type 'integer
64 :group 'simula)
65
a26389d1 66
8ca3cd44
RS
67(defconst simula-substatement-offset-default 3
68 "Extra indentation after DO, THEN, ELSE, WHEN and OTHERWISE.")
69
5636765c 70(defcustom simula-substatement-offset simula-substatement-offset-default
fb7ada5f 71 "Extra indentation after DO, THEN, ELSE, WHEN and OTHERWISE."
5636765c
SE
72 :type 'integer
73 :group 'simula)
a26389d1 74
8ca3cd44
RS
75(defconst simula-continued-statement-offset-default 3
76 "Extra indentation for lines not starting a statement or substatement.
77If value is a list, each line in a multipleline continued statement
78will have the car of the list extra indentation with respect to
79the previous line of the statement.")
80
a1506d29 81(defcustom simula-continued-statement-offset
5636765c 82 simula-continued-statement-offset-default
fb7ada5f 83 "Extra indentation for lines not starting a statement or substatement.
a26389d1
ER
84If value is a list, each line in a multipleline continued statement
85will have the car of the list extra indentation with respect to
5636765c
SE
86the previous line of the statement."
87 :type 'integer
88 :group 'simula)
a26389d1 89
8ca3cd44
RS
90(defconst simula-label-offset-default -4711
91 "Offset of SIMULA label lines relative to usual indentation.")
92
5636765c 93(defcustom simula-label-offset simula-label-offset-default
fb7ada5f 94 "Offset of SIMULA label lines relative to usual indentation."
5636765c
SE
95 :type 'integer
96 :group 'simula)
a26389d1 97
8ca3cd44
RS
98(defconst simula-if-indent-default '(0 . 0)
99 "Extra indentation of THEN and ELSE with respect to the starting IF.
100Value is a cons cell, the car is extra THEN indentation and the cdr
101extra ELSE indentation. IF after ELSE is indented as the starting IF.")
102
5636765c 103(defcustom simula-if-indent simula-if-indent-default
fb7ada5f 104 "Extra indentation of THEN and ELSE with respect to the starting IF.
eb8c3be9 105Value is a cons cell, the car is extra THEN indentation and the cdr
5636765c
SE
106extra ELSE indentation. IF after ELSE is indented as the starting IF."
107 :type '(cons integer integer)
108 :group 'simula)
a26389d1 109
8ca3cd44
RS
110(defconst simula-inspect-indent-default '(0 . 0)
111 "Extra indentation of WHEN and OTHERWISE with respect to the INSPECT.
112Value is a cons cell, the car is extra WHEN indentation
113and the cdr extra OTHERWISE indentation.")
114
5636765c 115(defcustom simula-inspect-indent simula-inspect-indent-default
fb7ada5f 116 "Extra indentation of WHEN and OTHERWISE with respect to the INSPECT.
3005d32e 117Value is a cons cell, the car is extra WHEN indentation
5636765c
SE
118and the cdr extra OTHERWISE indentation."
119 :type '(cons integer integer)
120 :group 'simula)
a26389d1 121
8ca3cd44
RS
122(defconst simula-electric-indent-default nil
123 "Non-nil means `simula-indent-line' function may reindent previous line.")
124
5636765c 125(defcustom simula-electric-indent simula-electric-indent-default
fb7ada5f 126 "Non-nil means `simula-indent-line' function may reindent previous line."
5636765c
SE
127 :type 'boolean
128 :group 'simula)
a26389d1 129
8ca3cd44
RS
130(defconst simula-abbrev-keyword-default 'upcase
131 "Specify how to convert case for SIMULA keywords.
132Value is one of the symbols `upcase', `downcase', `capitalize',
82e736c1 133\(as in) `abbrev-table' or nil if they should not be changed.")
8ca3cd44 134
5636765c 135(defcustom simula-abbrev-keyword simula-abbrev-keyword-default
fb7ada5f 136 "Specify how to convert case for SIMULA keywords.
3005d32e 137Value is one of the symbols `upcase', `downcase', `capitalize',
82e736c1 138\(as in) `abbrev-table' or nil if they should not be changed."
5636765c
SE
139 :type '(choice (const upcase) (const downcase) (const capitalize)(const nil))
140 :group 'simula)
8ca3cd44
RS
141
142(defconst simula-abbrev-stdproc-default 'abbrev-table
143 "Specify how to convert case for standard SIMULA procedure and class names.
144Value is one of the symbols `upcase', `downcase', `capitalize',
82e736c1 145\(as in) `abbrev-table', or nil if they should not be changed.")
a26389d1 146
5636765c 147(defcustom simula-abbrev-stdproc simula-abbrev-stdproc-default
fb7ada5f 148 "Specify how to convert case for standard SIMULA procedure and class names.
3005d32e 149Value is one of the symbols `upcase', `downcase', `capitalize',
82e736c1 150\(as in) `abbrev-table', or nil if they should not be changed."
5636765c 151 :type '(choice (const upcase) (const downcase) (const capitalize)
e284737d 152 (const abbrev-table) (const nil))
5636765c 153 :group 'simula)
a26389d1 154
5636765c 155(defcustom simula-abbrev-file nil
fb7ada5f 156 "File with extra abbrev definitions for use in SIMULA mode.
3005d32e
RS
157These are used together with the standard abbrev definitions for SIMULA.
158Please note that the standard definitions are required
5636765c
SE
159for SIMULA mode to function correctly."
160 :type '(choice file (const nil))
161 :group 'simula)
a26389d1
ER
162
163(defvar simula-mode-syntax-table nil
3005d32e 164 "Syntax table in SIMULA mode buffers.")
a26389d1 165
cf38dd42
SM
166(defconst simula-syntax-propertize-function
167 (syntax-propertize-rules
168 ;; `comment' directive.
169 ("\\<\\(c\\)omment\\>" (1 "<"))
170 ;; end comments
171 ((concat "\\<end\\>\\([^;\n]\\).*?\\(\n\\|\\(.\\)\\(;\\|"
172 (regexp-opt '("end" "else" "when" "otherwise"))
173 "\\)\\)")
174 (1 "< b")
175 (3 "> b"))
176 ;; non-quoted single-quote char.
177 ("'\\('\\)'" (1 "."))))
e284737d 178
2ff2cda8
SM
179;; Regexps written with help from Alf-Ivar Holm <alfh@ifi.uio.no>.
180(defconst simula-font-lock-keywords-1
e284737d
SM
181 '(;;
182 ;; Compiler directives.
183 ("^%\\([^ \t\n].*\\)" 1 font-lock-constant-face t)
184 ;;
185 ;; Class and procedure names.
186 ("\\<\\(class\\|procedure\\)\\>[ \t]*\\(\\sw+\\)?"
187 (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t)))
2ff2cda8
SM
188 "Subdued level highlighting for Simula mode.")
189
190(defconst simula-font-lock-keywords-2
191 (append simula-font-lock-keywords-1
192 (list
193 ;;
883212ce
SM
194 ;; Constants.
195 '("\\<\\(false\\|none\\|notext\\|true\\)\\>" . font-lock-constant-face)
2ff2cda8
SM
196 ;;
197 ;; Keywords.
e284737d
SM
198 (regexp-opt
199 '("activate" "after" "and" "at" "before" "begin" "delay" "do"
200 "else" "end" "eq" "eqv" "external" "for" "ge" "go" "goto" "gt"
201 "hidden" "if" "imp" "in" "inner" "inspect" "is" "label" "le"
202 "lt" "ne" "new" "not" "or" "otherwise" "prior" "protected"
203 "qua" "reactivate" "step" "switch" "then" "this" "to" "until"
204 "virtual" "when" "while") 'words)
2ff2cda8
SM
205 ;;
206 ;; Types.
e284737d
SM
207 (cons (regexp-opt
208 '("array" "boolean" "character" "integer"
209 "long" "name" "real" "short" "text" "value" "ref") 'words)
210 'font-lock-type-face)))
2ff2cda8
SM
211 "Medium level highlighting for Simula mode.")
212
213(defconst simula-font-lock-keywords-3
214 (append simula-font-lock-keywords-2
215 (list
216 ;;
217 ;; Super-class names and super-slow.
218 '("\\<\\(\\sw+\\)[ \t]+class\\>" 1 font-lock-function-name-face)
219 ;;
220 ;; Types and their declarations.
221 (list (concat "\\<\\(array\\|boolean\\|character\\|integer\\|"
222 "long\\|name\\|real\\|short\\|text\\|value\\)\\>"
223 "\\([ \t]+\\sw+\\>\\)*")
d3aadf0b 224 '(font-lock-match-c-style-declaration-item-and-skip-to-next
2ff2cda8
SM
225 ;; Start with point after all type specifiers.
226 (goto-char (or (match-beginning 2) (match-end 1)))
227 ;; Finish with point after first type specifier.
228 (goto-char (match-end 1))
229 ;; Fontify as a variable name.
230 (1 font-lock-variable-name-face)))
231 ;;
232 ;; Object references and their declarations.
233 '("\\<\\(ref\\)\\>[ \t]*\\((\\(\\sw+\\))\\)?"
234 (3 font-lock-function-name-face nil t)
d3aadf0b 235 (font-lock-match-c-style-declaration-item-and-skip-to-next nil nil
2ff2cda8
SM
236 (1 font-lock-variable-name-face)))
237 ))
238 "Gaudy level highlighting for Simula mode.")
239
240(defvar simula-font-lock-keywords simula-font-lock-keywords-1
241 "Default expressions to highlight in Simula mode.")
242
8ca3cd44
RS
243; The following function is taken from cc-mode.el,
244; it determines the flavor of the Emacs running
8ca3cd44
RS
245
246(defvar simula-mode-menu
3296c443 247 '(["Indent Line" simula-indent-line t]
8ca3cd44
RS
248 ["Backward Statement" simula-previous-statement t]
249 ["Forward Statement" simula-next-statement t]
250 ["Backward Up Level" simula-backward-up-level t]
e284737d 251 ["Forward Down Statement" simula-forward-down-level t])
8ca3cd44
RS
252 "Lucid Emacs menu for SIMULA mode.")
253
a26389d1
ER
254(if simula-mode-syntax-table
255 ()
3005d32e 256 (setq simula-mode-syntax-table (copy-syntax-table (standard-syntax-table)))
a26389d1
ER
257 (modify-syntax-entry ?! "<" simula-mode-syntax-table)
258 (modify-syntax-entry ?$ "." simula-mode-syntax-table)
e284737d
SM
259 (modify-syntax-entry ?% "< b" simula-mode-syntax-table)
260 (modify-syntax-entry ?\n "> b" simula-mode-syntax-table)
a26389d1
ER
261 (modify-syntax-entry ?' "\"" simula-mode-syntax-table)
262 (modify-syntax-entry ?\( "()" simula-mode-syntax-table)
263 (modify-syntax-entry ?\) ")(" simula-mode-syntax-table)
264 (modify-syntax-entry ?\; ">" simula-mode-syntax-table)
265 (modify-syntax-entry ?\[ "." simula-mode-syntax-table)
266 (modify-syntax-entry ?\\ "." simula-mode-syntax-table)
267 (modify-syntax-entry ?\] "." simula-mode-syntax-table)
2ff2cda8 268 (modify-syntax-entry ?_ "_" simula-mode-syntax-table)
a26389d1
ER
269 (modify-syntax-entry ?\| "." simula-mode-syntax-table)
270 (modify-syntax-entry ?\{ "." simula-mode-syntax-table)
271 (modify-syntax-entry ?\} "." simula-mode-syntax-table))
272
e284737d
SM
273(defvar simula-mode-map
274 (let ((map (make-sparse-keymap)))
275 (define-key map "\C-c\C-u" 'simula-backward-up-level)
276 (define-key map "\C-c\C-p" 'simula-previous-statement)
277 (define-key map "\C-c\C-d" 'simula-forward-down-level)
278 (define-key map "\C-c\C-n" 'simula-next-statement)
279 ;; (define-key map "\C-c\C-g" 'simula-goto-definition)
280 ;; (define-key map "\C-c\C-h" 'simula-standard-help)
281 (define-key map "\177" 'backward-delete-char-untabify)
282 (define-key map ":" 'simula-electric-label)
283 (define-key map "\e\C-q" 'simula-indent-exp)
284 (define-key map "\t" 'simula-indent-command)
285 ;; Emacs 19 defines menus in the mode map
286 (define-key map [menu-bar simula]
287 (cons "SIMULA" (make-sparse-keymap "SIMULA")))
e284737d
SM
288 (define-key map [menu-bar simula indent-exp]
289 '("Indent Expression" . simula-indent-exp))
290 (define-key map [menu-bar simula indent-line]
291 '("Indent Line" . simula-indent-command))
292 (define-key map [menu-bar simula separator-navigate]
293 '("--"))
294 (define-key map [menu-bar simula backward-stmt]
295 '("Previous Statement" . simula-previous-statement))
296 (define-key map [menu-bar simula forward-stmt]
297 '("Next Statement" . simula-next-statement))
298 (define-key map [menu-bar simula backward-up]
299 '("Backward Up Level" . simula-backward-up-level))
300 (define-key map [menu-bar simula forward-down]
301 '("Forward Down Statement" . simula-forward-down-level))
302
303 (put 'simula-next-statement 'menu-enable '(not (eobp)))
304 (put 'simula-previous-statement 'menu-enable '(not (bobp)))
305 (put 'simula-forward-down-level 'menu-enable '(not (eobp)))
306 (put 'simula-backward-up-level 'menu-enable '(not (bobp)))
307 (put 'simula-indent-command 'menu-enable '(not buffer-read-only))
308 (put 'simula-indent-exp 'menu-enable '(not buffer-read-only))
309
310 ;; RMS: mouse-3 should not select this menu. mouse-3's global
311 ;; definition is useful in SIMULA mode and we should not interfere
312 ;; with that. The menu is mainly for beginners, and for them,
313 ;; the menubar requires less memory than a special click.
314 ;; in Lucid Emacs, we want the menu to popup when the 3rd button is
315 ;; hit. In 19.10 and beyond this is done automatically if we put
316 ;; the menu on mode-popup-menu variable, see c-common-init [cc-mode.el]
317 ;;(if (not (boundp 'mode-popup-menu))
318 ;; (define-key simula-mode-map 'button3 'simula-popup-menu))
319 map)
320 "Keymap used in `simula-mode'.")
8ca3cd44
RS
321
322;; menus for Lucid
e02f48d7 323(defun simula-popup-menu (_e)
8ca3cd44
RS
324 "Pops up the SIMULA menu."
325 (interactive "@e")
e284737d 326 (popup-menu (cons (concat mode-name " Mode Commands") simula-mode-menu)))
a26389d1 327
2ff2cda8 328;;;###autoload
ae0c2494 329(define-derived-mode simula-mode prog-mode "Simula"
a26389d1
ER
330 "Major mode for editing SIMULA code.
331\\{simula-mode-map}
332Variables controlling indentation style:
e284737d 333 `simula-tab-always-indent'
a26389d1
ER
334 Non-nil means TAB in SIMULA mode should always reindent the current line,
335 regardless of where in the line point is when the TAB command is used.
e284737d 336 `simula-indent-level'
a26389d1 337 Indentation of SIMULA statements with respect to containing block.
e284737d 338 `simula-substatement-offset'
a26389d1 339 Extra indentation after DO, THEN, ELSE, WHEN and OTHERWISE.
e284737d 340 `simula-continued-statement-offset' 3
a26389d1 341 Extra indentation for lines not starting a statement or substatement,
3005d32e 342 e.g. a nested FOR-loop. If value is a list, each line in a multiple-
a26389d1
ER
343 line continued statement will have the car of the list extra indentation
344 with respect to the previous line of the statement.
e284737d 345 `simula-label-offset' -4711
3005d32e 346 Offset of SIMULA label lines relative to usual indentation.
e284737d 347 `simula-if-indent' '(0 . 0)
a26389d1 348 Extra indentation of THEN and ELSE with respect to the starting IF.
eb8c3be9 349 Value is a cons cell, the car is extra THEN indentation and the cdr
3005d32e 350 extra ELSE indentation. IF after ELSE is indented as the starting IF.
e284737d 351 `simula-inspect-indent' '(0 . 0)
a26389d1 352 Extra indentation of WHEN and OTHERWISE with respect to the
3005d32e 353 corresponding INSPECT. Value is a cons cell, the car is
eb8c3be9 354 extra WHEN indentation and the cdr extra OTHERWISE indentation.
e284737d 355 `simula-electric-indent' nil
3005d32e 356 If this variable is non-nil, `simula-indent-line'
a26389d1 357 will check the previous line to see if it has to be reindented.
e284737d 358 `simula-abbrev-keyword' 'upcase
3005d32e
RS
359 Determine how SIMULA keywords will be expanded. Value is one of
360 the symbols `upcase', `downcase', `capitalize', (as in) `abbrev-table',
361 or nil if they should not be changed.
e284737d 362 `simula-abbrev-stdproc' 'abbrev-table
a26389d1 363 Determine how standard SIMULA procedure and class names will be
3005d32e
RS
364 expanded. Value is one of the symbols `upcase', `downcase', `capitalize',
365 (as in) `abbrev-table', or nil if they should not be changed.
a26389d1
ER
366
367Turning on SIMULA mode calls the value of the variable simula-mode-hook
e284737d 368with no arguments, if that value is non-nil."
175069ef
SM
369 (set (make-local-variable 'comment-column) 40)
370 ;; (set (make-local-variable 'end-comment-column) 75)
371 (set (make-local-variable 'paragraph-start) "[ \t]*$\\|\\f")
372 (set (make-local-variable 'paragraph-separate) paragraph-start)
373 (set (make-local-variable 'indent-line-function) 'simula-indent-line)
374 (set (make-local-variable 'comment-start) "! ")
375 (set (make-local-variable 'comment-end) " ;")
376 (set (make-local-variable 'comment-start-skip) "!+ *")
377 (set (make-local-variable 'parse-sexp-ignore-comments) nil)
378 (set (make-local-variable 'comment-multi-line) t)
379 (set (make-local-variable 'font-lock-defaults)
380 '((simula-font-lock-keywords simula-font-lock-keywords-1
381 simula-font-lock-keywords-2 simula-font-lock-keywords-3)
382 nil t ((?_ . "w"))))
cf38dd42
SM
383 (set (make-local-variable 'syntax-propertize-function)
384 simula-syntax-propertize-function)
e284737d 385 (abbrev-mode 1))
a26389d1 386
8ca3cd44
RS
387(defun simula-indent-exp ()
388 "Indent SIMULA expression following point."
389 (interactive)
390 (let ((here (point))
391 (simula-electric-indent nil)
392 end)
393 (simula-skip-comment-forward)
394 (if (eobp)
395 (goto-char here)
396 (unwind-protect
397 (progn
398 (simula-next-statement 1)
399 (setq end (point-marker))
400 (simula-previous-statement 1)
401 (beginning-of-line)
402 (while (< (point) end)
403 (if (not (looking-at "[ \t]*$"))
404 (simula-indent-line))
405 (forward-line 1)))
406 (and end (set-marker end nil))))))
a1506d29 407
a26389d1
ER
408
409(defun simula-indent-line ()
3005d32e
RS
410 "Indent this line as SIMULA code.
411If `simula-electric-indent' is non-nil, indent previous line if necessary."
a26389d1
ER
412 (let ((origin (- (point-max) (point)))
413 (indent (simula-calculate-indent))
414 (case-fold-search t))
415 (unwind-protect
8ca3cd44
RS
416 (if simula-electric-indent
417 (progn
418 ;;
419 ;; manually expand abbrev on last line, if any
420 ;;
421 (end-of-line 0)
422 (expand-abbrev)
423 ;; now maybe we should reindent that line
424 (beginning-of-line)
425 (skip-chars-forward " \t\f")
426 (if (and
427 (looking-at
428 "\\(end\\|if\\|then\\|else\\|when\\|otherwise\\)\\>")
429 (not (simula-context)))
430 ;; yes - reindent
431 (let ((post-indent (simula-calculate-indent)))
432 (if (eq (current-indentation) post-indent)
433 ()
434 (delete-horizontal-space)
435 (indent-to post-indent))))))
a26389d1
ER
436 (goto-char (- (point-max) origin))
437 (if (eq (current-indentation) indent)
438 (back-to-indentation)
439 (delete-horizontal-space)
440 (indent-to indent)))))
441
442
443(defun simula-indent-command (&optional whole-exp)
444 "Indent current line as SIMULA code, or insert TAB character.
3005d32e 445If `simula-tab-always-indent' is non-nil, always indent current line.
a26389d1
ER
446Otherwise, indent only if point is before any non-whitespace
447character on the line.
448
449A numeric argument, regardless of its value, means indent rigidly
450all the lines of the SIMULA statement after point so that this line
451becomes properly indented.
452The relative indentation among the lines of the statement are preserved."
453 (interactive "P")
454 (let ((case-fold-search t))
455 (if (or whole-exp simula-tab-always-indent
456 (save-excursion
457 (skip-chars-backward " \t\f")
458 (bolp)))
459 ;; reindent current line
460 (let ((indent (save-excursion
461 (beginning-of-line)
462 (simula-calculate-indent)))
463 (current (current-indentation))
464 (origin (- (point-max) (point)))
465 (bol (save-excursion
466 (skip-chars-backward " \t\f")
467 (bolp)))
468 beg end)
469 (unwind-protect
470 (if (eq current indent)
471 (if (save-excursion
472 (skip-chars-backward " \t\f")
473 (bolp))
474 (back-to-indentation))
475 (beginning-of-line)
476 (delete-horizontal-space)
477 (indent-to indent))
478 (if (not bol)
479 (goto-char (- (point-max) origin))))
480 (setq origin (point))
481 (if whole-exp
482 (save-excursion
483 (beginning-of-line 2)
484 (setq beg (point))
485 (goto-char origin)
486 (simula-next-statement 1)
487 (setq end (point))
488 (if (and (> end beg) (not (eq indent current)))
489 (indent-code-rigidly beg end (- indent current) "%")))))
490 (insert-tab))))
491
492
493(defun simula-context ()
e284737d 494 "Return value according to syntactic SIMULA context of point.
3005d32e 495 0 point inside COMMENT comment
a26389d1
ER
496 1 point on SIMULA-compiler directive line
497 2 point inside END comment
498 3 point inside string
499 4 point inside character constant
500 nil otherwise."
501 ;; first, find out if this is a compiler directive line
502 (if (save-excursion
503 (beginning-of-line)
504 (eq (following-char) ?%))
505 ;; YES - return 1
506 1
507 (save-excursion
508 ;; The current line is NOT a compiler directive line.
509 ;; Now, the strategy is to search backward to find a semicolon
510 ;; that is NOT inside a string. The point after semicolon MUST be
511 ;; outside a comment, since semicolons are comment-ending and
512 ;; comments are non-recursive. We take advantage of the fact
513 ;; that strings MUST end on the same line as they started, so
514 ;; that we can easily decide whether we are inside a string or not.
515 (let (return-value (origin (point)))
516 (skip-chars-backward "^;" (point-min))
517 ;; found semicolon or beginning of buffer
518 (let (loopvalue (saved-point origin))
519 (while (and (not (bobp))
520 (if (progn
521 (beginning-of-line)
522 ;; compiler directive line? If so, cont searching..
523 (eq (following-char) ?%))
524 t
525 (while (< (point) saved-point)
526 (skip-chars-forward "^;\"'")
527 (forward-char 1)
528 (cond
529 ((eq (preceding-char) ?\;)
530 (setq saved-point (point)))
531 ((eq (preceding-char) ?\")
532 (skip-chars-forward "^\";")
533 (if (eq (following-char) ?\;)
534 (setq saved-point (point) loopvalue t)
535 (forward-char 1)))
536 (t
537 (if (eq (following-char) ?')
538 (forward-char 1))
539 (skip-chars-forward "^';")
540 (if (eq (following-char) ?\;)
541 (setq saved-point (point) loopvalue t)
542 (forward-char 1)))))
543 loopvalue))
544 (backward-char 1)
545 (skip-chars-backward "^;")
546 (setq saved-point (point) loopvalue nil)))
547 ;; Now we are CERTAIN that we are outside comments and strings.
548 ;; The job now is to search forward again towards the origin
549 ;; skipping directives, comments and strings correctly,
550 ;; so that we know what context we are in when we find the origin.
551 (while (and
552 (< (point) origin)
553 (re-search-forward
554 "\\<end\\>\\|!\\|\"\\|'\\|^%\\|\\<comment\\>" origin 'move))
555 (cond
556 ((memq (preceding-char) '(?d ?D))
557 (setq return-value 2)
8ca3cd44
RS
558 (while (and (re-search-forward
559 ";\\|\\<end\\>\\|\\<else\\>\\|\\<otherwise\\>\\|\\<when\\>\\|^%"
560 origin 'move)
561 ;; found another END?
562 (or (memq (preceding-char) '(?d ?D))
563 ;; if directive, skip line
564 (and (eq (preceding-char) ?%)
565 (beginning-of-line 2))
566 ;; found other keyword, out of END comment
567 (setq return-value nil))))
568 (if (and (eq (char-syntax (preceding-char)) ?w)
569 (eq (char-syntax (following-char)) ?w))
570 (save-excursion
571 (backward-word 1)
572 (if (looking-at "end\\>\\|else\\>\\|otherwise\\>\\|when\\>")
573 (setq return-value nil)))))
a26389d1
ER
574 ((memq (preceding-char) '(?! ?t ?T))
575 ; skip comment
576 (setq return-value 0)
577 (skip-chars-forward "^%;" origin)
578 (while (and return-value (< (point) origin))
579 (if (eq (following-char) ?\;)
580 (setq return-value nil)
581 (if (bolp)
582 (beginning-of-line 2) ; skip directive inside comment
583 (forward-char 1)) ; or single '%'
584 (skip-chars-forward "^%;" origin))))
585 ((eq (preceding-char) ?\")
586 (if (not (search-forward "\"" origin 'move))
587 (setq return-value 3)))
588 ((eq (preceding-char) ?\')
589 (if (or (eq (point) origin) (eobp))
590 (setq return-value 4)
591 (forward-char 1)
592 (if (not (search-forward "'" origin 'move))
593 (setq return-value 4))))
594 ;; compiler directive line - skip
595 (t (beginning-of-line 2))))
596 return-value)
597 )))
598
599
600(defun simula-electric-label ()
3005d32e 601 "If this is a label that starts the line, reindent the line."
a26389d1
ER
602 (interactive)
603 (expand-abbrev)
604 (insert ?:)
605 (let ((origin (- (point-max) (point)))
606 (case-fold-search t)
607 ;; don't mix a label with an assignment operator := :-
8ca3cd44
RS
608 ;; therefore take a peek at next typed character...
609 (next-char (read-event)))
a26389d1 610 (unwind-protect
8ca3cd44
RS
611 (setq unread-command-events (append unread-command-events
612 (list next-char)))
a26389d1
ER
613 ;; Problem: find out if character just read is a command char
614 ;; that would insert something after ':' making it a label.
615 ;; At least \n, \r (and maybe \t) falls into this category.
616 ;; This is a real crock, it depends on traditional keymap
617 ;; bindings, that is, printing characters doing self-insert,
618 ;; and no other command sequence inserting '-' or '='.
619 ;; simula-electric-label can be easily fooled...
620 (if (and (not (memq next-char '(?= ?-)))
621 (or (memq next-char '(?\n ?\r))
622 (and (eq next-char ?\t)
623 simula-tab-always-indent)
624 (not (memq (following-char) '(?= ?-))))
625 (not (simula-context))
626 ;; label?
627 (progn
628 (backward-char 1)
629 (skip-chars-backward " \t\f")
630 (skip-chars-backward "a-zA-Z0-9_")
631 (if (looking-at "virtual\\>")
632 nil
633 (skip-chars-backward " \t\f")
634 (bolp))))
635 (let ((amount (simula-calculate-indent)))
636 (delete-horizontal-space)
637 (indent-to amount)))
638 (goto-char (- (point-max) origin)))))
a1506d29 639
a26389d1
ER
640
641(defun simula-backward-up-level (count)
642 "Move backward up COUNT block levels.
3005d32e 643If COUNT is negative, move forward up block level instead."
a26389d1
ER
644 (interactive "p")
645 (let ((origin (point))
646 (case-fold-search t))
647 (condition-case ()
648 (if (> count 0)
649 (while (> count 0)
650 (re-search-backward "\\<begin\\>\\|\\<end\\>")
651 (if (not (simula-context))
652 (setq count (if (memq (following-char) '(?b ?B))
653 (1- count)
654 (1+ count)))))
655 (while (< count 0)
656 (re-search-forward "\\<begin\\>\\|\\<end\\>")
657 (backward-word 1)
658 (if (not (simula-context))
659 (setq count (if (memq (following-char) '(?e ?E))
660 (1+ count)
661 (1- count))))
662 (backward-word -1)))
663 ;; If block level not found, jump back to origin and signal an error
664 (error (progn
665 (goto-char origin)
666 (error "No higher block level")))
667 (quit (progn
668 (goto-char origin)
669 (signal 'quit nil))))))
670
671
672(defun simula-forward-down-level (count)
673 "Move forward down COUNT block levels.
3005d32e 674If COUNT is negative, move backward down block level instead."
a26389d1
ER
675 (interactive "p")
676 ;; When we search for a deeper block level, we must never
677 ;; get out of the block where we started -> count >= start-count
678 (let ((start-count count)
679 (origin (point))
680 (case-fold-search t))
681 (condition-case ()
682 (if (< count 0)
683 (while (< count 0)
684 (re-search-backward "\\<begin\\>\\|\\<end\\>")
685 (if (not (simula-context))
686 (setq count (if (memq (following-char) '(?e ?E))
687 (1+ count)
688 (1- count))))
689 (if (< count start-count) (signal 'error nil)))
690 (while (> count 0)
691 (re-search-forward "\\<begin\\>\\|\\<end\\>")
692 (backward-word 1)
693 (if (not (simula-context))
694 (setq count (if (memq (following-char) '(?b ?B))
695 (1- count)
696 (1+ count))))
697 (backward-word -1)
698 ;; deeper level has to be found within starting block
699 (if (> count start-count) (signal 'error nil))))
700 ;; If block level not found, jump back to origin and signal an error
701 (error (progn
702 (goto-char origin)
703 (error "No containing block level")))
704 (quit (progn
705 (goto-char origin)
706 (signal 'quit nil))))))
707
a1506d29 708
a26389d1
ER
709(defun simula-previous-statement (count)
710 "Move backward COUNT statements.
3005d32e 711If COUNT is negative, move forward instead."
a26389d1
ER
712 (interactive "p")
713 (if (< count 0)
714 (simula-next-statement (- count))
715 (let (status
716 (case-fold-search t)
717 (origin (point)))
718 (condition-case ()
a1506d29 719 ;;
a26389d1
ER
720 (progn
721 (simula-skip-comment-backward)
722 (if (memq (preceding-char) '(?n ?N))
723 (progn
724 (backward-word 1)
725 (if (not (looking-at "\\<begin\\>"))
726 (backward-word -1)))
727 (if (eq (preceding-char) ?\;)
8ca3cd44
RS
728 (backward-char 1))
729 )
a26389d1
ER
730 (while (and (natnump (setq count (1- count)))
731 (setq status (simula-search-backward
732 ";\\|\\<begin\\>" nil 'move))))
733 (if status
734 (progn
735 (if (eq (following-char) ?\;)
736 (forward-char 1)
737 (backward-word -1))))
738 (simula-skip-comment-forward))
739 (error (progn (goto-char origin)
740 (error "Incomplete statement (too many ENDs)")))
741 (quit (progn (goto-char origin) (signal 'quit nil)))))))
742
743
744(defun simula-next-statement (count)
3005d32e
RS
745 "Move forward COUNT statements.
746If COUNT is negative, move backward instead."
a26389d1
ER
747 (interactive "p")
748 (if (< count 0)
749 (simula-previous-statement (- count))
750 (let (status
751 (case-fold-search t)
752 (origin (point)))
753 (condition-case ()
754 (progn
755 (simula-skip-comment-forward)
756 (if (looking-at "\\<end\\>") (forward-word 1))
757 (while (and (natnump (setq count (1- count)))
758 (setq status (simula-search-forward
759 ";\\|\\<end\\>" (point-max) 'move))))
760 (if (and status (/= (preceding-char) ?\;))
761 (progn
762 (backward-word 1)
763 (simula-skip-comment-backward))))
764 (error (progn (goto-char origin)
765 (error "Incomplete statement (too few ENDs)")))
766 (quit (progn (goto-char origin) (signal 'quit nil)))))))
767
768
8ca3cd44 769(defun simula-skip-comment-backward (&optional stop-at-end)
3005d32e 770 "Search towards bob to find first char that is outside a comment."
a26389d1
ER
771 (interactive)
772 (catch 'simula-out
773 (let (context)
774 (while t
775 (skip-chars-backward " \t\n\f")
776 (if (eq (preceding-char) ?\;)
777 (save-excursion
778 (backward-char 1)
8ca3cd44
RS
779 (setq context (simula-context))
780 (if (and stop-at-end (eq context 2))
781 (setq context nil)))
a26389d1
ER
782 (setq context (simula-context)))
783 (cond
784 ((memq context '(nil 3 4))
785 ;; check to see if we found a label
786 (if (and (eq (preceding-char) ?:)
787 (not (memq (following-char) '(?- ?=)))
788 (save-excursion
789 (skip-chars-backward ": \t\fa-zA-Z0-9_")
790 (not (looking-at "virtual\\>"))))
791 (skip-chars-backward ": \t\fa-zA-Z0-9_")
792 (throw 'simula-out nil)))
793 ((eq context 0)
794 ;; since we are inside a comment, it must start somewhere!
795 (while (and (re-search-backward "!\\|\\<comment\\>")
796 (memq (simula-context) '(0 1)))))
797 ((eq context 1)
8ca3cd44 798 (beginning-of-line)
a26389d1 799 (if (bobp)
8ca3cd44
RS
800 (throw 'simula-out nil)
801 (backward-char)))
a26389d1
ER
802 ((eq context 2)
803 ;; an END-comment must belong to an END
804 (re-search-backward "\\<end\\>")
805 (forward-word 1)
806 (throw 'simula-out nil))
807 ;; should be impossible to get here..
808 )))))
809
810
811(defun simula-skip-comment-forward ()
3005d32e 812 "Search towards eob to find first char that is outside a comment."
a26389d1
ER
813 ;; this function assumes we start with point .outside a comment
814 (interactive)
815 (catch 'simula-out
816 (while t
817 (skip-chars-forward " \t\n\f")
8ca3cd44
RS
818 ;; BUG: the following (0 2) branches don't take into account intermixing
819 ;; directive lines
a26389d1
ER
820 (cond
821 ((looking-at "!\\|\\<comment\\>")
822 (search-forward ";" nil 'move))
823 ((and (bolp) (eq (following-char) ?%))
824 (beginning-of-line 2))
825 ((and (looking-at "[a-z0-9_]*[ \t\f]*:[^-=]")
826 (not (looking-at "virtual\\>")))
827 (skip-chars-forward "a-zA-Z0-9_ \t\f:"))
828 (t
829 (throw 'simula-out t))))))
830
831
832(defun simula-forward-up-level ()
833 (let ((continue-loop t)
834 (origin (point))
835 (case-fold-search t)
836 return-value
837 temp)
838 (while continue-loop
839 (if (re-search-backward "\\<begin\\>\\|\\<end\\>" (point-min) 'move)
840 (setq temp (simula-context)
841 return-value (and (memq (preceding-char) '(?d ?D))
842 (memq temp '(nil 2)))
843 continue-loop (and (not return-value)
844 (simula-forward-up-level)))
845 (setq continue-loop nil)))
846 (if return-value
847 t
848 (goto-char origin)
849 nil)))
850
851
852(defun simula-calculate-indent ()
853 (save-excursion
854 (let ((where (simula-context))
855 (origin (point))
856 (indent 0)
857 continued
858 start-line
859 temp
860 found-end
861 prev-cont)
862 (cond
863 ((eq where 0)
864 ;;
865 ;; Comment.
866 ;; If comment started on previous non-blank line, indent to the
867 ;; column where the comment started, else indent as that line.
868 ;;
869 (skip-chars-backward " \t\n\f")
870 (while (and (not (bolp)) (eq (simula-context) 0))
871 (re-search-backward "^\\|!\\|\\<comment\\>"))
872 (skip-chars-forward " \t\n\f")
873 (prog1
874 (current-column)
875 (goto-char origin)))
8ca3cd44
RS
876 ((eq where 1)
877 ;;
878 ;; Directive. Always 0.
879 ;;
880 0)
a26389d1
ER
881 ;;
882 ;; Detect missing string delimiters
883 ;;
884 ((eq where 3)
885 (error "Inside string"))
886 ((eq where 4)
887 (error "Inside character constant"))
888 ;;
889 ;; check to see if inside ()'s
890 ;;
891 ((setq temp (simula-inside-parens))
892 temp)
893 ;;
894 ;; Calculate non-comment indentation
895 (t
896 ;; first, find out if this line starts with something that needs
eb8c3be9 897 ;; special indentation (END/IF/THEN/ELSE/WHEN/OTHERWISE or label)
a26389d1
ER
898 ;;
899 (skip-chars-forward " \t\f")
900 (cond
901 ;;
902 ;; END
903 ;;
904 ((looking-at "end\\>")
905 (setq indent (- simula-indent-level)
906 found-end t))
907 ;;
908 ;; IF/THEN/ELSE
909 ;;
910 ((looking-at "if\\>\\|then\\>\\|else\\>")
911 ;; search for the *starting* IF
912 (cond
913 ((memq (following-char) '(?T ?t))
914 (setq indent (car simula-if-indent)))
915 ((memq (following-char) '(?E ?e))
916 (setq indent (cdr simula-if-indent)))
917 (t
918 (forward-word 1)
919 (setq indent 0)))
920 (simula-find-if))
921 ;;
922 ;; WHEN/OTHERWISE
923 ;;
924 ((looking-at "when\\>\\|otherwise\\>")
925 ;; search for corresponding INSPECT
926 (if (memq (following-char) '(?W ?w))
927 (setq indent (car simula-inspect-indent))
928 (setq indent (cdr simula-inspect-indent)))
929 (simula-find-inspect))
930 ;;
931 ;; label:
932 ;;
933 ((and (not (looking-at "virtual\\>"))
934 (looking-at "[a-z0-9_]*[ \t\f]*:[^-=]"))
935 (setq indent simula-label-offset)))
936 ;; find line with non-comment text
8ca3cd44 937 (simula-skip-comment-backward 'dont-skip-end)
a26389d1
ER
938 (if (and found-end
939 (not (eq (preceding-char) ?\;))
940 (if (memq (preceding-char) '(?N ?n))
941 (save-excursion
ca3e10c7 942 (backward-word 1)
a26389d1
ER
943 (not (looking-at "begin\\>")))
944 t))
945 (progn
946 (simula-previous-statement 1)
947 (simula-skip-comment-backward)))
948 (setq start-line
5ed619e0 949 (line-beginning-position)
a26389d1
ER
950 ;; - perhaps this is a continued statement
951 continued
952 (save-excursion
953 (and (not (bobp))
954 ;; (not found-end)
955 (if (eq (char-syntax (preceding-char)) ?w)
956 (progn
957 (backward-word 1)
958 (not (looking-at
959 "begin\\|then\\|else\\|when\\|otherwise\\|do"
960 )))
961 (not (memq (preceding-char) '(?: ?\;)))))))
962 ;;
963 ;; MAIN calculation loop - count BEGIN/DO etc.
964 ;;
965 (while (not (bolp))
966 (if (re-search-backward
967 ";\\|\\<\\(begin\\|end\\|if\\|else\\|then\\|when\\|otherwise\\|do\\)\\>"
968 start-line 'move)
969 (if (simula-context)
970 ();; found something in a comment/string - ignore
971 (setq temp (following-char))
972 (cond
973 ((eq temp ?\;)
974 (simula-previous-statement 1))
975 ((looking-at "begin\\>")
976 (setq indent (+ indent simula-indent-level)))
977 ((looking-at "end\\>")
978 (forward-word 1)
979 (simula-previous-statement 1))
980 ((looking-at "do\\>")
981 (setq indent (+ indent simula-substatement-offset))
982 (simula-find-do-match))
983 ((looking-at "\\(if\\|then\\|else\\)\\>")
984 (if (memq temp '(?I ?i))
985 (forward-word 1)
986 (setq indent (+ indent
987 simula-substatement-offset
988 (if (memq temp '(?T ?t))
989 (car simula-if-indent)
990 (cdr simula-if-indent)))))
991 (simula-find-if))
992 ((looking-at "\\<when\\>\\|\\<otherwise\\>")
993 (setq indent (+ indent
994 simula-substatement-offset
995 (if (memq temp '(?W ?w))
996 (car simula-if-indent)
997 (cdr simula-if-indent))))
998 (simula-find-inspect)))
999 ;; found the start of a [sub]statement
eb8c3be9 1000 ;; add indentation for continued statement
a26389d1
ER
1001 (if continued
1002 (setq indent
1003 (+ indent
1004 (if (listp simula-continued-statement-offset)
1005 (car simula-continued-statement-offset)
1006 simula-continued-statement-offset))))
1007 (setq start-line
5ed619e0 1008 (line-beginning-position)
a26389d1
ER
1009 continued nil))
1010 ;; search failed .. point is at beginning of line
1011 ;; determine if we should continue searching
1012 ;; (at or before comment or label)
1013 ;; temp = t means finished
1014 (setq temp
a1506d29 1015 (and (not (simula-context))
a26389d1
ER
1016 (save-excursion
1017 (skip-chars-forward " \t\f")
1018 (or (looking-at "virtual")
1019 (not
1020 (looking-at
1021 "!\\|comment\\>\\|[a-z0-9_]*[ \t\f]*:[^-=]")))))
1022 prev-cont continued)
1023 ;; if we are finished, find current line's indentation
1024 (if temp
1025 (setq indent (+ indent (current-indentation))))
1026 ;; find next line with non-comment SIMULA text
1027 ;; maybe indent extra if statement continues
1028 (simula-skip-comment-backward)
1029 (setq continued
1030 (and (not (bobp))
1031 (if (eq (char-syntax (preceding-char)) ?w)
1032 (save-excursion
1033 (backward-word 1)
1034 (not (looking-at
1035 "begin\\|then\\|else\\|when\\|otherwise\\|do")))
1036 (not (memq (preceding-char) '(?: ?\;))))))
1037 ;; if we the state of the continued-variable
eb8c3be9 1038 ;; changed, add indentation for continued statement
a26389d1
ER
1039 (if (or (and prev-cont (not continued))
1040 (and continued
1041 (listp simula-continued-statement-offset)))
1042 (setq indent
1043 (+ indent
1044 (if (listp simula-continued-statement-offset)
1045 (car simula-continued-statement-offset)
1046 simula-continued-statement-offset))))
1047 ;; while ends if point is at beginning of line at loop test
1048 (if (not temp)
5ed619e0 1049 (setq start-line (line-beginning-position))
a26389d1
ER
1050 (beginning-of-line))))
1051 ;;
eb8c3be9 1052 ;; return indentation
a26389d1
ER
1053 ;;
1054 indent)))))
1055
1056
1057(defun simula-find-if ()
3005d32e 1058 "Find starting IF of a IF-THEN[-ELSE[-IF-THEN...]] statement."
a26389d1
ER
1059 (catch 'simula-out
1060 (while t
1061 (if (and (simula-search-backward "\\<if\\>\\|;\\|\\<begin\\>"nil t)
1062 (memq (following-char) '(?I ?i)))
1063 (save-excursion
1064 ;;
1065 ;; find out if this IF was really the start of the IF statement
1066 ;;
1067 (simula-skip-comment-backward)
1068 (if (and (eq (char-syntax (preceding-char)) ?w)
1069 (progn
1070 (backward-word 1)
1071 (looking-at "else\\>")))
1072 ()
1073 (throw 'simula-out t)))
1074 (if (not (looking-at "\\<if\\>"))
1075 (error "Missing IF or misplaced BEGIN or ';' (can't find IF)")
1076 ;;
1077 ;; we were at the starting IF in the first place..
1078 ;;
1079 (throw 'simula-out t))))))
1080
1081
1082(defun simula-find-inspect ()
3005d32e 1083 "Find INSPECT matching WHEN or OTHERWISE."
a26389d1
ER
1084 (catch 'simula-out
1085 (let ((level 0))
1086 ;;
1087 ;; INSPECTs can be nested, have to find the corresponding one
1088 ;;
1089 (while t
1090 (if (and (simula-search-backward "\\<inspect\\>\\|\\<otherwise\\>\\|;"
1091 nil t)
1092 (/= (following-char) ?\;))
1093 (if (memq (following-char) '(?O ?o))
1094 (setq level (1+ level))
1095 (if (zerop level)
1096 (throw 'simula-out t)
1097 (setq level (1- level))))
1098 (error "Missing INSPECT or misplaced ';' (can't find INSPECT)"))))))
1099
1100
1101(defun simula-find-do-match ()
e284737d 1102 "Find keyword matching DO: FOR, WHILE, INSPECT or WHEN."
a26389d1
ER
1103 (while (and (re-search-backward
1104 "\\<\\(do\\|for\\|while\\|inspect\\|when\\|end\\|begin\\)\\>\\|;"
1105 nil 'move)
1106 (simula-context)))
1107 (if (and (looking-at "\\<\\(for\\|while\\|inspect\\|when\\)\\>")
1108 (not (simula-context)))
1109 () ;; found match
1110 (error "No matching FOR, WHILE or INSPECT for DO, or misplaced ';'")))
1111
1112
1113(defun simula-inside-parens ()
3005d32e 1114 "Return position after `(' on line if inside parentheses, nil otherwise."
a26389d1
ER
1115 (save-excursion
1116 (let ((parlevel 0))
1117 (catch 'simula-out
1118 (while t
1119 (if (re-search-backward "(\\|)\\|;" nil t)
1120 (if (eq (simula-context) nil)
1121 ;; found something - check it out
1122 (cond
1123 ((eq (following-char) ?\;)
1124 (if (zerop parlevel)
1125 (throw 'simula-out nil)
eb8c3be9 1126 (error "Parenthesis mismatch or misplaced ';'")))
a26389d1
ER
1127 ((eq (following-char) ?\()
1128 (if (zerop parlevel)
1129 (throw 'simula-out (1+ (current-column)))
1130 (setq parlevel (1- parlevel))))
1131 (t (setq parlevel (1+ parlevel))))
1132 );; nothing - inside comment or string
1133 ;; search failed
1134 (throw 'simula-out nil)))))))
1135
1136
1137(defun simula-goto-definition ()
1138 "Goto point of definition of variable, procedure or class."
1139 (interactive))
1140
1141
1142(defun simula-expand-stdproc ()
1143 (if (or (not simula-abbrev-stdproc) (simula-context))
1144 (unexpand-abbrev)
1145 (cond
1146 ((eq simula-abbrev-stdproc 'upcase) (upcase-word -1))
1147 ((eq simula-abbrev-stdproc 'downcase) (downcase-word -1))
8ca3cd44
RS
1148 ((eq simula-abbrev-stdproc 'capitalize) (capitalize-word -1))
1149 ((eq simula-abbrev-stdproc 'abbrev-table)
1150 ;; If not in lowercase, expansions are always capitalized.
1151 ;; We then want to replace with the exact expansion.
1152 (if (equal (symbol-name last-abbrev) last-abbrev-text)
1153 ()
1154 (downcase-word -1)
1155 (expand-abbrev))))))
a26389d1
ER
1156
1157
1158(defun simula-expand-keyword ()
1159 (if (or (not simula-abbrev-keyword) (simula-context))
1160 (unexpand-abbrev)
1161 (cond
1162 ((eq simula-abbrev-keyword 'upcase) (upcase-word -1))
1163 ((eq simula-abbrev-keyword 'downcase) (downcase-word -1))
8ca3cd44
RS
1164 ((eq simula-abbrev-keyword 'capitalize) (capitalize-word -1))
1165 ((eq simula-abbrev-stdproc 'abbrev-table)
1166 (if (equal (symbol-name last-abbrev) last-abbrev-text)
1167 ()
1168 (downcase-word -1)
1169 (expand-abbrev))))))
a26389d1
ER
1170
1171
1172(defun simula-electric-keyword ()
3005d32e 1173 "Expand SIMULA keyword. If it starts the line, reindent."
a26389d1
ER
1174 ;; redisplay
1175 (let ((show-char (eq this-command 'self-insert-command)))
eb8c3be9 1176 ;; If the abbrev expansion results in reindentation, the user may have
a26389d1
ER
1177 ;; to wait some time before the character he typed is displayed
1178 ;; (the char causing the expansion is inserted AFTER the hook function
1179 ;; is called). This is annoying in case of normal characters.
1180 ;; However, if the user pressed a key bound to newline, it is better
1181 ;; to have the line inserted after the begin-end match.
1182 (if show-char
1183 (progn
1ba983e8 1184 (insert-char last-command-event 1)
a26389d1
ER
1185 (sit-for 0)
1186 (backward-char 1)))
1187 (if (let ((where (simula-context))
1188 (case-fold-search t))
1189 (if where
1190 (if (and (eq where 2) (eq (char-syntax (preceding-char)) ?w))
1191 (save-excursion
1192 (backward-word 1)
1193 (not (looking-at "end\\>"))))))
1194 (unexpand-abbrev)
1195 (cond
1196 ((not simula-abbrev-keyword) (unexpand-abbrev))
1197 ((eq simula-abbrev-keyword 'upcase) (upcase-word -1))
1198 ((eq simula-abbrev-keyword 'downcase) (downcase-word -1))
1199 ((eq simula-abbrev-keyword 'capitalize) (capitalize-word -1)))
1200 (let ((pos (- (point-max) (point)))
e02f48d7
JB
1201 (case-fold-search t))
1202 (condition-case nil
a26389d1
ER
1203 (progn
1204 ;; check if the expanded word is on the beginning of the line.
1205 (if (and (eq (char-syntax (preceding-char)) ?w)
1206 (progn
1207 (backward-word 1)
1208 (if (looking-at "end\\>")
1209 (save-excursion
1210 (simula-backward-up-level 1)
1211 (if (pos-visible-in-window-p)
1212 (sit-for 1)
23161c61 1213 (message "Matches %s"
a26389d1
ER
1214 (buffer-substring
1215 (point)
23161c61 1216 (+ (point) (window-width)))))))
a26389d1
ER
1217 (skip-chars-backward " \t\f")
1218 (bolp)))
1219 (let ((indent (simula-calculate-indent)))
1220 (if (eq indent (current-indentation))
1221 ()
1222 (delete-horizontal-space)
1223 (indent-to indent)))
1224 (skip-chars-forward " \t\f"))
1225 ;; check for END - blow whistles and ring bells
1226
1227 (goto-char (- (point-max) pos))
1228 (if show-char
1229 (delete-char 1)))
1230 (quit (goto-char (- (point-max) pos))))))))
1231
1232
8ca3cd44 1233(defun simula-search-backward (regexp &optional bound noerror)
e284737d
SM
1234 "Search backward from point for regular expression REGEXP,
1235ignoring matches found inside SIMULA comments, string literals,
1236and BEGIN..END blocks.
8ca3cd44
RS
1237Set point to the end of the occurrence found, and return point.
1238An optional second argument BOUND bounds the search, it is a buffer position.
1239The match found must not extend after that position. Optional third argument
1240NOERROR, if t, means if fail just return nil (no error).
1241If not nil and not t, move to limit of search and return nil."
e02f48d7
JB
1242 (let ((comb-regexp (concat regexp "\\|\\<end\\>"))
1243 (start-point (point))
1244 context match)
8ca3cd44
RS
1245 (catch 'simula-backward
1246 (while (re-search-backward comb-regexp bound 1)
1247 ;; We have a match, check SIMULA context at match-beginning
1248 ;; to see if we are outside comments etc.
1249 ;; Set MATCH to t if we found a true match,
1250 ;; set MATCH to 'BLOCK if we found a BEGIN..END block,
1251 ;; else set MATCH to nil.
1252 (save-match-data
1253 (setq context (simula-context))
1254 (cond
1255 ((eq context nil)
1256 (setq match (if (looking-at regexp) t 'BLOCK)))
e284737d
SM
1257 ;; A comment-ending `;' is part of the comment, and shouldn't match.
1258 ;; ((eq context 0)
1259 ;; (setq match (if (eq (following-char) ?\;) t nil)))
8ca3cd44
RS
1260 ((eq context 2)
1261 (setq match (if (and (looking-at regexp)
1262 (looking-at ";\\|\\<end\\>\\|\\<else\\>\\|\\<otherwise\\>\\|\\<when\\>"))
1263 t
1264 (if (looking-at "\\<end\\>") 'BLOCK nil))))
1265 (t (setq match nil))))
1266 ;; Exit if true match
1267 (if (eq match t) (throw 'simula-backward (point)))
1268 (if (eq match 'BLOCK)
1269 ;; We found the END of a block
1270 (let ((level 0))
1271 (while (natnump level)
1272 (if (re-search-backward "\\<begin\\>\\|\\<end\\>" bound 1)
1273 (let ((context (simula-context)))
1274 ;; We found a BEGIN -> decrease level count
1275 (cond ((and (eq context nil)
1276 (memq (following-char) '(?b ?B)))
1277 (setq level (1- level)))
1278 ;; END -> increase level count
1279 ((and (memq context '(nil 2))
1280 (memq (following-char) '(?e ?E)))
1281 (setq level (1+ level)))))
1282 ;; Block search failed. Action depends on noerror.
1283 (if (or (not noerror) (eq noerror t))
1284 (goto-char start-point))
1285 (if (not noerror)
1286 (signal 'search-failed (list regexp)))
1287 (throw 'simula-backward nil))))))
1288 ;; Search failed. Action depends on noerror.
1289 (if (or (not noerror) (eq noerror t))
1290 (goto-char start-point))
1291 (if noerror
1292 nil
1293 (signal 'search-failed (list regexp))))))
1294
1295
1296(defun simula-search-forward (regexp &optional bound noerror)
e284737d
SM
1297 "Search forward from point for regular expression REGEXP,
1298ignoring matches found inside SIMULA comments, string literals,
1299and BEGIN..END blocks.
8ca3cd44
RS
1300Set point to the end of the occurrence found, and return point.
1301An optional second argument BOUND bounds the search, it is a buffer position.
1302The match found must not extend after that position. Optional third argument
1303NOERROR, if t, means if fail just return nil (no error).
1304If not nil and not t, move to limit of search and return nil."
e02f48d7
JB
1305 (let ((comb-regexp (concat regexp "\\|\\<begin\\>"))
1306 (start-point (point))
1307 context match)
8ca3cd44
RS
1308 (catch 'simula-forward
1309 (while (re-search-forward comb-regexp bound 1)
1310 ;; We have a match, check SIMULA context at match-beginning
1311 ;; to see if we are outside comments.
1312 ;; Set MATCH to t if we found a true match,
1313 ;; set MATCH to 'BLOCK if we found a BEGIN..END block,
1314 ;; else set MATCH to nil.
1315 (save-match-data
1316 (save-excursion
1317 (goto-char (match-beginning 0))
1318 (setq context (simula-context))
1319 (cond
1320 ((not context)
1321 (setq match (if (looking-at regexp) t 'BLOCK)))
e284737d
SM
1322 ;; Comment-ending `;' is part of the comment, and shouldn't match.
1323 ;; ((eq context 0)
1324 ;; (setq match (if (eq (following-char) ?\;) t nil)))
8ca3cd44
RS
1325 ((eq context 2)
1326 (setq match (if (and (looking-at regexp)
1327 (looking-at ";\\|\\<end\\>\\|\\<else\\>\\|\\<otherwise\\>\\|\\<when\\>")) t nil)))
1328 (t (setq match nil)))))
1329 ;; Exit if true match
1330 (if (eq match t) (throw 'simula-forward (point)))
1331 (if (eq match 'BLOCK)
1332 ;; We found the BEGINning of a block
1333 (let ((level 0))
1334 (while (natnump level)
1335 (if (re-search-forward "\\<begin\\>\\|\\<end\\>" bound 1)
1336 (let ((context (simula-context)))
1337 ;; We found a BEGIN -> increase level count
1338 (cond ((eq context nil) (setq level (1+ level)))
1339 ;; END -> decrease level count
1340 ((and (eq context 2)
1341 ;; Don't match BEGIN inside END comment
1342 (memq (preceding-char) '(?d ?D)))
1343 (setq level (1- level)))))
1344 ;; Block search failed. Action depends on noerror.
1345 (if (or (not noerror) (eq noerror t))
1346 (goto-char start-point))
1347 (if (not noerror)
1348 (signal 'search-failed (list regexp)))
1349 (throw 'simula-forward nil))))))
1350 ;; Search failed. Action depends on noerror.
1351 (if (or (not noerror) (eq noerror t))
1352 (goto-char start-point))
1353 (if noerror
1354 nil
1355 (signal 'search-failed (list regexp))))))
a26389d1 1356
a1506d29 1357
a26389d1 1358(defun simula-install-standard-abbrevs ()
3005d32e 1359 "Define Simula keywords, procedures and classes in local abbrev table."
a26389d1
ER
1360 ;; procedure and class names are as of the SIMULA 87 standard.
1361 (interactive)
8fc98fc4 1362 (dolist (args
a26389d1
ER
1363 '(("abs" "Abs" simula-expand-stdproc)
1364 ("accum" "Accum" simula-expand-stdproc)
1365 ("activate" "ACTIVATE" simula-expand-keyword)
1366 ("addepsilon" "AddEpsilon" simula-expand-stdproc)
1367 ("after" "AFTER" simula-expand-keyword)
1368 ("and" "AND" simula-expand-keyword)
1369 ("arccos" "ArcCos" simula-expand-stdproc)
1370 ("arcsin" "ArcSin" simula-expand-stdproc)
1371 ("arctan" "ArcTan" simula-expand-stdproc)
1372 ("arctan2" "ArcTan2" simula-expand-stdproc)
1373 ("array" "ARRAY" simula-expand-keyword)
1374 ("at" "AT" simula-expand-keyword)
1375 ("before" "BEFORE" simula-expand-keyword)
1376 ("begin" "BEGIN" simula-expand-keyword)
1377 ("blanks" "Blanks" simula-expand-stdproc)
1378 ("boolean" "BOOLEAN" simula-expand-keyword)
1379 ("breakoutimage" "BreakOutImage" simula-expand-stdproc)
1380 ("bytefile" "ByteFile" simula-expand-stdproc)
1381 ("call" "Call" simula-expand-stdproc)
1382 ("cancel" "Cancel" simula-expand-stdproc)
1383 ("cardinal" "Cardinal" simula-expand-stdproc)
1384 ("char" "Char" simula-expand-stdproc)
1385 ("character" "CHARACTER" simula-expand-keyword)
1386 ("checkpoint" "CheckPoint" simula-expand-stdproc)
1387 ("class" "CLASS" simula-expand-keyword)
1388 ("clear" "Clear" simula-expand-stdproc)
1389 ("clocktime" "ClockTime" simula-expand-stdproc)
1390 ("close" "Close" simula-expand-stdproc)
1391 ("comment" "COMMENT" simula-expand-keyword)
1392 ("constant" "Constant" simula-expand-stdproc)
1393 ("copy" "Copy" simula-expand-stdproc)
1394 ("cos" "Cos" simula-expand-stdproc)
1395 ("cosh" "CosH" simula-expand-stdproc)
1396 ("cotan" "CoTan" simula-expand-stdproc)
1397 ("cputime" "CpuTime" simula-expand-stdproc)
1398 ("current" "Current" simula-expand-stdproc)
1399 ("datetime" "DateTime" simula-expand-stdproc)
1400 ("decimalmark" "DecimalMark" simula-expand-stdproc)
1401 ("delay" "DELAY" simula-expand-keyword)
1402 ("deleteimage" "DeleteImage" simula-expand-stdproc)
1403 ("detach" "Detach" simula-expand-stdproc)
1404 ("digit" "Digit" simula-expand-stdproc)
1405 ("directbytefile" "DirectByteFile" simula-expand-stdproc)
1406 ("directfile" "DirectFile" simula-expand-stdproc)
1407 ("discrete" "Discrete" simula-expand-stdproc)
1408 ("do" "DO" simula-expand-keyword)
1409 ("downcase" "Downcase" simula-expand-stdproc)
1410 ("draw" "Draw" simula-expand-stdproc)
1411 ("eject" "Eject" simula-expand-stdproc)
1412 ("else" "ELSE" simula-electric-keyword)
1413 ("empty" "Empty" simula-expand-stdproc)
1414 ("end" "END" simula-electric-keyword)
1415 ("endfile" "Endfile" simula-expand-stdproc)
1416 ("entier" "Entier" simula-expand-stdproc)
1417 ("eq" "EQ" simula-expand-keyword)
1418 ("eqv" "EQV" simula-expand-keyword)
1419 ("erlang" "Erlang" simula-expand-stdproc)
1420 ("error" "Error" simula-expand-stdproc)
1421 ("evtime" "EvTime" simula-expand-stdproc)
1422 ("exp" "Exp" simula-expand-stdproc)
1423 ("external" "EXTERNAL" simula-expand-keyword)
1424 ("false" "FALSE" simula-expand-keyword)
1425 ("field" "Field" simula-expand-stdproc)
1426 ("file" "File" simula-expand-stdproc)
1427 ("first" "First" simula-expand-stdproc)
1428 ("follow" "Follow" simula-expand-stdproc)
1429 ("for" "FOR" simula-expand-keyword)
1430 ("ge" "GE" simula-expand-keyword)
1431 ("getchar" "GetChar" simula-expand-stdproc)
1432 ("getfrac" "GetFrac" simula-expand-stdproc)
1433 ("getint" "GetInt" simula-expand-stdproc)
1434 ("getreal" "GetReal" simula-expand-stdproc)
1435 ("go" "GO" simula-expand-keyword)
1436 ("goto" "GOTO" simula-expand-keyword)
1437 ("gt" "GT" simula-expand-keyword)
1438 ("head" "Head" simula-expand-stdproc)
1439 ("hidden" "HIDDEN" simula-expand-keyword)
1440 ("histd" "HistD" simula-expand-stdproc)
1441 ("histo" "Histo" simula-expand-stdproc)
1442 ("hold" "Hold" simula-expand-stdproc)
1443 ("idle" "Idle" simula-expand-stdproc)
1444 ("if" "IF" simula-expand-keyword)
1445 ("image" "Image" simula-expand-stdproc)
1446 ("imagefile" "ImageFile" simula-expand-stdproc)
1447 ("imp" "IMP" simula-expand-keyword)
1448 ("in" "IN" simula-expand-keyword)
1449 ("inbyte" "InByte" simula-expand-stdproc)
1450 ("inbytefile" "InByteFile" simula-expand-stdproc)
1451 ("inchar" "InChar" simula-expand-stdproc)
1452 ("infile" "InFile" simula-expand-stdproc)
1453 ("infrac" "InFrac" simula-expand-stdproc)
1454 ("inimage" "InImage" simula-expand-stdproc)
1455 ("inint" "InInt" simula-expand-stdproc)
1456 ("inner" "INNER" simula-expand-keyword)
1457 ("inreal" "InReal" simula-expand-stdproc)
1458 ("inrecord" "InRecord" simula-expand-stdproc)
1459 ("inspect" "INSPECT" simula-expand-keyword)
1460 ("integer" "INTEGER" simula-expand-keyword)
1461 ("intext" "InText" simula-expand-stdproc)
1462 ("into" "Into" simula-expand-stdproc)
1463 ("is" "IS" simula-expand-keyword)
1464 ("isochar" "ISOChar" simula-expand-stdproc)
1465 ("isopen" "IsOpen" simula-expand-stdproc)
1466 ("isorank" "ISORank" simula-expand-stdproc)
1467 ("label" "LABEL" simula-expand-keyword)
1468 ("last" "Last" simula-expand-stdproc)
1469 ("lastitem" "LastItem" simula-expand-stdproc)
1470 ("lastloc" "LastLoc" simula-expand-stdproc)
1471 ("le" "LE" simula-expand-keyword)
1472 ("length" "Length" simula-expand-stdproc)
1473 ("letter" "Letter" simula-expand-stdproc)
1474 ("line" "Line" simula-expand-stdproc)
1475 ("linear" "Linear" simula-expand-stdproc)
1476 ("linesperpage" "LinesPerPage" simula-expand-stdproc)
1477 ("link" "Link" simula-expand-stdproc)
1478 ("linkage" "Linkage" simula-expand-stdproc)
1479 ("ln" "Ln" simula-expand-stdproc)
1480 ("locate" "Locate" simula-expand-stdproc)
1481 ("location" "Location" simula-expand-stdproc)
1482 ("lock" "Lock" simula-expand-stdproc)
1483 ("locked" "Locked" simula-expand-stdproc)
1484 ("log10" "Log10" simula-expand-stdproc)
1485 ("long" "LONG" simula-expand-keyword)
1486 ("lowcase" "LowCase" simula-expand-stdproc)
1487 ("lowerbound" "LowerBound" simula-expand-stdproc)
1488 ("lowten" "LowTen" simula-expand-stdproc)
1489 ("lt" "LT" simula-expand-keyword)
1490 ("main" "Main" simula-expand-stdproc)
1491 ("max" "Max" simula-expand-stdproc)
1492 ("maxint" "MaxInt" simula-expand-stdproc)
1493 ("maxlongreal" "MaxLongReal" simula-expand-stdproc)
1494 ("maxloc" "MaxLoc" simula-expand-stdproc)
1495 ("maxrank" "MaxRank" simula-expand-stdproc)
1496 ("maxreal" "MaxReal" simula-expand-stdproc)
1497 ("min" "Min" simula-expand-stdproc)
1498 ("minint" "MinInt" simula-expand-stdproc)
1499 ("minlongreal" "MinLongReal" simula-expand-stdproc)
1500 ("minrank" "MinRank" simula-expand-stdproc)
1501 ("minreal" "MinReal" simula-expand-stdproc)
1502 ("mod" "Mod" simula-expand-stdproc)
1503 ("more" "More" simula-expand-stdproc)
1504 ("name" "NAME" simula-expand-keyword)
1505 ("ne" "NE" simula-expand-keyword)
1506 ("negexp" "NegExp" simula-expand-stdproc)
1507 ("new" "NEW" simula-expand-keyword)
1508 ("nextev" "NextEv" simula-expand-stdproc)
1509 ("none" "NONE" simula-expand-keyword)
1510 ("normal" "Normal" simula-expand-stdproc)
1511 ("not" "NOT" simula-expand-keyword)
1512 ("notext" "NOTEXT" simula-expand-keyword)
1513 ("open" "Open" simula-expand-stdproc)
1514 ("or" "OR" simula-expand-keyword)
1515 ("otherwise" "OTHERWISE" simula-electric-keyword)
1516 ("out" "Out" simula-expand-stdproc)
1517 ("outbyte" "OutByte" simula-expand-stdproc)
1518 ("outbytefile" "OutByteFile" simula-expand-stdproc)
1519 ("outchar" "OutChar" simula-expand-stdproc)
1520 ("outfile" "OutFile" simula-expand-stdproc)
1521 ("outfix" "OutFix" simula-expand-stdproc)
1522 ("outfrac" "OutFrac" simula-expand-stdproc)
1523 ("outimage" "OutImage" simula-expand-stdproc)
1524 ("outint" "OutInt" simula-expand-stdproc)
1525 ("outreal" "OutReal" simula-expand-stdproc)
1526 ("outrecord" "OutRecord" simula-expand-stdproc)
1527 ("outtext" "OutText" simula-expand-stdproc)
1528 ("page" "Page" simula-expand-stdproc)
1529 ("passivate" "Passivate" simula-expand-stdproc)
1530 ("poisson" "Poisson" simula-expand-stdproc)
1531 ("pos" "Pos" simula-expand-stdproc)
1532 ("precede" "Precede" simula-expand-stdproc)
1533 ("pred" "Pred" simula-expand-stdproc)
1534 ("prev" "Prev" simula-expand-stdproc)
1535 ("printfile" "PrintFile" simula-expand-stdproc)
1536 ("prior" "PRIOR" simula-expand-keyword)
1537 ("procedure" "PROCEDURE" simula-expand-keyword)
1538 ("process" "Process" simula-expand-stdproc)
1539 ("protected" "PROTECTED" simula-expand-keyword)
1540 ("putchar" "PutChar" simula-expand-stdproc)
1541 ("putfix" "PutFix" simula-expand-stdproc)
1542 ("putfrac" "PutFrac" simula-expand-stdproc)
1543 ("putint" "PutInt" simula-expand-stdproc)
1544 ("putreal" "PutReal" simula-expand-stdproc)
1545 ("qua" "QUA" simula-expand-keyword)
1546 ("randint" "RandInt" simula-expand-stdproc)
1547 ("rank" "Rank" simula-expand-stdproc)
1548 ("reactivate" "REACTIVATE" simula-expand-keyword)
1549 ("real" "REAL" simula-expand-keyword)
1550 ("ref" "REF" simula-expand-keyword)
1551 ("resume" "Resume" simula-expand-stdproc)
1552 ("setaccess" "SetAccess" simula-expand-stdproc)
1553 ("setpos" "SetPos" simula-expand-stdproc)
1554 ("short" "SHORT" simula-expand-keyword)
1555 ("sign" "Sign" simula-expand-stdproc)
1556 ("simset" "SimSet" simula-expand-stdproc)
1557 ("simulaid" "SimulaId" simula-expand-stdproc)
1558 ("simulation" "Simulation" simula-expand-stdproc)
1559 ("sin" "Sin" simula-expand-stdproc)
1560 ("sinh" "SinH" simula-expand-stdproc)
1561 ("sourceline" "SourceLine" simula-expand-stdproc)
1562 ("spacing" "Spacing" simula-expand-stdproc)
1563 ("sqrt" "Sqrt" simula-expand-stdproc)
1564 ("start" "Start" simula-expand-stdproc)
1565 ("step" "STEP" simula-expand-keyword)
1566 ("strip" "Strip" simula-expand-stdproc)
1567 ("sub" "Sub" simula-expand-stdproc)
1568 ("subepsilon" "SubEpsilon" simula-expand-stdproc)
1569 ("suc" "Suc" simula-expand-stdproc)
1570 ("switch" "SWITCH" simula-expand-keyword)
1571 ("sysin" "SysIn" simula-expand-stdproc)
1572 ("sysout" "SysOut" simula-expand-stdproc)
1573 ("tan" "Tan" simula-expand-stdproc)
1574 ("tanh" "TanH" simula-expand-stdproc)
1575 ("terminate_program" "Terminate_Program" simula-expand-stdproc)
1576 ("terminated" "Terminated" simula-expand-stdproc)
1577 ("text" "TEXT" simula-expand-keyword)
1578 ("then" "THEN" simula-electric-keyword)
1579 ("this" "THIS" simula-expand-keyword)
1580 ("time" "Time" simula-expand-stdproc)
1581 ("to" "TO" simula-expand-keyword)
1582 ("true" "TRUE" simula-expand-keyword)
1583 ("uniform" "Uniform" simula-expand-stdproc)
1584 ("unlock" "Unlock" simula-expand-stdproc)
1585 ("until" "UNTIL" simula-expand-keyword)
1586 ("upcase" "Upcase" simula-expand-stdproc)
1587 ("upperbound" "UpperBound" simula-expand-stdproc)
1588 ("value" "VALUE" simula-expand-keyword)
1589 ("virtual" "VIRTUAL" simula-expand-keyword)
1590 ("wait" "Wait" simula-expand-stdproc)
1591 ("when" "WHEN" simula-electric-keyword)
8fc98fc4
SM
1592 ("while" "WHILE" simula-expand-keyword)))
1593 (define-abbrev simula-mode-abbrev-table
1594 (nth 0 args) (nth 1 args) (nth 2 args) nil 'system)))
1595
1596(if simula-abbrev-file
1597 (read-abbrev-file simula-abbrev-file))
1598(let (abbrevs-changed)
1599 (simula-install-standard-abbrevs))
a26389d1 1600
e284737d 1601;; Hilit mode support.
91dd4dc4
DN
1602(when (fboundp 'hilit-set-mode-patterns)
1603 (when (and (boundp 'hilit-patterns-alist)
1604 (not (assoc 'simula-mode hilit-patterns-alist)))
8ca3cd44
RS
1605 (hilit-set-mode-patterns
1606 'simula-mode
1607 '(
1608 ("^%\\([ \t\f].*\\)?$" nil comment)
1609 ("^%include\\>" nil include)
1610 ("\"[^\"\n]*\"\\|'.'\\|'![0-9]+!'" nil string)
1611 ("\\<\\(ACTIVATE\\|AFTER\\|AND\\|ARRAY\\|AT\\|BEFORE\\|BEGIN\\|BOOLEAN\\|CHARACTER\\|CLASS\\|DELAY\\|DO\\|ELSE\\|END\\|EQ\\|EQV\\|EXTERNAL\\|FALSE\\|FOR\\|GE\\|GO\\|GOTO\\|GT\\|HIDDEN\\|IF\\|IMP\\|IN\\|INNER\\|INSPECT\\|INTEGER\\|IS\\|LABEL\\|LE\\|LONG\\|LT\\|NAME\\|NE\\|NEW\\|NONE\\|NOT\\|NOTEXT\\|OR\\|OTHERWISE\\|PRIOR\\|PROCEDURE\\|PROTECTED\\|QUA\\|REACTIVATE\\|REAL\\|REF\\|SHORT\\|STEP\\|SWITCH\\|TEXT\\|THEN\\|THIS\\|TO\\|TRUE\\|UNTIL\\|VALUE\\|VIRTUAL\\|WHEN\\|WHILE\\)\\>" nil keyword)
1612 ("!\\|\\<COMMENT\\>" ";" comment))
91dd4dc4 1613 nil 'case-insensitive)))
8ca3cd44
RS
1614\f
1615;; defuns for submitting bug reports
1616
241760a3 1617(defconst simula-mode-help-address "bug-gnu-emacs@gnu.org"
e284737d 1618 "Address accepting submission of `simula-mode' bug reports.")
8ca3cd44 1619
3296c443
GM
1620(make-obsolete-variable 'simula-mode-help-address 'report-emacs-bug-address
1621 "24.4")
1622
1623(define-obsolete-function-alias 'simula-submit-bug-report
1624 'report-emacs-bug "24.4")
8ca3cd44 1625
51508f6d 1626(provide 'simula)
8ca3cd44 1627
a26389d1 1628;;; simula.el ends here