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