1;;; asm-mode.el --- mode for editing assembler code 2 3;; Copyright (C) 1991, 2001, 2002, 2003, 2004, 2005, 2006, 2007 4;; Free Software Foundation, Inc. 5 6;; Author: Eric S. Raymond <esr@snark.thyrsus.com> 7;; Maintainer: FSF 8;; Keywords: tools, languages 9 10;; This file is part of GNU Emacs. 11 12;; GNU Emacs is free software; you can redistribute it and/or modify 13;; it under the terms of the GNU General Public License as published by 14;; the Free Software Foundation; either version 2, or (at your option) 15;; any later version. 16 17;; GNU Emacs is distributed in the hope that it will be useful, 18;; but WITHOUT ANY WARRANTY; without even the implied warranty of 19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20;; GNU General Public License for more details. 21 22;; You should have received a copy of the GNU General Public License 23;; along with GNU Emacs; see the file COPYING. If not, write to the 24;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 25;; Boston, MA 02110-1301, USA. 26 27;;; Commentary: 28 29;; This mode was written by Eric S. Raymond <esr@snark.thyrsus.com>, 30;; inspired by an earlier asm-mode by Martin Neitzel. 31 32;; This minor mode is based on text mode. It defines a private abbrev table 33;; that can be used to save abbrevs for assembler mnemonics. It binds just 34;; five keys: 35;; 36;; TAB tab to next tab stop 37;; : outdent preceding label, tab to tab stop 38;; comment char place or move comment 39;; asm-comment-char specifies which character this is; 40;; you can use a different character in different 41;; Asm mode buffers. 42;; C-j, C-m newline and tab to tab stop 43;; 44;; Code is indented to the first tab stop level. 45 46;; This mode runs two hooks: 47;; 1) An asm-mode-set-comment-hook before the part of the initialization 48;; depending on asm-comment-char, and 49;; 2) an asm-mode-hook at the end of initialization. 50 51;;; Code: 52 53(defgroup asm nil 54 "Mode for editing assembler code." 55 :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces) 56 :group 'languages) 57 58(defcustom asm-comment-char ?\; 59 "*The comment-start character assumed by Asm mode." 60 :type 'character 61 :group 'asm) 62 63(defvar asm-mode-syntax-table 64 (let ((st (make-syntax-table))) 65 (modify-syntax-entry ?\n "> b" st) 66 (modify-syntax-entry ?/ ". 124b" st) 67 (modify-syntax-entry ?* ". 23" st) 68 st) 69 "Syntax table used while in Asm mode.") 70 71(defvar asm-mode-abbrev-table nil 72 "Abbrev table used while in Asm mode.") 73(define-abbrev-table 'asm-mode-abbrev-table ()) 74 75(defvar asm-mode-map 76 (let ((map (make-sparse-keymap))) 77 ;; Note that the comment character isn't set up until asm-mode is called. 78 (define-key map ":" 'asm-colon) 79 (define-key map "\C-c;" 'comment-region) 80 (define-key map "\C-j" 'newline-and-indent) 81 (define-key map "\C-m" 'newline-and-indent) 82 map) 83 "Keymap for Asm mode.") 84 85(defconst asm-font-lock-keywords 86 (append 87 '(("^\\(\\(\\sw\\|\\s_\\)+\\)\\>:?[ \t]*\\(\\sw+\\(\\.\\sw+\\)*\\)?" 88 (1 font-lock-function-name-face) (3 font-lock-keyword-face nil t)) 89 ;; label started from ".". 90 ("^\\(\\.\\(\\sw\\|\\s_\\)+\\)\\>:" 91 1 font-lock-function-name-face) 92 ("^\\((\\sw+)\\)?\\s +\\(\\(\\.?\\sw\\|\\s_\\)+\\(\\.\\sw+\\)*\\)" 93 2 font-lock-keyword-face) 94 ;; directive started from ".". 95 ("^\\(\\.\\(\\sw\\|\\s_\\)+\\)\\>[^:]?" 96 1 font-lock-keyword-face) 97 ;; %register 98 ("%\\sw+" . font-lock-variable-name-face)) 99 cpp-font-lock-keywords) 100 "Additional expressions to highlight in Assembler mode.") 101 102;;;###autoload 103(defun asm-mode () 104 "Major mode for editing typical assembler code. 105Features a private abbrev table and the following bindings: 106 107\\[asm-colon]\toutdent a preceding label, tab to next tab stop. 108\\[tab-to-tab-stop]\ttab to next tab stop. 109\\[asm-newline]\tnewline, then tab to next tab stop. 110\\[asm-comment]\tsmart placement of assembler comments. 111 112The character used for making comments is set by the variable 113`asm-comment-char' (which defaults to `?\\;'). 114 115Alternatively, you may set this variable in `asm-mode-set-comment-hook', 116which is called near the beginning of mode initialization. 117 118Turning on Asm mode runs the hook `asm-mode-hook' at the end of initialization. 119 120Special commands: 121\\{asm-mode-map}" 122 (interactive) 123 (kill-all-local-variables) 124 (setq mode-name "Assembler") 125 (setq major-mode 'asm-mode) 126 (setq local-abbrev-table asm-mode-abbrev-table) 127 (make-local-variable 'font-lock-defaults) 128 (setq font-lock-defaults '(asm-font-lock-keywords)) 129 (set (make-local-variable 'indent-line-function) 'asm-indent-line) 130 ;; Stay closer to the old TAB behavior (was tab-to-tab-stop). 131 (set (make-local-variable 'tab-always-indent) nil) 132 133 (run-hooks 'asm-mode-set-comment-hook) 134 ;; Make our own local child of asm-mode-map 135 ;; so we can define our own comment character. 136 (use-local-map (nconc (make-sparse-keymap) asm-mode-map)) 137 (local-set-key (vector asm-comment-char) 'asm-comment) 138 (set-syntax-table (make-syntax-table asm-mode-syntax-table)) 139 (modify-syntax-entry asm-comment-char "< b") 140 141 (make-local-variable 'comment-start) 142 (setq comment-start (string asm-comment-char)) 143 (make-local-variable 'comment-add) 144 (setq comment-add 1) 145 (make-local-variable 'comment-start-skip) 146 (setq comment-start-skip "\\(?:\\s<+\\|/[/*]+\\)[ \t]*") 147 (make-local-variable 'comment-end-skip) 148 (setq comment-end-skip "[ \t]*\\(\\s>\\|\\*+/\\)") 149 (make-local-variable 'comment-end) 150 (setq comment-end "") 151 (setq fill-prefix "\t") 152 (run-mode-hooks 'asm-mode-hook)) 153 154(defun asm-indent-line () 155 "Auto-indent the current line." 156 (interactive) 157 (let* ((savep (point)) 158 (indent (condition-case nil 159 (save-excursion 160 (forward-line 0) 161 (skip-chars-forward " \t") 162 (if (>= (point) savep) (setq savep nil)) 163 (max (asm-calculate-indentation) 0)) 164 (error 0)))) 165 (if savep 166 (save-excursion (indent-line-to indent)) 167 (indent-line-to indent)))) 168 169(defun asm-calculate-indentation () 170 (or 171 ;; Flush labels to the left margin. 172 (and (looking-at "\\(\\sw\\|\\s_\\)+:") 0) 173 ;; Same thing for `;;;' comments. 174 (and (looking-at "\\s<\\s<\\s<") 0) 175 ;; Simple `;' comments go to the comment-column. 176 (and (looking-at "\\s<\\(\\S<\\|\\'\\)") comment-column) 177 ;; The rest goes at the first tab stop. 178 (or (car tab-stop-list) tab-width))) 179 180(defun asm-colon () 181 "Insert a colon; if it follows a label, delete the label's indentation." 182 (interactive) 183 (let ((labelp nil)) 184 (save-excursion 185 (skip-syntax-backward "w_") 186 (skip-syntax-backward " ") 187 (if (setq labelp (bolp)) (delete-horizontal-space))) 188 (call-interactively 'self-insert-command) 189 (when labelp 190 (delete-horizontal-space) 191 (tab-to-tab-stop)))) 192 193;; Obsolete since Emacs-22.1. 194(defalias 'asm-newline 'newline-and-indent) 195 196(defun asm-comment () 197 "Convert an empty comment to a `larger' kind, or start a new one. 198These are the known comment classes: 199 200 1 -- comment to the right of the code (at the comment-column) 201 2 -- comment on its own line, indented like code 202 3 -- comment on its own line, beginning at the left-most column. 203 204Suggested usage: while writing your code, trigger asm-comment 205repeatedly until you are satisfied with the kind of comment." 206 (interactive) 207 (comment-normalize-vars) 208 (let (comempty comment) 209 (save-excursion 210 (beginning-of-line) 211 (with-no-warnings 212 (setq comment (comment-search-forward (line-end-position) t))) 213 (setq comempty (looking-at "[ \t]*$"))) 214 215 (cond 216 217 ;; Blank line? Then start comment at code indent level. 218 ;; Just like `comment-dwim'. -stef 219 ((save-excursion (beginning-of-line) (looking-at "^[ \t]*$")) 220 (indent-according-to-mode) 221 (insert asm-comment-char asm-comment-char ?\ )) 222 223 ;; Nonblank line w/o comment => start a comment at comment-column. 224 ;; Also: point before the comment => jump inside. 225 ((or (null comment) (< (point) comment)) 226 (indent-for-comment)) 227 228 ;; Flush-left or non-empty comment present => just insert character. 229 ((or (not comempty) (save-excursion (goto-char comment) (bolp))) 230 (insert asm-comment-char)) 231 232 ;; Empty code-level comment => upgrade to next comment level. 233 ((save-excursion (goto-char comment) (skip-chars-backward " \t") (bolp)) 234 (goto-char comment) 235 (insert asm-comment-char) 236 (indent-for-comment)) 237 238 ;; Empty comment ends non-empty code line => new comment above. 239 (t 240 (goto-char comment) 241 (skip-chars-backward " \t") 242 (delete-region (point) (line-end-position)) 243 (beginning-of-line) (insert "\n") (backward-char) 244 (asm-comment))))) 245 246(provide 'asm-mode) 247 248;;; arch-tag: 210e695f-f338-4376-8913-a4c5c72ac848 249;;; asm-mode.el ends here 250