github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/mpn/lisp/gmpasm-mode.el (about)

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