home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
emacs-19.28-src.tgz
/
tar.out
/
fsf
/
emacs
/
site-lisp
/
cc-mode-18.el
< prev
next >
Wrap
Lisp/Scheme
|
1996-09-28
|
12KB
|
335 lines
;;; cc-mode-18.el --- compatibility for cc-mode in Emacs 18
;; Authors: 1994 Barry A. Warsaw, Century Computing Inc. <bwarsaw@cen.com>
;; Maintainer: cc-mode-help@anthem.nlm.nih.gov
;; Created: 8-Feb-1994 (from cc-mode.el)
;; Version: 1.11
;; Last Modified: 1994/04/15 23:14:27
;; Keywords: C++ C editing major-mode Emacs 18 compatible
;; Copyright (C) 1994 Barry A. Warsaw
;; This file is not yet part of GNU Emacs, and hopefully never will be.
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2 of the License, or
;; (at your option) any later version.
;;
;; This program 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 General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;;; Commentary:
;; This file provides hooks into cc-mode for use with Emacs 18. All
;; native Emacs 18 support has been moved out of cc-mode.el proper. If
;; you find you need this file (i.e. you're using Emacs 18), you
;; should SERIOUSLY consider upgrading to FSF or Lucid 19. Emacs 18
;; simply doesn't have what it takes to edit C++ code.
;;
;; To use this, put the following in your .emacs file:
;;
;; (require 'cc-mode-18)
;; (or (assq 'c-emacs18-common-hook c-mode-common-hook)
;; (setq c-mode-common-hook (cons 'c-emacs18-common-hook
;; c-mode-common-hook)))
;;
;; I cannot provide any direct support for v18 support anymore, but I
;; will install and distribute contributed patches. This file, and
;; v18 support in general should be considered sold "As Is". Caveat
;; Emptor! :-)
;; LCD Archive Entry:
;; cc-mode-18.el|Barry A. Warsaw|cc-mode-help@anthem.nlm.nih.gov
;; |Compatibility for cc-mode in Emacs 18
;; |1994/04/15 23:14:27|1.11|
;;; Code:
(require 'cc-mode)
;; user definable variables
;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
(defvar c-untame-characters '(?\')
"*Utilize a backslashing workaround of an Emacs18 syntax deficiency.
If non-nil, this variable should contain a list of characters which
are prepended by a backslash in comment regions. By default, the list
contains only the most troublesome character, the single quote. To be
completely safe, set this variable to:
'(?\( ?\) ?\' ?\{ ?\} ?\[ ?\])
This variable has no effect under Emacs 19. For details on why this is
necessary in GNU Emacs 18, please refer to the cc-mode texinfo manual.")
(defvar c-backscan-limit 2000
"*Character limit for looking back while skipping syntactic whitespace.
This variable has no effect under Emacs 19. For details on why this
is necessary under GNU Emacs 18, please refer to the texinfo manual.")
;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT
;; extend the keymap
(defun c-emacs18-common-hook ()
;; Do all the set up necessary to get cc-mode working in Emacs 18,
;; but make sure we only do it once
(if (or (get 'c-mode 'c-emacs-18)
(not (featurep 'cc-mode))
(not (memq 'v18 c-emacs-features)))
;; do nothing if conditions we aren't in Emacs 18, or cc-mode
;; hasn't been loaded yet, or we've already run this hook
nil
;; extend the keymap for use with Emacs 18. c-mode-map must already
;; be set up (i.e. from cc-mode.el)
(define-key c-mode-map "\C-c'" 'c-tame-comments)
(define-key c-mode-map "'" 'c-tame-insert)
(define-key c-mode-map "[" 'c-tame-insert)
(define-key c-mode-map "]" 'c-tame-insert)
(define-key c-mode-map "(" 'c-tame-insert)
(define-key c-mode-map ")" 'c-tame-insert)
;; Vanilla GNU18 doesn't support mult-style comments. We'll do
;; the best we can, but some strange behavior may be encountered.
;; PATCH or UPGRADE!
(modify-syntax-entry ?/ ". 124" c-mode-syntax-table)
(modify-syntax-entry ?* ". 23" c-mode-syntax-table)
(modify-syntax-entry ?\n ">" c-mode-syntax-table)
(modify-syntax-entry ?/ ". 124" c++-mode-syntax-table)
(modify-syntax-entry ?* ". 23" c++-mode-syntax-table)
(modify-syntax-entry ?\n ">" c++-mode-syntax-table)
;; set up comment skipping interface functions, and other
;; non-compatible functions
(fset 'c-forward-syntactic-ws 'c-emacs18-fsws)
(fset 'c-backward-syntactic-ws 'c-emacs18-bsws)
(fset 'c-in-literal 'c-emacs18-il)
(fset 'c-mark-function 'c-emacs18-mark-function)
(fset 'c-insert-special-chars 'c-emacs18-insert-special-chars)
;; Emacs 18 can't handle parse-sexp-ignore-comments == t
(setq parse-sexp-ignore-comments nil)
;; put the property out there so we don't do this again
(put 'c-mode 'c-emacs-18 'c-emacs-18)
))
;; Emacs 18 support for whitespace skipping and literal parsing.
;; Emacs 19 has nice built-in functions to do this, but Emacs 18 does
;; not. Also note that only Emacs19 implementation currently has
;; support for multi-line macros, and this feature is imposes the
;; restriction that backslashes at the end of a line can only occur on
;; multi-line macro lines.
;; This is the best we can do in vanilla GNU 18 Emacsen.
(defun c-emacs18-fsws (&optional lim)
;; Forward skip syntactic whitespace for Emacs 18.
(let ((lim (or lim (point-max)))
stop)
(while (not stop)
(skip-chars-forward " \t\n\r\f" lim)
(cond
;; c++ comment
((looking-at "//") (end-of-line))
;; c comment
((looking-at "/\\*") (re-search-forward "*/" lim 'noerror))
;; preprocessor directive
((and (= (c-point 'boi) (point))
(= (following-char) ?#))
(end-of-line))
;; none of the above
(t (setq stop t))
))))
(defun c-emacs18-bsws (&optional lim)
;; Backward skip syntactic whitespace for Emacs 18.
(let ((lim (or lim (c-point 'bod)))
literal stop)
(if (and c-backscan-limit
(> (- (point) lim) c-backscan-limit))
(setq lim (- (point) c-backscan-limit)))
(while (not stop)
(skip-chars-backward " \t\n\r\f" lim)
;; c++ comment
(if (eq (setq literal (c-in-literal lim)) 'c++)
(progn
(skip-chars-backward "^/" lim)
(skip-chars-backward "/" lim)
(while (not (or (and (= (following-char) ?/)
(= (char-after (1+ (point))) ?/))
(<= (point) lim)))
(skip-chars-backward "^/" lim)
(skip-chars-backward "/" lim)))
;; c comment
(if (eq literal 'c)
(progn
(skip-chars-backward "^*" lim)
(skip-chars-backward "*" lim)
(while (not (or (and (= (following-char) ?*)
(= (preceding-char) ?/))
(<= (point) lim)))
(skip-chars-backward "^*" lim)
(skip-chars-backward "*" lim))
(or (bobp) (forward-char -1)))
;; preprocessor directive
(if (eq literal 'pound)
(progn
(beginning-of-line)
(setq stop (<= (point) lim)))
;; just outside of c block
(if (and (= (preceding-char) ?/)
(= (char-after (- (point) 2)) ?*))
(progn
(skip-chars-backward "^*" lim)
(skip-chars-backward "*" lim)
(while (not (or (and (= (following-char) ?*)
(= (preceding-char) ?/))
(<= (point) lim)))
(skip-chars-backward "^*" lim)
(skip-chars-backward "*" lim))
(or (bobp) (forward-char -1)))
;; none of the above
(setq stop t))))))))
;; Return `c' if in a C-style comment, `c++' if in a C++ style
;; comment, `string' if in a string literal, `pound' if on a
;; preprocessor line, or nil if not in a comment at all. Optional LIM
;; is used as the backward limit of the search. If omitted, or nil,
;; `beginning-of-defun' is used."
(defun c-emacs18-il (&optional lim)
;; Determine if point is in a C/C++ literal
(save-excursion
(let* ((here (c-point 'eol))
(state nil)
(match nil)
(lim (or lim (c-point 'bod))))
(goto-char lim )
(while (< (point) here)
(setq match
(and (re-search-forward "\\(/[/*]\\)\\|[\"']\\|\\(^[ \t]*#\\)"
here 'move)
(buffer-substring (match-beginning 0) (match-end 0))))
(setq state
(cond
;; no match
((null match) nil)
;; looking at the opening of a C++ style comment
((string= "//" match)
(if (<= here (progn (end-of-line) (point))) 'c++))
;; looking at the opening of a C block comment
((string= "/*" match)
(if (not (re-search-forward "*/" here 'move)) 'c
(if (= (+ (match-beginning 0) 2) here) 'c)))
;; looking at the opening of a double quote string
((string= "\"" match)
(if (not (save-restriction
;; this seems to be necessary since the
;; re-search-forward will not work without it
(narrow-to-region (point) here)
(re-search-forward
;; this regexp matches a double quote
;; which is preceded by an even number
;; of backslashes, including zero
"\\([^\\]\\|^\\)\\(\\\\\\\\\\)*\"" here 'move)))
'string))
;; looking at the opening of a single quote string
((string= "'" match)
(if (not (save-restriction
;; see comments from above
(narrow-to-region (point) here)
(re-search-forward
;; this matches a single quote which is
;; preceded by zero or two backslashes.
"\\([^\\]\\|^\\)\\(\\\\\\\\\\)?'"
here 'move)))
'string))
((string-match "[ \t]*#" match)
(if (<= here (progn (end-of-line) (point))) 'pound))
(t nil)))
) ; end-while
state)))
(defun c-emacs18-mark-function ()
"Put mark at end of a C/C++ defun, point at beginning."
(interactive)
(push-mark (point))
(end-of-defun)
(push-mark)
(beginning-of-defun)
(backward-paragraph))
(defun c-emacs18-insert-special-chars (arg)
;; insert last-command-char in the buffer and possibly tame it
(let ((numarg (prefix-numeric-value arg))
(literal (c-in-literal)))
(and (memq literal '(c c++))
(memq last-command-char c-untame-characters)
(= numarg 1)
(insert "\\"))
(self-insert-command numarg)))
;; Workarounds for GNU Emacs 18 scanning deficiencies
(defun c-tame-insert (arg)
"Safely inserts certain troublesome characters in comment regions.
This function is only necessary in GNU Emacs 18. For details, refer
to the accompanying texinfo manual.
See also the variable `c-untame-characters'."
(interactive "P")
(let ((literal (c-in-literal)))
(c-insert-special-chars arg)))
(defun c-tame-comments ()
"Backslashifies all untamed in comment regions found in the buffer.
This function is only necessary in GNU Emacs 18. For details, refer to
the accompanying texinfo manual.
See also the variable `c-untame-characters'."
(interactive)
;; make the list into a valid charset, escaping where necessary
(let ((charset (concat "^" (mapconcat
(function
(lambda (char)
(if (memq char '(?\\ ?^ ?-))
(concat "\\" (char-to-string char))
(char-to-string char))))
c-untame-characters ""))))
(save-excursion
(beginning-of-buffer)
(while (not (eobp))
(skip-chars-forward charset)
(if (and (not (zerop (following-char)))
(memq (c-in-literal) '(c c++))
(/= (preceding-char) ?\\ ))
(insert-char ?\\ 1))
(if (not (eobp))
(forward-char 1))))))
;; set up an Emacs session to use this stuff
;;(let ((hookfunsym 'c-emacs18-common-hook))
;; (if (fboundp 'add-hook)
;; (add-hook 'c-mode-common-hook hookfunsym)
;; do it the hard way
;; (if (not (memq hookfunsym c-mode-common-hook))
;; (setq c-mode-common-hook (cons hookfunsym c-mode-common-hook))
;; )))
(provide 'cc-mode-18)
;; cc-mode-18.el ends here