gmpasm-mode.el
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:13k
- ;;; gmpasm-mode.el -- GNU MP asm and m4 editing mode.
- ;; Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
- ;;
- ;; This file is part of the GNU MP Library.
- ;;
- ;; The GNU MP Library is free software; you can redistribute it and/or modify
- ;; it under the terms of the GNU Lesser General Public License as published by
- ;; the Free Software Foundation; either version 3 of the License, or (at your
- ;; option) any later version.
- ;;
- ;; The GNU MP Library 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 Lesser General Public
- ;; License for more details.
- ;;
- ;; You should have received a copy of the GNU Lesser General Public License
- ;; along with the GNU MP Library. If not, see http://www.gnu.org/licenses/.
- ;;; Commentary:
- ;;
- ;; gmpasm-mode is a major mode for editing m4 processed assembler code and
- ;; m4 macro files in GMP. It's similar to m4-mode, but has a number of
- ;; settings better suited to GMP.
- ;;
- ;;
- ;; Install
- ;; -------
- ;;
- ;; To make M-x gmpasm-mode available, put gmpasm-mode.el somewhere in your
- ;; load-path and the following in your .emacs
- ;;
- ;; (autoload 'gmpasm-mode "gmpasm-mode" nil t)
- ;;
- ;; To use gmpasm-mode automatically on all .asm and .m4 files, put the
- ;; following in your .emacs
- ;;
- ;; (add-to-list 'auto-mode-alist '("\.asm\'" . gmpasm-mode))
- ;; (add-to-list 'auto-mode-alist '("\.m4\'" . gmpasm-mode))
- ;;
- ;; To have gmpasm-mode only on gmp files, try instead something like the
- ;; following, which uses it only in a directory starting with "gmp", or a
- ;; sub-directory of such.
- ;;
- ;; (add-to-list 'auto-mode-alist
- ;; '("/gmp.*/.*\.\(asm\|m4\)\'" . gmpasm-mode))
- ;;
- ;; Byte compiling will slightly speed up loading. If you want a docstring
- ;; in the autoload you can use M-x update-file-autoloads if you set it up
- ;; right.
- ;;
- ;;
- ;; Emacsen
- ;; -------
- ;;
- ;; GNU Emacs 20.x, 21.x and XEmacs 20.x all work well. GNU Emacs 19.x
- ;; should work if replacements for the various 20.x-isms are available,
- ;; though comment-region with "C" doesn't do the right thing.
- ;;; Code:
- (defgroup gmpasm nil
- "GNU MP m4 and asm editing."
- :prefix "gmpasm-"
- :group 'languages)
- (defcustom gmpasm-mode-hook nil
- "*Hook called by `gmpasm-mode'."
- :type 'hook
- :group 'gmpasm)
- (defcustom gmpasm-comment-start-regexp "\([#;!@*|C]\|//\)"
- "*Regexp matching possible comment styles.
- See `gmpasm-mode' docstring for how this is used.
- Commenting styles within GMP include
- # - alpha, i386, i960, vax, traditional unix
- ; - a29k, clipper, hppa, m88k, ppc
- ! - sh, sparc, z8000
- | - m68k
- @ - arm
- * - cray
- C - GMP m4, see mpn/asm-defs.m4
- // - ia64"
- :type 'regexp
- :group 'gmpasm)
- (defun gmpasm-add-to-list-second (list-var element)
- "(gmpasm-add-to-list-second LIST-VAR ELEMENT)
- Add ELEMENT to LIST-VAR as the second element in the list, if it isn't
- already in the list. If LIST-VAR is nil, then ELEMENT is just added as the
- sole element in the list.
- This is like `add-to-list', but it puts the new value second in the list.
- The first cons cell is copied rather than changed in-place, so references to
- the list elsewhere won't be affected."
- (if (member element (symbol-value list-var))
- (symbol-value list-var)
- (set list-var
- (if (symbol-value list-var)
- (cons (car (symbol-value list-var))
- (cons element
- (cdr (symbol-value list-var))))
- (list element)))))
- (defun gmpasm-remove-from-list (list-var element)
- "(gmpasm-remove-from-list LIST-VAR ELEMENT)
- Remove ELEMENT from LIST-VAR, using `copy-sequence' and `delete'.
- This is vaguely like `add-to-list', but the element is removed from the list.
- The list is copied rather than changed in-place, so references to it elsewhere
- aren't affected."
- ;; Only the portion of the list up to the removed element needs to be
- ;; copied, but there's no need to bother arranging that, since this function
- ;; is only used for a couple of initializations.
- (set list-var (delete element (copy-sequence (symbol-value list-var)))))
- (defvar gmpasm-mode-map
- (let ((map (make-sparse-keymap)))
- ;; assembler and dnl commenting
- (define-key map "C-cC-c" 'comment-region)
- (define-key map "C-cC-d" 'gmpasm-comment-region-dnl)
- ;; kill an M-x compile, since it's not hard to put m4 into an infinite
- ;; loop
- (define-key map "C-cC-k" 'kill-compilation)
- map)
- "Keymap for `gmpasm-mode'.")
- (defvar gmpasm-mode-syntax-table
- (let ((table (make-syntax-table)))
- ;; underscore left as a symbol char, like C mode
- ;; m4 quotes
- (modify-syntax-entry ?` "('" table)
- (modify-syntax-entry ?' ")`" table)
- table)
- "Syntax table used in `gmpasm-mode'.
- '#' and 'n' aren't set as comment syntax. In m4 these are a comment
- outside quotes, but not inside. Omitting a syntax entry ensures that when
- inside quotes emacs treats parentheses and apostrophes the same way that m4
- does. When outside quotes this is not quite right, but having it right when
- nesting expressions is more important.
- '*', '!' or '|' aren't setup as comment syntax either, on CPUs which use
- these for comments. The GMP macro setups don't set them in m4 changecom(),
- since that prevents them being used in eval() expressions, and on that basis
- they don't change the way quotes and parentheses are treated by m4 and
- should be treated by emacs.")
- (defvar gmpasm-font-lock-keywords
- (eval-when-compile
- (list
- (cons
- (concat
- "\b"
- (regexp-opt
- '("deflit" "defreg" "defframe" "defframe_pushl"
- "define_not_for_expansion"
- "m4_error" "m4_warning"
- "ASM_START" "ASM_END"
- "PROLOGUE" "PROLOGUE_GP" "MULFUNC_PROLOGUE" "EPILOGUE"
- "DATASTART" "DATAEND"
- "forloop"
- "TEXT" "DATA" "ALIGN" "W32" "FLOAT64"
- "builtin" "changecom" "changequote" "changeword" "debugfile"
- "debugmode" "decr" "define" "defn" "divert" "divnum" "dumpdef"
- "errprint" "esyscmd" "eval" "__file__" "format" "gnu" "ifdef"
- "ifelse" "include" "incr" "index" "indir" "len" "__line__"
- "m4exit" "m4wrap" "maketemp" "patsubst" "popdef" "pushdef"
- "regexp" "shift" "sinclude" "substr" "syscmd" "sysval"
- "traceoff" "traceon" "translit" "undefine" "undivert" "unix")
- t)
- "\b") 'font-lock-keyword-face)))
- "`font-lock-keywords' for `gmpasm-mode'.
- The keywords are m4 builtins and some of the GMP macros used in asm files.
- L doesn't look good fontified, so it's omitted.
- The right assembler comment regexp is added dynamically buffer-local (with
- dnl too).")
- ;; Initialized if gmpasm-mode finds filladapt loaded.
- (defvar gmpasm-filladapt-token-table nil
- "Filladapt token table used in `gmpasm-mode'.")
- (defvar gmpasm-filladapt-token-match-table nil
- "Filladapt token match table used in `gmpasm-mode'.")
- (defvar gmpasm-filladapt-token-conversion-table nil
- "Filladapt token conversion table used in `gmpasm-mode'.")
- ;;;###autoload
- (defun gmpasm-mode ()
- "A major mode for editing GNU MP asm and m4 files.
- \{gmpasm-mode-map}
- `comment-start' and `comment-end' are set buffer-local to assembler
- commenting appropriate for the CPU by looking for something matching
- `gmpasm-comment-start-regexp' at the start of a line, or "#" is used if
- there's no match (if "#" isn't what you want, type in a desired comment
- and do \[gmpasm-mode] to reinitialize).
- `adaptive-fill-regexp' is set buffer-local to the standard regexp with
- `comment-start' and dnl added. If filladapt.el has been loaded it similarly
- gets `comment-start' and dnl added as buffer-local fill prefixes.
- Font locking has the m4 builtins, some of the GMP macros, m4 dnl commenting,
- and assembler commenting (based on the `comment-start' determined).
- Note that `gmpasm-comment-start-regexp' is only matched as a whole word, so
- the `C' in it is only matched as a whole word, not on something that happens
- to start with `C'. Also it's only the particular `comment-start' determined
- that's added for filling etc, not the whole `gmpasm-comment-start-regexp'.
- `gmpasm-mode-hook' is run after initializations are complete."
- (interactive)
- (kill-all-local-variables)
- (setq major-mode 'gmpasm-mode
- mode-name "gmpasm")
- (use-local-map gmpasm-mode-map)
- (set-syntax-table gmpasm-mode-syntax-table)
- (setq fill-column 76)
- ;; Short instructions might fit with 32, but anything with labels or
- ;; expressions soon needs the comments pushed out to column 40.
- (setq comment-column 40)
- ;; Don't want to find out the hard way which dumb assemblers don't like a
- ;; missing final newline.
- (set (make-local-variable 'require-final-newline) t)
- ;; The first match of gmpasm-comment-start-regexp at the start of a line
- ;; determines comment-start, or "#" if no match.
- (set (make-local-variable 'comment-start)
- (save-excursion
- (goto-char (point-min))
- (if (re-search-forward
- (concat "^\(" gmpasm-comment-start-regexp "\)\(\s-\|$\)")
- nil t)
- (match-string 1)
- "#")))
- (set (make-local-variable 'comment-end) "")
- ;; If comment-start ends in an alphanumeric then b is used to match it
- ;; only as a separate word. The test is for an alphanumeric rather than
- ;; w since we might try # or ! as w characters but without wanting b on
- ;; them.
- (let ((comment-regexp
- (concat (regexp-quote comment-start)
- (if (string-match "[a-zA-Z0-9]\'" comment-start) "\b"))))
- ;; Whitespace is required before a comment-start so m4 $# doesn't match
- ;; when comment-start is "#".
- (set (make-local-variable 'comment-start-skip)
- (concat "\(^\|\s-\)\(\<dnl\>\|" comment-regexp "\)[ t]*"))
- ;; Comment fontification based on comment-start, and always with dnl.
- ;; Same treatment of a space before "#" as in comment-start-skip, but
- ;; don't fontify that space.
- (add-to-list (make-local-variable 'gmpasm-font-lock-keywords)
- (list (concat "\(^\|\s-\)\(\(\<dnl\>\|"
- comment-regexp
- "\).*$\)")
- 2 'font-lock-comment-face))
- (set (make-local-variable 'font-lock-defaults)
- '(gmpasm-font-lock-keywords
- t ; no syntactic fontification (of strings etc)
- nil ; no case-fold
- ((?_ . "w")) ; _ part of a word while fontifying
- ))
- ;; Paragraphs are separated by blank lines, or lines with only dnl or
- ;; comment-start.
- (set (make-local-variable 'paragraph-separate)
- (concat "[ tf]*\(\(" comment-regexp "\|dnl\)[ t]*\)*$"))
- (set (make-local-variable 'paragraph-start)
- (concat "f\|" paragraph-separate))
- ;; Some sort of "def...(" m4 define, possibly with ` for quoting.
- ;; Could do something with PROLOGUE here, but in GMP the filename is
- ;; enough, it's not normally necessary to say the function name.
- (set (make-local-variable 'add-log-current-defun-header-regexp)
- "^def[a-z0-9_]+(`?\([a-zA-Z0-9_]+\)")
- ;; Adaptive fill gets dnl and comment-start as comment style prefixes on
- ;; top of the standard regexp (which has # and ; already actually).
- (set (make-local-variable 'adaptive-fill-regexp)
- (concat "[ t]*\(\("
- comment-regexp
- "\|dnl\|[-|#;>*]+\|(?[0-9]+[.)]\)[ t]*\)*"))
- (set (make-local-variable 'adaptive-fill-first-line-regexp)
- "\`\([ t]*dnl\)?[ t]*\'")
- (when (fboundp 'filladapt-mode)
- (unless gmpasm-filladapt-token-table
- (setq gmpasm-filladapt-token-table
- filladapt-token-table)
- (setq gmpasm-filladapt-token-match-table
- filladapt-token-match-table)
- (setq gmpasm-filladapt-token-conversion-table
- filladapt-token-conversion-table)
- ;; Numbered bullet points like "2.1" get matched at the start of a
- ;; line when it's really something like "2.1 cycles/limb", so remove
- ;; this from the list. The regexp for "1.", "2." etc is left
- ;; though.
- (gmpasm-remove-from-list 'gmpasm-filladapt-token-table
- '("[0-9]+\(\.[0-9]+\)+[ t]"
- bullet))
- ;; "%" as a comment prefix interferes with register names on some
- ;; CPUs, like %eax on x86, so remove this.
- (gmpasm-remove-from-list 'gmpasm-filladapt-token-table
- '("%+" postscript-comment))
- (add-to-list 'gmpasm-filladapt-token-match-table
- '(gmpasm-comment gmpasm-comment))
- (add-to-list 'gmpasm-filladapt-token-conversion-table
- '(gmpasm-comment . exact)))
- (set (make-local-variable 'filladapt-token-table)
- gmpasm-filladapt-token-table)
- (set (make-local-variable 'filladapt-token-match-table)
- gmpasm-filladapt-token-match-table)
- (set (make-local-variable 'filladapt-token-conversion-table)
- gmpasm-filladapt-token-conversion-table)
- ;; Add dnl and comment-start as fill prefixes.
- ;; Comments in filladapt.el say filladapt-token-table must begin
- ;; with ("^" beginning-of-line), so put our addition second.
- (gmpasm-add-to-list-second 'filladapt-token-table
- (list (concat "dnl[ t]\|" comment-regexp)
- 'gmpasm-comment))))
- (run-hooks 'gmpasm-mode-hook))
- (defun gmpasm-comment-region-dnl (beg end &optional arg)
- "(gmpasm-comment-region-dnl BEG END &optional ARG)
- Comment or uncomment each line in the region using `dnl'.
- With \[universal-argument] prefix arg, uncomment each line in region.
- This is `comment-region', but using "dnl"."
- (interactive "rnP")
- (let ((comment-start "dnl")
- (comment-end ""))
- (comment-region beg end arg)))
- (provide 'gmpasm-mode)
- ;;; gmpasm-mode.el ends here