Annotation of OpenXM_contrib/gmp/mpn/lisp/gmpasm-mode.el, Revision 1.1
1.1 ! maekawa 1: ;;; gmpasm-mode.el -- GNU MP asm and m4 editing mode.
! 2:
! 3:
! 4: ;; Copyright (C) 1999, 2000 Free Software Foundation, Inc.
! 5: ;;
! 6: ;; This file is part of the GNU MP Library.
! 7: ;;
! 8: ;; The GNU MP Library is free software; you can redistribute it and/or modify
! 9: ;; it under the terms of the GNU Lesser General Public License as published by
! 10: ;; the Free Software Foundation; either version 2.1 of the License, or (at your
! 11: ;; option) any later version.
! 12: ;;
! 13: ;; The GNU MP Library is distributed in the hope that it will be useful, but
! 14: ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 15: ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
! 16: ;; License for more details.
! 17: ;;
! 18: ;; You should have received a copy of the GNU Lesser General Public License
! 19: ;; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
! 20: ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
! 21: ;; MA 02111-1307, USA.
! 22:
! 23:
! 24: ;;; Commentary:
! 25: ;;
! 26: ;; gmpasm-mode is an editing mode for m4 processed assembler code and m4
! 27: ;; macro files in GMP. It's similar to m4-mode, but has a number of
! 28: ;; settings better suited to GMP.
! 29: ;;
! 30: ;;
! 31: ;; Install
! 32: ;; -------
! 33: ;;
! 34: ;; To make M-x gmpasm-mode available, put gmpasm-mode.el somewhere in the
! 35: ;; load-path and the following in .emacs
! 36: ;;
! 37: ;; (autoload 'gmpasm-mode "gmpasm-mode" nil t)
! 38: ;;
! 39: ;; To use gmpasm-mode automatically on all .asm and .m4 files, put the
! 40: ;; following in .emacs
! 41: ;;
! 42: ;; (add-to-list 'auto-mode-alist '("\\.asm\\'" . gmpasm-mode))
! 43: ;; (add-to-list 'auto-mode-alist '("\\.m4\\'" . gmpasm-mode))
! 44: ;;
! 45: ;; To have gmpasm-mode only on gmp files, try instead something like the
! 46: ;; following, which uses it only in a directory starting with "gmp", or a
! 47: ;; sub-directory of such.
! 48: ;;
! 49: ;; (add-to-list 'auto-mode-alist
! 50: ;; '("/gmp.*/.*\\.\\(asm\\|m4\\)\\'" . gmpasm-mode))
! 51: ;;
! 52: ;; Byte compiling will slightly speed up loading. If you want a docstring
! 53: ;; in the autoload you can use M-x update-file-autoloads if you set it up
! 54: ;; right.
! 55: ;;
! 56: ;;
! 57: ;; Emacsen
! 58: ;; -------
! 59: ;;
! 60: ;; FSF Emacs 20.x - gmpasm-mode is designed for this.
! 61: ;; XEmacs 20.x - seems to work.
! 62: ;;
! 63: ;; FSF Emacs 19.x - should work if replacements for some 20.x-isms are
! 64: ;; available. comment-region with "C" won't really do the right thing
! 65: ;; though.
! 66:
! 67:
! 68: ;;; Code:
! 69:
! 70: (defgroup gmpasm nil
! 71: "GNU MP m4 and asm editing."
! 72: :prefix "gmpasm-"
! 73: :group 'languages)
! 74:
! 75: (defcustom gmpasm-mode-hook nil
! 76: "*Hook called by `gmpasm-mode'."
! 77: :type 'hook
! 78: :group 'gmpasm)
! 79:
! 80: (defcustom gmpasm-comment-start-regexp "[#;!@C]"
! 81: "*Regexp matching possible comment styles.
! 82: See `gmpasm-mode' docstring for how this is used."
! 83: :type 'regexp
! 84: :group 'gmpasm)
! 85:
! 86:
! 87: (defun gmpasm-add-to-list-second (list-var element)
! 88: "(gmpasm-add-to-list-second LIST-VAR ELEMENT)
! 89:
! 90: Add ELEMENT to LIST-VAR as the second element in the list, if it isn't
! 91: already in the list. If LIST-VAR is nil, then ELEMENT is just added as the
! 92: sole element in the list.
! 93:
! 94: This is like `add-to-list', but it puts the new value second in the list.
! 95:
! 96: The first cons cell is copied rather than changed in-place, so references to
! 97: the list elsewhere won't be affected."
! 98:
! 99: (if (member element (symbol-value list-var))
! 100: (symbol-value list-var)
! 101: (set list-var
! 102: (if (symbol-value list-var)
! 103: (cons (car (symbol-value list-var))
! 104: (cons element
! 105: (cdr (symbol-value list-var))))
! 106: (list element)))))
! 107:
! 108:
! 109: (defun gmpasm-delete-from-list (list-var element)
! 110: "(gmpasm-delete-from-list LIST-VAR ELEMENT)
! 111:
! 112: Delete ELEMENT from LIST-VAR, using `delete'.
! 113: This is like `add-to-list', but the element is deleted from the list.
! 114: The list is copied rather than changed in-place, so references to it elsewhere
! 115: won't be affected."
! 116:
! 117: (set list-var (delete element (copy-sequence (symbol-value list-var)))))
! 118:
! 119:
! 120: (defvar gmpasm-mode-map
! 121: (let ((map (make-sparse-keymap)))
! 122:
! 123: ;; assembler and dnl commenting
! 124: (define-key map "\C-c\C-c" 'comment-region)
! 125: (define-key map "\C-c\C-d" 'gmpasm-comment-region-dnl)
! 126:
! 127: ;; kill an M-x compile, since it's not hard to put m4 into an infinite
! 128: ;; loop
! 129: (define-key map "\C-c\C-k" 'kill-compilation)
! 130:
! 131: map)
! 132: "Keymap for `gmpasm-mode'.")
! 133:
! 134:
! 135: (defvar gmpasm-mode-syntax-table
! 136: (let ((table (make-syntax-table)))
! 137: ;; underscore left as a symbol char, like C mode
! 138:
! 139: ;; m4 quotes
! 140: (modify-syntax-entry ?` "('" table)
! 141: (modify-syntax-entry ?' ")`" table)
! 142:
! 143: table)
! 144: "Syntax table used in `gmpasm-mode'.
! 145:
! 146: m4 ignores quote marks in # comments at the top level, but inside quotes #
! 147: isn't special and all quotes are active. There seems no easy way to express
! 148: this in the syntax table, so nothing is done for comments. Usually this is
! 149: best, since it picks up invalid apostrophes in comments inside quotes.")
! 150:
! 151:
! 152: (defvar gmpasm-font-lock-keywords
! 153: (eval-when-compile
! 154: (list
! 155: (cons
! 156: (concat
! 157: "\\b"
! 158: (regexp-opt
! 159: '("deflit" "defreg" "defframe" "defframe_pushl"
! 160: "define_not_for_expansion"
! 161: "ASM_START" "ASM_END" "PROLOGUE" "EPILOGUE"
! 162: "forloop"
! 163: "TEXT" "DATA" "ALIGN" "W32"
! 164: "builtin" "changecom" "changequote" "changeword" "debugfile"
! 165: "debugmode" "decr" "define" "defn" "divert" "divnum" "dumpdef"
! 166: "errprint" "esyscmd" "eval" "__file__" "format" "gnu" "ifdef"
! 167: "ifelse" "include" "incr" "index" "indir" "len" "__line__"
! 168: "m4exit" "m4wrap" "maketemp" "patsubst" "popdef" "pushdef"
! 169: "regexp" "shift" "sinclude" "substr" "syscmd" "sysval"
! 170: "traceoff" "traceon" "translit" "undefine" "undivert" "unix")
! 171: t)
! 172: "\\b") 'font-lock-keyword-face)))
! 173:
! 174: "`font-lock-keywords' for `gmpasm-mode'.
! 175:
! 176: The keywords are m4 builtins and some of the GMP macros used in asm files.
! 177: L and LF don't look good fontified, so they're omitted.
! 178:
! 179: The right assembler comment regexp is added dynamically buffer-local (with
! 180: dnl too).")
! 181:
! 182:
! 183: ;; Initialized if gmpasm-mode finds filladapt loaded.
! 184: (defvar gmpasm-filladapt-token-table nil
! 185: "Filladapt token table used in `gmpasm-mode'.")
! 186: (defvar gmpasm-filladapt-token-match-table nil
! 187: "Filladapt token match table used in `gmpasm-mode'.")
! 188: (defvar gmpasm-filladapt-token-conversion-table nil
! 189: "Filladapt token conversion table used in `gmpasm-mode'.")
! 190:
! 191:
! 192: ;;;###autoload
! 193: (defun gmpasm-mode ()
! 194: "A major mode for editing GNU MP asm and m4 files.
! 195:
! 196: \\{gmpasm-mode-map}
! 197: `comment-start' and `comment-end' are set buffer-local to assembler
! 198: commenting appropriate for the CPU by looking for something matching
! 199: `gmpasm-comment-start-regexp' at the start of a line, or \"#\" is used if
! 200: there's no match (if \"#\" isn't what you want, type in a desired comment
! 201: and do \\[gmpasm-mode] to reinitialize).
! 202:
! 203: `adaptive-fill-regexp' is set buffer-local to the standard regexp with
! 204: `comment-start' and dnl added. If filladapt.el has been loaded it similarly
! 205: gets `comment-start' and dnl added as buffer-local fill prefixes.
! 206:
! 207: Font locking has the m4 builtins, some of the GMP macros, m4 dnl commenting,
! 208: and assembler commenting (based on the `comment-start' determined).
! 209:
! 210: Note that `gmpasm-comment-start-regexp' is only matched as a whole word, so
! 211: the `C' in it is only matched as a whole word, not on something that happens
! 212: to start with `C'. Also it's only the particular `comment-start' determined
! 213: that's added for filling etc, not the whole `gmpasm-comment-start-regexp'.
! 214:
! 215: `gmpasm-mode-hook' is run after initializations are complete.
! 216: "
! 217:
! 218: (interactive)
! 219: (kill-all-local-variables)
! 220: (setq major-mode 'gmpasm-mode
! 221: mode-name "gmpasm")
! 222: (use-local-map gmpasm-mode-map)
! 223: (set-syntax-table gmpasm-mode-syntax-table)
! 224: (setq fill-column 76)
! 225:
! 226: ;; Short instructions might fit with 32, but anything with labels or
! 227: ;; expressions soon needs the comments pushed out to column 40.
! 228: (setq comment-column 40)
! 229:
! 230: ;; Don't want to find out the hard way which dumb assemblers don't like a
! 231: ;; missing final newline.
! 232: (set (make-local-variable 'require-final-newline) t)
! 233:
! 234: ;; The first match of gmpasm-comment-start-regexp at the start of a line
! 235: ;; determines comment-start, or "#" if no match.
! 236: (set (make-local-variable 'comment-start)
! 237: (save-excursion
! 238: (goto-char (point-min))
! 239: (if (re-search-forward
! 240: (concat "^\\(" gmpasm-comment-start-regexp "\\)\\(\\s-\\|$\\)")
! 241: nil t)
! 242: (match-string 1)
! 243: "#")))
! 244: (set (make-local-variable 'comment-end) "")
! 245:
! 246: ;; If comment-start ends in an alphanumeric then \b is used to match it
! 247: ;; only as a separate word. The test is for an alphanumeric rather than
! 248: ;; \w since we might try # or ! as \w characters but without wanting \b.
! 249: (let ((comment-regexp
! 250: (concat (regexp-quote comment-start)
! 251: (if (string-match "[a-zA-Z0-9]\\'" comment-start) "\\b"))))
! 252:
! 253: ;; Whitespace is required before a comment-start so m4 $# doesn't match
! 254: ;; when comment-start is "#".
! 255: ;; Only spaces or tabs match after, so newline isn't included in the
! 256: ;; font lock below.
! 257: (set (make-local-variable 'comment-start-skip)
! 258: (concat "\\(^\\|\\s-\\)" comment-regexp "[ \t]*"))
! 259:
! 260: ;; Comment fontification based on comment-start, matching through to the
! 261: ;; end of the line.
! 262: (add-to-list (make-local-variable 'gmpasm-font-lock-keywords)
! 263: (cons (concat
! 264: "\\(\\bdnl\\b\\|" comment-start-skip "\\).*$")
! 265: 'font-lock-comment-face))
! 266:
! 267: (set (make-local-variable 'font-lock-defaults)
! 268: '(gmpasm-font-lock-keywords
! 269: t ; no syntactic fontification (of strings etc)
! 270: nil ; no case-fold
! 271: ((?_ . "w")) ; _ part of a word while fontifying
! 272: ))
! 273:
! 274: ;; Paragraphs are separated by blank lines, or lines with only dnl or
! 275: ;; comment-start.
! 276: (set (make-local-variable 'paragraph-separate)
! 277: (concat "[ \t\f]*\\(\\(" comment-regexp "\\|dnl\\)[ \t]*\\)*$"))
! 278: (set (make-local-variable 'paragraph-start)
! 279: (concat "\f\\|" paragraph-separate))
! 280:
! 281: ;; Adaptive fill gets dnl and comment-start as comment style prefixes on
! 282: ;; top of the standard regexp (which has # and ; already actually).
! 283: (set (make-local-variable 'adaptive-fill-regexp)
! 284: (concat "[ \t]*\\(\\("
! 285: comment-regexp
! 286: "\\|dnl\\|[-|#;>*]+\\|(?[0-9]+[.)]\\)[ \t]*\\)*"))
! 287: (set (make-local-variable 'adaptive-fill-first-line-regexp)
! 288: "\\`\\([ \t]*dnl\\)?[ \t]*\\'")
! 289:
! 290: (when (fboundp 'filladapt-mode)
! 291: (when (not gmpasm-filladapt-token-table)
! 292: (setq gmpasm-filladapt-token-table
! 293: filladapt-token-table)
! 294: (setq gmpasm-filladapt-token-match-table
! 295: filladapt-token-match-table)
! 296: (setq gmpasm-filladapt-token-conversion-table
! 297: filladapt-token-conversion-table)
! 298:
! 299: ;; Numbered bullet points like "2.1" get matched at the start of a
! 300: ;; line when it's really something like "2.1 cycles/limb", so delete
! 301: ;; this from the list. The regexp for "1.", "2." etc is left
! 302: ;; though.
! 303: (gmpasm-delete-from-list 'gmpasm-filladapt-token-table
! 304: '("[0-9]+\\(\\.[0-9]+\\)+[ \t]"
! 305: bullet))
! 306:
! 307: ;; "%" as a comment prefix interferes with x86 register names
! 308: ;; like %eax, so delete this.
! 309: (gmpasm-delete-from-list 'gmpasm-filladapt-token-table
! 310: '("%+" postscript-comment))
! 311:
! 312: (add-to-list 'gmpasm-filladapt-token-match-table
! 313: '(gmpasm-comment gmpasm-comment))
! 314: (add-to-list 'gmpasm-filladapt-token-conversion-table
! 315: '(gmpasm-comment . exact))
! 316: )
! 317:
! 318: (set (make-local-variable 'filladapt-token-table)
! 319: gmpasm-filladapt-token-table)
! 320: (set (make-local-variable 'filladapt-token-match-table)
! 321: gmpasm-filladapt-token-match-table)
! 322: (set (make-local-variable 'filladapt-token-conversion-table)
! 323: gmpasm-filladapt-token-conversion-table)
! 324:
! 325: ;; Add dnl and comment-start as fill prefixes.
! 326: ;; Comments in filladapt.el say filladapt-token-table must begin
! 327: ;; with ("^" beginning-of-line), so put our addition second.
! 328: (gmpasm-add-to-list-second 'filladapt-token-table
! 329: (list (concat "dnl[ \t]\\|" comment-regexp)
! 330: 'gmpasm-comment))
! 331: ))
! 332:
! 333: (run-hooks 'gmpasm-mode-hook))
! 334:
! 335:
! 336: (defun gmpasm-comment-region-dnl (beg end &optional arg)
! 337: "(gmpasm-comment-region BEG END &option ARG)
! 338:
! 339: Comment or uncomment each line in the region using `dnl'.
! 340: With \\[universal-argument] prefix arg, uncomment each line in region.
! 341: This is `comment-region', but using \"dnl\"."
! 342:
! 343: (interactive "r\nP")
! 344: (let ((comment-start "dnl")
! 345: (comment-end ""))
! 346: (comment-region beg end arg)))
! 347:
! 348:
! 349: (provide 'gmpasm-mode)
! 350:
! 351: ;;; gmpasm-mode.el ends here
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>