version 1.1.1.1, 2000/09/09 14:12:31 |
version 1.1.1.2, 2003/08/25 16:06:21 |
|
|
;;; gmpasm-mode.el -- GNU MP asm and m4 editing mode. |
;;; gmpasm-mode.el -- GNU MP asm and m4 editing mode. |
|
|
|
|
;; Copyright (C) 1999, 2000 Free Software Foundation, Inc. |
;; Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. |
;; |
;; |
;; This file is part of the GNU MP Library. |
;; This file is part of the GNU MP Library. |
;; |
;; |
|
|
|
|
;;; Commentary: |
;;; Commentary: |
;; |
;; |
;; gmpasm-mode is an editing mode for m4 processed assembler code and m4 |
;; gmpasm-mode is a major mode for editing m4 processed assembler code and |
;; macro files in GMP. It's similar to m4-mode, but has a number of |
;; m4 macro files in GMP. It's similar to m4-mode, but has a number of |
;; settings better suited to GMP. |
;; settings better suited to GMP. |
;; |
;; |
;; |
;; |
;; Install |
;; Install |
;; ------- |
;; ------- |
;; |
;; |
;; To make M-x gmpasm-mode available, put gmpasm-mode.el somewhere in the |
;; To make M-x gmpasm-mode available, put gmpasm-mode.el somewhere in your |
;; load-path and the following in .emacs |
;; load-path and the following in your .emacs |
;; |
;; |
;; (autoload 'gmpasm-mode "gmpasm-mode" nil t) |
;; (autoload 'gmpasm-mode "gmpasm-mode" nil t) |
;; |
;; |
;; To use gmpasm-mode automatically on all .asm and .m4 files, put the |
;; To use gmpasm-mode automatically on all .asm and .m4 files, put the |
;; following in .emacs |
;; following in your .emacs |
;; |
;; |
;; (add-to-list 'auto-mode-alist '("\\.asm\\'" . gmpasm-mode)) |
;; (add-to-list 'auto-mode-alist '("\\.asm\\'" . gmpasm-mode)) |
;; (add-to-list 'auto-mode-alist '("\\.m4\\'" . gmpasm-mode)) |
;; (add-to-list 'auto-mode-alist '("\\.m4\\'" . gmpasm-mode)) |
|
|
;; Emacsen |
;; Emacsen |
;; ------- |
;; ------- |
;; |
;; |
;; FSF Emacs 20.x - gmpasm-mode is designed for this. |
;; GNU Emacs 20.x, 21.x and XEmacs 20.x all work well. GNU Emacs 19.x |
;; XEmacs 20.x - seems to work. |
;; should work if replacements for the various 20.x-isms are available, |
;; |
;; though comment-region with "C" doesn't do the right thing. |
;; FSF Emacs 19.x - should work if replacements for some 20.x-isms are |
|
;; available. comment-region with "C" won't really do the right thing |
|
;; though. |
|
|
|
|
|
;;; Code: |
;;; Code: |
|
|
:type 'hook |
:type 'hook |
:group 'gmpasm) |
:group 'gmpasm) |
|
|
(defcustom gmpasm-comment-start-regexp "[#;!@C]" |
(defcustom gmpasm-comment-start-regexp "[#;!@*|C]" |
"*Regexp matching possible comment styles. |
"*Regexp matching possible comment styles. |
See `gmpasm-mode' docstring for how this is used." |
See `gmpasm-mode' docstring for how this is used." |
:type 'regexp |
:type 'regexp |
Line 106 the list elsewhere won't be affected." |
|
Line 103 the list elsewhere won't be affected." |
|
(list element))))) |
(list element))))) |
|
|
|
|
(defun gmpasm-delete-from-list (list-var element) |
(defun gmpasm-remove-from-list (list-var element) |
"(gmpasm-delete-from-list LIST-VAR ELEMENT) |
"(gmpasm-remove-from-list LIST-VAR ELEMENT) |
|
|
Delete ELEMENT from LIST-VAR, using `delete'. |
Remove ELEMENT from LIST-VAR, using `copy-sequence' and `delete'. |
This is like `add-to-list', but the element is deleted from the list. |
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 |
The list is copied rather than changed in-place, so references to it elsewhere |
won't be affected." |
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))))) |
(set list-var (delete element (copy-sequence (symbol-value list-var))))) |
|
|
|
|
(defvar gmpasm-mode-map |
(defvar gmpasm-mode-map |
(let ((map (make-sparse-keymap))) |
(let ((map (make-sparse-keymap))) |
|
|
;; assembler and dnl commenting |
;; assembler and dnl commenting |
(define-key map "\C-c\C-c" 'comment-region) |
(define-key map "\C-c\C-c" 'comment-region) |
(define-key map "\C-c\C-d" 'gmpasm-comment-region-dnl) |
(define-key map "\C-c\C-d" 'gmpasm-comment-region-dnl) |
|
|
;; kill an M-x compile, since it's not hard to put m4 into an infinite |
;; kill an M-x compile, since it's not hard to put m4 into an infinite |
;; loop |
;; loop |
(define-key map "\C-c\C-k" 'kill-compilation) |
(define-key map "\C-c\C-k" 'kill-compilation) |
|
|
map) |
map) |
"Keymap for `gmpasm-mode'.") |
"Keymap for `gmpasm-mode'.") |
|
|
Line 135 won't be affected." |
|
Line 136 won't be affected." |
|
(defvar gmpasm-mode-syntax-table |
(defvar gmpasm-mode-syntax-table |
(let ((table (make-syntax-table))) |
(let ((table (make-syntax-table))) |
;; underscore left as a symbol char, like C mode |
;; underscore left as a symbol char, like C mode |
|
|
;; m4 quotes |
;; m4 quotes |
(modify-syntax-entry ?` "('" table) |
(modify-syntax-entry ?` "('" table) |
(modify-syntax-entry ?' ")`" table) |
(modify-syntax-entry ?' ")`" table) |
Line 143 won't be affected." |
|
Line 144 won't be affected." |
|
table) |
table) |
"Syntax table used in `gmpasm-mode'. |
"Syntax table used in `gmpasm-mode'. |
|
|
m4 ignores quote marks in # comments at the top level, but inside quotes # |
'#' and '\n' aren't set as comment syntax. In m4 these are a comment |
isn't special and all quotes are active. There seems no easy way to express |
outside quotes, but not inside. Omitting a syntax entry ensures that when |
this in the syntax table, so nothing is done for comments. Usually this is |
inside quotes emacs treats parentheses and apostrophes the same way that m4 |
best, since it picks up invalid apostrophes in comments inside quotes.") |
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 |
(defvar gmpasm-font-lock-keywords |
(eval-when-compile |
(eval-when-compile |
(list |
(list |
Line 158 best, since it picks up invalid apostrophes in comment |
|
Line 166 best, since it picks up invalid apostrophes in comment |
|
(regexp-opt |
(regexp-opt |
'("deflit" "defreg" "defframe" "defframe_pushl" |
'("deflit" "defreg" "defframe" "defframe_pushl" |
"define_not_for_expansion" |
"define_not_for_expansion" |
"ASM_START" "ASM_END" "PROLOGUE" "EPILOGUE" |
"m4_error" "m4_warning" |
|
"ASM_START" "ASM_END" |
|
"PROLOGUE" "PROLOGUE_GP" "MULFUNC_PROLOGUE" "EPILOGUE" |
|
"DATASTART" "DATAEND" |
"forloop" |
"forloop" |
"TEXT" "DATA" "ALIGN" "W32" |
"TEXT" "DATA" "ALIGN" "W32" "FLOAT64" |
"builtin" "changecom" "changequote" "changeword" "debugfile" |
"builtin" "changecom" "changequote" "changeword" "debugfile" |
"debugmode" "decr" "define" "defn" "divert" "divnum" "dumpdef" |
"debugmode" "decr" "define" "defn" "divert" "divnum" "dumpdef" |
"errprint" "esyscmd" "eval" "__file__" "format" "gnu" "ifdef" |
"errprint" "esyscmd" "eval" "__file__" "format" "gnu" "ifdef" |
Line 174 best, since it picks up invalid apostrophes in comment |
|
Line 185 best, since it picks up invalid apostrophes in comment |
|
"`font-lock-keywords' for `gmpasm-mode'. |
"`font-lock-keywords' for `gmpasm-mode'. |
|
|
The keywords are m4 builtins and some of the GMP macros used in asm files. |
The keywords are m4 builtins and some of the GMP macros used in asm files. |
L and LF don't look good fontified, so they're omitted. |
L doesn't look good fontified, so it's omitted. |
|
|
The right assembler comment regexp is added dynamically buffer-local (with |
The right assembler comment regexp is added dynamically buffer-local (with |
dnl too).") |
dnl too).") |
Line 212 the `C' in it is only matched as a whole word, not on |
|
Line 223 the `C' in it is only matched as a whole word, not on |
|
to start with `C'. Also it's only the particular `comment-start' determined |
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'. |
that's added for filling etc, not the whole `gmpasm-comment-start-regexp'. |
|
|
`gmpasm-mode-hook' is run after initializations are complete. |
`gmpasm-mode-hook' is run after initializations are complete." |
" |
|
|
|
(interactive) |
(interactive) |
(kill-all-local-variables) |
(kill-all-local-variables) |
Line 245 that's added for filling etc, not the whole `gmpasm-co |
|
Line 255 that's added for filling etc, not the whole `gmpasm-co |
|
|
|
;; If comment-start ends in an alphanumeric then \b is used to match it |
;; 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 |
;; 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. |
;; \w since we might try # or ! as \w characters but without wanting \b on |
|
;; them. |
(let ((comment-regexp |
(let ((comment-regexp |
(concat (regexp-quote comment-start) |
(concat (regexp-quote comment-start) |
(if (string-match "[a-zA-Z0-9]\\'" comment-start) "\\b")))) |
(if (string-match "[a-zA-Z0-9]\\'" comment-start) "\\b")))) |
|
|
;; Whitespace is required before a comment-start so m4 $# doesn't match |
;; Whitespace is required before a comment-start so m4 $# doesn't match |
;; when comment-start is "#". |
;; when comment-start is "#". |
;; Only spaces or tabs match after, so newline isn't included in the |
|
;; font lock below. |
|
(set (make-local-variable 'comment-start-skip) |
(set (make-local-variable 'comment-start-skip) |
(concat "\\(^\\|\\s-\\)" comment-regexp "[ \t]*")) |
(concat "\\(^\\|\\s-\\)\\(\\<dnl\\>\\|" comment-regexp "\\)[ \t]*")) |
|
|
;; Comment fontification based on comment-start, matching through to the |
;; Comment fontification based on comment-start, and always with dnl. |
;; end of the line. |
;; 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) |
(add-to-list (make-local-variable 'gmpasm-font-lock-keywords) |
(cons (concat |
(list (concat "\\(^\\|\\s-\\)\\(\\(\\<dnl\\>\\|" |
"\\(\\bdnl\\b\\|" comment-start-skip "\\).*$") |
comment-regexp |
'font-lock-comment-face)) |
"\\).*$\\)") |
|
2 'font-lock-comment-face)) |
|
|
(set (make-local-variable 'font-lock-defaults) |
(set (make-local-variable 'font-lock-defaults) |
'(gmpasm-font-lock-keywords |
'(gmpasm-font-lock-keywords |
Line 277 that's added for filling etc, not the whole `gmpasm-co |
|
Line 288 that's added for filling etc, not the whole `gmpasm-co |
|
(concat "[ \t\f]*\\(\\(" comment-regexp "\\|dnl\\)[ \t]*\\)*$")) |
(concat "[ \t\f]*\\(\\(" comment-regexp "\\|dnl\\)[ \t]*\\)*$")) |
(set (make-local-variable 'paragraph-start) |
(set (make-local-variable 'paragraph-start) |
(concat "\f\\|" paragraph-separate)) |
(concat "\f\\|" paragraph-separate)) |
|
|
;; Adaptive fill gets dnl and comment-start as comment style prefixes on |
;; Adaptive fill gets dnl and comment-start as comment style prefixes on |
;; top of the standard regexp (which has # and ; already actually). |
;; top of the standard regexp (which has # and ; already actually). |
(set (make-local-variable 'adaptive-fill-regexp) |
(set (make-local-variable 'adaptive-fill-regexp) |
Line 288 that's added for filling etc, not the whole `gmpasm-co |
|
Line 299 that's added for filling etc, not the whole `gmpasm-co |
|
"\\`\\([ \t]*dnl\\)?[ \t]*\\'") |
"\\`\\([ \t]*dnl\\)?[ \t]*\\'") |
|
|
(when (fboundp 'filladapt-mode) |
(when (fboundp 'filladapt-mode) |
(when (not gmpasm-filladapt-token-table) |
(unless gmpasm-filladapt-token-table |
(setq gmpasm-filladapt-token-table |
(setq gmpasm-filladapt-token-table |
filladapt-token-table) |
filladapt-token-table) |
(setq gmpasm-filladapt-token-match-table |
(setq gmpasm-filladapt-token-match-table |
filladapt-token-match-table) |
filladapt-token-match-table) |
(setq gmpasm-filladapt-token-conversion-table |
(setq gmpasm-filladapt-token-conversion-table |
filladapt-token-conversion-table) |
filladapt-token-conversion-table) |
|
|
;; Numbered bullet points like "2.1" get matched at the start of a |
;; 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 delete |
;; 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 |
;; this from the list. The regexp for "1.", "2." etc is left |
;; though. |
;; though. |
(gmpasm-delete-from-list 'gmpasm-filladapt-token-table |
(gmpasm-remove-from-list 'gmpasm-filladapt-token-table |
'("[0-9]+\\(\\.[0-9]+\\)+[ \t]" |
'("[0-9]+\\(\\.[0-9]+\\)+[ \t]" |
bullet)) |
bullet)) |
|
|
;; "%" as a comment prefix interferes with x86 register names |
;; "%" as a comment prefix interferes with register names on some |
;; like %eax, so delete this. |
;; CPUs, like %eax on x86, so remove this. |
(gmpasm-delete-from-list 'gmpasm-filladapt-token-table |
(gmpasm-remove-from-list 'gmpasm-filladapt-token-table |
'("%+" postscript-comment)) |
'("%+" postscript-comment)) |
|
|
(add-to-list 'gmpasm-filladapt-token-match-table |
(add-to-list 'gmpasm-filladapt-token-match-table |
'(gmpasm-comment gmpasm-comment)) |
'(gmpasm-comment gmpasm-comment)) |
(add-to-list 'gmpasm-filladapt-token-conversion-table |
(add-to-list 'gmpasm-filladapt-token-conversion-table |
'(gmpasm-comment . exact)) |
'(gmpasm-comment . exact))) |
) |
|
|
|
(set (make-local-variable 'filladapt-token-table) |
(set (make-local-variable 'filladapt-token-table) |
gmpasm-filladapt-token-table) |
gmpasm-filladapt-token-table) |
(set (make-local-variable 'filladapt-token-match-table) |
(set (make-local-variable 'filladapt-token-match-table) |
gmpasm-filladapt-token-match-table) |
gmpasm-filladapt-token-match-table) |
(set (make-local-variable 'filladapt-token-conversion-table) |
(set (make-local-variable 'filladapt-token-conversion-table) |
gmpasm-filladapt-token-conversion-table) |
gmpasm-filladapt-token-conversion-table) |
|
|
;; Add dnl and comment-start as fill prefixes. |
;; Add dnl and comment-start as fill prefixes. |
;; Comments in filladapt.el say filladapt-token-table must begin |
;; Comments in filladapt.el say filladapt-token-table must begin |
;; with ("^" beginning-of-line), so put our addition second. |
;; with ("^" beginning-of-line), so put our addition second. |
(gmpasm-add-to-list-second 'filladapt-token-table |
(gmpasm-add-to-list-second 'filladapt-token-table |
(list (concat "dnl[ \t]\\|" comment-regexp) |
(list (concat "dnl[ \t]\\|" comment-regexp) |
'gmpasm-comment)) |
'gmpasm-comment)))) |
)) |
|
|
|
(run-hooks 'gmpasm-mode-hook)) |
(run-hooks 'gmpasm-mode-hook)) |
|
|
|
|
(defun gmpasm-comment-region-dnl (beg end &optional arg) |
(defun gmpasm-comment-region-dnl (beg end &optional arg) |
"(gmpasm-comment-region BEG END &option ARG) |
"(gmpasm-comment-region-dnl BEG END &optional ARG) |
|
|
Comment or uncomment each line in the region using `dnl'. |
Comment or uncomment each line in the region using `dnl'. |
With \\[universal-argument] prefix arg, uncomment each line in region. |
With \\[universal-argument] prefix arg, uncomment each line in region. |