Download
(defgroup cobol nil
"Major mode for editing COBOL source files in Emacs.
While in cobol-mode use C-h m for a description of the mode's features."
:prefix 'cobol-
:group 'languages)
(defvar cobol-skeleton-map
(let ((map (make-sparse-keymap)))
(define-key map [?i] 'cobol-if-skel)
map)
"Keymap for `cobol-mode'.")
(defvar cobol-mode-map
(let ((map (make-sparse-keymap)))
(define-key map [tab] 'indent-according-to-mode)
(define-key map [?\C-c ?\C-c] 'column-marker-here)
(define-key map [?\C-c ?\C-f] 'auto-fill-mode)
(define-key map [?\C-c ?\C-r] 'popup-ruler)
(define-key map [?\C-c ?\C-s] cobol-skeleton-map)
(define-key map [?\C-c return] 'comment-indent-new-line)
map)
"Keymap for `cobol-mode'.")
(defvar cobol-mode-syntax-table
(let ((st (make-syntax-table)))
(modify-syntax-entry ?\n " " st)
(modify-syntax-entry ?\! "." st)
(modify-syntax-entry ?\" "." st)
(modify-syntax-entry ?\# "w" st)
(modify-syntax-entry ?\$ "w" st)
(modify-syntax-entry ?\% "'" st)
(modify-syntax-entry ?\& "'" st)
(modify-syntax-entry ?\' "." st)
(modify-syntax-entry ?\( "()" st)
(modify-syntax-entry ?\) ")(" st)
(modify-syntax-entry ?\* "." st)
(modify-syntax-entry ?\+ "." st)
(modify-syntax-entry ?\, "." st)
(modify-syntax-entry ?\- "w" st)
(modify-syntax-entry ?\. "." st)
(modify-syntax-entry ?\/ "." st)
(modify-syntax-entry ?\: "." st)
(modify-syntax-entry ?\; "." st)
(modify-syntax-entry ?\< "." st)
(modify-syntax-entry ?\= "." st)
(modify-syntax-entry ?\> "." st)
(modify-syntax-entry ?\? "." st)
(modify-syntax-entry ?\@ "." st)
(modify-syntax-entry ?\[ "(]" st)
(modify-syntax-entry ?\\ "." st)
(modify-syntax-entry ?\] ")[" st)
(modify-syntax-entry ?^ "w" st)
(modify-syntax-entry ?\_ "w" st)
(modify-syntax-entry ?\{ "(}" st)
(modify-syntax-entry ?\| "." st)
(modify-syntax-entry ?\} "){" st)
st)
"Syntax table for `cobol-mode'.")
(defvar cobol-keywords-directives
'( "ANSI" "BLANK" "NOBLANK"
"CALL-SHARED" "CANCEL" "NOCANCEL"
"CHECK" "CODE" "NOCODE"
"COLUMNS" "COMPACT" "NOCOMPACT"
"COMPILE" "CONSULT" "NOCONSULT"
"CROSSREF" "NOCROSSREF" "DIAGNOSE-74"
"NODIAGNOSE-74" "DIAGNOSE-85" "NODIAGNOSE-85"
"DIAGNOSEALL" "NODIAGNOSEALL" "ENDIF"
"ENDUNIT" "ENV" "ERRORFILE"
"ERRORS" "FIPS" "NOFIPS"
"FMAP" "HEADING" "HEAP"
"HIGHPIN" "HIGHREQUESTERS" "ICODE"
"NOICODE" "IF" "IFNOT"
"INNERLIST" "NOINNERLIST" "INSPECT"
"NOINSPECT" "LARGEDATA" "LD"
"LESS-CODE" "LIBRARY" "LINES"
"LIST" "NOLIST" "LMAP"
"NOLMAP" "MAIN" "MAP"
"NOMAP" "NLD" "NONSTOP"
"NON-SHARED" "OPTIMIZE" "PERFORM-TRACE"
"PORT" "NOPORT" "RESETTOG"
"RUNNABLE" "RUNNAMED" "SAVE"
"SAVEABEND" "NOSAVEABEND" "SEARCH"
"NOSEARCH" "SECTION" "SETTOG"
"SHARED" "SHOWCOPY" "NOSHOWCOPY"
"SHOWFILE" "NOSHOWFILE" "SOURCE"
"SQL" "NOSQL" "SQLMEM"
"SUBSET" "SUBTYPE" "SUPPRESS"
"NOSUPPRESS" "SYMBOLS" "NOSYMBOLS"
"SYNTAX" "TANDEM" "TRAP2"
"NOTRAP2" "TRAP2-74" "NOTRAP2-74"
"UL" "WARN" "NOWARN"
)
"List of COBOL compiler directives.
Used to create the `font-lock-keywords' table.")
(defvar cobol-keywords-statements
'( "ACCEPT" "ADD" "ADD TO"
"ADD GIVING" "ADD CORRESPONDING" "ALTER"
"CALL" "CANCEL" "CHECKPOINT"
"CLOSE" "COMPUTE" "CONTINUE"
"COPY" "DELETE" "DISPLAY"
"DIVIDE" "DIVIDE INTO" "DIVIDE GIVING"
"DIVIDE GIVING REMAINDER" "ENTER"
"ENTER COBOL" "EVALUATE" "EXIT"
"GO TO" "IF" "INITIALIZE"
"INSPECT" "INSPECT TALLYING" "INSPECT REPLACING"
"INSPECT TALLYING REPLACING" "INSPECT CONVERTING"
"LOCKFILE" "MERGE" "MOVE"
"MOVE TO" "MOVE CORRESPONDING" "MULTIPLY"
"MULTIPLY BY" "MULTIPLY GIVING" "OPEN"
"PERFORM" "PERFORM TIMES" "PERFORM UNTIL"
"PERFORM VARYING" "READ" "RELEASE"
"REPLACE" "RETURN" "REWRITE"
"SEARCH" "SEARCH VARYING" "SEARCH ALL"
"SET" "SET TO" "SET UP"
"SET DOWN" "SORT" "START"
"STARTBACKUP" "STOP" "STRING"
"SUBTRACT" "SUBTRACT FROM" "SUBTRACT GIVING"
"SUBTRACT CORRESPONDING" "UNLOCKFILE"
"UNLOCKRECORD" "UNSTRING" "USE"
"USE DEBUGGING" "USE AFTER EXCEPTION" "WRITE"
)
"List of COBOL statement keywords.
Used to create the `font-lock-keywords' table.")
(defvar cobol-keywords-deprecated
'( )
"List of COBOL keywords and Builtin functions now deprecated.
Used to create the `font-lock-keywords' table")
(defvar cobol-keywords-reserved
'( "ACCEPT" "ACCESS" "ADD"
"ADDRESS" "ADVANCING" "AFTER"
"ALL" "ALPHABET" "ALPHABETIC"
"ALPHABETIC-LOWER" "ALPHABETIC-UPPER" "ALPHANUMERIC"
"ALPHANUMERIC-EDITED" "ALSO" "ALTER"
"ALTERNATE" "AND" "ANY"
"APPROXIMATE" "AREA" "AREAS"
"ASCENDING" "ASSIGN" "AT"
"AUTHOR" "BEFORE" "BINARY"
"BLANK" "BLOCK" "BOTTOM"
"BY" "CALL" "CANCEL"
"CD" "CF" "CH"
"CHARACTER" "CHARACTERS" "CHARACTER-SET"
"CHECKPOINT" "CLASS" "CLOCK-UNITS"
"CLOSE" "COBOL" "CODE"
"CODE-SET" "COLLATING" "COLUMN"
"COMMA" "COMMON" "COMMUNICATION"
"COMP" "COMP-3" "COMP-5"
"COMPUTATIONAL" "COMPUTATIONAL-3" "COMPUTATIONAL-5"
"COMPUTE" "CONFIGURATION" "CONTAINS"
"CONTENT" "CONTINUE" "CONTROL"
"CONTROLS" "CONVERTING" "COPY"
"CORR" "CORRESPONDING" "COUNT"
"CURRENCY" "DATA" "DATE"
"DATE-COMPILED" "DATE-WRITTEN" "DAY"
"DAY-OF-WEEK" "DE" "DEBUG-CONTENTS"
"DEBUG-ITEM" "DEBUG-LINE" "DEBUG-SUB-2"
"DEBUG-SUB-3" "DEBUGGING" "DECIMAL-POINT"
"DECLARATIVES" "DEBUG-NAME" "DEBUG-SUB-1"
"DELETE" "DELIMITED" "DELIMITER"
"DEPENDING" "DESCENDING" "DESTINATION"
"DETAIL" "DISABLE" "DISPLAY"
"DIVIDE" "DIVISION" "DOWN"
"DUPLICATES" "DYNAMIC" "EGI"
"ELSE" "EMI" "ENABLE"
"END" "END-ADD" "END-COMPUTE"
"END-DELETE" "END-DIVIDE" "END-EVALUATE"
"END-IF" "END-MULTIPLY" "END-OF-PAGE"
"END-PERFORM" "END-READ" "END-RECEIVE"
"END-RETURN" "END-REWRITE" "END-SEARCH"
"END-START" "END-STRING" "END-SUBTRACT"
"END-UNSTRING" "END-WRITE" "ENTER"
"EOP" "EQUAL" "ERROR"
"ESI" "EVALUATE" "EVERY"
"EXCEPTION" "EXCLUSIVE" "EXIT"
"EXTEND" "EXTENDED-STORAGE" "EXTERNAL"
"FALSE" "FD" "FILE"
"FILE-CONTROL" "FILLER" "FINAL"
"FIRST" "FOOTING" "FOR"
"FROM" "FUNCTION" "GENERATE"
"GENERIC" "GIVING" "GLOBAL"
"GO" "GREATER" "GROUP"
"GUARDIAN-ERR" "HEADING" "HIGH-VALUE"
"HIGH-VALUES" "I-O" "I-O-CONTROL"
"IDENTIFICATION" "IF" "IN"
"INDEX" "INDEXED" "INDICATE"
"INITIAL" "INITIALIZE" "INITIATE"
"INPUT" "INPUT-OUTPUT" "INSPECT"
"INSTALLATION" "INTO" "INVALID"
"IS" "JUST" "JUSTIFIED"
"KEY" "LABEL" "LAST"
"LEADING" "LEFT" "LENGTH"
"LESS" "LIMIT" "LIMITS"
"LINAGE" "LINAGE-COUNTER" "LINE"
"LINE-COUNTER" "LINKAGE" "LOCK"
"LOCKFILE" "LOW-VALUE" "LOW-VALUES"
"MEMORY" "MERGE" "MESSAGE"
"MODE" "MODULES" "MOVE"
"MULTIPLE" "MULTIPLY" "NATIVE"
"NEGATIVE" "NEXT" "NO"
"NOT" "NULL" "NULLS"
"NUMBER" "NUMERIC" "NUMERIC-EDITED"
"OBJECT-COMPUTER" "OCCURS" "OF"
"OFF" "OMITTED" "ON"
"OPEN" "OPTIONAL" "OR"
"ORDER" "ORGANIZATION" "OTHER"
"OUTPUT" "OVERFLOW" "PACKED-DECIMAL"
"PADDING" "PAGE" "PAGE-COUNTER"
"PERFORM" "PF" "PH"
"PIC" "PICTURE" "PLUS"
"POINTER" "POSITION" "POSITIVE"
"PRINTING" "PROCEDURE" "PROCEDURES"
"PROCEED" "PROGRAM" "PROGRAM-ID"
"PROGRAM-STATUS" "PROGRAM-STATUS-1" "PROGRAM-STATUS-2"
"PROMPT" "PROTECTED" "PURGE"
"QUEUE" "QUOTE" "QUOTES"
"RANDOM" "RD" "READ"
"RECEIVE" "RECEIVE-CONTROL" "RECORD"
"RECORDS" "REDEFINES" "REEL"
"REFERENCE" "REFERENCES" "RELATIVE"
"RELEASE" "REMAINDER" "REMOVAL"
"RENAMES" "REPLACE" "REPLACING"
"REPLY" "REPORT" "REPORTING"
"REPORTS" "RERUN" "RESERVE"
"RESET" "RETURN" "REVERSED"
"REWIND" "REWRITE" "RF"
"RH" "RIGHT" "ROUNDED"
"RUN" "SAME" "SD"
"SEARCH" "SECTION" "SECURITY"
"SEGMENT" "SEGMENT-LIMIT" "SELECT"
"SEND" "SENTENCE" "SEPARATE"
"SEQUENCE" "SEQUENTIAL" "SET"
"SHARED" "SIGN" "SIZE"
"SORT" "SORT-MERGE" "SOURCE"
"SOURCE-COMPUTER" "SPACE" "SPACES"
"SPECIAL-NAMES" "STANDARD" "STANDARD-1"
"STANDARD-2" "START" "STARTBACKUP"
"STATUS" "STOP" "STRING"
"SUB-QUEUE-1" "SUB-QUEUE-2" "SUB-QUEUE-3"
"SUBTRACT" "SUM" "SUPPRESS"
"SYMBOLIC" "SYNC" "SYNCDEPTH"
"SYNCHRONIZED" "TABLE" "TAL"
"TALLYING" "TAPE" "TERMINAL"
"TERMINATE" "TEST" "TEXT"
"THAN" "THEN" "THROUGH"
"THRU" "TIME" "TIMES"
"TO" "TOP" "TRAILING"
"TRUE" "TYPE" "UNIT"
"UNLOCK" "UNLOCKFILE" "UNLOCKRECORD"
"UNSTRING" "UNTIL" "UP"
"UPON" "USAGE" "USE"
"USING" "VALUE" "VALUES"
"VARYING" "WHEN" "WITH"
"WORDS" "WORKING-STORAGE" "WRITE"
"ZERO" "ZEROES"
)
"List of COBOL keywords reserved only in certain language contexts.
Used to create the `font-lock-keywords' table.")
(defvar cobol-keywords-std-fcns
'( "ACOS" "ANNUITY" "ASIN"
"ATAN" "CHAR" "COS"
"CURRENT-DATE" "DATE-OF-INTEGER" "DAY-OF-INTEGER"
"FACTORIAL" "INTEGER" "INTEGER-OF-DATE"
"INTEGER-OF-DAY" "INTEGER-PART" "LENGTH"
"LOG" "LOG10" "LOWER-CASE"
"MAX" "MEAN" "MEDIAN"
"MIDRANGE" "MIN" "MOD"
"NUMVAL" "NUMVAL-C" "ORD"
"ORD-MAX" "ORD-MIN" "PRESENT-VALUE"
"RANDOM" "RANGE" "REM"
"REVERSE" "SIN" "SQRT"
"STANDARD-DEVIATION" "SUM" "TAN"
"UPPER-CASE" "VARIANCE" "WHEN-COMPILED"
)
"List of COBOL standard functions.
Used to create the `font-lock-keywords' table.")
(defvar cobol-keywords-privileged
'( )
"List of COBOL privileged functions.
Used to create the `font-lock-keywords' table.")
(defvar cobol-keywords-builtin
'( "#IN" "#OUT"
"#TERM" "#TEMP"
"#DYNAMIC" "COBOL85^ARMTRAP"
"COBOL85^COMPLETION" "COBOL_COMPLETION_"
"COBOL_CONTROL_" "COBOL_GETENV_"
"COBOL_PUTENV_" "COBOL85^RETURN^SORT^ERRORS"
"COBOL_RETURN_SORT_ERRORS_" "COBOL85^REWIND^SEQUENTIAL"
"COBOL_REWIND_SEQUENTIAL_" "COBOL85^SET^SORT^PARAM^TEXT"
"COBOL_SET_SORT_PARAM_TEXT_" "COBOL85^SET^SORT^PARAM^VALUE"
"COBOL_SET_SORT_PARAM_VALUE_" "COBOL_SET_MAX_RECORD_"
"COBOL_SETMODE_" "COBOL85^SPECIAL^OPEN"
"COBOL_SPECIAL_OPEN_" "COBOLASSIGN"
"COBOL_ASSIGN_" "COBOLFILEINFO"
"COBOL_FILE_INFO_" "COBOLSPOOLOPEN"
"CREATEPROCESS" "ALTERPARAMTEXT"
"CHECKLOGICALNAME" "CHECKMESSAGE"
"DELETEASSIGN" "DELETEPARAM"
"DELETESTARTUP" "GETASSIGNTEXT"
"GETASSIGNVALUE" "GETBACKUPCPU"
"GETPARAMTEXT" "GETSTARTUPTEXT"
"PUTASSIGNTEXT" "PUTASSIGNVALUE"
"PUTPARAMTEXT" "PUTSTARTUPTEXT"
)
"List of COBOL privileged builtin functions.
Used to create the `font-lock-keywords' table.")
(defvar cobol-keyword-fcn-names-regexp
"^.\\{6\\}\\s-\\{1,4\\}\\(\\w+\\)\\s-*\\."
"Defines a regexp that finds the names of paragraphs.
Used to create the `font-lock-keywords' table.")
(defvar cobol-keyword-section-names-regexp
"^.\\{6\\}\\s-\\{1,4\\}\\(\\w+\\s-+\\(division\\|section\\)\\)\\."
"Defines a regexp that finds the names of paragraphs.
Used to create the `font-lock-keywords' table.")
(defcustom cobol-begin-matches-semi t
"If not nil, the b of begin matches the semicolon in end
Otherwise it matches the d of end. It always matches the d when no
:type 'boolean
:group 'cobol)
(defcustom cobol-font-lock-always t
"`cobol-mode' makes sure `font-lock-mode' is on for cobol-mode buffers.
Some things don't work if it's off so insuring it's on is the default."
:type 'boolean
:group 'cobol)
(defcustom cobol-primecode-warning t
"Highlight instances of ]a ]d and ]e in column 1 with a warning face.
This alerts you that submission of this file to RMS/PrimeCode will fail
due to invalid contents. nil disables this warning."
:type 'boolean
:group 'cobol)
(defun cobol-keyword-anywhere-regexp ( word-list )
"Returns a regexp that finds any of the words in WORD-LIST.
But only if the keyword is surrounded by non-word chars."
(concat "\\<"(regexp-opt word-list t)"\\W"))
(defvar cobol-keyword-on-directive-line-regexp () "Internal use only.")
(defun cobol-keyword-on-directive-line-regexp ( word-list )
"Returns a function to find WORD-LIST only if line starts with ?"
(setq cobol-keyword-on-directive-line-regexp
(concat "\\b"(regexp-opt word-list t)"\\b"))
'cobol-font-lock-directive-line)
(defvar cobol-amid-font-lock-excursion nil
)
(make-variable-buffer-local 'cobol-amid-font-lock-excursion)
(defun cobol-font-lock-directive-line ( search-limit )
(let ((looking t))
(while
(and looking
(or cobol-amid-font-lock-excursion
(when (re-search-forward "^\\?.+\n" search-limit t)
(setq cobol-amid-font-lock-excursion (point))
(goto-char (match-beginning 0)))))
(if (re-search-forward cobol-keyword-on-directive-line-regexp
cobol-amid-font-lock-excursion t)
(setq looking nil)
(goto-char cobol-amid-font-lock-excursion)
(setq cobol-amid-font-lock-excursion nil)))
(not looking)))
(defcustom cobol-comment-sequence-regexp nil
"regexp matching lines whose sequence/labels to mark as comments.
An empty string marks all, nil marks none."
:type `(choice :tag "Sequence handling"
(regexp :tag "Regexp")
(const :tag "All" "^")
(const :tag "None" nil))
:group 'cobol)
(defvar cobol-find-syntactic--state ()
"Used by `cobol-find-syntactic-keywords' to find multiple syntactic
elements which all must be anchored to the beginning of a line.
nil = no search done yet on this line.
0 = check for compiler directive line
1 = sequence/label area checked. look at body.
2 = body not a comment, any trailing comment marked, check for strings
marker = terminated string found check for more.")
(make-variable-buffer-local 'cobol-find-syntactic--state)
(defun cobol-find-syntactic-keywords ( search-limit )
"Used by `font-lock-syntactic-keywords' to find comments and strings.
Returns t if either a comment or string is found, nil if neither is found.
match-data 1&2 are set for comments, 3&4 are set for a normal string, 5&6 are
set for eol-terminated strings. Where the match pair mark the start character
and end character respectively. Point is moved to the next line during this
function only after the last search completes for the current line. A state
machine, controlled by `cobol-find-syntactic--state' sequences the searches."
(let ((found nil)
(save (point)))
(while (and (< (point) search-limit)
(not found))
(cond
((or (null cobol-find-syntactic--state)
(equal cobol-find-syntactic--state (make-marker)))
(if (looking-at "^\\(\\?\\|......\\?\\)")
(forward-line 1)
(setq cobol-find-syntactic--state 0)
)
)
((= 0 cobol-find-syntactic--state)
(when (and cobol-comment-sequence-regexp
(looking-at "^.\\(?:.\\|\n\\)")
(looking-at cobol-comment-sequence-regexp)
(looking-at ".\\{1,6\\}"))
(setq found t)
(let* ((start (car (match-data)))
(mid1 (copy-marker (1+ start)))
(end (cadr (match-data)))
mid2)
(if (/= end mid1)
(setq mid2 (copy-marker (1- end)))
(setq mid2 end
end (copy-marker (1+ end))))
(set-match-data
(list start end
start mid1
mid2 end))))
(setq cobol-find-syntactic--state 1)
)
((= 1 cobol-find-syntactic--state)
(when (looking-at "^......\\(?:*\\|/\\)")
(looking-at "......\\(.\\).*\\(\n\\|'\\)")
(forward-line 1)
(setq cobol-find-syntactic--state ()
found t))
(when cobol-find-syntactic--state
(setq cobol-find-syntactic--state 2
found (looking-at "^.\\{72\\}\\(.\\).*\\(\n\\)"))))
((= 2 cobol-find-syntactic--state)
(if (looking-at "^......[-d D][^\"\n]\\{0,64\\}\"")
(let* ((open-quote (list (copy-marker (1- (match-end 0)))
(copy-marker (match-end 0))))
(leol (copy-marker (min (+ 72 (point))
(line-end-position))))
close-quote)
(setq found t)
(goto-char (cadr open-quote))
(if (search-forward "\"" leol t)
(progn
(setq close-quote (match-data)
cobol-find-syntactic--state (cadr close-quote))
(beginning-of-line)
(set-match-data
`(,(car open-quote) ,(cadr close-quote)
nil nil nil nil
,@open-quote ,@close-quote))
)
(forward-line 1)
(setq close-quote (list (copy-marker (1- leol)) leol)
cobol-find-syntactic--state ())
(set-match-data
`(,(car open-quote) ,(cadr close-quote)
nil nil nil nil
nil nil nil nil
,@open-quote ,@close-quote))
))
(forward-line 1)
(setq cobol-find-syntactic--state ())))
((markerp cobol-find-syntactic--state)
(let ((leol (copy-marker (min (+ 72 (point))
(line-end-position))))
open-quote close-quote)
(goto-char cobol-find-syntactic--state)
(if (search-forward "\"" leol t)
(progn
(setq open-quote (match-data)
found t)
(if (search-forward "\"" leol t)
(progn
(beginning-of-line)
(setq close-quote (match-data)
cobol-find-syntactic--state (cadr close-quote))
(set-match-data
`(,(car open-quote) ,(cadr close-quote)
nil nil nil nil
,@open-quote ,@close-quote))
)
(forward-line 1)
(setq close-quote (list (copy-marker (1- leol)) leol)
cobol-find-syntactic--state ())
(set-match-data
`(,(car open-quote) ,(cadr close-quote)
nil nil nil nil
nil nil nil nil
,@open-quote ,@close-quote))
))
(forward-line 1)
(setq cobol-find-syntactic--state ()))
))))
(and (> (point) search-limit) (goto-char search-limit))
(prog1 found (or found (goto-char save)))))
(defvar cobol-static-font-lock-keywords
`(("^[^\n?].\\{5\\}\\([^ ?Dd*/-]\\)" 1 font-lock-warning-face)
("^[^\n?].\\{5\\}\\([?Dd-]\\)" 1 font-lock-builtin-face)
(,(cobol-keyword-on-directive-line-regexp cobol-keywords-directives)
1 font-lock-builtin-face)
(,(cobol-keyword-anywhere-regexp cobol-keywords-builtin)
1 font-lock-builtin-face)
(,(cobol-keyword-anywhere-regexp (append cobol-keywords-std-fcns
cobol-keywords-statements))
1 font-lock-keyword-face)
(,(cobol-keyword-anywhere-regexp (append cobol-keywords-deprecated
cobol-keywords-privileged))
1 font-lock-warning-face)
(,cobol-keyword-section-names-regexp 1 font-lock-type-face)
(,cobol-keyword-fcn-names-regexp 1 font-lock-function-name-face)))
(defvar cobol-font-lock-keywords ())
(defun cobol-build-font-lock-keywords ()
"Creates `font-lock-keywords' based on current customize settings."
(append cobol-static-font-lock-keywords
`(,(when cobol-primecode-warning
'("^\\][ade]" . font-lock-warning-face)))))
(defvar cobol-font-lock-syntactic-keywords
`(
(cobol-find-syntactic-keywords (1 "<" t t) (2 ">" t t)
(3 "\"" t t) (4 "\"" t t)
(5 "|" t t) (6 "|" t t))
)
"A list of regexp's or functions. Used to add syntax-table properties to
characters that can't be set by the syntax-table alone.")
(defun cobol-setup-font-lock ()
"Sets up the buffer local value for font-lock-defaults and optionally
turns on font-lock-mode"
(set (make-local-variable 'parse-sexp-lookup-properties) t)
(set (make-local-variable 'parse-sexp-ignore-comments) t)
(set (make-local-variable 'cobol-font-lock-keywords)
(cobol-build-font-lock-keywords))
(setq cobol-find-syntactic--state ())
(setq font-lock-defaults
'(cobol-font-lock-keywords
nil
t
nil
nil
(font-lock-syntactic-keywords . cobol-font-lock-syntactic-keywords )))
(when cobol-font-lock-always (font-lock-mode t)))
(defcustom cobol-column-marker-1 7
"*Turns on column-marker-1 (which see) at the specified column.
Use of this feature requires the column-marker.el package be loaded or on
the search list."
:type 'integer
:group 'cobol)
(make-variable-buffer-local 'cobol-column-marker-1)
(defcustom cobol-column-marker-2 73
"*Turns on column-marker-2 (which see) at the specified column.
Use of this feature requires the column-marker.el package."
:type 'integer
:group 'cobol)
(make-variable-buffer-local 'cobol-column-marker-2)
(defun cobol-setup-column-markers ()
"Turns on column markers if configured and available.
See `cobol-column-marker-1' and `cobol-column-marker-2' "
(if (condition-case ()
(progn (require 'column-marker) nil)
(error t))
(if (not (and (zerop cobol-column-marker-1)
(zerop cobol-column-marker-2)))
(message "column markers are configured but %s"
" column-marker feature not available."))
(setq indent-tabs-mode nil)
(column-marker-1 cobol-column-marker-1)
(column-marker-2 cobol-column-marker-2)))
(defcustom cobol-imenu-menubar t
"If not nil, `imenu-add-to-menubar' is called during mode initialization.
This adds a [Menu name] menu to your menu bar. By default the menu contains a
list of all procedures, sections and pages in your program. You can go
directly to any item on the menu by selecting it. You can control what
appears on this menu by modifying `cobol-imenu-expression-alist'. You must turn
imenu on for this to work. See `imenu' in the Emacs reference manual for more
information. Personally I recommend customizing `imenu-sort-function' to sort
by name."
:type '(choice :tag "Menu Name"
(string :tag "Menu Name")
(const "Index")
(const :tag "None" nil))
:group 'cobol)
(defvar cobol-imenu-syntax-alist ()
"Overrides to `cobol-mode-syntax-table' used during `imenu-generic-expression' search."
)
(defcustom cobol-imenu-expression-alist
`((nil ,cobol-keyword-fcn-names-regexp 1)
(nil ,cobol-keyword-section-names-regexp 1)
("?Sections" "^\\?section\\s-+\\(\\w+\\)\\b" 1)
("?Pages" "^\\?page\\s-+\"\\s-*\\(.+?\\)\"" 1)
)
"A list of regular expressions for creating an `imenu' index.
Each element has the form (list-name regexp num).
Where list-name is the name of the submenu under which items matching regexp
are found and num is the expression index defining the label to use for the
submenu entry. When num = 0 the entire matching regexp text appears under
list-name. When list-name is nil the matching entries appear in the root
imenu list rather than in a submenu. See also `cobol-imenu-menubar'"
:type '(repeat (list (choice :tag "Submenu Name" string (const nil))
regexp (integer :tag "Regexp index")))
:group 'cobol)
(defcustom cobol-display-which-function t
"This option turns `which-func' on for all `cobol-mode' buffers.
`which-func' is a package that causes the current function, section or
page to be displayed on the mode line. `which-func' uses `imenu'. Also
see `cobol-imenu-expression-alist' for more information."
:type 'boolean
:group 'cobol)
(defun cobol-setup-imenu ()
"Installs cobol-imenu-generic-expression & cobol-imenu-syntax-alist."
(setq imenu-generic-expression cobol-imenu-expression-alist)
(setq imenu-syntax-alist cobol-imenu-syntax-alist)
(setq imenu-case-fold-search t)
(when cobol-imenu-menubar
(if (condition-case ()
(progn (require 'imenu) t)
(error nil))
(imenu-add-menubar-index)
(message "cobol-imenu-menubar is set but imenu feature not available.")))
(when cobol-display-which-function
(if (condition-case ()
(progn (require 'which-func) t)
(error nil))
(which-function-mode t)
(message "cobol-display-which-function set but which-func not available"))))
(defcustom cobol-restrict-auto-fill t
"When not nil a buffer local value for `fill-nobreak-predicate' is created
to prevent code from being accidentally realligned. The function uses syntax
highlighting to detect comments so `font-lock-mode' must be enabled to work."
:type 'boolean
:group 'cobol)
(defun cobol-setup-adaptive-fill ()
"Sets up the COBOL-MODE adaptive-fill variables."
(set (make-local-variable 'fill-individual-varying-indent)
nil)
(set (make-local-variable 'auto-fill-inhibit-regexp)
"\\s-*[^*/]")
(set (make-local-variable 'comment-use-syntax)
t)
(set (make-local-variable 'comment-start)
"*")
(set (make-local-variable 'comment-end)
"")
(set (make-local-variable 'comment-padding)
" ")
(set (make-local-variable 'comment-start-skip)
"\\(\\s<\\|*\\)\\s-*")
(set (make-local-variable 'sentence-end)
"\\()
(set (make-local-variable 'paragraph-start)
"^\\([\n\f]\\|\\s-*begin\\b\\)")
(set (make-local-variable 'paragraph-separate)
"\\(^\n\\|\\s-end\\([)
(set (make-local-variable 'adaptive-fill-regexp)
"^\\s-*\\(!\\|--\\)[~%^&()_#[*|)
(set (make-local-variable 'adaptive-fill-first-line-regexp)
adaptive-fill-regexp)
(when cobol-restrict-auto-fill
(fset (make-local-variable 'fill-nobreak-predicate)
(lambda ()
(not (eq (get-text-property (point) 'face)
'font-lock-comment-face))))))
(defun cobol-setup-indent ()
"Sets default indentation or sets up cobol-indent if available."
(if (condition-case ()
(progn (require 'cobol-indent) t)
(error nil))
(set (make-local-variable 'indent-line-function) 'cobol-indent-line)
(set (make-local-variable 'indent-line-function) 'indent-relative-maybe)))
(defcustom cobol-keywords-case 'upper
"*Indicates if keywords in skeletons should be all UPPER CASE, all lower
case or Camel Case (First Char Upper & Rest Lower)."
:type '(choice (const :tag "ALL CAPS" 'upper)
(const :tag "all small" 'lower)
(const :tag "Camel Case" 'camel)
(const :tag "DON'T Change" ()))
:group 'cobol)
(defun cobol-setup-skel ()
"Configures skeleton.el functions for the COBOL environemnt."
(set (make-local-variable 'skeleton-transformation) 'cobol-skel-transform)
(setq skeleton-further-elements '((abbrev-mode nil))))
(defun cobol-skel-transform ( element )
"Called by `skeleton-insert'. Gives ELEMENT `cobol-keywords-case' capitalization."
(if (stringp element)
(cond
((eq cobol-keywords-case 'upper) (upcase element))
((eq cobol-keywords-case 'lower) (downcase element))
((eq cobol-keywords-case 'camel) (capitalize element))
( t element ))
element))
(defun cobol-set-line-syntax ()
"Applies font-lock-syntactic-keywords to current line.
Used to set properties necessary for proper indentation."
(if font-lock-mode
(save-excursion
(font-lock-fontify-syntactic-keywords-region
(line-beginning-position) (line-end-position))
()
)))
(define-skeleton cobol-if-skel
"This is an example skeleton."
nil >
"IF (" _ ") THEN" > \n
"BEGIN" (cobol-set-line-syntax) > \n
_ & > \n
"END\;" (cobol-set-line-syntax) > \n)
(defcustom cobol-abbrev-mode t
"Sets the default value for `abbrev-mode' upon entry into `cobol-mode'."
:type 'boolean
:group 'cobol)
(defvar cobol-mode-abbrev-table-list
'(("$i" "" cobol-if-skel))
"List of pre-defined `cobol-mode' abbrev definitions.
Use \\[list-abbrevs] to see all defined abbrevs.")
(defvar cobol-mode-abbrev-table)
(defun cobol-setup-abbrevs ()
"Installs the `cobol-mode-abbrev-table' as `local-abbrev-table'"
(define-abbrev-table 'cobol-mode-abbrev-table cobol-mode-abbrev-table-list)
(setq local-abbrev-table cobol-mode-abbrev-table)
(setq skeleton-further-elements '((abbrev-mode nil)))
(abbrev-mode cobol-abbrev-mode)
)
(defun cobol-mode ()
"A major mode for editing COBOL language program source files.
Customization options are available via
\\[customize-group] <ret> COBOL <ret>
This mode provides COBOL specific support for such packages as:
`font-lock-mode' `show-paren-mode' `imenu'
`which-function' `skeleton-insert' `auto-fill-mode'
`adaptive-fill-mode' `filladapt-mode' `abbrev-mode'
** Note ** Many things won't work correctly if `font-lock-mode' is off.
cobol-mode also implements the following \\[execute-extended-command] ... commands
`cobol-mode' Activates this mode for the current buffer
`cobol-begin-end-skel' Inserts a Begin/End skeleton
`cobol-case-skel' Inserts a labeled case statement skeleton
`cobol-if-skel' Inserts an if/then statement skeleton
`cobol-if-else-skel' Inserts an if/then/else statement skeleton
`cobol-proc-skel' Example of a skeleton procedure
\\{cobol-mode-map}
Use \\[describe-bindings] to see ALL key bindings.
Some settings I like:
Turn on `skeleton-pair-insert-maybe' for (), [] and \"\"
Turn on `imenu' and set `imenu-sort-function' to imenu--sort-by-name
Turn on `recentf-mode'. You might need `recentf-auto-cleanup' = 'never
Set `column-marker-1' to 79 so you can tell what TEDIT users can't see.
Load `popup-ruler' for a TEDIT F9 type ruler on steroids.
I find `transient-mark-mode' totally indespensible.
CUA mode has some really great rectangle functions."
(interactive)
(kill-all-local-variables)
(set (make-local-variable 'major-mode) 'cobol-mode)
(set (make-local-variable 'mode-name) "COBOL")
(set (make-local-variable 'make-backup-files) nil)
(use-local-map cobol-mode-map)
(set-syntax-table cobol-mode-syntax-table)
(cobol-setup-font-lock)
(cobol-setup-adaptive-fill)
(cobol-setup-abbrevs)
(cobol-setup-imenu)
(cobol-setup-indent)
(cobol-setup-skel)
(cobol-setup-column-markers)
(show-paren-mode 1)
(run-hooks 'cobol-mode-hook))
(provide 'cobol-mode)