/[emacs]/emacs/lisp/progmodes/fortran.el
ViewVC logotype

Diff of /emacs/lisp/progmodes/fortran.el

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.96.2.1 by miles, Fri Apr 4 06:20:32 2003 UTC revision 1.96.2.2 by miles, Tue Oct 14 23:30:17 2003 UTC
# Line 1  Line 1 
1  ;;; fortran.el --- Fortran mode for GNU Emacs  ;;; fortran.el --- Fortran mode for GNU Emacs
2    
3  ;; Copyright (c) 1986, 93, 94, 95, 97, 98, 99, 2000, 2001  ;; Copyright (c) 1986, 93, 94, 95, 97, 98, 99, 2000, 01, 2003
4  ;;   Free Software Foundation, Inc.  ;;   Free Software Foundation, Inc.
5    
6  ;; Author: Michael D. Prange <prange@erl.mit.edu>  ;; Author: Michael D. Prange <prange@erl.mit.edu>
7  ;; Maintainer: Glenn Morris <gmorris@ast.cam.ac.uk>  ;; Maintainer: Glenn Morris <gmorris@ast.cam.ac.uk>
8  ;; Keywords: languages  ;; Keywords: fortran, languages
9    
10  ;; This file is part of GNU Emacs.  ;; This file is part of GNU Emacs.
11    
# Line 53  Line 53 
53  ;;   second in column 6.  ;;   second in column 6.
54  ;; * Support any other extensions to f77 grokked by GNU Fortran I've missed.  ;; * Support any other extensions to f77 grokked by GNU Fortran I've missed.
55    
56    (eval-when-compile                      ; silence compiler
57      (defvar dabbrev-case-fold-search)
58      (defvar imenu-case-fold-search)
59      (defvar imenu-syntax-alist))
60    
61    
62  (defgroup fortran nil  (defgroup fortran nil
63    "Fortran mode for Emacs"    "Major mode for editing fixed format Fortran code."
64    :link '(custom-manual "(emacs)Fortran")    :link  '(custom-manual "(emacs)Fortran")
65    :group 'languages)    :group 'languages)
66    
67  (defgroup fortran-indent nil  (defgroup fortran-indent nil
68    "Indentation variables in Fortran mode"    "Indentation variables in Fortran mode."
69    :prefix "fortran-"    :prefix "fortran-"
70    :group 'fortran)    :group  'fortran)
71    
72  (defgroup fortran-comment nil  (defgroup fortran-comment nil
73    "Comment-handling variables in Fortran mode"    "Comment-handling variables in Fortran mode."
74    :prefix "fortran-"    :prefix "fortran-"
75    :group 'fortran)    :group  'fortran)
76    
77    
78  ;;;###autoload  ;;;###autoload
79  (defcustom fortran-tab-mode-default nil  (defcustom fortran-tab-mode-default nil
80    "*Default tabbing/carriage control style for empty files in Fortran mode.    "*Default tabbing/carriage control style for empty files in Fortran mode.
81  A value of t specifies tab-digit style of continuation control.  A non-nil value specifies tab-digit style of continuation control.
82  A value of nil specifies that continuation lines are marked  A value of nil specifies that continuation lines are marked
83  with a character in column 6."  with a character in column 6."
84    :type 'boolean    :type  'boolean
85    :group 'fortran-indent)    :group 'fortran-indent)
86    
87  ;; Buffer local, used to display mode line.  (defcustom fortran-tab-mode-string "/t"
88  (defcustom fortran-tab-mode-string nil    "*String to appear in mode line in TAB format buffers."
89    "String to appear in mode line when TAB format mode is on."    :type  'string
   :type '(choice (const nil) string)  
90    :group 'fortran-indent)    :group 'fortran-indent)
 (make-variable-buffer-local 'fortran-tab-mode-string)  
91    
92  (defcustom fortran-do-indent 3  (defcustom fortran-do-indent 3
93    "*Extra indentation applied to DO blocks."    "*Extra indentation applied to DO blocks."
94    :type 'integer    :type  'integer
95    :group 'fortran-indent)    :group 'fortran-indent)
96    
97  (defcustom fortran-if-indent 3  (defcustom fortran-if-indent 3
98    "*Extra indentation applied to IF blocks."    "*Extra indentation applied to IF blocks."
99    :type 'integer    :type  'integer
100    :group 'fortran-indent)    :group 'fortran-indent)
101    
102  (defcustom fortran-structure-indent 3  (defcustom fortran-structure-indent 3
103    "*Extra indentation applied to STRUCTURE, UNION, MAP and INTERFACE blocks."    "*Extra indentation applied to STRUCTURE, UNION, MAP and INTERFACE blocks."
104    :type 'integer    :type  'integer
105    :group 'fortran-indent)    :group 'fortran-indent)
106    
107  (defcustom fortran-continuation-indent 5  (defcustom fortran-continuation-indent 5
108    "*Extra indentation applied to Fortran continuation lines."    "*Extra indentation applied to continuation lines."
109    :type 'integer    :type  'integer
110    :group 'fortran-indent)    :group 'fortran-indent)
111    
112  (defcustom fortran-comment-indent-style 'fixed  (defcustom fortran-comment-indent-style 'fixed
113    "*How to indent comments.    "*How to indent comments.
114  nil forces comment lines not to be touched,  nil forces comment lines not to be touched;
115  `fixed' makes fixed comment indentation to `fortran-comment-line-extra-indent'  `fixed' indents to `fortran-comment-line-extra-indent' columns beyond
116    columns beyond `fortran-minimum-statement-indent-fixed' (for    `fortran-minimum-statement-indent-fixed' (if `indent-tabs-mode' nil), or
117    `indent-tabs-mode' of nil) or `fortran-minimum-statement-indent-tab' (for    `fortran-minimum-statement-indent-tab' (if `indent-tabs-mode' non-nil);
   `indent-tabs-mode' of t), and  
118  `relative' indents to current Fortran indentation plus  `relative' indents to current Fortran indentation plus
119    `fortran-comment-line-extra-indent'."    `fortran-comment-line-extra-indent'."
120    :type '(radio (const :tag "Untouched" nil) (const fixed) (const relative))    :type  '(radio (const :tag "Untouched" nil) (const fixed) (const relative))
121    :group 'fortran-indent)    :group 'fortran-indent)
122    
123  (defcustom fortran-comment-line-extra-indent 0  (defcustom fortran-comment-line-extra-indent 0
124    "*Amount of extra indentation for text within full-line comments."    "*Amount of extra indentation for text within full-line comments."
125    :type 'integer    :type  'integer
126    :group 'fortran-indent    :group 'fortran-indent
127    :group 'fortran-comment)    :group 'fortran-comment)
128    
# Line 127  nil forces comment lines not to be touch Line 130  nil forces comment lines not to be touch
130    "*Delimiter inserted to start new full-line comment.    "*Delimiter inserted to start new full-line comment.
131  You might want to change this to \"*\", for instance."  You might want to change this to \"*\", for instance."
132    :version "21.1"    :version "21.1"
133    :type 'string    :type    'string
134    :group 'fortran-comment)    :group   'fortran-comment)
135    
136  ;; This used to match preprocessor lines too, but that messes up  ;; This used to match preprocessor lines too, but that messes up
137  ;; filling and doesn't seem to be necessary.  ;; filling and doesn't seem to be necessary.
# Line 136  You might want to change this to \"*\", Line 139  You might want to change this to \"*\",
139    "^[CcDd*!]\\(\\([^ \t\n]\\)\\2+\\)?[ \t]*"    "^[CcDd*!]\\(\\([^ \t\n]\\)\\2+\\)?[ \t]*"
140    "*Regexp to match the start of a full-line comment."    "*Regexp to match the start of a full-line comment."
141    :version "21.1"    :version "21.1"
142    :type 'regexp    :type    'regexp
143    :group 'fortran-comment)    :group   'fortran-comment)
144    
145  (defcustom fortran-directive-re  (defcustom fortran-directive-re
146    "^[ \t]*#.*"    "^[ \t]*#.*"
# Line 145  You might want to change this to \"*\", Line 148  You might want to change this to \"*\",
148  The matching text will be fontified with `font-lock-keyword-face'.  The matching text will be fontified with `font-lock-keyword-face'.
149  The matching line will be given zero indentation."  The matching line will be given zero indentation."
150    :version "21.4"    :version "21.4"
151    :type 'regexp    :type    'regexp
152    :group 'fortran-indent)    :group   'fortran-indent)
153    
154  (defcustom fortran-minimum-statement-indent-fixed 6  (defcustom fortran-minimum-statement-indent-fixed 6
155    "*Minimum statement indentation for fixed format continuation style."    "*Minimum statement indentation for fixed format continuation style."
156    :type 'integer    :type  'integer
157    :group 'fortran-indent)    :group 'fortran-indent)
158    
159  (defcustom fortran-minimum-statement-indent-tab (max tab-width 6)  (defcustom fortran-minimum-statement-indent-tab (max tab-width 6)
160    "*Minimum statement indentation for TAB format continuation style."    "*Minimum statement indentation for TAB format continuation style."
161    :type 'integer    :type  'integer
162    :group 'fortran-indent)    :group 'fortran-indent)
163    
164  ;; Note that this is documented in the v18 manuals as being a string  ;; Note that this is documented in the v18 manuals as being a string
# Line 164  The matching line will be given zero ind Line 167  The matching line will be given zero ind
167  (defcustom fortran-comment-indent-char " "  (defcustom fortran-comment-indent-char " "
168    "*Single-character string inserted for Fortran comment indentation.    "*Single-character string inserted for Fortran comment indentation.
169  Normally a space."  Normally a space."
170    :type 'string    :type  'string
171    :group 'fortran-comment)    :group 'fortran-comment)
172    
173  (defcustom fortran-line-number-indent 1  (defcustom fortran-line-number-indent 1
174    "*Maximum indentation for Fortran line numbers.    "*Maximum indentation for Fortran line numbers.
175  5 means right-justify them within their five-column field."  5 means right-justify them within their five-column field."
176    :type 'integer    :type  'integer
177    :group 'fortran-indent)    :group 'fortran-indent)
178    
179  (defcustom fortran-check-all-num-for-matching-do nil  (defcustom fortran-check-all-num-for-matching-do nil
180    "*Non-nil causes all numbered lines to be treated as possible DO loop ends."    "*Non-nil causes all numbered lines to be treated as possible DO loop ends."
181    :type 'boolean    :type  'boolean
182    :group 'fortran)    :group 'fortran)
183    
184  (defcustom fortran-blink-matching-if nil  (defcustom fortran-blink-matching-if nil
185    "*Non-nil causes \\[fortran-indent-line] on ENDIF statement to blink on matching IF.    "*Non-nil causes \\[fortran-indent-line] on ENDIF to blink on matching IF.
186  Also, from an ENDDO statement blink on matching DO [WHILE] statement."  Also, from an ENDDO statement blink on matching DO [WHILE] statement."
187    :type 'boolean    :type  'boolean
188    :group 'fortran)    :group 'fortran)
189    
190  (defcustom fortran-continuation-string "$"  (defcustom fortran-continuation-string "$"
191    "*Single-character string used for Fortran continuation lines.    "*Single-character string used for Fortran continuation lines.
192  In fixed format continuation style, this character is inserted in  In fixed format continuation style, this character is inserted in
193  column 6 by \\[fortran-split-line] to begin a continuation line.  column 6 by \\[fortran-split-line] to begin a continuation line.
194  Also, if \\[fortran-indent-line] finds this at the beginning of a line, it will  Also, if \\[fortran-indent-line] finds this at the beginning of a
195  convert the line into a continuation line of the appropriate style.  line, it will convert the line into a continuation line of the
196  Normally $."  appropriate style. Normally $."
197    :type 'string    :type  'string
198    :group 'fortran)    :group 'fortran)
199    
200  (defcustom fortran-comment-region "c$$$"  (defcustom fortran-comment-region "c$$$"
201    "*String inserted by \\[fortran-comment-region] at start of each \    "*String inserted by \\[fortran-comment-region] at start of each \
202  line in region."  line in region."
203    :type 'string    :type  'string
204    :group 'fortran-comment)    :group 'fortran-comment)
205    
206  (defcustom fortran-electric-line-number t  (defcustom fortran-electric-line-number t
207    "*Non-nil causes line number digits to be moved to the correct \    "*Non-nil causes line numbers to be moved to the correct column as typed."
208  column as typed."    :type  'boolean
   :type 'boolean  
209    :group 'fortran)    :group 'fortran)
210    
211  (defvar fortran-column-ruler-fixed  (defcustom fortran-column-ruler-fixed
212    "0   4 6  10        20        30        40        5\    "0   4 6  10        20        30        40        5\
213  0        60        70\n\  0        60        70\n\
214  \[   ]|{   |    |    |    |    |    |    |    |    \  \[   ]|{   |    |    |    |    |    |    |    |    \
215  \|    |    |    |    |}\n"  \|    |    |    |    |}\n"
216    "String displayed above current line by \\[fortran-column-ruler].    "String displayed above current line by \\[fortran-column-ruler].
217  This variable used in fixed format mode.")  This variable is used in fixed format mode.
218    See the variable `fortran-column-ruler-tab' for TAB format mode."
219      :type  'string
220      :group 'fortran)
221    
222  (defvar fortran-column-ruler-tab  (defcustom fortran-column-ruler-tab
223    "0       810        20        30        40        5\    "0       810        20        30        40        5\
224  0        60        70\n\  0        60        70\n\
225  \[   ]|  { |    |    |    |    |    |    |    |    \  \[   ]|  { |    |    |    |    |    |    |    |    \
226  \|    |    |    |    |}\n"  \|    |    |    |    |}\n"
227    "String displayed above current line by \\[fortran-column-ruler].    "String displayed above current line by \\[fortran-column-ruler].
228  This variable used in TAB format mode.")  This variable is used in TAB format mode.
229    See the variable `fortran-column-ruler-fixed' for fixed format mode."
230      :type  'string
231      :group 'fortran)
232    
233  (defvar fortran-analyze-depth 100  (defcustom fortran-analyze-depth 100
234    "Number of lines to scan to determine whether to use fixed or TAB \    "Number of lines to scan to identify fixed or TAB format style."
235  format style.")    :type  'integer
236      :group 'fortran)
237    
238  (defcustom fortran-break-before-delimiters t  (defcustom fortran-break-before-delimiters t
239    "*Non-nil causes filling to break lines before delimiters."    "*Non-nil causes filling to break lines before delimiters.
240    :type 'boolean  Delimiters are whitespace, commas, quotes, and operators."
241      :type  'boolean
242    :group 'fortran)    :group 'fortran)
243    
244  (defvar fortran-mode-syntax-table  (defcustom fortran-mode-hook nil
245    (let ((table (make-syntax-table)))    "Hook run when entering Fortran mode."
246      ;; We might like `;' to be punctuation (g77 multi-statement    :type  'hook
247      ;; lines), but that screws abbrevs.    :group 'fortran)
     (modify-syntax-entry ?\; "w" table)  
     (modify-syntax-entry ?\r " " table)  
     (modify-syntax-entry ?+ "." table)  
     (modify-syntax-entry ?- "." table)  
     (modify-syntax-entry ?= "." table)  
     (modify-syntax-entry ?* "." table)  
     (modify-syntax-entry ?/ "." table)  
     (modify-syntax-entry ?\' "\"" table)  
     (modify-syntax-entry ?\" "\"" table)  
     ;; Consistent with GNU Fortran -- see the manual.  
     (modify-syntax-entry ?\\ "\\" table)  
     ;; This might be better as punctuation, as for C, but this way you  
     ;; can treat floating-point numbers as symbols.  
     (modify-syntax-entry ?. "_" table)  ; e.g. `a.ne.b'  
     (modify-syntax-entry ?_ "_" table)  
     (modify-syntax-entry ?$ "_" table)  ; esp. VMSisms  
     (modify-syntax-entry ?\! "<" table)  
     (modify-syntax-entry ?\n ">" table)  
     table)  
   "Syntax table in use in Fortran mode buffers.")  
248    
249  ;; Comments are real pain in Fortran because there is no way to  
250  ;; represent the standard comment syntax in an Emacs syntax table.  (defvar fortran-if-start-re "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*("
251  ;; (We can do so for F90-style).  Therefore an unmatched quote in a    "Regexp matching the start of an IF statement.")
252  ;; standard comment will throw fontification off on the wrong track.  
253  ;; So we do syntactic fontification with regexps.  (defvar fortran-end-prog-re1
254      "end\
255    \\([ \t]*\\(program\\|subroutine\\|function\\|block[ \t]*data\\)\\>\
256    \\([ \t]*\\(\\sw\\|\\s_\\)+\\)?\\)?"
257      "Regexp possibly matching the end of a subprogram.")
258    
259    (defvar fortran-end-prog-re
260      (concat "^[ \t0-9]*" fortran-end-prog-re1)
261      "Regexp possibly matching the end of a subprogram, from the line start.
262    See also `fortran-end-prog-re1'.")
263    
264  (defvar fortran-font-lock-keywords-1 nil  (defconst fortran-type-types
265      (concat "\\<"
266              (mapconcat 'identity          ; " " -> "[ \t]*"
267                         (split-string
268                          (regexp-opt
269                           (let ((simple-types
270                                  '("character" "byte" "integer" "logical"
271                                    "none" "real" "complex"
272                                    "double precision" "double complex"))
273                                 (structured-types '("structure" "union" "map"))
274                                 (other-types '("record" "dimension"
275                                                "parameter" "common" "save"
276                                                "external" "intrinsic" "data"
277                                                "equivalence")))
278                             (append
279                              (mapcar (lambda (x) (concat "implicit " x))
280                                      simple-types)
281                              simple-types
282                              (mapcar (lambda (x) (concat "end " x))
283                                      structured-types)
284                              structured-types
285                              other-types)) 'paren))
286                         "[ \t]*") "\\>")
287      "Regexp matching Fortran types.")
288    
289    (defvar fortran-font-lock-keywords-1
290      ;; Program, subroutine and function declarations, plus calls.
291      '(("\\<\\(block[ \t]*data\\|call\\|entry\\|function\\|\
292    program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?"
293         (1 font-lock-keyword-face)
294         (2 font-lock-function-name-face nil t)))
295    "Subdued level highlighting for Fortran mode.")    "Subdued level highlighting for Fortran mode.")
296    
297  (defvar fortran-font-lock-keywords-2 nil  (defvar fortran-font-lock-keywords-2
298      (append fortran-font-lock-keywords-1
299              (list
300               ;; Fontify all type specifiers (must be first - see below).
301               (cons fortran-type-types 'font-lock-type-face)
302               ;; Builtin keywords (except logical, do and goto - see below).
303               (concat "\\<" (regexp-opt
304                              '("continue" "format" "end" "enddo"
305                                "if" "then" "else" "endif" "elseif"
306                                "while" "inquire" "stop" "return"
307                                "include" "open" "close" "read"
308                                "write" "format" "print" "select" "case"
309                                "cycle" "exit" "rewind" "backspace")
310                              'paren) "\\>")
311               ;; Builtin operators.
312               (concat "\\." (regexp-opt
313                              '("and" "or" "not" "lt" "le" "eq" "ge"
314                                "gt" "ne" "true" "false")
315                              'paren) "\\.")
316               ;; do/goto keywords and targets, and goto tags.
317               '("\\<\\(do\\|go *to\\)\\>[ \t]*\\([0-9]+\\)?"
318                 (1 font-lock-keyword-face)
319                 (2 font-lock-constant-face nil t))
320               '("^ *\\([0-9]+\\)" . font-lock-constant-face)))
321    "Medium level highlighting for Fortran mode.")    "Medium level highlighting for Fortran mode.")
322    
323  (defvar fortran-font-lock-keywords-3 nil  (defvar fortran-font-lock-keywords-3
324      (append
325       fortran-font-lock-keywords-1
326       ;; All type specifiers plus their declared items.
327       (list
328        (list (concat fortran-type-types "[ \t(/]*\\(*\\)?")
329              ;; Type specifier.
330              '(1 font-lock-type-face)
331              ;; Declaration item (or just /.../ block name).
332              `(font-lock-match-c-style-declaration-item-and-skip-to-next
333                ;; Start after any *(...) expression.
334                (condition-case nil
335                    (and (match-beginning ,(1+ (regexp-opt-depth
336                                                fortran-type-types)))
337                         (forward-sexp)
338                         (forward-sexp))
339                  (error nil))
340                ;; No need to clean up.
341                nil
342                ;; Fontify as a variable name, functions fontified elsewhere.
343                (1 font-lock-variable-name-face nil t))))
344       ;; Things extra to `fortran-font-lock-keywords-3' (must be done first).
345       (list
346        ;; Goto-like `err=label'/`end=label' in read/write statements.
347        '(", *\\(e\\(nd\\|rr\\)\\)\\> *\\(= *\\([0-9]+\\)\\)?"
348          (1 font-lock-keyword-face) (4 font-lock-constant-face nil t))
349        ;; Standard continuation character and in a TAB-formatted line.
350        '("^ \\{5\\}\\([^ 0\n]\\)" 1 font-lock-string-face)
351        '("^\t\\([1-9]\\)"         1 font-lock-string-face))
352       `((,fortran-directive-re (0 font-lock-keyword-face t)))
353       ;; `fortran-font-lock-keywords-2' without types (see above).
354       (cdr (nthcdr (length fortran-font-lock-keywords-1)
355                    fortran-font-lock-keywords-2)))
356    "Gaudy level highlighting for Fortran mode.")    "Gaudy level highlighting for Fortran mode.")
357    
358  (defvar fortran-font-lock-syntactic-keywords nil  ;; Comments are real pain in Fortran because there is no way to
359    ;; represent the standard comment syntax in an Emacs syntax table.
360    ;; (We can do so for F90-style).  Therefore an unmatched quote in a
361    ;; standard comment will throw fontification off on the wrong track.
362    ;; So we do syntactic fontification with regexps.
363    (defvar fortran-font-lock-syntactic-keywords
364      '(("^[cd\\*]" 0 (11))
365        ("^[^cd\\*\t\n].\\{71\\}\\([^\n]+\\)" 1 (11)))
366    "`font-lock-syntactic-keywords' for Fortran.    "`font-lock-syntactic-keywords' for Fortran.
367  These get fixed-format comments fontified.")  These get fixed-format comments fontified.")
368    
 (let ((comment-chars "cd\\*")           ; `d' for `debugging' comments  
       (fortran-type-types  
        (eval-when-compile  
          (let ((re (regexp-opt  
                     (let ((simple-types  
                            '("character" "byte" "integer" "logical"  
                              "none" "real" "complex"  
                              "double precision" "double complex"))  
                           (structured-types '("structure" "union" "map"))  
                           (other-types '("record" "dimension"  
                                          "parameter" "common" "save"  
                                          "external" "intrinsic" "data"  
                                          "equivalence")))  
                       (append  
                        (mapcar (lambda (x) (concat "implicit " x))  
                                simple-types)  
                        simple-types  
                        (mapcar (lambda (x) (concat "end " x))  
                                structured-types)  
                        structured-types  
                        other-types)))))  
            ;; In the optimized regexp above, replace spaces by a  
            ;; regexp for optional whitespace; regexp-opt would have  
            ;; escaped that.  
            (mapconcat #'identity (split-string re) "[ \t]*"))))  
       (fortran-keywords  
        (eval-when-compile  
          (regexp-opt '("continue" "format" "end" "enddo" "if" "then"  
                        "else" "endif" "elseif" "while" "inquire" "stop"  
                        "return" "include" "open" "close" "read" "write"  
                        "format" "print" "select" "case" "cycle" "exit"  
                        "rewind" "backspace"))))  
       (fortran-logicals  
        (eval-when-compile  
          (regexp-opt '("and" "or" "not" "lt" "le" "eq" "ge" "gt" "ne"  
                        "true" "false")))))  
   (setq fortran-font-lock-syntactic-keywords  
         ;; Fixed format comments.  (!-style handled normally.)  
         (list  
          (list (concat "^[" comment-chars "]") 0 '(11))  
          (list (concat "^[^" comment-chars "\t\n]" ".\\{71\\}"  
                        "\\([^\n]+\\)")  
                1 '(11))))  
   (setq fortran-font-lock-keywords-1  
         (list  
          ;; Program, subroutine and function declarations, plus calls.  
          (list (concat "\\<\\(block[ \t]*data\\|call\\|entry\\|function\\|"  
                        "program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?")  
                '(1 font-lock-keyword-face)  
                '(2 font-lock-function-name-face nil t))))  
   (setq fortran-font-lock-keywords-2  
         (append fortran-font-lock-keywords-1  
                 (list  
                  ;; Fontify all type specifiers (must be first; see below).  
                  (cons (concat "\\<\\(" fortran-type-types "\\)\\>")  
                        'font-lock-type-face)  
                  ;; Fontify all builtin keywords (except logical, do  
                  ;; and goto; see below).  
                  (concat "\\<\\(" fortran-keywords "\\)\\>")  
                  ;; Fontify all builtin operators.  
                  (concat "\\.\\(" fortran-logicals "\\)\\.")  
                  ;; Fontify do/goto keywords and targets, and goto tags.  
                  (list "\\<\\(do\\|go *to\\)\\>[ \t]*\\([0-9]+\\)?"  
                        '(1 font-lock-keyword-face)  
                        '(2 font-lock-constant-face nil t))  
                  (cons "^ *\\([0-9]+\\)" 'font-lock-constant-face))))  
   (setq fortran-font-lock-keywords-3  
         (append  
          ;; The list `fortran-font-lock-keywords-1'.  
          fortran-font-lock-keywords-1  
          ;; Fontify all type specifiers plus their declared items.  
          (list  
           (list (concat "\\<\\(" fortran-type-types "\\)\\>[ \t(/]*\\(*\\)?")  
                 ;; Fontify the type specifier.  
                 '(1 font-lock-type-face)  
                 ;; Fontify each declaration item (or just the /.../ block name).  
                 `(font-lock-match-c-style-declaration-item-and-skip-to-next  
                   ;; Start after any *(...) expression.  
                   (condition-case nil  
                       (and (and (match-beginning ,(+ 2 (regexp-opt-depth  
                                                         fortran-type-types)))  
                                 (forward-sexp))  
                            (forward-sexp))  
                     (error nil))  
                   ;; No need to clean up.  
                   nil  
                   ;; Fontify as a variable name, functions are  
                   ;; fontified elsewhere.  
                   (1 font-lock-variable-name-face nil t))))  
          ;; Things extra to `fortran-font-lock-keywords-3'  
          ;; (must be done first).  
          (list  
           ;; Fontify goto-like `err=label'/`end=label' in read/write  
           ;; statements.  
           '(", *\\(e\\(nd\\|rr\\)\\)\\> *\\(= *\\([0-9]+\\)\\)?"  
             (1 font-lock-keyword-face) (4 font-lock-constant-face nil t))  
           ;; Highlight standard continuation character and in a  
           ;; TAB-formatted line.  
           '("^     \\([^ 0]\\)" 1 font-lock-string-face)  
           '("^\t\\([1-9]\\)" 1 font-lock-string-face))  
          (list  
           ;; cpp stuff (ugh)  
 ;;;       '("^# *[a-z]+" . font-lock-keyword-face))  
           `(,fortran-directive-re (0 font-lock-keyword-face t)))  
          ;; The list `fortran-font-lock-keywords-2' less that for types  
          ;; (see above).  
          (cdr (nthcdr (length fortran-font-lock-keywords-1)  
                       fortran-font-lock-keywords-2)))))  
   
369  (defvar fortran-font-lock-keywords fortran-font-lock-keywords-1  (defvar fortran-font-lock-keywords fortran-font-lock-keywords-1
370    "Default expressions to highlight in Fortran mode.")    "Default expressions to highlight in Fortran mode.")
371    
372  (defvar fortran-imenu-generic-expression  (defvar fortran-imenu-generic-expression
373    ;; These patterns could be confused by sequence nos. in cols 72+ and    ;; These patterns could be confused by sequence nos. in cols 72+ and
374    ;; don't allow continuations everywhere.    ;; don't allow continuations everywhere.
# Line 407  These get fixed-format comments fontifie Line 389  These get fixed-format comments fontifie
389       ;; Variable to index:       ;; Variable to index:
390       "\\(\\sw+\\)")       "\\(\\sw+\\)")
391      3)      3)
392     ;; Un-named block data     ;; Un-named block data.
393     (list nil "^\\s-+\\(block\\s-*data\\)\\s-*$" 1))     '(nil "^\\s-+\\(block\\s-*data\\)\\s-*$" 1))
394    "Imenu generic expression for `imenu-default-create-index-function'.")    "Value for `imenu-generic-expression' in Fortran mode.")
395    
396    
397    (defvar fortran-mode-syntax-table
398      (let ((table (make-syntax-table)))
399        ;; We might like `;' to be punctuation (g77 multi-statement
400        ;; lines), but that screws abbrevs.
401        (modify-syntax-entry ?\; "w"  table)
402        (modify-syntax-entry ?\r " "  table)
403        (modify-syntax-entry ?+  "."  table)
404        (modify-syntax-entry ?-  "."  table)
405        (modify-syntax-entry ?=  "."  table)
406        (modify-syntax-entry ?*  "."  table)
407        (modify-syntax-entry ?/  "."  table)
408        (modify-syntax-entry ?\' "\"" table)
409        (modify-syntax-entry ?\" "\"" table)
410        ;; Consistent with GNU Fortran -- see the manual.
411        (modify-syntax-entry ?\\ "\\" table)
412        ;; This might be better as punctuation, as for C, but this way you
413        ;; can treat floating-point numbers as symbols.
414        (modify-syntax-entry ?.  "_"  table) ; e.g. `a.ne.b'
415        (modify-syntax-entry ?_  "_"  table)
416        (modify-syntax-entry ?$  "_"  table) ; esp. VMSisms
417        (modify-syntax-entry ?\! "<"  table)
418        (modify-syntax-entry ?\n ">"  table)
419        table)
420      "Syntax table used in Fortran mode.")
421    
422    (defvar fortran-gud-syntax-table
423      (let ((st (make-syntax-table fortran-mode-syntax-table)))
424        (modify-syntax-entry ?\n "." st)
425        st)
426      "Syntax table used to parse Fortran expressions for printing in GUD.")
427    
428  (defvar fortran-mode-map  (defvar fortran-mode-map
429    (let ((map (make-sparse-keymap)))    (let ((map (make-sparse-keymap)))
430      (define-key map ";" 'fortran-abbrev-start)      (define-key map ";"        'fortran-abbrev-start)
431      (define-key map "\C-c;" 'fortran-comment-region)      (define-key map "\C-c;"    'fortran-comment-region)
432      (define-key map "\M-;" 'fortran-indent-comment)      (define-key map "\M-;"     'fortran-indent-comment)
433      (define-key map "\M-\n" 'fortran-split-line)      (define-key map "\M-\n"    'fortran-split-line)
434      (define-key map "\M-\C-q" 'fortran-indent-subprogram)      (define-key map "\M-\C-q"  'fortran-indent-subprogram)
435      (define-key map "\C-c\C-w" 'fortran-window-create-momentarily)      (define-key map "\C-c\C-w" 'fortran-window-create-momentarily)
436      (define-key map "\C-c\C-r" 'fortran-column-ruler)      (define-key map "\C-c\C-r" 'fortran-column-ruler)
437      (define-key map "\C-c\C-p" 'fortran-previous-statement)      (define-key map "\C-c\C-p" 'fortran-previous-statement)
438      (define-key map "\C-c\C-n" 'fortran-next-statement)      (define-key map "\C-c\C-n" 'fortran-next-statement)
439      (define-key map "\C-c\C-d" 'fortran-join-line) ; like f90      (define-key map "\C-c\C-d" 'fortran-join-line) ; like f90
440      (define-key map "\M-^" 'fortran-join-line) ; subvert delete-indentation      (define-key map "\M-^"     'fortran-join-line) ; subvert delete-indentation
441      (define-key map "0" 'fortran-electric-line-number)      (define-key map "0" 'fortran-electric-line-number)
442      (define-key map "1" 'fortran-electric-line-number)      (define-key map "1" 'fortran-electric-line-number)
443      (define-key map "2" 'fortran-electric-line-number)      (define-key map "2" 'fortran-electric-line-number)
# Line 435  These get fixed-format comments fontifie Line 449  These get fixed-format comments fontifie
449      (define-key map "8" 'fortran-electric-line-number)      (define-key map "8" 'fortran-electric-line-number)
450      (define-key map "9" 'fortran-electric-line-number)      (define-key map "9" 'fortran-electric-line-number)
451    
452      ;; Menu      (easy-menu-define fortran-menu map "Menu for Fortran mode."
453      (easy-menu-define        `("Fortran"
454       fortran-mode-menu map ""          ["Manual" (info "(emacs)Fortran")]
455       `("Fortran"          ("Customization"
456         ["Manual" (info "(emacs)Fortran")]           ,(custom-menu-create 'fortran)
457         ("Customization"           ["Set"  Custom-set t]
458          ,(custom-menu-create 'fortran)           ["Save" Custom-save t]
459          ["Set" Custom-set t]           ["Reset to Current" Custom-reset-current t]
460          ["Save" Custom-save t]           ["Reset to Saved"   Custom-reset-saved t]
461          ["Reset to Current" Custom-reset-current t]           ["Reset to Standard Settings" Custom-reset-standard t]
462          ["Reset to Saved" Custom-reset-saved t]           )
463          ["Reset to Standard Settings" Custom-reset-standard t])          "--"
464         "----"          ["Comment Region" fortran-comment-region mark-active]
465         ["Toggle Auto-fill" auto-fill-mode :style toggle          ["Uncomment Region"
466          :selected auto-fill-function]           (fortran-comment-region (region-beginning) (region-end) 1)
467         ["Toggle abbrev-mode" abbrev-mode :style toggle :selected abbrev-mode]           mark-active]
468         "----"          ["Indent Region"     indent-region mark-active]
469         ["Comment-out Region" fortran-comment-region mark-active]          ["Indent Subprogram" fortran-indent-subprogram t]
470         ["Uncomment-out region"          "--"
471          (fortran-comment-region (region-beginning) (region-end) 1)          ["Beginning of Subprogram" fortran-beginning-of-subprogram t]
472          mark-active]          ["End of Subprogram"       fortran-end-of-subprogram       t]
473         ["Indent Region" indent-region mark-active]          ("Mark"
474         ["Indent Subprogram" fortran-indent-subprogram t]           ["Subprogram" mark-defun      t]
475         "----"           ["IF Block"   fortran-mark-if t]
476         ["Beginning of Subprogram" fortran-beginning-of-subprogram t]           ["DO Block"   fortran-mark-do t]
477         ["End of Subprogram" fortran-end-of-subprogram t]           )
478         ("Mark"          ["Narrow to Subprogram" narrow-to-defun t]
479          ["Subprogram" mark-defun t]          ["Widen" widen t]
480          ["IF Block" fortran-mark-if t]          "--"
481          ["DO Block" fortran-mark-do t])          ["Temporary column ruler" fortran-column-ruler  t]
482         ["Narrow to Subprogram" narrow-to-defun t]          ["72-column window"       fortran-window-create t]
483         ["Widen" widen t]          ["Full Width Window"
484         "----"           (enlarge-window-horizontally (- (frame-width) (window-width)))
485         ["Temporary column ruler" fortran-column-ruler t]           (< (window-width) (frame-width))]
486         ["72-column window" fortran-window-create t]          ["Momentary 72-column window" fortran-window-create-momentarily t]
487         ["Full Width Window"          "--"
488          (enlarge-window-horizontally (- (frame-width) (window-width)))          ["Break Line at Point"    fortran-split-line t]
489          (< (window-width) (frame-width))]          ["Join Line"              fortran-join-line  t]
490         ["Momentary 72-column window" fortran-window-create-momentarily t]          ["Fill Statement/Comment" fill-paragraph     t]
491         "----"          "--"
492         ["Break Line at Point" fortran-split-line t]          ["Toggle auto-fill"   auto-fill-mode :selected auto-fill-function
493         ["Join Line" fortran-join-line t]           :style toggle]
494         ["Fill Statement/Comment" fill-paragraph  t]          ["Toggle abbrev-mode" abbrev-mode    :selected abbrev-mode
495         "----"           :style toggle]
496         ["Add imenu menu"          ["Add imenu Menu" imenu-add-menubar-index
497          imenu-add-menubar-index (not (and (boundp 'imenu--index-alist)           :active   (not (lookup-key (current-local-map) [menu-bar index]))
498                                            imenu--index-alist))]))           :included (fboundp 'imenu-add-to-menubar)]))
499      map)      map)
500    "Keymap used in Fortran mode.")    "Keymap used in Fortran mode.")
501    
502    
503  (defvar fortran-mode-abbrev-table  (defvar fortran-mode-abbrev-table
504    (let (abbrevs-changed)    (let (abbrevs-changed)
# Line 557  These get fixed-format comments fontifie Line 572  These get fixed-format comments fontifie
572         (";w"    "write"             )         (";w"    "write"             )
573         (";wh"   "where"             )))         (";wh"   "where"             )))
574      fortran-mode-abbrev-table))      fortran-mode-abbrev-table))
   
 (eval-when-compile                      ; silence compiler  
   (defvar imenu-case-fold-search)  
   (defvar imenu-syntax-alist))  
575    
576  (defcustom fortran-mode-hook nil  
   "Hook run by Fortran mode."  
   :type 'hook  
   :group 'fortran)  
577    
578  ;;;###autoload  ;;;###autoload
579  (defun fortran-mode ()  (defun fortran-mode ()
580    "Major mode for editing Fortran code.    "Major mode for editing Fortran code in fixed format.
581    For free format code, use `f90-mode'.
582    
583  \\[fortran-indent-line] indents the current Fortran line correctly.  \\[fortran-indent-line] indents the current Fortran line correctly.
584  DO statements must not share a common CONTINUE.  Note that DO statements must not share a common CONTINUE.
585    
586  Type ;? or ;\\[help-command] to display a list of built-in abbrevs for  Type ;? or ;\\[help-command] to display a list of built-in abbrevs for\
587  Fortran keywords.   Fortran keywords.
588    
589  Key definitions:  Key definitions:
590  \\{fortran-mode-map}  \\{fortran-mode-map}
591    
592  Variables controlling indentation style and extra features:  Variables controlling indentation style and extra features:
593    
594   `comment-start'  `comment-start'
595      If you want to use comments starting with `!',    To use comments starting with `!', set this to the string \"!\".
596      set this to the string \"!\".  `fortran-do-indent'
597   `fortran-do-indent'    Extra indentation within DO blocks (default 3).
598      Extra indentation within do blocks.  (default 3)  `fortran-if-indent'
599   `fortran-if-indent'    Extra indentation within IF blocks (default 3).
600      Extra indentation within if blocks.  (default 3)  `fortran-structure-indent'
601   `fortran-structure-indent'    Extra indentation within STRUCTURE, UNION, MAP and INTERFACE blocks.
602      Extra indentation within structure, union, map and interface blocks.    (default 3)
603      (default 3)  `fortran-continuation-indent'
604   `fortran-continuation-indent'    Extra indentation applied to continuation statements (default 5).
605      Extra indentation applied to continuation statements.  (default 5)  `fortran-comment-line-extra-indent'
606   `fortran-comment-line-extra-indent'    Amount of extra indentation for text in full-line comments (default 0).
607      Amount of extra indentation for text within full-line comments.  (default 0)  `fortran-comment-indent-style'
608   `fortran-comment-indent-style'    How to indent the text in full-line comments. Allowed values are:
609      nil    means don't change indentation of text in full-line comments,    nil       don't change the indentation
610      fixed  means indent that text at `fortran-comment-line-extra-indent' beyond    fixed     indent to `fortran-comment-line-extra-indent' beyond the
611             the value of `fortran-minimum-statement-indent-fixed' (for fixed                value of either
612             format continuation style) or `fortran-minimum-statement-indent-tab'                  `fortran-minimum-statement-indent-fixed' (fixed format) or
613             (for TAB format continuation style).                  `fortran-minimum-statement-indent-tab' (TAB format),
614      relative  means indent at `fortran-comment-line-extra-indent' beyond the                depending on the continuation format in use.
615      relative  indent to `fortran-comment-line-extra-indent' beyond the
616                indentation for a line of code.                indentation for a line of code.
617      (default 'fixed)    (default 'fixed)
618   `fortran-comment-indent-char'  `fortran-comment-indent-char'
619      Single-character string to be inserted instead of space for    Single-character string to be inserted instead of space for
620      full-line comment indentation.  (default \" \")    full-line comment indentation (default \" \").
621   `fortran-minimum-statement-indent-fixed'  `fortran-minimum-statement-indent-fixed'
622      Minimum indentation for Fortran statements in fixed format mode.  (def.6)    Minimum indentation for statements in fixed format mode (default 6).
623   `fortran-minimum-statement-indent-tab'  `fortran-minimum-statement-indent-tab'
624      Minimum indentation for Fortran statements in TAB format mode.  (default 9)    Minimum indentation for statements in TAB format mode (default 9).
625   `fortran-line-number-indent'  `fortran-line-number-indent'
626      Maximum indentation for line numbers.  A line number will get    Maximum indentation for line numbers (default 1).  A line number will
627      less than this much indentation if necessary to avoid reaching    get less than this much indentation if necessary to avoid reaching
628      column 5.  (default 1)    column 5.
629   `fortran-check-all-num-for-matching-do'  `fortran-check-all-num-for-matching-do'
630      Non-nil causes all numbered lines to be treated as possible \"continue\"    Non-nil causes all numbered lines to be treated as possible \"continue\"
631      statements.  (default nil)    statements (default nil).
632   `fortran-blink-matching-if'  `fortran-blink-matching-if'
633      Non-nil causes \\[fortran-indent-line] on an ENDIF statement to blink on    Non-nil causes \\[fortran-indent-line] on an ENDIF (or ENDDO) statement
634      matching IF.  Also, from an ENDDO statement, blink on matching DO [WHILE]    to blink on the matching IF (or DO [WHILE]).  (default nil)
635      statement.  (default nil)  `fortran-continuation-string'
636   `fortran-continuation-string'    Single-character string to be inserted in column 5 of a continuation
637      Single-character string to be inserted in column 5 of a continuation    line (default \"$\").
638      line.  (default \"$\")  `fortran-comment-region'
639   `fortran-comment-region'    String inserted by \\[fortran-comment-region] at start of each line in
640      String inserted by \\[fortran-comment-region] at start of each line in    the region (default \"c$$$\").
641      region.  (default \"c$$$\")  `fortran-electric-line-number'
642   `fortran-electric-line-number'    Non-nil causes line number digits to be moved to the correct column
643      Non-nil causes line number digits to be moved to the correct column    as typed (default t).
644      as typed.  (default t)  `fortran-break-before-delimiters'
645   `fortran-break-before-delimiters'    Non-nil causes lines to be broken before delimiters (default t).
     Non-nil causes lines to be broken before delimiters.  
     (default t)  
646    
647  Turning on Fortran mode calls the value of the variable `fortran-mode-hook'  Turning on Fortran mode calls the value of the variable `fortran-mode-hook'
648  with no args, if that value is non-nil."  with no args, if that value is non-nil."
649    (interactive)    (interactive)
650    (kill-all-local-variables)    (kill-all-local-variables)
651    (setq local-abbrev-table fortran-mode-abbrev-table)    (setq major-mode 'fortran-mode
652            mode-name "Fortran"
653            local-abbrev-table fortran-mode-abbrev-table)
654    (set-syntax-table fortran-mode-syntax-table)    (set-syntax-table fortran-mode-syntax-table)
655    ;; Font Lock mode support.    (use-local-map fortran-mode-map)
656    (make-local-variable 'font-lock-defaults)    (set (make-local-variable 'indent-line-function) 'fortran-indent-line)
657    (setq font-lock-defaults '((fortran-font-lock-keywords    (set (make-local-variable 'indent-region-function)
658                                fortran-font-lock-keywords-1         (lambda (start end)
659                                fortran-font-lock-keywords-2           (let (fortran-blink-matching-if ; avoid blinking delay
660                                fortran-font-lock-keywords-3)                 indent-region-function)
661                               nil t ((?/ . "$/") ("_$" . "w"))             (indent-region start end nil))))
662                               fortran-beginning-of-subprogram))    (set (make-local-variable 'require-final-newline) t)
663    (set (make-local-variable 'font-lock-syntactic-keywords)    ;; The syntax tables don't understand the column-0 comment-markers.
664         fortran-font-lock-syntactic-keywords)    (set (make-local-variable 'comment-use-syntax) nil)
665    (make-local-variable 'fortran-break-before-delimiters)    (set (make-local-variable 'comment-padding) "$$$")
666    (setq fortran-break-before-delimiters t)    (set (make-local-variable 'comment-start) fortran-comment-line-start)
   (make-local-variable 'indent-line-function)  
   (setq indent-line-function 'fortran-indent-line)  
   (make-local-variable 'comment-indent-function)  
   (setq comment-indent-function 'fortran-comment-indent)  
667    (set (make-local-variable 'comment-start-skip)    (set (make-local-variable 'comment-start-skip)
668         ;; We can't reuse `fortran-comment-line-start-skip' directly because         ;; We can't reuse `fortran-comment-line-start-skip' directly because
669         ;; it contains backrefs whereas we need submatch-1 to end at the         ;; it contains backrefs whereas we need submatch-1 to end at the
670         ;; beginning of the comment delimiter.         ;; beginning of the comment delimiter.
671         ;; (concat "\\(\\)\\(![ \t]*\\|" fortran-comment-line-start-skip "\\)")         ;; (concat "\\(\\)\\(![ \t]*\\|" fortran-comment-line-start-skip "\\)")
672         "\\(\\)\\(?:^[CcDd*]\\|!\\)\\(?:\\([^ \t\n]\\)\\2+\\)?[ \t]*")         "\\(\\)\\(?:^[CcDd*]\\|!\\)\\(?:\\([^ \t\n]\\)\\2+\\)?[ \t]*")
673    (set (make-local-variable 'comment-padding) "$$$")    (set (make-local-variable 'comment-indent-function) 'fortran-comment-indent)
674    (set (make-local-variable 'comment-start) fortran-comment-line-start)    (set (make-local-variable 'abbrev-all-caps) t)
675    ;; The syntax tables don't understand the column-0 comment-markers.    (set (make-local-variable 'normal-auto-fill-function) 'fortran-auto-fill)
676    (set (make-local-variable 'comment-use-syntax) nil)    (set (make-local-variable 'indent-tabs-mode) (fortran-analyze-file-format))
677    (make-local-variable 'require-final-newline)    (setq mode-line-process '(indent-tabs-mode fortran-tab-mode-string))
   (setq require-final-newline t)  
   (make-local-variable 'abbrev-all-caps)  
   (setq abbrev-all-caps t)  
   (make-local-variable 'indent-tabs-mode)  
   (setq indent-tabs-mode nil)  
 ;;;(setq abbrev-mode t) ; ?? (abbrev-mode 1) instead??  
678    (set (make-local-variable 'fill-column) 72)    (set (make-local-variable 'fill-column) 72)
   (use-local-map fortran-mode-map)  
   (setq mode-name "Fortran")  
   (setq major-mode 'fortran-mode)  
   (make-local-variable 'fortran-comment-line-extra-indent)  
   (make-local-variable 'fortran-minimum-statement-indent-fixed)  
   (make-local-variable 'fortran-minimum-statement-indent-tab)  
   (make-local-variable 'fortran-column-ruler-fixed)  
   (make-local-variable 'fortran-column-ruler-tab)  
   (setq fortran-tab-mode-string " TAB-format")  
   (setq indent-tabs-mode (fortran-analyze-file-format))  
   (setq imenu-case-fold-search t)  
   (setq imenu-generic-expression fortran-imenu-generic-expression)  
   (setq imenu-syntax-alist '(("_$" . "w")))  
679    (set (make-local-variable 'fill-paragraph-function) 'fortran-fill-paragraph)    (set (make-local-variable 'fill-paragraph-function) 'fortran-fill-paragraph)
680    (set (make-local-variable 'normal-auto-fill-function) 'fortran-auto-fill)    (set (make-local-variable 'font-lock-defaults)
681    (set (make-local-variable 'indent-line-function) 'fortran-indent-line)         '((fortran-font-lock-keywords
682    (set (make-local-variable 'indent-region-function)            fortran-font-lock-keywords-1
683         (lambda (start end)            fortran-font-lock-keywords-2
684           (let (fortran-blink-matching-if ; avoid blinking delay            fortran-font-lock-keywords-3)
685                 indent-region-function)           nil t ((?/ . "$/") ("_$" . "w"))
686             (indent-region start end nil))))           fortran-beginning-of-subprogram))
687      (set (make-local-variable 'font-lock-syntactic-keywords)
688           fortran-font-lock-syntactic-keywords)
689      (set (make-local-variable 'imenu-case-fold-search) t)
690      (set (make-local-variable 'imenu-generic-expression)
691           fortran-imenu-generic-expression)
692      (set (make-local-variable 'imenu-syntax-alist) '(("_$" . "w")))
693    (set (make-local-variable 'beginning-of-defun-function)    (set (make-local-variable 'beginning-of-defun-function)
694         #'fortran-beginning-of-subprogram)         #'fortran-beginning-of-subprogram)
695    (set (make-local-variable 'end-of-defun-function)    (set (make-local-variable 'end-of-defun-function)
# Line 703  with no args, if that value is non-nil." Line 697  with no args, if that value is non-nil."
697    (set (make-local-variable 'add-log-current-defun-function)    (set (make-local-variable 'add-log-current-defun-function)
698         #'fortran-current-defun)         #'fortran-current-defun)
699    (set (make-local-variable 'dabbrev-case-fold-search) 'case-fold-search)    (set (make-local-variable 'dabbrev-case-fold-search) 'case-fold-search)
700      (set (make-local-variable 'gud-find-expr-function) 'fortran-gud-find-expr)
701    (run-hooks 'fortran-mode-hook))    (run-hooks 'fortran-mode-hook))
702    
703    
704    (defun fortran-gud-find-expr ()
705      ;; Consider \n as punctuation (end of expression).
706      (with-syntax-table fortran-gud-syntax-table
707        (gud-find-c-expr)))
708    
709  (defsubst fortran-comment-indent ()  (defsubst fortran-comment-indent ()
710    (save-excursion    "Return the indentation appropriate for the current comment line.
711      (if (looking-at fortran-comment-line-start-skip) 0  This is 0 for a line matching `fortran-comment-line-start-skip', else
712    the value of `comment-column' (leaving at least one space after code)."
713      (if (looking-at fortran-comment-line-start-skip) 0
714        (save-excursion
715        (skip-chars-backward " \t")        (skip-chars-backward " \t")
716        (max (+ 1 (current-column))        (max (1+ (current-column)) comment-column))))
            comment-column))))  
717    
718  (defun fortran-indent-comment ()  (defun fortran-indent-comment ()
719    "Align or create comment on current line.    "Align or create comment on current line.
720  Existing comments of all types are recognized and aligned.  Existing comments of all types are recognized and aligned.
721  If the line has no comment, a side-by-side comment is inserted and aligned  If the line has no comment, a side-by-side comment is inserted and aligned,
722  if the value of `comment-start' is not nil and allows such comments.  if the value of `comment-start' is not nil and allows such comments.
723  Otherwise, a separate-line comment is inserted, on this line  Otherwise, a separate-line comment is inserted, on this line
724  or on a new line inserted before this line if this line is not blank."  or on a new line inserted before this line if this line is not blank."
725    (interactive)    (interactive "*")
726    (beginning-of-line)    (beginning-of-line)
727    ;; Recognize existing comments of either kind.    ;; Recognize existing comments of either kind.
728    (cond ((fortran-find-comment-start-skip 'all)    (cond ((fortran-find-comment-start-skip 'all)
729           (goto-char (match-beginning 0))           (goto-char (match-beginning 0))
730           (if (bolp)           (if (bolp)
731               (fortran-indent-line)               (fortran-indent-line)
732             (if (not (= (current-column)             (unless (= (current-column) (fortran-comment-indent))
733                         (fortran-comment-indent)))               (delete-horizontal-space)
734                 (progn (delete-horizontal-space)               (indent-to (fortran-comment-indent)))))
                       (indent-to (fortran-comment-indent))))))  
735          ;; No existing comment.          ;; No existing comment.
736          ;; If side-by-side comments are defined, insert one,          ;; If side-by-side comments are defined, insert one,
737          ;; unless line is now blank.          ;; unless line is now blank.
# Line 753  or on a new line inserted before this li Line 755  or on a new line inserted before this li
755                        (- (fortran-calculate-indent) (current-column))))))                        (- (fortran-calculate-indent) (current-column))))))
756    
757  (defun fortran-comment-region (beg-region end-region arg)  (defun fortran-comment-region (beg-region end-region arg)
758    "Comments every line in the region.    "Comment every line in the region.
759  Puts `fortran-comment-region' at the beginning of every line in the region.  Inserts the string variable `fortran-comment-region' at the beginning of
760  BEG-REGION and END-REGION are args which specify the region boundaries.  every line in the region.
761    BEG-REGION and END-REGION specify the region boundaries.
762  With non-nil ARG, uncomments the region."  With non-nil ARG, uncomments the region."
763    (interactive "*r\nP")    (interactive "*r\nP")
764    (let ((end-region-mark (copy-marker end-region))    (let ((end-region-mark (copy-marker end-region))
765          (save-point (point-marker)))          (save-point (point-marker)))
766      (goto-char beg-region)      (goto-char beg-region)
767      (beginning-of-line)      (beginning-of-line)
768      (if (not arg)                       ;comment the region      (if arg
769          (progn (insert fortran-comment-region)          (let ((com (regexp-quote fortran-comment-region))) ; uncomment
770                 (while (and  (= (forward-line 1) 0)            (if (looking-at com)
771                              (< (point) end-region-mark))                (delete-region (point) (match-end 0)))
772                   (insert fortran-comment-region)))            (while (and (zerop (forward-line 1))
773        (let ((com (regexp-quote fortran-comment-region))) ;uncomment the region                        (< (point) end-region-mark))
774          (if (looking-at com)              (if (looking-at com)
775              (delete-region (point) (match-end 0)))                  (delete-region (point) (match-end 0)))))
776          (while (and  (= (forward-line 1) 0)        (insert fortran-comment-region)   ; comment
777                       (< (point) end-region-mark))        (while (and (zerop (forward-line 1))
778            (if (looking-at com)                    (< (point) end-region-mark))
779                (delete-region (point) (match-end 0))))))          (insert fortran-comment-region)))
780      (goto-char save-point)      (goto-char save-point)
781      (set-marker end-region-mark nil)      (set-marker end-region-mark nil)
782      (set-marker save-point nil)))      (set-marker save-point nil)))
783    
784    
785  (defun fortran-abbrev-start ()  (defun fortran-abbrev-start ()
786    "Typing ;\\[help-command] or ;? lists all the Fortran abbrevs.    "Typing ;\\[help-command] or ;? lists all the Fortran abbrevs.
787  Any other key combination is executed normally."  Any other key combination is executed normally."
788    (interactive)    (interactive "*")
789    (let (c)    (insert last-command-char)
790      (insert last-command-char)    (let (char event)
791      (if (or (eq (setq c (read-event)) ??)    ;insert char if not equal to `?'      (if (fboundp 'next-command-event) ; XEmacs
792              (eq c help-char))          (setq event (next-command-event)
793                  char (event-to-character event))
794          (setq event (read-event)
795                char event))
796        ;; Insert char if not equal to `?', or if abbrev-mode is off.
797        (if (and abbrev-mode (or (eq char ??) (eq char help-char)))
798          (fortran-abbrev-help)          (fortran-abbrev-help)
799        (setq unread-command-events (list c)))))        (setq unread-command-events (list event)))))
800    
801  (defun fortran-abbrev-help ()  (defun fortran-abbrev-help ()
802    "List the currently defined abbrevs in Fortran mode."    "List the currently defined abbrevs in Fortran mode."
# Line 797  Any other key combination is executed no Line 806  Any other key combination is executed no
806    (message "Listing abbrev table...done"))    (message "Listing abbrev table...done"))
807    
808  (defun fortran-prepare-abbrev-list-buffer ()  (defun fortran-prepare-abbrev-list-buffer ()
809      "Create a buffer listing the Fortran mode abbreviations."
810    (save-excursion    (save-excursion
811      (set-buffer (get-buffer-create "*Abbrevs*"))      (set-buffer (get-buffer-create "*Abbrevs*"))
812      (erase-buffer)      (erase-buffer)
# Line 808  Any other key combination is executed no Line 818  Any other key combination is executed no
818    
819  (defun fortran-column-ruler ()  (defun fortran-column-ruler ()
820    "Insert a column ruler momentarily above current line, till next keystroke.    "Insert a column ruler momentarily above current line, till next keystroke.
821  The ruler is defined by the value of `fortran-column-ruler-fixed' when in fixed  The ruler is defined by the value of `fortran-column-ruler-fixed' in fixed
822  format mode, and `fortran-column-ruler-tab' when in TAB format mode.  format mode, and `fortran-column-ruler-tab' in TAB format mode.
823  The key typed is executed unless it is SPC."  The next key typed is executed unless it is SPC."
824    (interactive)    (interactive)
825    (momentary-string-display    (momentary-string-display
826     (if indent-tabs-mode     (if indent-tabs-mode
# Line 861  See also `fortran-window-create'." Line 871  See also `fortran-window-create'."
871    
872  (defun fortran-split-line ()  (defun fortran-split-line ()
873    "Break line at point and insert continuation marker and alignment."    "Break line at point and insert continuation marker and alignment."
874    (interactive)    (interactive "*")
875    (delete-horizontal-space)    (delete-horizontal-space)
876    (if (save-excursion    (if (save-excursion
877          (let ((pos (point)))          (let ((pos (point)))
# Line 871  See also `fortran-window-create'." Line 881  See also `fortran-window-create'."
881        (insert ?\n (match-string 0))        (insert ?\n (match-string 0))
882      (if indent-tabs-mode      (if indent-tabs-mode
883          (insert ?\n ?\t (fortran-numerical-continuation-char))          (insert ?\n ?\t (fortran-numerical-continuation-char))
884        (insert "\n " fortran-continuation-string))) ; Space after \n important        (insert "\n " fortran-continuation-string))) ; space after \n important
885    (fortran-indent-line))                ; when the cont string is C, c or *.    (fortran-indent-line))               ; when cont string is C, c or *
886    
887  (defun fortran-remove-continuation ()  (defun fortran-remove-continuation ()
888    (if (looking-at "\\(     [^ 0\n]\\|\t[1-9]\\|&\\)")    "Delete any Fortran continuation characters at point.
889        (progn (replace-match "")  Returns t if anything actually deleted."
890               (delete-indentation)    (when (looking-at "\\( \\{5\\}[^ 0\n]\\|\t[1-9]\\|&\\)")
891               t)))      (replace-match "")
892        (delete-indentation)
893        t))
894    
895  (defun fortran-join-line (arg)  (defun fortran-join-line (arg)
896    "Join current line to the previous one and re-indent.    "Join current line to the previous one and re-indent.
# Line 899  Continuation lines are correctly handled Line 911  Continuation lines are correctly handled
911    
912  (defun fortran-numerical-continuation-char ()  (defun fortran-numerical-continuation-char ()
913    "Return a digit for tab-digit style of continuation lines.    "Return a digit for tab-digit style of continuation lines.
914  If, previous line is a tab-digit continuation line, returns that digit  If previous line is a tab-digit continuation line, return that digit
915  plus one.  Otherwise return 1.  Zero not allowed."  plus one, otherwise return 1.  Zero not allowed."
916    (save-excursion    (save-excursion
917      (forward-line -1)      (forward-line -1)
918      (if (looking-at "\t[1-9]")      (if (looking-at "\t[1-9]")
919          (+ ?1 (% (- (char-after (+ (point) 1)) ?0) 9))          (+ ?1 (% (- (char-after (1+ (point))) ?0) 9))
920        ?1)))        ?1)))
921    
922  (put 'fortran-electric-line-number 'delete-selection t)  (put 'fortran-electric-line-number 'delete-selection t)
923  (defun fortran-electric-line-number (arg)  (defun fortran-electric-line-number (arg)
924    "Self insert, but if part of a Fortran line number indent it automatically.    "Self insert, but if part of a Fortran line number indent it automatically.
925  Auto-indent does not happen if a numeric ARG is used."  Auto-indent does not happen if a numeric ARG is used."
926    (interactive "P")    (interactive "*P")
927    (if (or arg (not fortran-electric-line-number))    (if (or arg (not fortran-electric-line-number))
928        (if arg        (if arg
929            (self-insert-command (prefix-numeric-value arg))            (self-insert-command (prefix-numeric-value arg))
# Line 919  Auto-indent does not happen if a numeric Line 931  Auto-indent does not happen if a numeric
931      (if (or (and (= 5 (current-column))      (if (or (and (= 5 (current-column))
932                   (save-excursion                   (save-excursion
933                     (beginning-of-line)                     (beginning-of-line)
934                     (looking-at " \\{5\\}"))) ;In col 5 with only spaces to left.                      ;; In col 5 with only spaces to the left.
935                       (looking-at " \\{5\\}")))
936              (and (= (if indent-tabs-mode              (and (= (if indent-tabs-mode
937                          fortran-minimum-statement-indent-tab                          fortran-minimum-statement-indent-tab
938                        fortran-minimum-statement-indent-fixed) (current-column))                        fortran-minimum-statement-indent-fixed) (current-column))
939                   (eq ?\t (char-after (line-beginning-position))) ;In col 8                   ;; In col 8 with a single tab to the left.
940                                          ; with a single tab to the left.                   (eq ?\t (char-after (line-beginning-position)))
941                   (not (or (eq last-command 'fortran-indent-line)                   (not (or (eq last-command 'fortran-indent-line)
942                            (eq last-command                            (eq last-command
943                                'fortran-indent-new-line))))                                'fortran-indent-new-line))))
944              (save-excursion              (save-excursion
945                (re-search-backward "[^ \t0-9]"                (re-search-backward "[^ \t0-9]"
946                                    (line-beginning-position)                                    (line-beginning-position)
947                                    t))   ;not a line number                                    t))   ; not a line number
948              (looking-at "[0-9]"))       ;within a line number              (looking-at "[0-9]"))       ; within a line number
949          (self-insert-command (prefix-numeric-value arg))          (self-insert-command (prefix-numeric-value arg))
950        (skip-chars-backward " \t")        (skip-chars-backward " \t")
951        (insert last-command-char)        (insert last-command-char)
952        (fortran-indent-line))))        (fortran-indent-line))))
   
 (defvar fortran-end-prog-re1  
   "end\  
 \\([ \t]*\\(program\\|subroutine\\|function\\|block[ \t]*data\\)\\>\  
 \\([ \t]*\\(\\sw\\|\\s_\\)+\\)?\\)?")  
 (defvar fortran-end-prog-re  
   (concat "^[ \t0-9]*" fortran-end-prog-re1)  
   "Regexp possibly marking subprogram end.")  
953    
954    
955  (defun fortran-check-end-prog-re ()  (defun fortran-check-end-prog-re ()
956    "Check a preliminary match against `fortran-end-prog-re'."    "Check a preliminary match against `fortran-end-prog-re'."
957    ;; Having got a possible match for the subprogram end, we need a    ;; Having got a possible match for the subprogram end, we need a
# Line 1004  Directive lines are treated as comments. Line 1010  Directive lines are treated as comments.
1010                  (concat "[ \t]*"                  (concat "[ \t]*"
1011                          (regexp-quote fortran-continuation-string)))                          (regexp-quote fortran-continuation-string)))
1012                 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]"))))                 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]"))))
1013      (while (and (setq not-first-statement (= (forward-line -1) 0))      (while (and (setq not-first-statement (zerop (forward-line -1)))
1014                  (or (looking-at fortran-comment-line-start-skip)                  (or (looking-at fortran-comment-line-start-skip)
1015                      (looking-at fortran-directive-re)                      (looking-at fortran-directive-re)
1016                        (looking-at
1017                         (concat "[ \t]*"
1018                                 (regexp-quote fortran-continuation-string)))
1019                      (looking-at "[ \t]*$\\| \\{5\\}[^ 0\n]\\|\t[1-9]")                      (looking-at "[ \t]*$\\| \\{5\\}[^ 0\n]\\|\t[1-9]")
1020                      (looking-at (concat "[ \t]*" comment-start-skip)))))                      (looking-at (concat "[ \t]*" comment-start-skip)))))
1021      (cond ((and continue-test      (cond ((and continue-test
# Line 1026  Directive lines are treated as comments. Line 1035  Directive lines are treated as comments.
1035    (let (not-last-statement)    (let (not-last-statement)
1036      (beginning-of-line)      (beginning-of-line)
1037      (while (and (setq not-last-statement      (while (and (setq not-last-statement
1038                        (and (= (forward-line 1) 0)                        (and (zerop (forward-line 1))
1039                             (not (eobp))))                             (not (eobp))))
1040                  (or (looking-at fortran-comment-line-start-skip)                  (or (looking-at fortran-comment-line-start-skip)
1041                      (looking-at fortran-directive-re)                      (looking-at fortran-directive-re)
# Line 1034  Directive lines are treated as comments. Line 1043  Directive lines are treated as comments.
1043                      (looking-at (concat "[ \t]*" comment-start-skip)))))                      (looking-at (concat "[ \t]*" comment-start-skip)))))
1044      (if (not not-last-statement)      (if (not not-last-statement)
1045          'last-statement)))          'last-statement)))
1046    
1047    
1048  (defun fortran-blink-match (regex keyword find-begin)  (defun fortran-blink-match (regex keyword find-begin)
1049    "From a line matching REGEX, blink matching KEYWORD statement line.    "From a line matching REGEX, blink matching KEYWORD statement line.
# Line 1043  Use function FIND-BEGIN to match it." Line 1053  Use function FIND-BEGIN to match it."
1053          (case-fold-search t)          (case-fold-search t)
1054          matching          matching
1055          message)          message)
1056      (if (save-excursion      (when (save-excursion
1057            (beginning-of-line)              (beginning-of-line)
1058            (skip-chars-forward " \t0-9")              (skip-chars-forward " \t0-9")
1059            (looking-at regex))              (looking-at regex))
1060          (progn        (if (not (setq matching (funcall find-begin)))
1061            (if (not (setq matching (funcall find-begin)))            (setq message (concat "No matching " keyword "."))
1062                (setq message (concat "No matching " keyword "."))          (if (< matching top-of-window)
1063              (if (< matching top-of-window)              (save-excursion
1064                  (save-excursion                (goto-char matching)
1065                    (goto-char matching)                (beginning-of-line)
1066                    (beginning-of-line)                (setq message
1067                    (setq message                      (concat "Matches "
1068                          (concat "Matches "                              (buffer-substring (point)
1069                                  (buffer-substring (point)                                                (line-end-position)))))))
1070                                                    (line-end-position)))))))        (if message
1071            (if message            (message "%s" message)
1072                (message "%s" message)          (goto-char matching)
1073              (goto-char matching)          (sit-for 1)
1074              (sit-for 1)          (goto-char end-point)))))
             (goto-char end-point))))))  
1075    
1076  (defun fortran-blink-matching-if ()  (defun fortran-blink-matching-if ()
1077    "From an ENDIF or ELSE statement, blink the matching IF statement."    "From an ENDIF or ELSE statement, blink the matching IF statement."
# Line 1097  Return point or nil." Line 1106  Return point or nil."
1106        ;; Search for one.        ;; Search for one.
1107        (save-excursion        (save-excursion
1108          (let ((count 1))          (let ((count 1))
1109            (while (and (not (= count 0))            (while (and (not (zerop count))
1110                        (not (eq (fortran-next-statement) 'last-statement))                        (not (eq (fortran-next-statement) 'last-statement))
1111                        ;; Keep local to subprogram                        ;; Keep local to subprogram.
1112                        (not (and (looking-at fortran-end-prog-re)                        (not (and (looking-at fortran-end-prog-re)
1113                                  (fortran-check-end-prog-re))))                                  (fortran-check-end-prog-re))))
1114              (skip-chars-forward " \t0-9")              (skip-chars-forward " \t0-9")
# Line 1107  Return point or nil." Line 1116  Return point or nil."
1116                     (setq count (1- count)))                     (setq count (1- count)))
1117                    ((looking-at                    ((looking-at
1118                      "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?do[ \t]+[^0-9]")                      "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?do[ \t]+[^0-9]")
1119                     (setq count (+ count 1)))))                     (setq count (1+ count)))))
1120            (and (= count 0)            (and (zerop count)
1121                 ;; All pairs accounted for.                 ;; All pairs accounted for.
1122                 (point)))))))                 (point)))))))
1123    
# Line 1126  Return point or nil.  Ignores labelled D Line 1135  Return point or nil.  Ignores labelled D
1135        ;; Search for one.        ;; Search for one.
1136        (save-excursion        (save-excursion
1137          (let ((count 1))          (let ((count 1))
1138            (while (and (not (= count 0))            (while (and (not (zerop count))
1139                        (not (eq (fortran-previous-statement) 'first-statement))                        (not (eq (fortran-previous-statement) 'first-statement))
1140                        ;; Keep local to subprogram                        ;; Keep local to subprogram.
1141                        (not (and (looking-at fortran-end-prog-re)                        (not (and (looking-at fortran-end-prog-re)
1142                                  (fortran-check-end-prog-re))))                                  (fortran-check-end-prog-re))))
1143              (skip-chars-forward " \t0-9")              (skip-chars-forward " \t0-9")
# Line 1137  Return point or nil.  Ignores labelled D Line 1146  Return point or nil.  Ignores labelled D
1146                    ;; Note labelled loop ends not considered.                    ;; Note labelled loop ends not considered.
1147                    ((looking-at "end[ \t]*do\\b")                    ((looking-at "end[ \t]*do\\b")
1148                     (setq count (1+ count)))))                     (setq count (1+ count)))))
1149            (and (= count 0)            (and (zerop count)
1150                 ;; All pairs accounted for.                 ;; All pairs accounted for.
1151                 (point)))))))                 (point)))))))
1152    
# Line 1154  The marks are pushed." Line 1163  The marks are pushed."
1163            (push-mark)            (push-mark)
1164            (goto-char if-point)))))            (goto-char if-point)))))
1165    
 (defvar fortran-if-start-re "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(")  
   
1166  (defun fortran-end-if ()  (defun fortran-end-if ()
1167    "Search forwards for first unmatched ENDIF.    "Search forwards for first unmatched ENDIF.
1168  Return point or nil."  Return point or nil."
# Line 1169  Return point or nil." Line 1176  Return point or nil."
1176        ;; letter on line but this should not cause troubles.        ;; letter on line but this should not cause troubles.
1177        (save-excursion        (save-excursion
1178          (let ((count 1))          (let ((count 1))
1179            (while (and (not (= count 0))            (while (and (not (zerop count))
1180                        (not (eq (fortran-next-statement) 'last-statement))                        (not (eq (fortran-next-statement) 'last-statement))
1181                        ;; Keep local to subprogram.                        ;; Keep local to subprogram.
1182                        (not (and (looking-at fortran-end-prog-re)                        (not (and (looking-at fortran-end-prog-re)
1183                                  (fortran-check-end-prog-re))))                                  (fortran-check-end-prog-re))))
1184              (skip-chars-forward " \t0-9")              (skip-chars-forward " \t0-9")
1185              (cond ((looking-at "end[ \t]*if\\b")              (cond ((looking-at "end[ \t]*if\\b")
1186                     (setq count (- count 1)))                     (setq count (1- count)))
1187                    ((looking-at fortran-if-start-re)                    ((looking-at fortran-if-start-re)
1188                     (save-excursion                     (save-excursion
1189                       (if (or                       (if (or
1190                            (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")                            (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")
1191                            (let (then-test) ; Multi-line if-then.                            (let (then-test) ; multi-line if-then
1192                              (while                              (while
1193                                  (and                                  (and
1194                                   (= (forward-line 1) 0)                                   (zerop (forward-line 1))
1195                                   ;; Search forward for then.                                   ;; Search forward for then.
1196                                   (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")                                   (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")
1197                                   (not                                   (not
# Line 1192  Return point or nil." Line 1199  Return point or nil."
1199                                          (looking-at                                          (looking-at
1200                                           ".*then\\b[ \t]*[^ \t(=a-z0-9]")))))                                           ".*then\\b[ \t]*[^ \t(=a-z0-9]")))))
1201                              then-test))                              then-test))
1202                           (setq count (+ count 1)))))))                           (setq count (1+ count)))))))
1203            (and (= count 0)            (and (zerop count)
1204                 ;; All pairs accounted for.                 ;; All pairs accounted for.
1205                 (point)))))))                 (point)))))))
1206    
# Line 1217  Return point or nil." Line 1224  Return point or nil."
1224                   ;; Multi-line if-then.                   ;; Multi-line if-then.
1225                   (let (then-test)                   (let (then-test)
1226                     (while                     (while
1227                       (and (= (forward-line 1) 0)                         (and (zerop (forward-line 1))
1228                              ;; Search forward for then.                              ;; Search forward for then.
1229                              (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")                              (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")
1230                              (not                              (not
# Line 1230  Return point or nil." Line 1237  Return point or nil."
1237        ;; Search for one.        ;; Search for one.
1238        (save-excursion        (save-excursion
1239          (let ((count 1))          (let ((count 1))
1240            (while (and (not (= count 0))            (while (and (not (zerop count))
1241                        (not (eq (fortran-previous-statement) 'first-statement))                        (not (eq (fortran-previous-statement) 'first-statement))
1242                        ;; Keep local to subprogram.                        ;; Keep local to subprogram.
1243                        (not (and (looking-at fortran-end-prog-re)                        (not (and (looking-at fortran-end-prog-re)
# Line 1240  Return point or nil." Line 1247  Return point or nil."
1247                     (save-excursion                     (save-excursion
1248                       (if (or                       (if (or
1249                            (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")                            (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")
1250                            (let (then-test) ; Multi-line if-then.                            (let (then-test) ; multi-line if-then
1251                              (while                              (while
1252                                  (and                                  (and
1253                                   (= (forward-line 1) 0)                                   (zerop (forward-line 1))
1254                                   ;; Search forward for then.                                   ;; Search forward for then.
1255                                   (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")                                   (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")
1256                                   (not                                   (not
# Line 1252  Return point or nil." Line 1259  Return point or nil."
1259                                           (concat ".*then\\b[ \t]*"                                           (concat ".*then\\b[ \t]*"
1260                                                   "[^ \t(=a-z0-9]"))))))                                                   "[^ \t(=a-z0-9]"))))))
1261                              then-test))                              then-test))
1262                           (setq count (- count 1)))))                           (setq count (1- count)))))
1263                    ((looking-at "end[ \t]*if\\b")                    ((looking-at "end[ \t]*if\\b")
1264                     (setq count (+ count 1)))))                     (setq count (1+ count)))))
1265            (and (= count 0)            (and (zerop count)
1266                 ;; All pairs accounted for.                 ;; All pairs accounted for.
1267                 (point)))))))                 (point)))))))
1268    
1269    
1270  (defun fortran-indent-line ()  (defun fortran-indent-line ()
1271    "Indent current Fortran line based on its contents and on previous lines."    "Indent current Fortran line based on its contents and on previous lines."
1272    (interactive)    (interactive "*")
1273    (let ((cfi (fortran-calculate-indent)))    (let ((cfi (fortran-calculate-indent)))
1274      (save-excursion      (save-excursion
1275        (beginning-of-line)        (beginning-of-line)
# Line 1275  Return point or nil." Line 1283  Return point or nil."
1283      ;; Never leave point in left margin.      ;; Never leave point in left margin.
1284      (if (< (current-column) cfi)      (if (< (current-column) cfi)
1285          (move-to-column cfi))          (move-to-column cfi))
1286      (if (and auto-fill-function      (and auto-fill-function
1287               (> (save-excursion (end-of-line) (current-column))           (> (save-excursion (end-of-line) (current-column))
1288                  fill-column))              fill-column)
1289          (save-excursion           (save-excursion
1290            (end-of-line)             (end-of-line)
1291            (fortran-fill)))             (fortran-fill)))
1292      (if fortran-blink-matching-if      (when fortran-blink-matching-if
1293          (progn        (fortran-blink-matching-if)
1294            (fortran-blink-matching-if)        (fortran-blink-matching-do))))
           (fortran-blink-matching-do)))))  
1295    
1296  (defun fortran-auto-fill ()  (defun fortran-auto-fill ()
1297      "Function to use for `normal-auto-fill-function' in Fortran mode."
1298    (if (> (current-column) (current-fill-column))    (if (> (current-column) (current-fill-column))
1299        (let ((cfi (fortran-calculate-indent)))        (let ((cfi (fortran-calculate-indent)))
1300          (save-excursion          (save-excursion
# Line 1309  Return point or nil." Line 1317  Return point or nil."
1317  (defalias 'fortran-indent-new-line 'reindent-then-newline-and-indent)  (defalias 'fortran-indent-new-line 'reindent-then-newline-and-indent)
1318    
1319  (defun fortran-indent-subprogram ()  (defun fortran-indent-subprogram ()
1320    "Properly indent the Fortran subprogram which contains point."    "Properly indent the Fortran subprogram containing point."
1321    (interactive)    (interactive "*")
1322    (save-excursion    (save-excursion
1323      (mark-defun)      (mark-defun)
1324      (message "Indenting subprogram...")      (message "Indenting subprogram...")
# Line 1328  Return point or nil." Line 1336  Return point or nil."
1336        (setq first-statement (fortran-previous-statement))        (setq first-statement (fortran-previous-statement))
1337        (if first-statement        (if first-statement
1338            (setq icol fortran-minimum-statement-indent)            (setq icol fortran-minimum-statement-indent)
1339          (progn          (if (= (point) (point-min))
1340            (if (= (point) (point-min))              (setq icol fortran-minimum-statement-indent)
1341                (setq icol fortran-minimum-statement-indent)            (setq icol (fortran-current-line-indentation)))
1342              (setq icol (fortran-current-line-indentation)))          (skip-chars-forward " \t0-9")
1343            (skip-chars-forward " \t0-9")          (cond ((looking-at "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(")
1344            (cond ((looking-at "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(")                 (if (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t_$(=a-z0-9]")
1345                   (if (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t_$(=a-z0-9]")                         (let (then-test) ; multi-line if-then
1346                           (let (then-test)       ;multi-line if-then                           (while (and (zerop (forward-line 1))
1347                             (while (and (= (forward-line 1) 0)                                       ;; Search forward for then.
1348                                         ;;search forward for then                                       (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")
1349                                         (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")                                       (not (setq then-test
1350                                         (not (setq then-test                                                  (looking-at
1351                                                    (looking-at                                                   ".*then\\b[ \t]\
                                                    ".*then\\b[ \t]\  
1352  *[^ \t_$(=a-z0-9]")))))  *[^ \t_$(=a-z0-9]")))))
1353                             then-test))                           then-test))
1354                       (setq icol (+ icol fortran-if-indent))))                     (setq icol (+ icol fortran-if-indent))))
1355                  ((looking-at "else\\(if\\)?\\b")                ((looking-at "else\\(if\\)?\\b")
1356                   (setq icol (+ icol fortran-if-indent)))                 (setq icol (+ icol fortran-if-indent)))
1357                  ((looking-at "select[ \t]*case[ \t](.*)")                ((looking-at "select[ \t]*case[ \t](.*)")
1358                   (setq icol (+ icol fortran-if-indent)))                 (setq icol (+ icol fortran-if-indent)))
1359                  ((looking-at "case[ \t]*(.*)")                ((looking-at "case[ \t]*(.*)")
1360                   (setq icol (+ icol fortran-if-indent)))                 (setq icol (+ icol fortran-if-indent)))
1361                  ((looking-at "case[ \t]*default\\b")                ((looking-at "case[ \t]*default\\b")
1362                   (setq icol (+ icol fortran-if-indent)))                 (setq icol (+ icol fortran-if-indent)))
1363                  ((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b")                ((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b")
1364                   (setq icol (+ icol fortran-if-indent)))                 (setq icol (+ icol fortran-if-indent)))
1365                  ((looking-at "where[ \t]*(.*)[ \t]*\n")                ((looking-at "where[ \t]*(.*)[ \t]*\n")
1366                   (setq icol (+ icol fortran-if-indent)))                 (setq icol (+ icol fortran-if-indent)))
1367                  ((looking-at "do\\b")                ((looking-at "do\\b")
1368                   (setq icol (+ icol fortran-do-indent)))                 (setq icol (+ icol fortran-do-indent)))
1369                  ((looking-at                ((looking-at
1370                    "\\(structure\\|union\\|map\\|interface\\)\                  "\\(structure\\|union\\|map\\|interface\\)\
1371  \\b[ \t]*[^ \t=(a-z]")  \\b[ \t]*[^ \t=(a-z]")
1372                   (setq icol (+ icol fortran-structure-indent)))                 (setq icol (+ icol fortran-structure-indent)))
1373                  ((and (looking-at fortran-end-prog-re1)                ((and (looking-at fortran-end-prog-re1)
1374                        (fortran-check-end-prog-re))                      (fortran-check-end-prog-re))
1375                   ;; Previous END resets indent to minimum                 ;; Previous END resets indent to minimum.
1376                   (setq icol fortran-minimum-statement-indent))))))                 (setq icol fortran-minimum-statement-indent)))))
1377      (save-excursion      (save-excursion
1378        (beginning-of-line)        (beginning-of-line)
1379        (cond ((looking-at "[ \t]*$"))        (cond ((looking-at "[ \t]*$"))
# Line 1380  Return point or nil." Line 1387  Return point or nil."
1387                      (setq icol (+ fortran-minimum-statement-indent                      (setq icol (+ fortran-minimum-statement-indent
1388                                    fortran-comment-line-extra-indent))))                                    fortran-comment-line-extra-indent))))
1389               (setq fortran-minimum-statement-indent 0))               (setq fortran-minimum-statement-indent 0))
1390              ((or (looking-at (concat "[ \t]*"              ((or (looking-at (concat "[ \t]*"
1391                                       (regexp-quote                                       (regexp-quote
1392                                        fortran-continuation-string)))                                        fortran-continuation-string)))
1393                   (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]"))                   (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]"))
1394               (setq icol (+ icol fortran-continuation-indent)))               (skip-chars-forward " \t")
1395                 ;; Do not introduce extra whitespace into a broken string.
1396                 (setq icol
1397                       (if (fortran-is-in-string-p (point))
1398                           6
1399                         (+ icol fortran-continuation-indent))))
1400              (first-statement)              (first-statement)
1401              ((and fortran-check-all-num-for-matching-do              ((and fortran-check-all-num-for-matching-do
1402                    (looking-at "[ \t]*[0-9]+")                    (looking-at "[ \t]*[0-9]+")
# Line 1414  Return point or nil." Line 1426  Return point or nil."
1426                      (message "Warning: `end' not in column %d.  Probably\                      (message "Warning: `end' not in column %d.  Probably\
1427   an unclosed block." fortran-minimum-statement-indent))))))   an unclosed block." fortran-minimum-statement-indent))))))
1428      (max fortran-minimum-statement-indent icol)))      (max fortran-minimum-statement-indent icol)))
1429    
1430    
1431  (defun fortran-current-line-indentation ()  (defun fortran-current-line-indentation ()
1432    "Indentation of current line, ignoring Fortran line number or continuation.    "Indentation of current line, ignoring Fortran line number or continuation.
# Line 1439  non-indentation text within the comment. Line 1452  non-indentation text within the comment.
1452      (current-column)))      (current-column)))
1453    
1454  (defun fortran-indent-to-column (col)  (defun fortran-indent-to-column (col)
1455    "Indent current line with spaces to column COL.    "Indent current line to column COL.
1456  notes: 1) A non-zero/non-blank character in column 5 indicates a continuation  notes: 1) A non-zero/non-blank character in column 5 indicates a continuation
1457            line, and this continuation character is retained on indentation;            line, and this continuation character is retained on indentation;
1458         2) If `fortran-continuation-string' is the first non-whitespace         2) If `fortran-continuation-string' is the first non-whitespace
# Line 1472  notes: 1) A non-zero/non-blank character Line 1485  notes: 1) A non-zero/non-blank character
1485                         (insert ?\t (fortran-numerical-continuation-char) 1))                         (insert ?\t (fortran-numerical-continuation-char) 1))
1486                (forward-char 6))                (forward-char 6))
1487            (delete-horizontal-space)            (delete-horizontal-space)
1488            ;; Put line number in columns 0-4            ;; Put line number in columns 0-4, or
1489            ;; or put continuation character in column 5.            ;; continuation character in column 5.
1490            (cond ((eobp))            (cond ((eobp))
1491                  ((looking-at (regexp-quote fortran-continuation-string))                  ((looking-at (regexp-quote fortran-continuation-string))
1492                   (if indent-tabs-mode                   (if indent-tabs-mode
# Line 1497  notes: 1) A non-zero/non-blank character Line 1510  notes: 1) A non-zero/non-blank character
1510        (delete-horizontal-space)        (delete-horizontal-space)
1511        (indent-to col)        (indent-to col)
1512        ;; Indent any comment following code on the same line.        ;; Indent any comment following code on the same line.
1513        (if (fortran-find-comment-start-skip)        (when (fortran-find-comment-start-skip)
1514            (progn (goto-char (match-beginning 0))          (goto-char (match-beginning 0))
1515                   (if (not (= (current-column) (fortran-comment-indent)))          (unless (= (current-column) (fortran-comment-indent))
1516                       (progn (delete-horizontal-space)            (delete-horizontal-space)
1517                              (indent-to (fortran-comment-indent)))))))))            (indent-to (fortran-comment-indent)))))))
1518    
1519  (defun fortran-line-number-indented-correctly-p ()  (defun fortran-line-number-indented-correctly-p ()
1520    "Return t if current line's line number is correctly indented.    "Return t if current line's line number is correctly indented.
# Line 1521  Otherwise return nil." Line 1534  Otherwise return nil."
1534          charnum)          charnum)
1535      (save-excursion      (save-excursion
1536        (beginning-of-line)        (beginning-of-line)
1537        (if (looking-at "[ \t]*[0-9]+")        (when (looking-at "[ \t]*[0-9]+")
1538            (progn          (skip-chars-forward " \t")
1539              (skip-chars-forward " \t")          (skip-chars-forward "0")        ; skip past leading zeros
1540              (skip-chars-forward "0")    ;skip past leading zeros          (setq charnum
1541              (setq charnum                (buffer-substring (point) (progn
1542                    (buffer-substring (point) (progn                                            (skip-chars-forward "0-9")
1543                                                (skip-chars-forward "0-9")                                            (point))))
1544                                                (point))))          (beginning-of-line)
1545              (beginning-of-line)          (save-restriction
1546              (save-restriction            (save-excursion
1547                (save-excursion              (narrow-to-defun)
1548                  (narrow-to-defun)              (and (re-search-backward
1549                  (and (re-search-backward                    (concat
1550                        (concat                     "\\(^[ \t0-9]*do[ \t]*0*"
1551                         "\\(^[ \t0-9]*do[ \t]*0*"                     charnum "\\b\\)\\|" "\\(^[ \t]*0*"
1552                         charnum "\\b\\)\\|" "\\(^[ \t]*0*"                     charnum "\\b\\)")
1553                         charnum "\\b\\)")                    nil t)
1554                        nil t)                   (looking-at
1555                       (looking-at                    (concat "^[ \t0-9]*do[ \t]*0*"
1556                        (concat "^[ \t0-9]*do[ \t]*0*"                            charnum)))))))))
                               charnum))))))))))  
1557    
1558  (defun fortran-find-comment-start-skip (&optional all)  (defun fortran-find-comment-start-skip (&optional all)
1559    "Move to past `comment-start-skip' found on current line.    "Move to past `comment-start-skip' found on current line.
1560  Return non-nil if `comment-start-skip' found, nil if not.  Return non-nil if `comment-start-skip' found, nil if not.
1561  If ALL is nil, only match comments that start in column > 0."  If ALL is nil, only match comments that start in column > 0."
   (interactive)  
1562    ;; Hopefully at some point we can just use the line below!  -stef    ;; Hopefully at some point we can just use the line below!  -stef
1563    ;; (comment-search-forward (line-end-position) t))    ;; (comment-search-forward (line-end-position) t))
1564    (when (or all comment-start-skip)    (when (or all comment-start-skip)
# Line 1566  If ALL is nil, only match comments that Line 1577  If ALL is nil, only match comments that
1577            (goto-char pos)            (goto-char pos)
1578            nil)))))            nil)))))
1579    
1580  ;;From: ralf@up3aud1.gwdg.de (Ralf Fassel)  ;; From: ralf@up3aud1.gwdg.de (Ralf Fassel)
1581  ;; Test if TAB format continuation lines work.  ;; Test if TAB format continuation lines work.
1582  (defun fortran-is-in-string-p (where)  (defun fortran-is-in-string-p (where)
1583    "Return non-nil iff WHERE (a buffer position) is inside a Fortran string."    "Return non-nil iff WHERE (a buffer position) is inside a Fortran string."
# Line 1577  If ALL is nil, only match comments that Line 1588  If ALL is nil, only match comments that
1588       ((save-excursion                   ; comment lines too       ((save-excursion                   ; comment lines too
1589          (beginning-of-line)          (beginning-of-line)
1590          (looking-at fortran-comment-line-start-skip)) nil)          (looking-at fortran-comment-line-start-skip)) nil)
1591       (t (let (;; ok, serious now. Init some local vars:       (t (let ((parse-state '(0 nil nil nil nil nil 0))
               (parse-state '(0 nil nil nil nil nil 0))  
1592                (quoted-comment-start (if comment-start                (quoted-comment-start (if comment-start
1593                                          (regexp-quote comment-start)))                                          (regexp-quote comment-start)))
1594                (not-done t)                (not-done t)
1595                parse-limit end-of-line)                parse-limit end-of-line)
1596            ;; move to start of current statement            ;; Move to start of current statement.
1597            (fortran-next-statement)            (fortran-next-statement)
1598            (fortran-previous-statement)            (fortran-previous-statement)
1599            ;; now parse up to WHERE            ;; Now parse up to WHERE.
1600            (while not-done            (while not-done
1601              (if (or ;; skip to next line if:              (if (or ;; Skip to next line if:
1602                   ;; - comment line?                   ;; - comment line?
1603                   (looking-at fortran-comment-line-start-skip)                   (looking-at fortran-comment-line-start-skip)
1604                   ;; - at end of line?                   ;; - at end of line?
# Line 1601  If ALL is nil, only match comments that Line 1611  If ALL is nil, only match comments that
1611                  (if (> (forward-line) 0)                  (if (> (forward-line) 0)
1612                      (setq not-done nil))                      (setq not-done nil))
1613                ;; else:                ;; else:
1614                ;; if we are at beginning of code line, skip any                ;; If we are at beginning of code line, skip any
1615                ;; whitespace, labels and tab continuation markers.                ;; whitespace, labels and tab continuation markers.
1616                (if (bolp) (skip-chars-forward " \t0-9"))                (if (bolp) (skip-chars-forward " \t0-9"))
1617                ;; if we are in column <= 5 now, check for continuation char                ;; If we are in column <= 5 now, check for continuation char.
1618                (cond ((= 5 (current-column)) (forward-char 1))                (cond ((= 5 (current-column)) (forward-char 1))
1619                      ((and (< (current-column) 5)                      ((and (< (current-column) 5)
1620                            (equal fortran-continuation-string                            (equal fortran-continuation-string
1621                                   (char-to-string (following-char)))                                   (char-to-string (following-char)))
1622                            (forward-char 1))))                            (forward-char 1))))
1623                ;; find out parse-limit from here                ;; Find out parse-limit from here.
1624                (setq end-of-line (line-end-position))                (setq end-of-line (line-end-position))
1625                (setq parse-limit (min where end-of-line))                (setq parse-limit (min where end-of-line))
1626                ;; parse max up to comment-start, if non-nil and in current line                ;; Parse max up to comment-start, if non-nil and in current line.
1627                (if comment-start                (if comment-start
1628                    (save-excursion                    (save-excursion
1629                      (if (re-search-forward quoted-comment-start end-of-line t)                      (if (re-search-forward quoted-comment-start end-of-line t)
1630                          (setq parse-limit (min (point) parse-limit)))))                          (setq parse-limit (min (point) parse-limit)))))
1631                ;; now parse if still in limits                ;; Now parse if still in limits.
1632                (if (< (point) where)                (if (< (point) where)
1633                    (setq parse-state (parse-partial-sexp                    (setq parse-state (parse-partial-sexp
1634                                       (point) parse-limit nil nil parse-state))                                       (point) parse-limit nil nil parse-state))
1635                  (setq not-done nil))))                  (setq not-done nil))))
1636            ;; result is            ;; Result.
1637            (nth 3 parse-state))))))            (nth 3 parse-state))))))
1638    
1639  ;; From old version.  ;; From old version.
1640  (defalias 'fortran-auto-fill-mode 'auto-fill-mode)  (defalias 'fortran-auto-fill-mode 'auto-fill-mode)
1641    
1642  (defun fortran-fill ()  (defun fortran-fill ()
1643      "Fill the current line at an appropriate point(s)."
1644    (let* ((auto-fill-function #'fortran-auto-fill)    (let* ((auto-fill-function #'fortran-auto-fill)
1645           (opoint (point))           (opoint (point))
1646           (bol (line-beginning-position))           (bol (line-beginning-position))
# Line 1638  If ALL is nil, only match comments that Line 1649  If ALL is nil, only match comments that
1649           (quote           (quote
1650            (save-excursion            (save-excursion
1651              (goto-char bol)              (goto-char bol)
1652              (if (looking-at fortran-comment-line-start-skip)              ;; OK to break quotes on comment lines.
1653                  nil                     ; OK to break quotes on comment lines.              (unless (looking-at fortran-comment-line-start-skip)
1654                  (let (fcpoint start)
1655                (move-to-column fill-column)                (move-to-column fill-column)
1656                (if (fortran-is-in-string-p (point))                (when (fortran-is-in-string-p (setq fcpoint (point)))
1657                    (save-excursion (re-search-backward "\\S\"\\s\"\\S\"" bol t)                  (save-excursion
1658                                    (if fortran-break-before-delimiters                    (re-search-backward "\\S\"\\s\"\\S\"" bol t)
1659                                        (point)                    (setq start
1660                                      (1+ (point))))))))                          (if fortran-break-before-delimiters
1661           ;; decide where to split the line. If a position for a quoted                              (point)
1662                              (1+ (point)))))
1663                    (if (re-search-forward "\\S\"\\s\"\\S\"" eol t)
1664                        (backward-char 2))
1665                    ;; If the current string is longer than 72 - 6 chars,
1666                    ;; break it at the fill column (else infinite loop).
1667                    (if (> (- (point) start)
1668                           (- fill-column 6 fortran-continuation-indent))
1669                        fcpoint
1670                      start))))))
1671             ;; Decide where to split the line. If a position for a quoted
1672           ;; string was found above then use that, else break the line           ;; string was found above then use that, else break the line
1673           ;; before the last delimiter.           ;; before the last delimiter.
1674           ;; Delimiters are whitespace, commas, and operators.           ;; Delimiters are whitespace, commas, and operators.
# Line 1655  If ALL is nil, only match comments that Line 1677  If ALL is nil, only match comments that
1677            (or quote            (or quote
1678                (save-excursion                (save-excursion
1679                  (move-to-column (1+ fill-column))                  (move-to-column (1+ fill-column))
1680                    ;; GM Make this a defcustom as in f90-mode? Add ", (?
1681                  (skip-chars-backward "^ \t\n,'+-/*=)"                  (skip-chars-backward "^ \t\n,'+-/*=)"
1682  ;;;              (if fortran-break-before-delimiters  ;;;              (if fortran-break-before-delimiters
1683  ;;;                  "^ \t\n,'+-/*=" "^ \t\n,'+-/*=)")  ;;;                  "^ \t\n,'+-/*=" "^ \t\n,'+-/*=)")
1684                   )                   )
1685                  (if (<= (point) (1+ bos))                  (when (<= (point) (1+ bos))
1686                      (progn                    (move-to-column (1+ fill-column))
1687                        (move-to-column (1+ fill-column))                    ;; What is this doing???
1688                        ;;what is this doing???                    (or (re-search-forward "[\t\n,'+-/*)=]" eol t)
1689                        (if (not (re-search-forward "[\t\n,'+-/*)=]" eol t))                        (goto-char bol)))
                           (goto-char bol))))  
1690                  (if (bolp)                  (if (bolp)
1691                      (re-search-forward "[ \t]" opoint t)                      (re-search-forward "[ \t]" opoint t)
1692                    (backward-char)                    (backward-char)
# Line 1674  If ALL is nil, only match comments that Line 1696  If ALL is nil, only match comments that
1696                  (if fortran-break-before-delimiters                  (if fortran-break-before-delimiters
1697                      (point)                      (point)
1698                    (1+ (point)))))))                    (1+ (point)))))))
1699      ;; if we are in an in-line comment, don't break unless the      ;; If we are in an in-line comment, don't break unless the
1700      ;; line of code is longer than it should be. Otherwise      ;; line of code is longer than it should be. Otherwise
1701      ;; break the line at the column computed above.      ;; break the line at the column computed above.
1702      ;;      ;;
1703      ;; Need to use fortran-find-comment-start-skip to make sure that quoted !'s      ;; Need to use fortran-find-comment-start-skip to make sure that
1704      ;; don't prevent a break.      ;; quoted !'s don't prevent a break.
1705      (when (and (save-excursion      (when (and (save-excursion
1706                   (beginning-of-line)                   (beginning-of-line)
1707                   (if (not (fortran-find-comment-start-skip))                   (if (not (fortran-find-comment-start-skip))
# Line 1700  If ALL is nil, only match comments that Line 1722  If ALL is nil, only match comments that
1722        (end-of-line))))        (end-of-line))))
1723    
1724  (defun fortran-break-line ()  (defun fortran-break-line ()
1725      "Call `fortran-split-line'.  Joins continuation lines first, then refills."
1726    (let ((opoint (point))    (let ((opoint (point))
1727          (bol (line-beginning-position))          (bol (line-beginning-position))
1728          (comment-string          (comment-string
# Line 1707  If ALL is nil, only match comments that Line 1730  If ALL is nil, only match comments that
1730             (if (fortran-find-comment-start-skip)             (if (fortran-find-comment-start-skip)
1731                 (delete-and-extract-region                 (delete-and-extract-region
1732                  (match-beginning 0) (line-end-position))))))                  (match-beginning 0) (line-end-position))))))
1733      ;; Forward line 1 really needs to go to next non white line      ;; Forward line 1 really needs to go to next non white line.
1734      (if (save-excursion (forward-line)      (if (save-excursion (forward-line)
1735                          (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]"))                          (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]"))
1736          (progn          (progn
# Line 1726  If ALL is nil, only match comments that Line 1749  If ALL is nil, only match comments that
1749    
1750  (defun fortran-analyze-file-format ()  (defun fortran-analyze-file-format ()
1751    "Return nil if fixed format is used, t if TAB formatting is used.    "Return nil if fixed format is used, t if TAB formatting is used.
1752  Use `fortran-tab-mode-default' if no non-comment statements are found in the  Use `fortran-tab-mode-default' if no non-comment statements are found
1753  file before the end or the first `fortran-analyze-depth' lines."  before the end or in the first `fortran-analyze-depth' lines."
1754    (let ((i 0))    (let ((i 0))
1755      (save-excursion      (save-excursion
1756        (goto-char (point-min))        (goto-char (point-min))
       (setq i 0)  
1757        (while (not (or        (while (not (or
1758                     (eobp)                     (eobp)
1759                     (eq (char-after) ?\t)                     (eq (char-after) ?\t)
# Line 1742  file before the end or the first `fortra Line 1764  file before the end or the first `fortra
1764        (cond        (cond
1765         ((eq (char-after) ?\t) t)         ((eq (char-after) ?\t) t)
1766         ((looking-at " \\{6\\}") nil)         ((looking-at " \\{6\\}") nil)
1767         (fortran-tab-mode-default t)         (t fortran-tab-mode-default)))))
        (t nil)))))  
   
 (or (assq 'fortran-tab-mode-string minor-mode-alist)  
     (setq minor-mode-alist (cons  
                             '(fortran-tab-mode-string  
                               (indent-tabs-mode fortran-tab-mode-string))  
                             minor-mode-alist)))  
1768    
1769  (defun fortran-fill-paragraph (&optional justify)  (defun fortran-fill-paragraph (&optional justify)
1770    "Fill surrounding comment block as paragraphs, else fill statement.    "Fill surrounding comment block as paragraphs, else fill statement.
1771  Intended as the value of `fill-paragraph-function'."  Intended as the value of `fill-paragraph-function'.
1772    (interactive "P")  A comment block is filled by calling `fill-comment-paragraph' with
1773    argument JUSTIFY, otherwise `fortran-fill-statement' is called.
1774    Always returns non-nil (to prevent `fill-paragraph' being called)."
1775      (interactive "*P")
1776    (or (fill-comment-paragraph justify)    (or (fill-comment-paragraph justify)
1777        (fortran-fill-statement)        (fortran-fill-statement)
1778        t))        t))
1779    
1780  (defun fortran-fill-statement ()  (defun fortran-fill-statement ()
1781    "Fill a fortran statement up to `fill-column'."    "Fill a Fortran statement up to `fill-column'."
1782    (interactive)    (interactive "*")
1783    (let ((auto-fill-function #'fortran-auto-fill))    (let ((auto-fill-function #'fortran-auto-fill))
1784      (if (not (save-excursion      (unless (save-excursion
1785                 (beginning-of-line)                (beginning-of-line)
1786                 (or (looking-at "[ \t]*$")                (or (looking-at "[ \t]*$")
1787                     (looking-at fortran-comment-line-start-skip)                    (looking-at fortran-comment-line-start-skip)
1788                     (and comment-start-skip                    (and comment-start-skip
1789                          (looking-at (concat "[ \t]*" comment-start-skip))))))                         (looking-at (concat "[ \t]*" comment-start-skip)))))
1790          (save-excursion        (save-excursion
1791            ;; Find beginning of statement.          ;; Find beginning of statement.
1792            (fortran-next-statement)          (fortran-next-statement)
1793            (fortran-previous-statement)          (fortran-previous-statement)
1794            ;; Re-indent initially.          ;; Re-indent initially.
1795            (fortran-indent-line)          (fortran-indent-line)
1796            ;; Replace newline plus continuation field plus indentation with          ;; Replace newline plus continuation field plus indentation with
1797            ;; single space.          ;; single space.
1798            (while (progn          (while (progn
1799                     (forward-line)                   (forward-line)
1800                     (fortran-remove-continuation)))                   (fortran-remove-continuation)))
1801            (fortran-previous-statement)))          (fortran-previous-statement)))
1802      (fortran-indent-line)))      (fortran-indent-line)))
1803    
1804  (defun fortran-strip-sequence-nos (&optional do-space)  (defun fortran-strip-sequence-nos (&optional do-space)
1805    "Delete all text in column 72 and up (assumed to be sequence numbers).    "Delete all text in column 72 and up (assumed to be sequence numbers).
1806  Normally also deletes trailing whitespace after stripping such text.  Normally also deletes trailing whitespace after stripping such text.
1807  Supplying prefix arg DO-SPACE prevents stripping the whitespace."  Supplying prefix arg DO-SPACE prevents stripping the whitespace."
1808    (interactive "p")    (interactive "*p")
1809    (save-excursion    (save-excursion
1810      (goto-char (point-min))      (goto-char (point-min))
1811      (while (re-search-forward "^.\\{72\\}\\(.*\\)" nil t)      (while (re-search-forward "^.\\{72\\}\\(.*\\)" nil t)
# Line 1802  Supplying prefix arg DO-SPACE prevents s Line 1820  Supplying prefix arg DO-SPACE prevents s
1820      ;; We must be inside function body for this to work.      ;; We must be inside function body for this to work.
1821      (fortran-beginning-of-subprogram)      (fortran-beginning-of-subprogram)
1822      (let ((case-fold-search t))         ; case-insensitive      (let ((case-fold-search t))         ; case-insensitive
1823        ;; search for fortran subprogram start        ;; Search for fortran subprogram start.
1824        (if (re-search-forward        (if (re-search-forward
1825             (concat "^[ \t]*\\(program\\|subroutine\\|function"             (concat "^[ \t]*\\(program\\|subroutine\\|function"
1826                     "\\|[ \ta-z0-9*()]*[ \t]+function\\|"                     "\\|[ \ta-z0-9*()]*[ \t]+function\\|"
# Line 1812  Supplying prefix arg DO-SPACE prevents s Line 1830  Supplying prefix arg DO-SPACE prevents s
1830             t)             t)
1831            (or (match-string-no-properties 2)            (or (match-string-no-properties 2)
1832                (progn                (progn
1833                  ;; move to EOL or before first left paren                  ;; Move to EOL or before first left paren.
1834                  (if (re-search-forward "[(\n]" nil t)                  (if (re-search-forward "[(\n]" nil t)
1835                      (progn (backward-char)                      (progn (backward-char)
1836                             (skip-chars-backward " \t"))                             (skip-chars-backward " \t"))
# Line 1824  Supplying prefix arg DO-SPACE prevents s Line 1842  Supplying prefix arg DO-SPACE prevents s
1842    
1843  (provide 'fortran)  (provide 'fortran)
1844    
1845    ;;; arch-tag: 74935096-21c4-4cab-8ee5-6ef16090dc04
1846  ;;; fortran.el ends here  ;;; fortran.el ends here

Legend:
Removed from v.1.96.2.1  
changed lines
  Added in v.1.96.2.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26