;;; fortran.el --- Fortran mode for GNU Emacs;; Copyright (c) 1986, 1993, 1994, 1995 Free Software Foundation, Inc.;; Author: Michael D. Prange <prange@erl.mit.edu>;; Maintainer: bug-fortran-mode@erl.mit.edu;; Version 1.30.6-x (July 27, 1995);; Keywords: languages;; This file is part of XEmacs.;; XEmacs is free software; you can redistribute it and/or modify it;; under the terms of the GNU General Public License as published by;; the Free Software Foundation; either version 2, or (at your option);; any later version.;; XEmacs is distributed in the hope that it will be useful, but;; WITHOUT ANY WARRANTY; without even the implied warranty of;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU;; General Public License for more details.;; You should have received a copy of the GNU General Public License;; along with XEmacs; see the file COPYING. If not, write to the Free;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA;; 02111-1307, USA.;;; Synched up with: FSF 19.34.;;; Commentary:;; Fortran mode has been upgraded and is now maintained by Stephen A. Wood;; (saw@cebaf.gov). It now will use either fixed format continuation line;; markers (character in 6th column), or tab format continuation line style;; (digit after a TAB character.) A auto-fill mode has been added to;; automatically wrap fortran lines that get too long.;; We acknowledge many contributions and valuable suggestions by;; Lawrence R. Dodd, Ralf Fassel, Ralph Finch, Stephen Gildea,;; Dr. Anil Gokhale, Ulrich Mueller, Mark Neale, Eric Prestemon, ;; Gary Sabot and Richard Stallman.;; This file may be used with GNU Emacs version 18.xx if the following;; variable and function substitutions are made.;; Replace:;; frame-width with screen-width;; auto-fill-function with auto-fill-hook;; comment-indent-function with comment-indent-hook;; (setq unread-command-events (list c)) with (setq unread-command-char c);; Bugs to bug-fortran-mode@erl.mit.edu;;; Code:(defconstfortran-mode-version"version 1.30.6-x")(defgroupfortrannil"Fortran mode for Emacs":group'languages)(defgroupfortran-indentnil"Indentation variables in Fortran mode":prefix"fortran-":group'fortran)(defgroupfortran-commentnil"Comment-handling variables in Fortran mode":prefix"fortran-":group'fortran);;;###autoload(defcustomfortran-tab-mode-defaultnil"*Default tabbing/carriage control style for empty files in Fortran mode.A value of t specifies tab-digit style of continuation control.A value of nil specifies that continuation lines are markedwith a character in column 6.":type'boolean:group'fortran-indent);; Buffer local, used to display mode line.(defcustomfortran-tab-mode-stringnil"String to appear in mode line when TAB format mode is on.":type'(choice(constnil)string):group'fortran-indent)(defcustomfortran-do-indent3"*Extra indentation applied to DO blocks.":type'integer:group'fortran-indent)(defcustomfortran-if-indent3"*Extra indentation applied to IF blocks.":type'integer:group'fortran-indent)(defcustomfortran-structure-indent3"*Extra indentation applied to STRUCTURE, UNION, MAP and INTERFACE blocks.":type'integer:group'fortran-indent)(defcustomfortran-continuation-indent5"*Extra indentation applied to Fortran continuation lines.":type'integer:group'fortran-indent)(defcustomfortran-comment-indent-style'fixed"*nil forces comment lines not to be touched,'fixed makes fixed comment indentation to `fortran-comment-line-extra-indent'columns beyond `fortran-minimum-statement-indent-fixed' (for`indent-tabs-mode' of nil) or `fortran-minimum-statement-indent-tab' (for`indent-tabs-mode' of t), and 'relative indents to currentFortran indentation plus `fortran-comment-line-extra-indent'.":type'(radio(constnil)(constfixed)(constrelative)):group'fortran-indent)(defcustomfortran-comment-line-extra-indent0"*Amount of extra indentation for text within full-line comments.":type'integer:group'fortran-indent:group'fortran-comment)(defcustomcomment-line-startnil"*Delimiter inserted to start new full-line comment.":type'(choicestring(constnil)):group'fortran-comment)(defcustomcomment-line-start-skipnil"*Regexp to match the start of a full-line comment.":type'(choicestring(constnil)):group'fortran-comment)(defcustomfortran-minimum-statement-indent-fixed6"*Minimum statement indentation for fixed format continuation style.":type'integer:group'fortran-indent)(defcustomfortran-minimum-statement-indent-tab(maxtab-width6)"*Minimum statement indentation for TAB format continuation style.":type'integer:group'fortran-indent);; Note that this is documented in the v18 manuals as being a string;; of length one rather than a single character.;; The code in this file accepts either format for compatibility.(defcustomfortran-comment-indent-char" ""*Single-character string inserted for Fortran comment indentation.Normally a space.":type'string:group'fortran-comment)(defcustomfortran-line-number-indent1"*Maximum indentation for Fortran line numbers.5 means right-justify them within their five-column field.":type'integer:group'fortran-indent)(defcustomfortran-check-all-num-for-matching-donil"*Non-nil causes all numbered lines to be treated as possible DO loop ends.":type'boolean:group'fortran)(defcustomfortran-blink-matching-ifnil"*Non-nil causes \\[fortran-indent-line] on ENDIF statement to blink on matching IF.Also, from an ENDDO statement blink on matching DO [WHILE] statement.":type'boolean:group'fortran)(defcustomfortran-continuation-string"$""*Single-character string used for Fortran continuation lines.In fixed format continuation style, this character is inserted incolumn 6 by \\[fortran-split-line] to begin a continuation line.Also, if \\[fortran-indent-line] finds this at the beginning of a line, it willconvert the line into a continuation line of the appropriate style.Normally $.":type'string:group'fortran)(defcustomfortran-comment-region"c$$$""*String inserted by \\[fortran-comment-region]\ at start of each line in region.":type'string:group'fortran-comment)(defcustomfortran-electric-line-numbert"*Non-nil causes line number digits to be moved to the correct column as\ typed.":type'boolean:group'fortran)(defcustomfortran-startup-messaget"*Non-nil displays a startup message when Fortran mode is first called.":type'boolean:group'fortran)(defvarfortran-column-ruler-fixed"0 4 6 10 20 30 40 5\\0 60 70\n\\[ ]|{ | | | | | | | | \\| | | | |}\n""*String displayed above current line by \\[fortran-column-ruler].This variable used in fixed format mode.")(defvarfortran-column-ruler-tab"0 810 20 30 40 5\\0 60 70\n\\[ ]| { | | | | | | | | \\| | | | |}\n""*String displayed above current line by \\[fortran-column-ruler].This variable used in TAB format mode.")(defconstbug-fortran-mode"bug-fortran-mode@erl.mit.edu""Address of mailing list for Fortran mode bugs.")(defvarfortran-mode-syntax-tablenil"Syntax table in use in Fortran mode buffers.")(defvarfortran-analyze-depth100"Number of lines to scan to determine whether to use fixed or TAB format\ style.")(defcustomfortran-break-before-delimiterst"*Non-nil causes `fortran-fill' to break lines before delimiters.":type'boolean:group'fortran)(iffortran-mode-syntax-table()(setqfortran-mode-syntax-table(make-syntax-table))(modify-syntax-entry?\;"w"fortran-mode-syntax-table)(modify-syntax-entry?\r" "fortran-mode-syntax-table)(modify-syntax-entry?+"."fortran-mode-syntax-table)(modify-syntax-entry?-"."fortran-mode-syntax-table)(modify-syntax-entry?="."fortran-mode-syntax-table);; XEmacs change;;(modify-syntax-entry ?* "." fortran-mode-syntax-table)(modify-syntax-entry?/"."fortran-mode-syntax-table)(modify-syntax-entry?\'"\""fortran-mode-syntax-table)(modify-syntax-entry?\""\""fortran-mode-syntax-table)(modify-syntax-entry?\\"/"fortran-mode-syntax-table)(modify-syntax-entry?."_"fortran-mode-syntax-table)(modify-syntax-entry?_"_"fortran-mode-syntax-table)(modify-syntax-entry?$"_"fortran-mode-syntax-table)(modify-syntax-entry?@"_"fortran-mode-syntax-table)(modify-syntax-entry?\!"<"fortran-mode-syntax-table);; XEmacs change;;(modify-syntax-entry ?\n ">" fortran-mode-syntax-table);; XEmacs: an attempt to make font-lock understand fortran comments.(modify-syntax-entry?\n"> 1"fortran-mode-syntax-table)(modify-syntax-entry?*". 2"fortran-mode-syntax-table)(modify-syntax-entry?c"w 2"fortran-mode-syntax-table)(modify-syntax-entry?C"w 2"fortran-mode-syntax-table));; Comments are real pain in Fortran because there is no way to represent the;; standard comment syntax in an Emacs syntax table (we can for VAX-style).;; Therefore an unmatched quote in a standard comment will throw fontification;; off on the wrong track. So we do syntactic fontification with regexps.;; Regexps done by simon@gnu with help from Ulrik Dickow <dickow@nbi.dk> and;; probably others Si's forgotten about (sorry).(defconstfortran-font-lock-keywords-1nil"Subdued level highlighting for Fortran mode.")(defconstfortran-font-lock-keywords-2nil"Medium level highlighting for Fortran mode.")(defconstfortran-font-lock-keywords-3nil"Gaudy level highlighting for Fortran mode.")(let((comment-chars"c!*")(fortran-type-types; (make-regexp; (let ((simple-types '("character" "byte" "integer" "logical"; "none" "real" "complex"; "double[ \t]*precision" "double[ \t]*complex")); (structured-types '("structure" "union" "map")); (other-types '("record" "dimension" "parameter" "common" "save"; "external" "intrinsic" "data" "equivalence"))); (append; (mapcar (lambda (x) (concat "implicit[ \t]*" x)) simple-types); simple-types; (mapcar (lambda (x) (concat "end[ \t]*" x)) structured-types); structured-types; other-types)))(concat"byte\\|c\\(haracter\\|om\\(mon\\|plex\\)\\)\\|""d\\(ata\\|imension\\|ouble""[ \t]*\\(complex\\|precision\\)\\)\\|""e\\(nd[ \t]*\\(map\\|structure\\|union\\)\\|""quivalence\\|xternal\\)\\|""i\\(mplicit[ \t]*\\(byte\\|""c\\(haracter\\|omplex\\)\\|""double[ \t]*\\(complex\\|precision\\)\\|""integer\\|logical\\|none\\|real\\)\\|""nt\\(eger\\|rinsic\\)\\)\\|""logical\\|map\\|none\\|parameter\\|re\\(al\\|cord\\)\\|""s\\(ave\\|tructure\\)\\|union"))(fortran-keywords; ("continue" "format" "end" "enddo" "if" "then" "else" "endif"; "elseif" "while" "inquire" "stop" "return" "include" "open"; "close" "read" "write" "format" "print")(concat"c\\(lose\\|ontinue\\)\\|""e\\(lse\\(\\|if\\)\\|nd\\(\\|do\\|if\\)\\)\\|format\\|""i\\(f\\|n\\(clude\\|quire\\)\\)\\|open\\|print\\|""re\\(ad\\|turn\\)\\|stop\\|then\\|w\\(hile\\|rite\\)"))(fortran-logicals; ("and" "or" "not" "lt" "le" "eq" "ge" "gt" "ne" "true" "false")"and\\|eq\\|false\\|g[et]\\|l[et]\\|n\\(e\\|ot\\)\\|or\\|true"))(setqfortran-font-lock-keywords-1(list;;;; Fontify syntactically (assuming strings cannot be quoted or span lines).(cons(concat"^["comment-chars"].*")'font-lock-comment-face)'(fortran-match-!-comment.font-lock-comment-face)(list(concat"^[^"comment-chars"\t\n]"(make-string71?.)"\\(.*\\)")'(1font-lock-comment-face))'("'[^'\n]*'?".font-lock-string-face);;;; Program, subroutine and function declarations, plus calls.(list(concat"\\<\\(block[ \t]*data\\|call\\|entry\\|function\\|""program\\|subroutine\\)\\>[ \t]*\\(\\(\\sw\\|\\s_\\)+\\)?")'(1font-lock-keyword-face)'(2font-lock-function-name-facenilt))))(setqfortran-font-lock-keywords-2(appendfortran-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]+\\)?"'(1font-lock-keyword-face)'(2font-lock-reference-facenilt))(cons"^ *\\([0-9]+\\)"'font-lock-reference-face))))(setqfortran-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.'(1font-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.(and(match-beginning15)(forward-sexp1));; No need to clean up.nil;; Fontify as a variable name, functions are fontified elsewhere.(1font-lock-variable-name-facenilt))));;;; 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]+\\)\\)?"(1font-lock-keyword-face)(4font-lock-reference-facenilt));;;; Highlight standard continuation character and in a TAB-formatted line.'("^ \\([^ 0]\\)"1font-lock-string-face)'("^\t\\([1-9]\\)"1font-lock-string-face));;;; The list `fortran-font-lock-keywords-2' less that for types (see above).(cdr(nthcdr(lengthfortran-font-lock-keywords-1)fortran-font-lock-keywords-2)))))(defvarfortran-font-lock-keywordsfortran-font-lock-keywords-1"Default expressions to highlight in Fortran mode.");; XEmacs change(put'fortran-mode'font-lock-defaults'((fortran-font-lock-keywordsfortran-font-lock-keywords-1fortran-font-lock-keywords-2fortran-font-lock-keywords-3)tt((?/."$/"))));; Our previous version.;(defconst fortran-font-lock-keywords-1; (purecopy; (list; ;; fontify comments; '("^[cC*].*$" . font-lock-comment-face); ;;; ;; fontify preprocessor directives.; '("^#[ \t]*[a-z]+" . font-lock-preprocessor-face); ;;; ;; fontify names being defined.; '("^#[ \t]*\\(define\\|undef\\)[ \t]+\\(\\(\\sw\\|\\s_\\)+\\)" 2; font-lock-function-name-face); ;;; ;; fontify other preprocessor lines.; '("^#[ \t]*\\(if\\|ifn?def\\|elif\\)[ \t]+\\([^\n]+\\)"; 2 font-lock-function-name-face t); ;; Subroutine and function declarations; '("^[ \t]*subroutine.*$" . font-lock-function-name-face); '("^[ \t].*function.*$" . font-lock-function-name-face); '("^[ \t].*program.*$" . font-lock-function-name-face); '("^[ \t].*entry.*$" . font-lock-function-name-face); )); "For consideration as a value of `fortran-font-lock-keywords'.;This does fairly subdued highlighting of comments and function names.");(defconst fortran-font-lock-keywords-2; (purecopy; (append fortran-font-lock-keywords-1; (list; ;; Variable declarations; '("^[ \t]*\\(\\(integer\\|logical\\|real\\|complex\\|double[ \t]*precision\\|character\\|parameter\\)[^ \t]*\\)" ; 1 font-lock-keyword-face); ;; Common blocks, external, etc; '("^[ \t]*\\(common\\|save\\|external\\|intrinsic\\|data\\)" 1 font-lock-keyword-face); ;; Other keywords; '("^[ \t]*[0-9]*[ \t]*\\(if\\)[ \t]*("; 1 font-lock-keyword-face); ;; Then; ;; '("^\\(\\([ \t]*[0-9]*[ \t]*\\)\\|\\( [^ ]\\)\\).*[ \t]*\\(then\\)[ \t]*"; ;; 4 font-lock-keyword-face); '("\\(then\\)[ \t]*$" 1 font-lock-keyword-face); ;; '("^[ \t]*[0-9]*[ \t]*\\(end[ \t]*if\\)[ \t]*$"; '("\\(end[ \t]*if\\)[ \t]*$"; 1 font-lock-keyword-face) ; ;; '("\\(else[ \t]*\\(if\\)?\\)"; ;; the below works better <mdb@cdc.noaa.gov>; '("^[ \t]*[0-9]*[ \t]*\\(else[ \t]*\\(if\\)?\\)"; 1 font-lock-keyword-face); '("^[ \t]*[0-9]*[ \t]*\\(do\\)[ \t]*[0-9]+"; 1 font-lock-keyword-face); '("^[ \t]*[0-9]*[ \t]*\\(do\\)[ \t]*[a-z0-9_$]+[ \t]*="; 1 font-lock-keyword-face); '("^[ \t]*[0-9]*[ \t]*\\(end[ \t]*do\\)"; 1 font-lock-keyword-face); '("^[ \t]*[0-9]+[ \t]*\\(continue\\)" 1 font-lock-keyword-face); '("^[ \t]*[0-9]*[ \t]*\\(call\\)" 1 font-lock-keyword-face); '("^[ \t]*[0-9]*[ \t]*\\(go[ \t]*to\\)" 1 font-lock-keyword-face); '("^[ \t]*[0-9]*[ \t]*\\(open\\|close\\|read\\|write\\|format\\)[ \t]*("; 1 font-lock-keyword-face); '("^[ \t]*[0-9]*[ \t]*\\(print\\)[ \t]*[*'0-9]+" 1 font-lock-keyword-face); '("^[ \t]*[0-9]*[ \t]*\\(end\\|return\\)[ \t]*$" 1 font-lock-keyword-face); '("^[ \t]*[0-9]*[ \t]*\\(stop\\)[ \t]*['0-9]*" 1 font-lock-keyword-face); ;; Boolean and relational operations, logical true and false; '("\\.\\(and\\|or\\|not\\|lt\\|le\\|eq\\|ge\\|gt\\|ne\\|true\\|false\\)\\."; . font-lock-keyword-face); ))); "For consideration as a value of `fortran-font-lock-keywords'.;This highlights variable types, \"keywords,\" etc.")(defvarfortran-mode-map()"Keymap used in Fortran mode.")(iffortran-mode-map()(setqfortran-mode-map(make-sparse-keymap))(define-keyfortran-mode-map";"'fortran-abbrev-start)(define-keyfortran-mode-map"\C-c;"'fortran-comment-region)(define-keyfortran-mode-map"\e\C-a"'beginning-of-fortran-subprogram)(define-keyfortran-mode-map"\e\C-e"'end-of-fortran-subprogram)(define-keyfortran-mode-map"\e;"'fortran-indent-comment);; Separate M-BS from C-M-h. The former should remain;; backward-kill-word.(define-keyfortran-mode-map[(controlmetah)]'mark-fortran-subprogram)(define-keyfortran-mode-map"\e\n"'fortran-split-line)(define-keyfortran-mode-map"\n"'fortran-indent-new-line)(define-keyfortran-mode-map"\e\C-q"'fortran-indent-subprogram)(define-keyfortran-mode-map"\C-c\C-w"'fortran-window-create-momentarily)(define-keyfortran-mode-map"\C-c\C-r"'fortran-column-ruler)(define-keyfortran-mode-map"\C-c\C-p"'fortran-previous-statement)(define-keyfortran-mode-map"\C-c\C-n"'fortran-next-statement)(define-keyfortran-mode-map"\t"'fortran-indent-line)(define-keyfortran-mode-map"0"'fortran-electric-line-number)(define-keyfortran-mode-map"1"'fortran-electric-line-number)(define-keyfortran-mode-map"2"'fortran-electric-line-number)(define-keyfortran-mode-map"3"'fortran-electric-line-number)(define-keyfortran-mode-map"4"'fortran-electric-line-number)(define-keyfortran-mode-map"5"'fortran-electric-line-number)(define-keyfortran-mode-map"6"'fortran-electric-line-number)(define-keyfortran-mode-map"7"'fortran-electric-line-number)(define-keyfortran-mode-map"8"'fortran-electric-line-number)(define-keyfortran-mode-map"9"'fortran-electric-line-number))(defvarfortran-mode-abbrev-tablenil)(iffortran-mode-abbrev-table()(let((acabbrevs-changed))(define-abbrev-table'fortran-mode-abbrev-table())(define-abbrevfortran-mode-abbrev-table";au""automatic"nil)(define-abbrevfortran-mode-abbrev-table";b""byte"nil)(define-abbrevfortran-mode-abbrev-table";bd""block data"nil)(define-abbrevfortran-mode-abbrev-table";ch""character"nil)(define-abbrevfortran-mode-abbrev-table";cl""close"nil)(define-abbrevfortran-mode-abbrev-table";c""continue"nil)(define-abbrevfortran-mode-abbrev-table";cm""common"nil)(define-abbrevfortran-mode-abbrev-table";cx""complex"nil)(define-abbrevfortran-mode-abbrev-table";df""define"nil)(define-abbrevfortran-mode-abbrev-table";di""dimension"nil)(define-abbrevfortran-mode-abbrev-table";do""double"nil)(define-abbrevfortran-mode-abbrev-table";dc""double complex"nil)(define-abbrevfortran-mode-abbrev-table";dp""double precision"nil)(define-abbrevfortran-mode-abbrev-table";dw""do while"nil)(define-abbrevfortran-mode-abbrev-table";e""else"nil)(define-abbrevfortran-mode-abbrev-table";ed""enddo"nil)(define-abbrevfortran-mode-abbrev-table";el""elseif"nil)(define-abbrevfortran-mode-abbrev-table";en""endif"nil)(define-abbrevfortran-mode-abbrev-table";eq""equivalence"nil)(define-abbrevfortran-mode-abbrev-table";ew""endwhere"nil)(define-abbrevfortran-mode-abbrev-table";ex""external"nil)(define-abbrevfortran-mode-abbrev-table";ey""entry"nil)(define-abbrevfortran-mode-abbrev-table";f""format"nil)(define-abbrevfortran-mode-abbrev-table";fa"".false."nil)(define-abbrevfortran-mode-abbrev-table";fu""function"nil)(define-abbrevfortran-mode-abbrev-table";g""goto"nil)(define-abbrevfortran-mode-abbrev-table";im""implicit"nil)(define-abbrevfortran-mode-abbrev-table";ib""implicit byte"nil)(define-abbrevfortran-mode-abbrev-table";ic""implicit complex"nil)(define-abbrevfortran-mode-abbrev-table";ich""implicit character"nil)(define-abbrevfortran-mode-abbrev-table";ii""implicit integer"nil)(define-abbrevfortran-mode-abbrev-table";il""implicit logical"nil)(define-abbrevfortran-mode-abbrev-table";ir""implicit real"nil)(define-abbrevfortran-mode-abbrev-table";inc""include"nil)(define-abbrevfortran-mode-abbrev-table";in""integer"nil)(define-abbrevfortran-mode-abbrev-table";intr""intrinsic"nil)(define-abbrevfortran-mode-abbrev-table";l""logical"nil)(define-abbrevfortran-mode-abbrev-table";n""namelist"nil)(define-abbrevfortran-mode-abbrev-table";o""open"nil); was ;op(define-abbrevfortran-mode-abbrev-table";pa""parameter"nil)(define-abbrevfortran-mode-abbrev-table";pr""program"nil)(define-abbrevfortran-mode-abbrev-table";ps""pause"nil)(define-abbrevfortran-mode-abbrev-table";p""print"nil)(define-abbrevfortran-mode-abbrev-table";rc""record"nil)(define-abbrevfortran-mode-abbrev-table";re""real"nil)(define-abbrevfortran-mode-abbrev-table";r""read"nil)(define-abbrevfortran-mode-abbrev-table";rt""return"nil)(define-abbrevfortran-mode-abbrev-table";rw""rewind"nil)(define-abbrevfortran-mode-abbrev-table";s""stop"nil)(define-abbrevfortran-mode-abbrev-table";sa""save"nil)(define-abbrevfortran-mode-abbrev-table";st""structure"nil)(define-abbrevfortran-mode-abbrev-table";sc""static"nil)(define-abbrevfortran-mode-abbrev-table";su""subroutine"nil)(define-abbrevfortran-mode-abbrev-table";tr"".true."nil)(define-abbrevfortran-mode-abbrev-table";ty""type"nil)(define-abbrevfortran-mode-abbrev-table";vo""volatile"nil)(define-abbrevfortran-mode-abbrev-table";w""write"nil)(define-abbrevfortran-mode-abbrev-table";wh""where"nil)(setqabbrevs-changedac)));;;###autoload(defunfortran-mode()"Major mode for editing Fortran code.\\[fortran-indent-line] indents the current Fortran line correctly. DO statements must not share a common CONTINUE.Type ;? or ;\\[help-command] to display a list of built-in\ abbrevs for Fortran keywords.Key definitions:\\{fortran-mode-map}Variables controlling indentation style and extra features: comment-start Normally nil in Fortran mode. If you want to use comments starting with `!', set this to the string \"!\". fortran-do-indent Extra indentation within do blocks. (default 3) fortran-if-indent Extra indentation within if blocks. (default 3) fortran-structure-indent Extra indentation within structure, union, map and interface blocks. (default 3) fortran-continuation-indent Extra indentation applied to continuation statements. (default 5) fortran-comment-line-extra-indent Amount of extra indentation for text within full-line comments. (default 0) fortran-comment-indent-style nil means don't change indentation of text in full-line comments, fixed means indent that text at `fortran-comment-line-extra-indent' beyond the value of `fortran-minimum-statement-indent-fixed' (for fixed format continuation style) or `fortran-minimum-statement-indent-tab' (for TAB format continuation style). relative means indent at `fortran-comment-line-extra-indent' beyond the indentation for a line of code. (default 'fixed) fortran-comment-indent-char Single-character string to be inserted instead of space for full-line comment indentation. (default \" \") fortran-minimum-statement-indent-fixed Minimum indentation for Fortran statements in fixed format mode. (def.6) fortran-minimum-statement-indent-tab Minimum indentation for Fortran statements in TAB format mode. (default 9) fortran-line-number-indent Maximum indentation for line numbers. A line number will get less than this much indentation if necessary to avoid reaching column 5. (default 1) fortran-check-all-num-for-matching-do Non-nil causes all numbered lines to be treated as possible \"continue\" statements. (default nil) fortran-blink-matching-if Non-nil causes \\[fortran-indent-line] on an ENDIF statement to blink on matching IF. Also, from an ENDDO statement, blink on matching DO [WHILE] statement. (default nil) fortran-continuation-string Single-character string to be inserted in column 5 of a continuation line. (default \"$\") fortran-comment-region String inserted by \\[fortran-comment-region] at start of each line in region. (default \"c$$$\") fortran-electric-line-number Non-nil causes line number digits to be moved to the correct column as typed. (default t) fortran-break-before-delimiters Non-nil causes `fortran-fill' breaks lines before delimiters. (default t) fortran-startup-message Set to nil to inhibit message first time Fortran mode is used.Turning on Fortran mode calls the value of the variable `fortran-mode-hook'with no args, if that value is non-nil."(interactive)(kill-all-local-variables)(iffortran-startup-message(message"Emacs Fortran mode %s. Bugs to %s"fortran-mode-versionbug-fortran-mode))(setqfortran-startup-messagenil)(setqlocal-abbrev-tablefortran-mode-abbrev-table)(set-syntax-tablefortran-mode-syntax-table);; Font Lock mode support. (Removed for XEmacs);; (make-local-variable 'font-lock-defaults);; (setq font-lock-defaults '((fortran-font-lock-keywords;; fortran-font-lock-keywords-1;; fortran-font-lock-keywords-2;; fortran-font-lock-keywords-3);; t t ((?/ . "$/"))))(make-local-variable'fortran-break-before-delimiters)(setqfortran-break-before-delimiterst)(make-local-variable'indent-line-function)(setqindent-line-function'fortran-indent-line)(make-local-variable'comment-indent-function)(setqcomment-indent-function'fortran-comment-hook)(make-local-variable'comment-line-start-skip)(setqcomment-line-start-skip"^[Cc*]\\(\\([^ \t\n]\\)\\2\\2*\\)?[ \t]*\\|^#.*")(make-local-variable'comment-line-start)(setqcomment-line-start"c")(make-local-variable'comment-start-skip)(setqcomment-start-skip"![ \t]*")(make-local-variable'comment-start)(setqcomment-startnil)(make-local-variable'require-final-newline)(setqrequire-final-newlinet)(make-local-variable'abbrev-all-caps)(setqabbrev-all-capst)(make-local-variable'indent-tabs-mode)(setqindent-tabs-modenil);;;(setq abbrev-mode t) ; ?? (abbrev-mode 1) instead??(setqfill-column72); Already local?(use-local-mapfortran-mode-map)(setqmode-name"Fortran")(setqmajor-mode'fortran-mode);;;(make-local-variable 'fortran-tab-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)(make-local-variable'fortran-tab-mode-string)(setqfortran-tab-mode-string" TAB-format")(setqindent-tabs-mode(fortran-analyze-file-format))(run-hooks'fortran-mode-hook))(defunfortran-comment-hook()(save-excursion(skip-chars-backward" \t")(max(+1(current-column))comment-column)))(defunfortran-indent-comment()"Align or create comment on current line.Existing comments of all types are recognized and aligned.If the line has no comment, a side-by-side comment is inserted and alignedif the value of comment-start is not nil.Otherwise, a separate-line comment is inserted, on this lineor on a new line inserted before this line if this line is not blank."(interactive)(beginning-of-line);; Recognize existing comments of either kind.(cond((looking-atcomment-line-start-skip)(fortran-indent-line))((fortran-find-comment-start-skip); catches any inline comment and; leaves point after comment-start-skip(ifcomment-start-skip(progn(goto-char(match-beginning0))(if(not(=(current-column)(fortran-comment-hook)))(progn(delete-horizontal-space)(indent-to(fortran-comment-hook)))))(end-of-line))); otherwise goto end of line or sth else?;; No existing comment.;; If side-by-side comments are defined, insert one,;; unless line is now blank.((andcomment-start(not(looking-at"^[ \t]*$")))(end-of-line)(delete-horizontal-space)(indent-to(fortran-comment-hook))(insertcomment-start));; Else insert separate-line comment, making a new line if nec.(t(if(looking-at"^[ \t]*$")(delete-horizontal-space)(beginning-of-line)(insert"\n")(forward-char-1))(insertcomment-line-start)(insert-char(if(stringpfortran-comment-indent-char)(areffortran-comment-indent-char0)fortran-comment-indent-char)(-(calculate-fortran-indent)(current-column))))))(defunfortran-comment-region(beg-regionend-regionarg)"Comments every line in the region.Puts fortran-comment-region at the beginning of every line in the region. BEG-REGION and END-REGION are args which specify the region boundaries. With non-nil ARG, uncomments the region."(interactive"*r\nP")(let((end-region-mark(make-marker))(save-point(point-marker)))(set-markerend-region-markend-region)(goto-charbeg-region)(beginning-of-line)(if(notarg);comment the region(progn(insertfortran-comment-region)(while(and(=(forward-line1)0)(<(point)end-region-mark))(insertfortran-comment-region)))(let((com(regexp-quotefortran-comment-region)));uncomment the region(if(looking-atcom)(delete-region(point)(match-end0)))(while(and(=(forward-line1)0)(<(point)end-region-mark))(if(looking-atcom)(delete-region(point)(match-end0))))))(goto-charsave-point)(set-markerend-region-marknil)(set-markersave-pointnil)))(defunfortran-abbrev-start()"Typing ;\\[help-command] or ;? lists all the Fortran abbrevs. Any other key combination is executed normally."(interactive);; XEmacs change(let(ec)(insertlast-command-char)(setqe(next-command-event)c(event-to-charactere));; insert char if not equal to `?'(if(or(=c??)(eqchelp-char))(fortran-abbrev-help)(setqunread-command-events(liste)))))(defunfortran-abbrev-help()"List the currently defined abbrevs in Fortran mode."(interactive)(message"Listing abbrev table...")(display-buffer(fortran-prepare-abbrev-list-buffer))(message"Listing abbrev table...done"))(defunfortran-prepare-abbrev-list-buffer()(save-excursion(set-buffer(get-buffer-create"*Abbrevs*"))(erase-buffer)(insert-abbrev-table-description'fortran-mode-abbrev-tablet)(goto-char(point-min))(set-buffer-modified-pnil)(edit-abbrevs-mode))(get-buffer-create"*Abbrevs*"))(defunfortran-column-ruler()"Inserts a column ruler momentarily above current line, till next keystroke.The ruler is defined by the value of `fortran-column-ruler-fixed' when in fixedformat mode, and `fortran-column-ruler-tab' when in TAB format mode.The key typed is executed unless it is SPC."(interactive)(momentary-string-display(ifindent-tabs-modefortran-column-ruler-tabfortran-column-ruler-fixed)(save-excursion(beginning-of-line)(if(eq(window-start(selected-window))(window-point(selected-window)))(progn(forward-line)(point))(point)))nil"Type SPC or any command to erase ruler."))(defunfortran-window-create()"Makes the window 72 columns wide.See also `fortran-window-create-momentarily'."(interactive)(condition-caseerror(progn(let((window-min-width2))(if(<(window-width)(frame-width))(enlarge-window-horizontally(-(frame-width)(window-width)1)))(split-window-horizontally73)(other-window1)(switch-to-buffer" fortran-window-extra"t)(select-window(previous-window))))(error(message"No room for Fortran window.")'error)))(defunfortran-window-create-momentarily(&optionalarg)"Momentarily makes the window 72 columns wide.Optional ARG non-nil and non-unity disables the momentary feature.See also `fortran-window-create'."(interactive"p")(if(or(notarg)(=arg1))(save-window-excursion(if(not(equal(fortran-window-create)'error))(progn(message"Type SPC to continue editing.");; XEmacs change(let((char(next-command-event)))(or(equal(event-to-characterchar)?)(setqunread-command-events(listchar)))))))(fortran-window-create)))(defunfortran-split-line()"Break line at point and insert continuation marker and alignment."(interactive)(delete-horizontal-space)(if(save-excursion(beginning-of-line)(looking-atcomment-line-start-skip))(insert"\n"comment-line-start" ")(ifindent-tabs-mode(progn(insert"\n\t")(insert-char(fortran-numerical-continuation-char)1))(insert"\n "fortran-continuation-string)));Space after \n important(fortran-indent-line));when the cont string is C, c or *.(defunfortran-numerical-continuation-char()"Return a digit for tab-digit style of continuation lines.If, previous line is a tab-digit continuation line, returns that digitplus one. Otherwise return 1. Zero not allowed."(save-excursion(forward-line-1)(if(looking-at"\t[1-9]")(+?1(%(-(char-after(+(point)1))?0)9))?1)))(defundelete-horizontal-regexp(chars)"Delete all characters in CHARS around point.CHARS is like the inside of a [...] in a regular expressionexcept that ] is never special and \ quotes ^, - or \."(interactive"*s")(skip-chars-backwardchars)(delete-region(point)(progn(skip-chars-forwardchars)(point))))(defunfortran-electric-line-number(arg)"Self insert, but if part of a Fortran line number indent it automatically.Auto-indent does not happen if a numeric arg is used."(interactive"P")(if(orarg(notfortran-electric-line-number))(ifarg(self-insert-command(prefix-numeric-valuearg))(self-insert-command1))(if(or(and(=5(current-column))(save-excursion(beginning-of-line)(looking-at" ")));In col 5 with only spaces to left.(and(=(ifindent-tabs-modefortran-minimum-statement-indent-tabfortran-minimum-statement-indent-fixed)(current-column))(save-excursion(beginning-of-line)(looking-at"\t"));In col 8 with a single tab to the left.(not(or(eqlast-command'fortran-indent-line)(eqlast-command'fortran-indent-new-line))))(save-excursion(re-search-backward"[^ \t0-9]"(save-excursion(beginning-of-line)(point))t));not a line number(looking-at"[0-9]");within a line number)(self-insert-command(prefix-numeric-valuearg))(skip-chars-backward" \t")(insertlast-command-char)(fortran-indent-line))))(defunbeginning-of-fortran-subprogram()"Moves point to the beginning of the current Fortran subprogram."(interactive)(let((case-fold-searcht))(beginning-of-line-1)(re-search-backward"^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]"nil'move)(if(looking-at"^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]")(forward-line1))))(defunend-of-fortran-subprogram()"Moves point to the end of the current Fortran subprogram."(interactive)(let((case-fold-searcht))(beginning-of-line2)(re-search-forward"^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]"nil'move)(goto-char(match-beginning0))(forward-line1)))(defunmark-fortran-subprogram()"Put mark at end of Fortran subprogram, point at beginning. The marks are pushed."(interactive)(end-of-fortran-subprogram)(push-mark(point))(beginning-of-fortran-subprogram))(defunfortran-previous-statement()"Moves point to beginning of the previous Fortran statement.Returns `first-statement' if that statement is the firstnon-comment Fortran statement in the file, and nil otherwise."(interactive)(let(not-first-statementcontinue-test)(beginning-of-line)(setqcontinue-test(and(not(looking-atcomment-line-start-skip))(or(looking-at(concat"[ \t]*"(regexp-quotefortran-continuation-string)))(or(looking-at" [^ 0\n]")(looking-at"\t[1-9]")))))(while(and(setqnot-first-statement(=(forward-line-1)0))(or(looking-atcomment-line-start-skip)(looking-at"[ \t]*$")(looking-at" [^ 0\n]")(looking-at"\t[1-9]")(looking-at(concat"[ \t]*"comment-start-skip)))))(cond((andcontinue-test(notnot-first-statement))(message"Incomplete continuation statement."))(continue-test(fortran-previous-statement))((notnot-first-statement)'first-statement))))(defunfortran-next-statement()"Moves point to beginning of the next Fortran statement.Returns `last-statement' if that statement is the lastnon-comment Fortran statement in the file, and nil otherwise."(interactive)(let(not-last-statement)(beginning-of-line)(while(and(setqnot-last-statement(and(=(forward-line1)0)(not(eobp))))(or(looking-atcomment-line-start-skip)(looking-at"[ \t]*$")(looking-at" [^ 0\n]")(looking-at"\t[1-9]")(looking-at(concat"[ \t]*"comment-start-skip)))))(if(notnot-last-statement)'last-statement)))(defunfortran-blink-matching-if();; From a Fortran ENDIF statement, blink the matching IF statement.(let((top-of-window(window-start))matching-if(endif-point(point))message)(if(save-excursion(beginning-of-line)(skip-chars-forward" \t0-9")(looking-at"end[ \t]*if\\b"))(progn(if(not(setqmatching-if(fortran-beginning-if)))(setqmessage"No matching if.")(if(<matching-iftop-of-window)(save-excursion(goto-charmatching-if)(beginning-of-line)(setqmessage(concat"Matches "(buffer-substring(point)(progn(end-of-line)(point))))))))(ifmessage(message"%s"message)(goto-charmatching-if)(sit-for1)(goto-charendif-point))))))(defunfortran-blink-matching-do();; From a Fortran ENDDO statement, blink on the matching DO or DO WHILE;; statement. This is basically copied from fortran-blink-matching-if.(let((top-of-window(window-start))matching-do(enddo-point(point))message)(if(save-excursion(beginning-of-line)(skip-chars-forward" \t0-9")(looking-at"end[ \t]*do\\b"))(progn(if(not(setqmatching-do(fortran-beginning-do)))(setqmessage"No matching do.")(if(<matching-dotop-of-window)(save-excursion(goto-charmatching-do)(beginning-of-line)(setqmessage(concat"Matches "(buffer-substring(point)(progn(end-of-line)(point))))))))(ifmessage(message"%s"message)(goto-charmatching-do)(sit-for1)(goto-charenddo-point))))))(defunfortran-mark-do()"Put mark at end of Fortran DO [WHILE]-ENDDO construct, point at beginning. The marks are pushed."(interactive)(let(enddo-pointdo-point)(if(setqenddo-point(fortran-end-do))(if(not(setqdo-point(fortran-beginning-do)))(message"No matching do.");; Set mark, move point.(goto-charenddo-point)(push-mark)(goto-chardo-point)))))(defunfortran-end-do();; Search forward for first unmatched ENDDO. Return point or nil.(if(save-excursion(beginning-of-line)(skip-chars-forward" \t0-9")(looking-at"end[ \t]*do\\b"));; Sitting on one.(match-beginning0);; Search for one.(save-excursion(let((count1))(while(and(not(=count0))(not(eq(fortran-next-statement)'last-statement));; Keep local to subprogram(not(looking-at"^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]")))(skip-chars-forward" \t0-9")(cond((looking-at"end[ \t]*do\\b")(setqcount(-count1)))((looking-at"do[ \t]+[^0-9]")(setqcount(+count1)))))(and(=count0);; All pairs accounted for.(point))))))(defunfortran-beginning-do();; Search backwards for first unmatched DO [WHILE]. Return point or nil.(if(save-excursion(beginning-of-line)(skip-chars-forward" \t0-9")(looking-at"do[ \t]+"));; Sitting on one.(match-beginning0);; Search for one.(save-excursion(let((count1))(while(and(not(=count0))(not(eq(fortran-previous-statement)'first-statement));; Keep local to subprogram(not(looking-at"^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]")))(skip-chars-forward" \t0-9")(cond((looking-at"do[ \t]+[^0-9]")(setqcount(-count1)))((looking-at"end[ \t]*do\\b")(setqcount(+count1)))))(and(=count0);; All pairs accounted for.(point))))))(defunfortran-mark-if()"Put mark at end of Fortran IF-ENDIF construct, point at beginning.The marks are pushed."(interactive)(let(endif-pointif-point)(if(setqendif-point(fortran-end-if))(if(not(setqif-point(fortran-beginning-if)))(message"No matching if.");; Set mark, move point.(goto-charendif-point)(push-mark)(goto-charif-point)))))(defunfortran-end-if();; Search forwards for first unmatched ENDIF. Return point or nil.(if(save-excursion(beginning-of-line)(skip-chars-forward" \t0-9")(looking-at"end[ \t]*if\\b"));; Sitting on one.(match-beginning0);; Search for one. The point has been already been moved to first;; letter on line but this should not cause troubles.(save-excursion(let((count1))(while(and(not(=count0))(not(eq(fortran-next-statement)'last-statement));; Keep local to subprogram.(not(looking-at"^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]")))(skip-chars-forward" \t0-9")(cond((looking-at"end[ \t]*if\\b")(setqcount(-count1)))((looking-at"if[ \t]*(")(save-excursion(if(or(looking-at".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")(let(then-test); Multi-line if-then.(while(and(=(forward-line1)0);; Search forward for then.(or(looking-at" [^ 0\n]")(looking-at"\t[1-9]"))(not(setqthen-test(looking-at".*then\\b[ \t]*[^ \t(=a-z0-9]")))))then-test))(setqcount(+count1)))))))(and(=count0);; All pairs accounted for.(point))))))(defunfortran-beginning-if();; Search backwards for first unmatched IF-THEN. Return point or nil.(if(save-excursion;; May be sitting on multi-line if-then statement, first move to;; beginning of current statement. Note: `fortran-previous-statement';; moves to previous statement *unless* current statement is first;; one. Only move forward if not first-statement.(if(not(eq(fortran-previous-statement)'first-statement))(fortran-next-statement))(skip-chars-forward" \t0-9")(and(looking-at"if[ \t]*(")(save-match-data(or(looking-at".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]");; Multi-line if-then.(let(then-test)(while(and(=(forward-line1)0);; Search forward for then.(or(looking-at" [^ 0\n]")(looking-at"\t[1-9]"))(not(setqthen-test(looking-at".*then\\b[ \t]*[^ \t(=a-z0-9]")))))then-test)))));; Sitting on one.(match-beginning0);; Search for one.(save-excursion(let((count1))(while(and(not(=count0))(not(eq(fortran-previous-statement)'first-statement));; Keep local to subprogram.(not(looking-at"^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]")))(skip-chars-forward" \t0-9")(cond((looking-at"if[ \t]*(")(save-excursion(if(or(looking-at".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")(let(then-test); Multi-line if-then.(while(and(=(forward-line1)0);; Search forward for then.(or(looking-at" [^ 0\n]")(looking-at"\t[1-9]"))(not(setqthen-test(looking-at".*then\\b[ \t]*[^ \t(=a-z0-9]")))))then-test))(setqcount(-count1)))))((looking-at"end[ \t]*if\\b")(setqcount(+count1)))))(and(=count0);; All pairs accounted for.(point))))))(defunfortran-indent-line()"Indents current Fortran line based on its contents and on previous lines."(interactive)(let((cfi(calculate-fortran-indent)))(save-excursion(beginning-of-line)(if(or(not(=cfi(fortran-current-line-indentation)))(and(re-search-forward"^[ \t]*[0-9]+"(+(point)4)t)(not(fortran-line-number-indented-correctly-p))))(fortran-indent-to-columncfi)(beginning-of-line)(if(and(not(looking-atcomment-line-start-skip))(fortran-find-comment-start-skip))(fortran-indent-comment))));; Never leave point in left margin.(if(<(current-column)cfi)(move-to-columncfi))(if(andauto-fill-function(>(save-excursion(end-of-line)(current-column))fill-column))(save-excursion(end-of-line)(fortran-fill)))(iffortran-blink-matching-if(progn(fortran-blink-matching-if)(fortran-blink-matching-do)))))(defunfortran-indent-new-line()"Reindent the current Fortran line, insert a newline and indent the newline.An abbrev before point is expanded if `abbrev-mode' is non-nil."(interactive)(ifabbrev-mode(expand-abbrev))(save-excursion(beginning-of-line)(skip-chars-forward" \t")(if(or(looking-at"[0-9]");Reindent only where it is most(looking-at"end");likely to be necessary(looking-at"else")(looking-at(regexp-quotefortran-continuation-string)))(fortran-indent-line)))(newline)(fortran-indent-line))(defunfortran-indent-subprogram()"Properly indents the Fortran subprogram which contains point."(interactive)(save-excursion(mark-fortran-subprogram)(message"Indenting subprogram...")(indent-region(point)(markt)nil)); XEmacs change(message"Indenting subprogram...done."))(defuncalculate-fortran-indent()"Calculates the Fortran indent column based on previous lines."(let(icolfirst-statement(case-fold-searcht)(fortran-minimum-statement-indent(ifindent-tabs-modefortran-minimum-statement-indent-tabfortran-minimum-statement-indent-fixed)))(save-excursion(setqfirst-statement(fortran-previous-statement))(iffirst-statement(setqicolfortran-minimum-statement-indent)(progn(if(=(point)(point-min))(setqicolfortran-minimum-statement-indent)(setqicol(fortran-current-line-indentation)))(skip-chars-forward" \t0-9")(cond((looking-at"if[ \t]*(")(if(or(looking-at".*)[ \t]*then\\b[ \t]*[^ \t_$(=a-z0-9]")(let(then-test);multi-line if-then(while(and(=(forward-line1)0);;search forward for then(or(looking-at" [^ 0\n]")(looking-at"\t[1-9]"))(not(setqthen-test(looking-at".*then\\b[ \t]\*[^ \t_$(=a-z0-9]")))))then-test))(setqicol(+icolfortran-if-indent))))((looking-at"\\(else\\|elseif\\)\\b")(setqicol(+icolfortran-if-indent)))((looking-at"select[ \t]*case[ \t](.*)\\b")(setqicol(+icolfortran-if-indent)))((looking-at"case[ \t]*(.*)[ \t]*\n")(setqicol(+icolfortran-if-indent)))((looking-at"case[ \t]*default\\b")(setqicol(+icolfortran-if-indent)))((looking-at"\\(otherwise\\|else[ \t]*where\\)\\b")(setqicol(+icolfortran-if-indent)))((looking-at"where[ \t]*(.*)[ \t]*\n")(setqicol(+icolfortran-if-indent)))((looking-at"do\\b")(setqicol(+icolfortran-do-indent)))((looking-at"\\(structure\\|union\\|map\\|interface\\)\\b[ \t]*[^ \t=(a-z]")(setqicol(+icolfortran-structure-indent)))((looking-at"end\\b[ \t]*[^ \t=(a-z]");; Previous END resets indent to minimum(setqicolfortran-minimum-statement-indent))))))(save-excursion(beginning-of-line)(cond((looking-at"[ \t]*$"))((looking-atcomment-line-start-skip)(cond((eqfortran-comment-indent-style'relative)(setqicol(+icolfortran-comment-line-extra-indent)))((eqfortran-comment-indent-style'fixed)(setqicol(+fortran-minimum-statement-indentfortran-comment-line-extra-indent))))(setqfortran-minimum-statement-indent0))((or(looking-at(concat"[ \t]*"(regexp-quotefortran-continuation-string)))(looking-at" [^ 0\n]")(looking-at"\t[1-9]"))(setqicol(+icolfortran-continuation-indent)))((looking-at"[ \t]*#"); Check for cpp directive.(setqfortran-minimum-statement-indent0icol0))(first-statement)((andfortran-check-all-num-for-matching-do(looking-at"[ \t]*[0-9]+")(fortran-check-for-matching-do))(setqicol(-icolfortran-do-indent)))(t(skip-chars-forward" \t0-9")(cond((looking-at"end[ \t]*if\\b")(setqicol(-icolfortran-if-indent)))((looking-at"\\(else\\|elseif\\)\\b")(setqicol(-icolfortran-if-indent)))((looking-at"case[ \t]*(.*)[ \t]*\n")(setqicol(-icolfortran-if-indent)))((looking-at"case[ \t]*default\\b")(setqicol(-icolfortran-if-indent)))((looking-at"\\(otherwise\\|else[ \t]*where\\)\\b")(setqicol(-icolfortran-if-indent)))((looking-at"end[ \t]*where\\b")(setqicol(-icolfortran-if-indent)))((and(looking-at"continue\\b")(fortran-check-for-matching-do))(setqicol(-icolfortran-do-indent)))((looking-at"end[ \t]*do\\b")(setqicol(-icolfortran-do-indent)))((looking-at"end[ \t]*\\\(structure\\|union\\|map\\|interface\\)\\b[ \t]*[^ \t=(a-z]")(setqicol(-icolfortran-structure-indent)))((looking-at"end[ \t]*select\\b[ \t]*[^ \t=(a-z]")(setqicol(-icolfortran-if-indent)))((and(looking-at"end\\b[ \t]*[^ \t=(a-z]")(not(=icolfortran-minimum-statement-indent)))(message"Warning: `end' not in column %d. Probably\ an unclosed block."fortran-minimum-statement-indent))))))(maxfortran-minimum-statement-indenticol)))(defunfortran-current-line-indentation()"Indentation of current line, ignoring Fortran line number or continuation.This is the column position of the first non-whitespace characteraside from the line number and/or column 5/8 line-continuation character.For comment lines, returns indentation of the firstnon-indentation text within the comment."(save-excursion(beginning-of-line)(cond((looking-atcomment-line-start-skip)(goto-char(match-end0))(skip-chars-forward(if(stringpfortran-comment-indent-char)fortran-comment-indent-char(char-to-stringfortran-comment-indent-char))))((or(looking-at" [^ 0\n]")(looking-at"\t[1-9]"))(goto-char(match-end0)))(t;; Move past line number.(skip-chars-forward"[ \t0-9]");From Uli));; Move past whitespace.(skip-chars-forward" \t")(current-column)))(defunfortran-indent-to-column(col)"Indents current line with spaces to column COL.notes: 1) A non-zero/non-blank character in column 5 indicates a continuation line, and this continuation character is retained on indentation; 2) If `fortran-continuation-string' is the first non-whitespace character, this is a continuation line; 3) A non-continuation line which has a number as the first non-whitespace character is a numbered line. 4) A TAB followed by a digit indicates a continuation line."(save-excursion(beginning-of-line)(if(looking-atcomment-line-start-skip)(iffortran-comment-indent-style(let((char(if(stringpfortran-comment-indent-char)(areffortran-comment-indent-char0)fortran-comment-indent-char)))(goto-char(match-end0))(delete-horizontal-regexp(concat" \t"(char-to-stringchar)))(insert-charchar(-col(current-column)))))(if(looking-at"\t[1-9]")(ifindent-tabs-mode(goto-char(match-end0))(delete-char2)(insert" ")(insertfortran-continuation-string))(if(looking-at" [^ 0\n]")(ifindent-tabs-mode(progn(delete-char6)(insert"\t")(insert-char(fortran-numerical-continuation-char)1))(forward-char6))(delete-horizontal-space);; Put line number in columns 0-4;; or put continuation character in column 5.(cond((eobp))((looking-at(regexp-quotefortran-continuation-string))(ifindent-tabs-mode(progn(indent-to(ifindent-tabs-modefortran-minimum-statement-indent-tabfortran-minimum-statement-indent-fixed))(delete-char1)(insert-char(fortran-numerical-continuation-char)1))(indent-to5)(forward-char1)))((looking-at"[0-9]+")(let((extra-space(-5(-(match-end0)(point)))))(if(<extra-space0)(message"Warning: line number exceeds 5-digit limit.")(indent-to(minfortran-line-number-indentextra-space))))(skip-chars-forward"0-9")))));; Point is now after any continuation character or line number.;; Put body of statement where specified.(delete-horizontal-space)(indent-tocol);; Indent any comment following code on the same line.(if(andcomment-start-skip(fortran-find-comment-start-skip))(progn(goto-char(match-beginning0))(if(not(=(current-column)(fortran-comment-hook)))(progn(delete-horizontal-space)(indent-to(fortran-comment-hook)))))))))(defunfortran-line-number-indented-correctly-p()"Return t if current line's line number is correctly indented.Do not call if there is no line number."(save-excursion(beginning-of-line)(skip-chars-forward" \t")(and(<=(current-column)fortran-line-number-indent)(or(=(current-column)fortran-line-number-indent)(progn(skip-chars-forward"0-9")(=(current-column)5))))))(defunfortran-check-for-matching-do()"When called from a numbered statement, returns t if matching DO is found.Otherwise return a nil."(let(charnum(case-fold-searcht))(save-excursion(beginning-of-line)(if(looking-at"[ \t]*[0-9]+")(progn(skip-chars-forward" \t")(skip-chars-forward"0");skip past leading zeros(setqcharnum(buffer-substring(point)(progn(skip-chars-forward"0-9")(point))))(beginning-of-line)(and(re-search-backward(concat"\\(^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]\\)\\|""\\(^[ \t0-9]*do[ \t]*0*"charnum"\\b\\)\\|""\\(^[ \t]*0*"charnum"\\b\\)")nilt)(looking-at(concat"^[ \t0-9]*do[ \t]*0*"charnum))))))))(defunfortran-find-comment-start-skip()"Move to past `comment-start-skip' found on current line.Return t if `comment-start-skip' found, nil if not.";;; In order to move point only if comment-start-skip is found,;;; this one uses a lot of save-excursions. Note that re-search-forward;;; moves point even if comment-start-skip is inside a string-constant.;;; Some code expects certain values for match-beginning and end(interactive)(if(save-excursion(re-search-forwardcomment-start-skip(save-excursion(end-of-line)(point))t))(let((save-match-beginning(match-beginning0))(save-match-end(match-end0)))(if(fortran-is-in-string-p(match-beginning0))(save-excursion(goto-charsave-match-end)(fortran-find-comment-start-skip)); recurse for rest of line(goto-charsave-match-beginning)(re-search-forwardcomment-start-skip(save-excursion(end-of-line)(point))t)(goto-char(match-end0))t))nil));;;From: simon@gnu (Simon Marshall);;; Find the next ! not in a string.(defunfortran-match-!-comment(limit)(let(found)(while(and(setqfound(search-forward"!"limitt))(fortran-is-in-string-p(point))))(if(notfound)nil;; Cheaper than `looking-at' "!.*".(store-match-data(list(1-(point))(progn(end-of-line)(min(point)limit))))t)));; The above function is about 10% faster than the below...;;(defun fortran-match-!-comment (limit);; (let (found);; (while (and (setq found (re-search-forward "!.*" limit t));; (fortran-is-in-string-p (match-beginning 0))));; found));;;From: ralf@up3aud1.gwdg.de (Ralf Fassel);;; Test if TAB format continuation lines work.(defunfortran-is-in-string-p(where)"Return non-nil if POS (a buffer position) is inside a Fortran string,nil else."(save-excursion(goto-charwhere)(cond((bolp)nil); bol is never inside a string((save-excursion; comment lines too(beginning-of-line)(looking-atcomment-line-start-skip))nil)(t(let(;; ok, serious now. Init some local vars:(parse-state'(0nilnilnilnilnil0))(quoted-comment-start(ifcomment-start(regexp-quotecomment-start)))(not-donet)parse-limitend-of-line);; move to start of current statement(fortran-next-statement)(fortran-previous-statement);; now parse up to WHERE(whilenot-done(if(or;; skip to next line if:;; - comment line?(looking-atcomment-line-start-skip);; - at end of line?(eolp);; - not in a string and after comment-start?(and(not(nth3parse-state))comment-start(equalcomment-start(char-to-string(preceding-char)))));; get around a bug in forward-line in versions <= 18.57(if(or(>(forward-line1)0)(eobp))(setqnot-donenil));; else:;; if we are at beginning of code line, skip any;; whitespace, labels and tab continuation markers.(if(bolp)(skip-chars-forward" \t0-9"));; if we are in column <= 5 now, check for continuation char(cond((=5(current-column))(forward-char1))((and(<(current-column)5)(equalfortran-continuation-string(char-to-string(following-char)))(forward-char1))));; find out parse-limit from here(setqend-of-line(save-excursion(end-of-line)(point)))(setqparse-limit(minwhereend-of-line));; parse max up to comment-start, if non-nil and in current line(ifcomment-start(save-excursion(if(re-search-forwardquoted-comment-startend-of-linet)(setqparse-limit(min(point)parse-limit)))));; now parse if still in limits(if(<(point)where)(setqparse-state(parse-partial-sexp(point)parse-limitnilnilparse-state))(setqnot-donenil))));; result is(nth3parse-state))))))(defunfortran-auto-fill-mode(arg)"Toggle fortran-auto-fill mode.With ARG, turn `fortran-auto-fill' mode on iff ARG is positive.In `fortran-auto-fill' mode, inserting a space at a column beyond `fill-column'automatically breaks the line at a previous space."(interactive"P")(prog1(setqauto-fill-function(if(if(nullarg)(notauto-fill-function)(>(prefix-numeric-valuearg)0))'fortran-do-auto-fillnil))(redraw-modeline)))(defunfortran-do-auto-fill()(if(>(current-column)fill-column)(fortran-indent-line)))(defunfortran-fill()(interactive)(let*((opoint(point))(bol(save-excursion(beginning-of-line)(point)))(eol(save-excursion(end-of-line)(point)))(bos(mineol(+bol(fortran-current-line-indentation))))(quote(save-excursion(goto-charbol)(if(looking-atcomment-line-start-skip)nil; OK to break quotes on comment lines.(move-to-columnfill-column)(cond((fortran-is-in-string-p(point))(save-excursion(re-search-backward"[^']'[^']"bolt)(iffortran-break-before-delimiters(point)(1+(point)))))(tnil)))));;;; decide where to split the line. If a position for a quoted;; string was found above then use that, else break the line;; before the last delimiter.;; Delimiters are whitespace, commas, and operators.;; Will break before a pair of *'s.;;(fill-point(orquote(save-excursion(move-to-column(1+fill-column))(skip-chars-backward"^ \t\n,'+-/*=)";;; (if fortran-break-before-delimiters;;; "^ \t\n,'+-/*=" "^ \t\n,'+-/*=)"))(if(<=(point)(1+bos))(progn(move-to-column(1+fill-column));;;what is this doing???(if(not(re-search-forward"[\t\n,'+-/*)=]"eolt))(goto-charbol))))(if(bolp)(re-search-forward"[ \t]"opointt)(forward-char-1)(if(looking-at"'")(forward-char1)(skip-chars-backward" \t\*")))(iffortran-break-before-delimiters(point)(1+(point)))))));; if we are in an in-line comment, don't break unless the;; line of code is longer than it should be. Otherwise;; break the line at the column computed above.;;;; Need to use fortran-find-comment-start-skip to make sure that quoted !'s;; don't prevent a break.(if(not(or(save-excursion(if(and(re-search-backwardcomment-start-skipbolt)(not(fortran-is-in-string-p(point))))(progn(skip-chars-backward" \t")(<(current-column)(1+fill-column)))))(save-excursion(goto-charfill-point)(bolp))))(if(>(save-excursion(goto-charfill-point)(current-column))(1+fill-column))(progn(goto-charfill-point)(fortran-break-line))(save-excursion(if(>(save-excursion(goto-charfill-point)(current-column))(+(calculate-fortran-indent)fortran-continuation-indent))(progn(goto-charfill-point)(fortran-break-line))))))))(defunfortran-break-line()(let((bol(save-excursion(beginning-of-line)(point)))(eol(save-excursion(end-of-line)(point)))(comment-stringnil))(save-excursion(if(andcomment-start-skip(fortran-find-comment-start-skip))(progn(re-search-backwardcomment-start-skipbolt)(setqcomment-string(buffer-substring(point)eol))(delete-region(point)eol))));;; Forward line 1 really needs to go to next non white line(if(save-excursion(forward-line1)(or(looking-at" [^ 0\n]")(looking-at"\t[1-9]")))(progn(end-of-line)(delete-region(point)(match-end0))(delete-horizontal-space)(fortran-fill))(fortran-split-line))(ifcomment-string(save-excursion(goto-charbol)(end-of-line)(delete-horizontal-space)(indent-to(fortran-comment-hook))(insertcomment-string)))))(defunfortran-analyze-file-format()"Returns nil if fixed format is used, t if TAB formatting is used.Use `fortran-tab-mode-default' if no non-comment statements are found in thefile before the end or the first `fortran-analyze-depth' lines."(let((i0))(save-excursion(goto-char(point-min))(setqi0)(while(not(or(eobp)(looking-at"\t")(looking-at" ")(>ifortran-analyze-depth)))(forward-line)(setqi(1+i)))(cond((looking-at"\t")t)((looking-at" ")nil)(fortran-tab-mode-defaultt)(tnil)))))(or(assq'fortran-tab-mode-stringminor-mode-alist)(setqminor-mode-alist(cons'(fortran-tab-mode-string(indent-tabs-modefortran-tab-mode-string))minor-mode-alist)))(provide'fortran);;; fortran.el ends here