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 >
Lisp/Scheme  |  1996-09-28  |  12KB  |  335 lines

  1. ;;; cc-mode-18.el --- compatibility for cc-mode in Emacs 18
  2.  
  3. ;; Authors: 1994 Barry A. Warsaw, Century Computing Inc. <bwarsaw@cen.com>
  4. ;; Maintainer:      cc-mode-help@anthem.nlm.nih.gov
  5. ;; Created:         8-Feb-1994 (from cc-mode.el)
  6. ;; Version:         1.11
  7. ;; Last Modified:   1994/04/15 23:14:27
  8. ;; Keywords: C++ C editing major-mode Emacs 18 compatible
  9.  
  10. ;; Copyright (C) 1994 Barry A. Warsaw
  11.  
  12. ;; This file is not yet part of GNU Emacs, and hopefully never will be.
  13. ;;
  14. ;; This program is free software; you can redistribute it and/or modify
  15. ;; it under the terms of the GNU General Public License as published by
  16. ;; the Free Software Foundation; either version 2 of the License, or
  17. ;; (at your option) any later version.
  18. ;; 
  19. ;; This program is distributed in the hope that it will be useful,
  20. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22. ;; GNU General Public License for more details.
  23. ;; 
  24. ;; You should have received a copy of the GNU General Public License
  25. ;; along with this program; if not, write to the Free Software
  26. ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  27.  
  28. ;;; Commentary:
  29.  
  30. ;; This file provides hooks into cc-mode for use with Emacs 18. All
  31. ;; native Emacs 18 support has been moved out of cc-mode.el proper. If
  32. ;; you find you need this file (i.e. you're using Emacs 18), you
  33. ;; should SERIOUSLY consider upgrading to FSF or Lucid 19.  Emacs 18
  34. ;; simply doesn't have what it takes to edit C++ code.
  35. ;;
  36. ;; To use this, put the following in your .emacs file:
  37. ;;
  38. ;; (require 'cc-mode-18)
  39. ;; (or (assq 'c-emacs18-common-hook c-mode-common-hook)
  40. ;;     (setq c-mode-common-hook (cons 'c-emacs18-common-hook
  41. ;;                                    c-mode-common-hook)))
  42. ;;
  43. ;; I cannot provide any direct support for v18 support anymore, but I
  44. ;; will install and distribute contributed patches.  This file, and
  45. ;; v18 support in general should be considered sold "As Is".  Caveat
  46. ;; Emptor! :-)
  47.  
  48. ;; LCD Archive Entry:
  49. ;; cc-mode-18.el|Barry A. Warsaw|cc-mode-help@anthem.nlm.nih.gov
  50. ;; |Compatibility for cc-mode in Emacs 18
  51. ;; |1994/04/15 23:14:27|1.11|
  52.  
  53. ;;; Code:
  54. (require 'cc-mode)
  55.  
  56.  
  57. ;; user definable variables
  58. ;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  59.  
  60. (defvar c-untame-characters '(?\')
  61.   "*Utilize a backslashing workaround of an Emacs18 syntax deficiency.
  62. If non-nil, this variable should contain a list of characters which
  63. are prepended by a backslash in comment regions.  By default, the list
  64. contains only the most troublesome character, the single quote.  To be
  65. completely safe, set this variable to:
  66.  
  67.     '(?\( ?\) ?\' ?\{ ?\} ?\[ ?\])
  68.  
  69. This variable has no effect under Emacs 19. For details on why this is
  70. necessary in GNU Emacs 18, please refer to the cc-mode texinfo manual.")
  71.  
  72. (defvar c-backscan-limit 2000
  73.   "*Character limit for looking back while skipping syntactic whitespace.
  74. This variable has no effect under Emacs 19.  For details on why this
  75. is necessary under GNU Emacs 18, please refer to the texinfo manual.")
  76.  
  77.  
  78. ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  79. ;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT
  80.  
  81. ;; extend the keymap
  82. (defun c-emacs18-common-hook ()
  83.   ;; Do all the set up necessary to get cc-mode working in Emacs 18,
  84.   ;; but make sure we only do it once
  85.   (if (or (get 'c-mode 'c-emacs-18)
  86.       (not (featurep 'cc-mode))
  87.       (not (memq 'v18 c-emacs-features)))
  88.       ;; do nothing if conditions we aren't in Emacs 18, or cc-mode
  89.       ;; hasn't been loaded yet, or we've already run this hook
  90.       nil
  91.     ;; extend the keymap for use with Emacs 18. c-mode-map must already
  92.     ;; be set up (i.e. from cc-mode.el)
  93.     (define-key c-mode-map "\C-c'" 'c-tame-comments)
  94.     (define-key c-mode-map "'"     'c-tame-insert)
  95.     (define-key c-mode-map "["     'c-tame-insert)
  96.     (define-key c-mode-map "]"     'c-tame-insert)
  97.     (define-key c-mode-map "("     'c-tame-insert)
  98.     (define-key c-mode-map ")"     'c-tame-insert)
  99.  
  100.     ;; Vanilla GNU18 doesn't support mult-style comments.  We'll do
  101.     ;; the best we can, but some strange behavior may be encountered.
  102.     ;; PATCH or UPGRADE!
  103.     (modify-syntax-entry ?/  ". 124" c-mode-syntax-table)
  104.     (modify-syntax-entry ?*  ". 23"  c-mode-syntax-table)
  105.     (modify-syntax-entry ?\n ">"     c-mode-syntax-table)
  106.  
  107.     (modify-syntax-entry ?/  ". 124" c++-mode-syntax-table)
  108.     (modify-syntax-entry ?*  ". 23"  c++-mode-syntax-table)
  109.     (modify-syntax-entry ?\n ">"     c++-mode-syntax-table)
  110.  
  111.     ;; set up comment skipping interface functions, and other
  112.     ;; non-compatible functions
  113.     (fset 'c-forward-syntactic-ws 'c-emacs18-fsws)
  114.     (fset 'c-backward-syntactic-ws 'c-emacs18-bsws)
  115.     (fset 'c-in-literal 'c-emacs18-il)
  116.     (fset 'c-mark-function 'c-emacs18-mark-function)
  117.     (fset 'c-insert-special-chars 'c-emacs18-insert-special-chars)
  118.  
  119.     ;; Emacs 18 can't handle parse-sexp-ignore-comments == t
  120.     (setq parse-sexp-ignore-comments nil)
  121.  
  122.     ;; put the property out there so we don't do this again
  123.     (put 'c-mode 'c-emacs-18 'c-emacs-18)
  124.     ))
  125.  
  126.  
  127. ;; Emacs 18 support for whitespace skipping and literal parsing.
  128.  
  129. ;; Emacs 19 has nice built-in functions to do this, but Emacs 18 does
  130. ;; not.  Also note that only Emacs19 implementation currently has
  131. ;; support for multi-line macros, and this feature is imposes the
  132. ;; restriction that backslashes at the end of a line can only occur on
  133. ;; multi-line macro lines.
  134.  
  135. ;; This is the best we can do in vanilla GNU 18 Emacsen.
  136. (defun c-emacs18-fsws (&optional lim)
  137.   ;; Forward skip syntactic whitespace for Emacs 18.
  138.   (let ((lim (or lim (point-max)))
  139.     stop)
  140.     (while (not stop)
  141.       (skip-chars-forward " \t\n\r\f" lim)
  142.       (cond
  143.        ;; c++ comment
  144.        ((looking-at "//") (end-of-line))
  145.        ;; c comment
  146.        ((looking-at "/\\*") (re-search-forward "*/" lim 'noerror))
  147.        ;; preprocessor directive
  148.        ((and (= (c-point 'boi) (point))
  149.          (= (following-char) ?#))
  150.     (end-of-line))
  151.        ;; none of the above
  152.        (t (setq stop t))
  153.        ))))
  154.  
  155. (defun c-emacs18-bsws (&optional lim)
  156.   ;; Backward skip syntactic whitespace for Emacs 18.
  157.   (let ((lim (or lim (c-point 'bod)))
  158.     literal stop)
  159.     (if (and c-backscan-limit
  160.          (> (- (point) lim) c-backscan-limit))
  161.     (setq lim (- (point) c-backscan-limit)))
  162.     (while (not stop)
  163.       (skip-chars-backward " \t\n\r\f" lim)
  164.       ;; c++ comment
  165.       (if (eq (setq literal (c-in-literal lim)) 'c++)
  166.       (progn
  167.         (skip-chars-backward "^/" lim)
  168.         (skip-chars-backward "/" lim)
  169.         (while (not (or (and (= (following-char) ?/)
  170.                  (= (char-after (1+ (point))) ?/))
  171.                 (<= (point) lim)))
  172.           (skip-chars-backward "^/" lim)
  173.           (skip-chars-backward "/" lim)))
  174.     ;; c comment
  175.     (if (eq literal 'c)
  176.         (progn
  177.           (skip-chars-backward "^*" lim)
  178.           (skip-chars-backward "*" lim)
  179.           (while (not (or (and (= (following-char) ?*)
  180.                    (= (preceding-char) ?/))
  181.                   (<= (point) lim)))
  182.         (skip-chars-backward "^*" lim)
  183.         (skip-chars-backward "*" lim))
  184.           (or (bobp) (forward-char -1)))
  185.       ;; preprocessor directive
  186.       (if (eq literal 'pound)
  187.           (progn
  188.         (beginning-of-line)
  189.         (setq stop (<= (point) lim)))
  190.         ;; just outside of c block
  191.         (if (and (= (preceding-char) ?/)
  192.              (= (char-after (- (point) 2)) ?*))
  193.         (progn
  194.           (skip-chars-backward "^*" lim)
  195.           (skip-chars-backward "*" lim)
  196.           (while (not (or (and (= (following-char) ?*)
  197.                        (= (preceding-char) ?/))
  198.                   (<= (point) lim)))
  199.             (skip-chars-backward "^*" lim)
  200.             (skip-chars-backward "*" lim))
  201.           (or (bobp) (forward-char -1)))
  202.           ;; none of the above
  203.           (setq stop t))))))))
  204.  
  205.  
  206. ;; Return `c' if in a C-style comment, `c++' if in a C++ style
  207. ;; comment, `string' if in a string literal, `pound' if on a
  208. ;; preprocessor line, or nil if not in a comment at all.  Optional LIM
  209. ;; is used as the backward limit of the search.  If omitted, or nil,
  210. ;; `beginning-of-defun' is used."
  211. (defun c-emacs18-il (&optional lim)
  212.   ;; Determine if point is in a C/C++ literal
  213.   (save-excursion
  214.     (let* ((here (c-point 'eol))
  215.        (state nil)
  216.        (match nil)
  217.        (lim  (or lim (c-point 'bod))))
  218.       (goto-char lim )
  219.       (while (< (point) here)
  220.     (setq match
  221.           (and (re-search-forward "\\(/[/*]\\)\\|[\"']\\|\\(^[ \t]*#\\)"
  222.                       here 'move)
  223.            (buffer-substring (match-beginning 0) (match-end 0))))
  224.     (setq state
  225.           (cond
  226.            ;; no match
  227.            ((null match) nil)
  228.            ;; looking at the opening of a C++ style comment
  229.            ((string= "//" match)
  230.         (if (<= here (progn (end-of-line) (point))) 'c++))
  231.            ;; looking at the opening of a C block comment
  232.            ((string= "/*" match)
  233.         (if (not (re-search-forward "*/" here 'move)) 'c
  234.           (if (= (+ (match-beginning 0) 2) here) 'c)))
  235.            ;; looking at the opening of a double quote string
  236.            ((string= "\"" match)
  237.         (if (not (save-restriction
  238.                ;; this seems to be necessary since the
  239.                ;; re-search-forward will not work without it
  240.                (narrow-to-region (point) here)
  241.                (re-search-forward
  242.                 ;; this regexp matches a double quote
  243.                 ;; which is preceded by an even number
  244.                 ;; of backslashes, including zero
  245.                 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)*\"" here 'move)))
  246.             'string))
  247.            ;; looking at the opening of a single quote string
  248.            ((string= "'" match)
  249.         (if (not (save-restriction
  250.                ;; see comments from above
  251.                (narrow-to-region (point) here)
  252.                (re-search-forward
  253.                 ;; this matches a single quote which is
  254.                 ;; preceded by zero or two backslashes.
  255.                 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)?'"
  256.                 here 'move)))
  257.             'string))
  258.            ((string-match "[ \t]*#" match)
  259.         (if (<= here (progn (end-of-line) (point))) 'pound))
  260.            (t nil)))
  261.     ) ; end-while
  262.       state)))
  263.  
  264.  
  265. (defun c-emacs18-mark-function ()
  266.   "Put mark at end of a C/C++ defun, point at beginning."
  267.   (interactive)
  268.   (push-mark (point))
  269.   (end-of-defun)
  270.   (push-mark)
  271.   (beginning-of-defun)
  272.   (backward-paragraph))
  273.  
  274.  
  275. (defun c-emacs18-insert-special-chars (arg)
  276.   ;; insert last-command-char in the buffer and possibly tame it
  277.   (let ((numarg (prefix-numeric-value arg))
  278.     (literal (c-in-literal)))
  279.     (and (memq literal '(c c++))
  280.      (memq last-command-char c-untame-characters)
  281.      (= numarg 1)
  282.      (insert "\\"))
  283.     (self-insert-command numarg)))
  284.  
  285.  
  286. ;; Workarounds for GNU Emacs 18 scanning deficiencies
  287. (defun c-tame-insert (arg)
  288.   "Safely inserts certain troublesome characters in comment regions.
  289. This function is only necessary in GNU Emacs 18.  For details, refer
  290. to the accompanying texinfo manual.
  291.  
  292. See also the variable `c-untame-characters'."
  293.   (interactive "P")
  294.   (let ((literal (c-in-literal)))
  295.     (c-insert-special-chars arg)))
  296.  
  297. (defun c-tame-comments ()
  298.   "Backslashifies all untamed in comment regions found in the buffer.
  299. This function is only necessary in GNU Emacs 18. For details, refer to
  300. the accompanying texinfo manual.
  301.  
  302. See also the variable `c-untame-characters'."
  303.   (interactive)
  304.   ;; make the list into a valid charset, escaping where necessary
  305.   (let ((charset (concat "^" (mapconcat
  306.                   (function
  307.                    (lambda (char)
  308.                  (if (memq char '(?\\ ?^ ?-))
  309.                      (concat "\\" (char-to-string char))
  310.                    (char-to-string char))))
  311.                   c-untame-characters ""))))
  312.     (save-excursion
  313.       (beginning-of-buffer)
  314.       (while (not (eobp))
  315.     (skip-chars-forward charset)
  316.     (if (and (not (zerop (following-char)))
  317.          (memq (c-in-literal) '(c c++))
  318.          (/= (preceding-char) ?\\ ))
  319.         (insert-char  ?\\ 1))
  320.     (if (not (eobp))
  321.         (forward-char 1))))))
  322.  
  323.  
  324. ;; set up an Emacs session to use this stuff
  325. ;;(let ((hookfunsym 'c-emacs18-common-hook))
  326. ;;  (if (fboundp 'add-hook)
  327. ;;      (add-hook 'c-mode-common-hook hookfunsym)
  328.     ;; do it the hard way
  329. ;;    (if (not (memq hookfunsym c-mode-common-hook))
  330. ;;    (setq c-mode-common-hook (cons hookfunsym c-mode-common-hook))
  331. ;;      )))
  332.  
  333. (provide 'cc-mode-18)
  334. ;; cc-mode-18.el ends here
  335.