Commit 8cb8832f authored by Glenn Morris's avatar Glenn Morris

Reformat and update copyright years.

(fortran-if-indent): Doc fix.
(fortran-font-lock-keywords-2): Add "where", "elsewhere".
(fortran-font-lock-keywords-4): New variable.
(fortran-blocks-re, fortran-end-block-re)
(fortran-start-block-re): New constants, for hideshow.
(hs-special-modes-alist): Add a Fortran entry.
(fortran-mode-map): Bind fortran-end-of-block,
fortran-beginning-of-block to \M-\C-n, \M-\C-p.
(fortran-mode): Doc fix. Add fortran-font-lock-keywords-4.
(fortran-looking-at-if-then, fortran-end-of-block)
(fortran-beginning-of-block): New functions, for hideshow.
parent fcca5273
;;; fortran.el --- Fortran mode for GNU Emacs
;; Copyright (c) 1986, 93, 94, 95, 97, 98, 99, 2000, 01, 03, 04
;; Free Software Foundation, Inc.
;; Copyright (C) 1986, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
;; 2003, 2004, 2005 Free Software Foundation, Inc.
;; Author: Michael D. Prange <prange@erl.mit.edu>
;; Maintainer: Glenn Morris <gmorris@ast.cam.ac.uk>
......@@ -95,7 +95,7 @@ with a character in column 6."
:group 'fortran-indent)
(defcustom fortran-if-indent 3
"*Extra indentation applied to IF blocks."
"*Extra indentation applied to IF, SELECT CASE and WHERE blocks."
:type 'integer
:group 'fortran-indent)
......@@ -321,7 +321,8 @@ program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?"
"while" "inquire" "stop" "return"
"include" "open" "close" "read"
"write" "format" "print" "select" "case"
"cycle" "exit" "rewind" "backspace")
"cycle" "exit" "rewind" "backspace"
"where" "elsewhere")
'paren) "\\>")
;; Builtin operators.
(concat "\\." (regexp-opt
......@@ -370,6 +371,29 @@ program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?"
fortran-font-lock-keywords-2)))
"Gaudy level highlighting for Fortran mode.")
(defvar fortran-font-lock-keywords-4
(append fortran-font-lock-keywords-3
(list (list
(concat "\\<"
(regexp-opt
'("int" "ifix" "idint" "real" "float" "sngl"
"dble" "cmplx" "ichar" "char" "aint" "dint"
"anint" "dnint" "nint" "idnint" "iabs" "abs"
"dabs" "cabs" "mod" "amod" "dmod" "isign"
"sign" "dsign" "idim" "dim" "ddim" "dprod"
"max" "max0" "amax1" "dmax1" "amax0" "max1"
"min0" "amin1" "dmin1" "amin0" "min1" "len"
"index" "lge" "lgt" "lle" "llt" "aimag"
"conjg" "sqrt" "dsqrt" "csqrt" "exp" "dexp"
"cexp" "log" "alog" "dlog" "clog" "log10"
"alog10" "dlog10" "sin" "dsin" "csin" "cos"
"dcos" "ccos" "tan" "dtan" "asin" "dasin"
"acos" "dacos" "atan" "datan" "atan2" "datan2"
"sinh" "dsinh" "cosh" "dcosh" "tanh" "dtanh")
'paren) "[ \t]*(") '(1 font-lock-builtin-face))))
"Maximum highlighting for Fortran mode.
Consists of level 3 plus all other intrinsics not already highlighted.")
;; Comments are real pain in Fortran because there is no way to
;; represent the standard comment syntax in an Emacs syntax table.
;; (We can do so for F90-style). Therefore an unmatched quote in a
......@@ -408,6 +432,64 @@ These get fixed-format comments fontified.")
'(nil "^\\s-+\\(block\\s-*data\\)\\s-*$" 1))
"Value for `imenu-generic-expression' in Fortran mode.")
;; Hideshow support.
(defconst fortran-blocks-re
(concat "block[ \t]*data\\|select[ \t]*case\\|"
(regexp-opt '("do" "if" "interface" "function" "map" "program"
"structure" "subroutine" "union" "where")))
"Regexp potentially indicating the start or end of a Fortran \"block\".
Omits naked END statements, and DO-loops closed by anything other
than ENDDO.")
(defconst fortran-end-block-re
;; Do-loops terminated by things other than ENDDO cannot be handled
;; with a regexp. This omission does not seem to matter to hideshow...
(concat "^[ \t0-9]*\\<end[ \t]*\\("
fortran-blocks-re
;; Naked END statement.
"\\|!\\|$\\)")
"Regexp matching the end of a Fortran \"block\", from the line start.
Note that only ENDDO is handled for the end of a DO-loop. Used
in the Fortran entry in `hs-special-modes-alist'.")
(defconst fortran-start-block-re
(concat
"^[ \t0-9]*\\(" ; statement number
;; Structure label for DO, IF, SELECT, WHERE.
"\\(\\(\\sw+[ \t]*:[ \t]*\\)?"
;; IF blocks are a nuisance:
;; IF ( ... ) foo is not a block, but a single statement.
;; IF ( ... ) THEN can be split over multiple lines.
;; [So can, eg, a DO WHILE (... ), but that is less common, I hope.]
;; The regexp below allows for it to be split over at most 2 lines.
;; That leads to the problem of not matching two consecutive IF
;; statements as one, eg:
;; IF ( ... ) foo
;; IF ( ... ) THEN
;; It simply is not possible to do this in a 100% correct fashion
;; using a regexp - see the functions fortran-end-if,
;; fortran-beginning-if for the hoops we have to go through.
;; An alternative is to match on THEN at a line end, eg:
;; ".*)[ \t]*then[ \t]*\\($\\|!\\)"
;; This would also match ELSE branches, though. This does not seem
;; right to me, because then one has neighbouring blocks that are
;; not nested in each other.
"\\(if[ \t]*(\\(.*\\|"
".*\n\\([^if]*\\([^i].\\|.[^f]\\|.\\>\\)\\)\\)\\<then\\|"
"do\\|select[ \t]*case\\|where\\)\\)\\|"
(regexp-opt '("interface" "function" "map" "program"
"structure" "subroutine" "union"))
"\\|block[ \t]*data\\)[ \t]*")
"Regexp matching the start of a Fortran \"block\", from the line start.
A simple regexp cannot do this in fully correct fashion, so this
tries to strike a compromise between complexity and flexibility.
Used in the Fortran entry in `hs-special-modes-alist'.")
(add-to-list 'hs-special-modes-alist
`(fortran-mode ,fortran-start-block-re ,fortran-end-block-re
"^[cC*!]" fortran-end-of-block nil))
(defvar fortran-mode-syntax-table
(let ((table (make-syntax-table)))
......@@ -422,7 +504,8 @@ These get fixed-format comments fontified.")
(modify-syntax-entry ?/ "." table)
(modify-syntax-entry ?\' "\"" table)
(modify-syntax-entry ?\" "\"" table)
;; Consistent with GNU Fortran -- see the manual.
;; Consistent with GNU Fortran's default -- see the manual.
;; The F77 standard imposes no rule on this issue.
(modify-syntax-entry ?\\ "\\" table)
;; This might be better as punctuation, as for C, but this way you
;; can treat floating-point numbers as symbols.
......@@ -446,6 +529,8 @@ These get fixed-format comments fontified.")
(define-key map "\C-c;" 'fortran-comment-region)
(define-key map "\M-;" 'fortran-indent-comment)
(define-key map "\M-\n" 'fortran-split-line)
(define-key map "\M-\C-n" 'fortran-end-of-block)
(define-key map "\M-\C-p" 'fortran-beginning-of-block)
(define-key map "\M-\C-q" 'fortran-indent-subprogram)
(define-key map "\C-c\C-w" 'fortran-window-create-momentarily)
(define-key map "\C-c\C-r" 'fortran-column-ruler)
......@@ -606,7 +691,7 @@ Key definitions:
Variables controlling indentation style and extra features:
`comment-start'
`fortran-comment-line-start'
To use comments starting with `!', set this to the string \"!\".
`fortran-do-indent'
Extra indentation within DO blocks (default 3).
......@@ -696,7 +781,8 @@ with no args, if that value is non-nil."
'((fortran-font-lock-keywords
fortran-font-lock-keywords-1
fortran-font-lock-keywords-2
fortran-font-lock-keywords-3)
fortran-font-lock-keywords-3
fortran-font-lock-keywords-4)
nil t ((?/ . "$/") ("_$" . "w"))
fortran-beginning-of-subprogram))
(set (make-local-variable 'font-lock-syntactic-keywords)
......@@ -1059,6 +1145,84 @@ Directive lines are treated as comments."
(if (not not-last-statement)
'last-statement)))
(defun fortran-looking-at-if-then ()
"Return non-nil if at the start of a line with an IF ... THEN statement."
;; cf f90-looking-at-if-then.
(let ((p (point))
(i (fortran-beginning-if)))
(if i
(save-excursion
(goto-char i)
(beginning-of-line)
(= (point) p)))))
;; Used in hs-special-modes-alist.
(defun fortran-end-of-block (&optional num)
"Move point forward to the end of the current code block.
With optional argument NUM, go forward that many balanced blocks.
If NUM is negative, go backward to the start of a block. Does
not check for consistency of block types. Interactively, pushes
mark before moving point."
(interactive "p")
(if (interactive-p) (push-mark (point) t))
(and num (< num 0) (fortran-beginning-of-block (- num)))
(let ((case-fold-search t)
(count (or num 1)))
(end-of-line)
(while (and (> count 0)
(re-search-forward
(concat "\\(" fortran-blocks-re
(if fortran-check-all-num-for-matching-do
"\\|^[ \t]*[0-9]+" "")
"\\|continue\\|end\\)\\>")
nil 'move))
(beginning-of-line)
(if (if (looking-at (concat "^[0-9 \t]*" fortran-if-start-re))
(fortran-looking-at-if-then)
(looking-at fortran-start-block-re))
(setq count (1+ count))
(if (or (looking-at fortran-end-block-re)
(and (or (looking-at "^[0-9 \t]*continue")
(and fortran-check-all-num-for-matching-do
(looking-at "[ \t]*[0-9]+")))
(fortran-check-for-matching-do)))
(setq count (1- count))))
(end-of-line))
(if (> count 0) (error "Missing block end"))))
(defun fortran-beginning-of-block (&optional num)
"Move point backwards to the start of the current code block.
With optional argument NUM, go backward that many balanced
blocks. If NUM is negative, go forward to the end of a block.
Does not check for consistency of block types. Interactively,
pushes mark before moving point."
(interactive "p")
(if (interactive-p) (push-mark (point) t))
(and num (< num 0) (fortran-end-of-block (- num)))
(let ((case-fold-search t)
(count (or num 1)))
(beginning-of-line)
(while (and (> count 0)
(re-search-backward
(concat "\\(" fortran-blocks-re
(if fortran-check-all-num-for-matching-do
"\\|^[ \t]*[0-9]+" "")
"\\|continue\\|end\\)\\>")
nil 'move))
(beginning-of-line)
(if (if (looking-at (concat "^[0-9 \t]*" fortran-if-start-re))
(fortran-looking-at-if-then)
(looking-at fortran-start-block-re))
(setq count (1- count))
(if (or (looking-at fortran-end-block-re)
(and (or (looking-at "^[0-9 \t]*continue")
(and fortran-check-all-num-for-matching-do
(looking-at "[ \t]*[0-9]+")))
(fortran-check-for-matching-do)))
(setq count (1+ count)))))
;; Includes an un-named main program block.
(if (> count 0) (error "Missing block start"))))
(defun fortran-blink-match (regex keyword find-begin)
"From a line matching REGEX, blink matching KEYWORD statement line.
......@@ -1679,8 +1843,9 @@ If ALL is nil, only match comments that start in column > 0."
(1+ (point)))))
(if (re-search-forward "\\S\"\\s\"\\S\"" eol t)
(backward-char 2))
;; If the current string is longer than 72 - 6 chars,
;; break it at the fill column (else infinite loop).
;; If the current string is longer than (fill-column
;; - 6) chars, break it at the fill column (else
;; infinite loop).
(if (> (- (point) start)
(- fill-column 6 fortran-continuation-indent))
fcpoint
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment