Annotation of OpenXM_contrib/gmp/mpn/lisp/gmpasm-mode.el, Revision 1.1.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>