Hi Vin,
Thanks for responding. Well, my crash never occurs when I start with a
-vanilla, leading me to thing that this is possibly due to some gotcha
in my init.el (or custom.el, but, don't have much in my custom.el) file.
For your benefit, I am attaching my init.el here - everything in there
was scooped from somewhere in the net. I'll build xemacs with the
debugging turned on and then send you my results; please give me some time.
Thanks,
Arvind.
Vin Shelton wrote:
Arvind, thanks for your report. Can you give us a recipe to
reproduce
your crash? I use XEmacs fairly extensively on my Solaris boxes at
work, and it works reliably. (I generally build with the Sun C
compiler, but I do on occasion build with gcc, currently version
3.2.2, I believe.)
Arvind Devarajan <arvind.sankruthi(a)oracle.com> writes:
>
/usr/dt/lib:/usr/openwin/lib:/home2/gcc/bin/../lib/gcc-lib/sparc-sun-solaris2.6/3.1/../../..:/home2/gcc//lib/gcc-lib/sparc-sun-solaris2.6/3.1/../../..
>
>
Unrelated to your problem, but aren't those last 2 directories in your
runtime library path the same?
> Operating system description file: `s/sol2.h'
> Machine description file: `m/sparc.h'
> Compiler: gcc -g -O3 -Wall -Wno-switch
> -Winline -Wmissing-prototypes -Wsign-compare -Wshadow -Wpointer-arith
> Relocating allocator for buffers: yes
> GNU version of malloc: yes
>
>Window System:
> Compiling in support for the X window system:
> - X Windows headers location: /usr/dt/include
> /usr/openwin/include
> - X Windows libraries location: /usr/dt/lib
> /usr/openwin/lib
> - Handling WM_COMMAND properly.
> Using Lucid menubars.
> Using Lucid scrollbars.
> Using Motif dialog boxes.
> Using Motif native widgets.
>
>TTY:
> Compiling in support for ncurses.
>
>Images:
> Compiling in support for GIF images (builtin).
> Compiling in support for XPM images.
> Compiling in support for PNG images.
> Compiling in support for JPEG images.
>
>Sound:
>
>Databases:
> Compiling in support for Berkeley database.
> Compiling in support for DBM.
>
>Internationalization:
>
>Mail:
> Compiling in support for "dot-locking" mail spool file locking method.
>
>Other Features:
> Inhibiting IPv6 canonicalization at startup.
> Compiling in support for ToolTalk.
> Compiling in support for dynamic shared object modules.
>
>/*Call stack obtained from gdb:*/
>
>#0 0xef00a5f0 in ?? ()
>#1 0xeefb973c in ?? ()
>#2 0xef6cd97c in ?? ()
>#3 0xef68041c in ?? ()
>#4 0xef6cda48 in ?? ()
>#5 0xef39f9a4 in ?? ()
>#6 0xef3a8208 in ?? ()
>#7 0xef3a8420 in ?? ()
>#8 0xef3a8630 in ?? ()
>#9 0x17b08c in MenuProcedureEntry ()
>#10 0x6a7a8 in Fscroll_left ()
>#11 0x61710 in output_display_line ()
>#12 0x7cdf0 in x_any_window_to_frame ()
>#13 0x7fff8 in x_show_gc_cursor ()
>#14 0x558b0 in create_text_block ()
>#15 0x5542c in add_glyph_rune ()
>#16 0x7ff24 in Fx_set_scrollbar_pointer ()
>#17 0x598b4 in regenerate_window_incrementally ()
>#18 0x7ec70 in x_initialize_frame_size ()
>#19 0xafd6c in Fexpand_file_name ()
>#20 0xabfbc in buffer_insert_c_string_1 ()
>#21 0x5fe64 in vars_of_redisplay ()
>#22 0x7dc74 in init_x_parm_symbols ()
>---Type <return> to continue, or q <return> to quit---
>#23 0x6031c in sync_rune_structs ()
>#24 0x7db38 in init_x_parm_symbols ()
>#25 0x5faf0 in Fforce_cursor_redisplay ()
>#26 0x7b2a8 in x_generate_shadow_pixels ()
>#27 0x7bac0 in x_redraw_exposed_area ()
>
>
This backtrace doesn't help much. Can you build an XEmacs with
debugging enabled (ie configured --debug)? A recipe that reliably
reproduces your crash from a -vanilla XEmacs would be more likely to
get investigated.
Thanks,
Vin
;; Options Menu Settings
;; =====================
(cond
((and (string-match "XEmacs" emacs-version)
(boundp 'emacs-major-version)
(or (and
(= emacs-major-version 19)
(>= emacs-minor-version 14))
(= emacs-major-version 20))
(fboundp 'load-options-file))
(load-options-file "/home/asankrut/.xemacs-options")))
;; ============================
;; End of Options Menu Settings
;; If a C file is being edited...
(add-hook 'c-mode-common-hook
;; Auto-insert newlines
(lambda() (c-toggle-auto-state 1)
;; Align open braces under "if", "for", etc.
(c-set-offset 'substatement-open 0))
)
;; (add-hook 'c-mode-common-hook
;; Turn on auto-insertion of newline
;; (lambda () (c-toggle-auto-state 1)
;; ============================
;; Get matching parenthesis
(global-set-key "%" 'match-paren)
(defun match-paren (arg)
"Go to the matching parenthesis if on parenthesis otherwise insert %."
(interactive "p")
(cond ((looking-at "\\s\(") (forward-list 1) (backward-char 1))
((looking-at "\\s\)") (forward-char 1) (backward-list 1))
(t (self-insert-command (or arg 1)))))
;; =======================
;; Number source lines
(provide 'setnu)
(defconst setnu-running-under-xemacs
(or (string-match "XEmacs" emacs-version)
(string-match "Lucid" emacs-version)))
(defconst setnu-mode-version "1.06"
"Version number for this release of setnu-mode.")
(defvar setnu-mode nil
"Non-nil if setnu-mode is active in the current buffer.")
(make-variable-buffer-local 'setnu-mode)
(defvar setnu-start-extent nil
"First extent of a chain of extents used by setnu-mode.
Each line has its own extent. Each line extent has a
`setnu-next-extent' property that points to the next extent in
the chain, which is the extent for the next line in the buffer.
There is also a `setnu-prev-extent' that points at the previous
extent in the chain. To distinguish them from other extents the
setnu-mode extents all have a non-nil `setnu' property.")
(make-variable-buffer-local 'setnu-start-extent)
(defvar setnu-glyph-obarray (make-vector 401 0)
"Obarray of symbols whose values are line number glyphs.
Each symbol name is the string represnetation of a number, perhaps
passed with spaces. The value of the symbol is a glyph that can
be made the begin glyph of an extent to display as a line number.")
(defvar setnu-begin-glyph-property (if (fboundp 'extent-property)
'begin-glyph
'before-string)
"Property name to use to set the begin glyph of an extent.")
(defvar setnu-line-number-format (if setnu-running-under-xemacs "%4d" "%6d
")
"String suitable for `format' that will generate a line number string.
`format' will be called with this string and one other argument
which will be an integer, the line number.")
(defvar setnu-line-number-face 'bold
"*Face used to display the line numbers.
Currently this works for XEmacs 19.12 and later versions only.")
(defun setnu-mode (&optional arg)
"Toggle setnu-mode.
With prefix argument, turn setnu-mode on if argument is positive.
When setnu-mode is enabled, a line number will appear at the left
margin of each line."
(interactive "P")
(let ((oldmode (not (not setnu-mode)))
(inhibit-quit t))
(setq setnu-mode (or (and arg (> (prefix-numeric-value arg) 0))
(and (null arg) (null setnu-mode))))
(if (not (eq oldmode setnu-mode))
(if setnu-mode
(setnu-mode-on)
(setnu-mode-off)))))
(defun turn-on-setnu-mode ()
"Turn on setnu-mode.
Useful for adding to a major-mode hook variable.
Example:
(add-hook 'text-mode-hook 'turn-on-setnu-mode)
to automatically turn on line numbering when enterting text-mode."
(setnu-mode 1))
;;; Internal functions
;;; The program is written using XEmacs terminology,
;;; e.g. extents, glyphs, etc. Functions are defined to twist
;;; the FSF Emacs overlay API into the XEmacs model.
(defconst setnu-running-under-xemacs
(or (string-match "XEmacs" emacs-version)
(string-match "Lucid" emacs-version)))
(if setnu-running-under-xemacs
(fset 'setnu-make-extent 'make-extent)
(fset 'setnu-make-extent 'make-overlay))
(if setnu-running-under-xemacs
(fset 'setnu-delete-extent 'delete-extent)
(fset 'setnu-delete-extent 'delete-overlay))
(if setnu-running-under-xemacs
(fset 'setnu-extent-property 'extent-property)
(fset 'setnu-extent-property 'overlay-get))
(if setnu-running-under-xemacs
(fset 'setnu-set-extent-property 'set-extent-property)
(fset 'setnu-set-extent-property 'overlay-put))
(if setnu-running-under-xemacs
(fset 'setnu-set-extent-endpoints 'set-extent-endpoints)
(fset 'setnu-set-extent-endpoints 'move-overlay))
(if setnu-running-under-xemacs
(fset 'setnu-extent-end-position 'extent-end-position)
(fset 'setnu-extent-end-position 'overlay-end))
(if setnu-running-under-xemacs
(fset 'setnu-extent-start-position 'extent-start-position)
(fset 'setnu-extent-start-position 'overlay-start))
(if setnu-running-under-xemacs
(defun setnu-set-extent-begin-glyph (e g)
(set-extent-begin-glyph e g 'outside-margin))
(defun setnu-set-extent-begin-glyph (e g)
(overlay-put e setnu-begin-glyph-property g)))
(fset 'setnu-make-glyph (if setnu-running-under-xemacs 'make-glyph
'identity))
(cond ((and setnu-running-under-xemacs (fboundp 'set-glyph-face))
(fset 'setnu-set-glyph-face 'set-glyph-face))
(setnu-running-under-xemacs
(fset 'setnu-set-glyph-face 'ignore))
(t ; FSF Emacs
(defun setnu-set-glyph-face (g face)
(put-text-property 0 (length g) 'face face g))))
(defun setnu-mode-off ()
"Internal shutdown of setnu-mode.
Deletes the extents associated with setnu-mode."
(if (and setnu-running-under-xemacs
(fboundp 'remove-specifier))
(remove-specifier left-margin-width (current-buffer)))
(if setnu-start-extent
(let (e ee)
(setq e setnu-start-extent)
(while e
(setq ee e)
(setq e (setnu-extent-property e 'setnu-next-extent))
(setnu-delete-extent ee))
(setq setnu-start-extent nil))))
(defun setnu-mode-on ()
"Internal startup of setnu-mode.
Sets up the extents associated with setnu-mode."
(if (and setnu-running-under-xemacs
(fboundp 'set-specifier))
(set-specifier left-margin-width 6 (current-buffer)))
(let ((done nil)
(curr-e nil)
(n 1)
(match-data (match-data))
e start numstr)
(unwind-protect
(save-excursion
(save-restriction
(widen)
(goto-char (point-min))
(setq start (point))
(while (not done)
(setq done (null (search-forward "\n" nil 0)))
(setq e (setnu-make-setnu-extent start (point)))
(if (null setnu-start-extent)
(setq setnu-start-extent e
curr-e e)
(setnu-set-extent-property curr-e 'setnu-next-extent e)
(setnu-set-extent-property e 'setnu-prev-extent curr-e)
(setq curr-e e))
(setq numstr (format setnu-line-number-format n))
(setnu-set-extent-property e 'line-number numstr)
(setnu-set-extent-begin-glyph e (setnu-number-glyph numstr))
(setq n (1+ n)
start (point)))))
(store-match-data match-data))))
(defun setnu-before-change-function (start end)
"Before change function for setnu-mode.
Notices when a delete is about to delete some lines and adjusts
the line number extents accordingly."
(if (or (not setnu-mode) (= start end))
() ;; not in setnu-mode or this is an insertion
(let ((inhibit-quit t)
(start-e nil)
(match-data (match-data))
end-e saved-next e ee)
(unwind-protect
(save-excursion
(save-restriction
(widen)
(goto-char start)
(if (search-forward "\n" end t)
(progn
(setq start-e (setnu-extent-at-create start nil)
saved-next (setnu-extent-property
start-e
'setnu-next-extent))
(setq end-e (setnu-extent-at-create end nil))
(setnu-set-extent-endpoints
start-e
(setnu-extent-start-position start-e)
(setnu-extent-end-position end-e))
(setnu-set-extent-property
start-e 'setnu-next-extent
(setnu-extent-property end-e 'setnu-next-extent))))
(if start-e
(progn
(setq e (setnu-extent-property start-e 'setnu-next-extent)
ee saved-next)
(while (and e (setnu-extent-property e 'setnu-next-extent))
(setq e (setnu-extent-property e 'setnu-next-extent)
ee (setnu-extent-property ee 'setnu-next-extent)))
(while (and e (not (eq ee start-e)))
(setnu-set-extent-begin-glyph
e (setnu-extent-property ee setnu-begin-glyph-property))
(setnu-set-extent-property
e 'line-number (setnu-extent-property ee 'line-number))
(setq e (setnu-extent-property e 'setnu-prev-extent)
ee (setnu-extent-property ee 'setnu-prev-extent)))
(setq end-e (setnu-extent-property start-e
'setnu-next-extent))
(and end-e
(setnu-set-extent-property end-e
'setnu-prev-extent
start-e))
(setq e saved-next)
(while (not (eq e end-e))
(setq ee e
e (setnu-extent-property e 'setnu-next-extent))
(setnu-delete-extent ee))))))
(store-match-data match-data)))))
(defun setnu-after-change-function (start end length)
"After change function for setnu-mode.
Notices when an insert has added some lines and adjusts
the line number extents accordingly."
(if (or (not setnu-mode) (= start end))
() ; not in setnu-mode or this is a deletion
(let ((inhibit-quit t)
(ee nil)
(match-data (match-data))
(new-lines 0)
start-e e saved-end saved-next n numstr)
(unwind-protect
(save-excursion
(save-restriction
(widen)
(setq start-e (setnu-extent-at-create start nil))
(if (< (setnu-extent-end-position start-e) (point))
;; bogus! insertion didn't put the text into
;; the extent because,
;; a. the extent was zero length or
;; b. this is FSF Emacs which means chars
;; inserted at the end position of an extent
;; are not inserted into the extent.
(setnu-set-extent-endpoints
start-e
(setnu-extent-start-position start-e)
end))
(setq saved-next (setnu-extent-property start-e
'setnu-next-extent)
saved-end (setnu-extent-end-position start-e)
e start-e)
(goto-char start)
(while (search-forward "\n" end 0)
(setnu-set-extent-endpoints e
(setnu-extent-start-position e)
(point))
(setq ee (setnu-make-setnu-extent (point) (point)))
(setnu-set-extent-property e 'setnu-next-extent ee)
(setnu-set-extent-property ee 'setnu-prev-extent e)
(setq e ee new-lines (1+ new-lines)))
(if ee
(progn
(setnu-set-extent-endpoints
e (setnu-extent-start-position e) saved-end)
(setnu-set-extent-property e 'setnu-next-extent saved-next)
(and saved-next
(setnu-set-extent-property
saved-next 'setnu-prev-extent e))
(setq e (setnu-extent-property start-e 'setnu-next-extent)
ee saved-next)
(while ee
(setnu-set-extent-begin-glyph
e (setnu-extent-property ee setnu-begin-glyph-property))
(setnu-set-extent-property
e 'line-number (setnu-extent-property ee 'line-number))
(setq e (setnu-extent-property e 'setnu-next-extent)
ee (setnu-extent-property ee 'setnu-next-extent)))
(setq n (1+ (string-to-int
(setnu-extent-property
(setnu-extent-property e 'setnu-prev-extent)
'line-number))))
(while e
(setq numstr (format setnu-line-number-format n))
(setnu-set-extent-property e 'line-number numstr)
(setnu-set-extent-begin-glyph
e (setnu-number-glyph numstr))
(setq e (setnu-extent-property e 'setnu-next-extent)
n (1+ n)))))))
(store-match-data match-data)))))
(defun setnu-number-glyph (number-string)
(let ((sym (intern number-string setnu-glyph-obarray)))
(if (boundp sym)
(symbol-value sym)
(let ((g (setnu-make-glyph number-string)))
(set sym g)
(setnu-set-glyph-face g setnu-line-number-face)
g ))))
(defun setnu-make-setnu-extent (beg end)
"Create an extent and set some properties that all setnu extents have."
(let ((e (setnu-make-extent beg end)))
(setnu-set-extent-property e 'setnu t)
;; (setnu-set-extent-property e 'begin-glyph-layout 'outside-margin)
(setnu-set-extent-property e 'detachable nil)
(setnu-set-extent-property e 'evaporate nil)
e ))
(cond ((fboundp 'overlays-in) ;; expect to see this in 19.30
(defun setnu-extent-at (pos buf)
"Finds the setnu extent at the position POS in the buffer BUF."
(catch 'done
(save-excursion
(and buf (set-buffer buf))
(let ((o-list (overlays-in pos (1+ pos))))
(while o-list
(if (overlay-get (car o-list) 'setnu)
(throw 'done (car o-list)))
(setq o-list (cdr o-list)))
nil )))))
((fboundp 'overlays-at)
(defun setnu-extent-at (pos buf)
"Finds the setnu extent at the position POS in the buffer BUF."
(catch 'done
(save-excursion
(and buf (set-buffer buf))
(let ((o-list (overlays-at pos)) o-lists)
;; search what overlays-at returns first. for all
;; but zero length extents this will return the
;; extent we want.
(while o-list
(if (overlay-get (car o-list) 'setnu)
(throw 'done (car o-list)))
(setq o-list (cdr o-list)))
;; No luck. Search the lists returned by
;; overlay-lists. Use overlays-recenter so we only
;; have to search the `before' lobe of the return
;; value.
(overlay-recenter (1- pos))
(setq o-lists (overlay-lists))
(setq o-list (cdr o-lists))
(while o-list
(if (and (overlay-get (car o-list) 'setnu)
(or (and (= pos (overlay-start (car o-list)))
(= pos (overlay-end (car o-list))))
(and (>= pos (overlay-start (car o-list)))
(< pos (overlay-end (car o-list))))))
(throw 'done (car o-list)))
(setq o-list (cdr o-list)))
nil )))))
((fboundp 'map-extents)
(defun setnu-extent-at (pos buf)
"Finds the setnu extent at the position POS in the buffer BUF."
(map-extents (function (lambda (e maparg)
(if (setnu-extent-property e 'setnu)
e
nil)))
buf pos pos)))
(t (error "can't find overlays-in, overlays-at, or map-extents!")))
(defun setnu-extent-at-create (pos buf)
"Like `setnu-extent-at' except if an extent isn't found, then
it is created based on where the extent failed to be found."
(let ((e (setnu-extent-at pos buf)) ee beg numstr)
(if e
e
;; no extent found so one must be created.
(save-excursion
(goto-char pos)
(beginning-of-line)
(setq e (setnu-extent-at (point) buf))
(cond (e
;; found one. extend it to cover this whole line.
;; this takes care of zero length extents that
;; might exist at bob or eob that can't be
;; inserted into.
(setq beg (point))
(forward-line 1)
(setnu-set-extent-endpoints e beg (point))
e )
((bobp)
;; we are at bob and there's no extent.
;;
;; this is because the extent that was there got
;; detached because all the text in the buffer was
;; deleted. so we create a new extent and make it
;; contain the whole buffer, since there can be no
;; other attached extents.
(setq e (setnu-make-setnu-extent (point-min) (point-max))
numstr (format setnu-line-number-format 1))
(setnu-set-extent-property e 'line-number numstr)
(setnu-set-extent-begin-glyph e (setnu-number-glyph numstr))
(setq setnu-start-extent e)
e )
(t
;; we must be at eob and there's no extent.
;;
;; this is because the extent that was there
;; shrank to zero length and was detached. create
;; a new extent that contains all text from point
;; to pos.
(setq e (setnu-make-setnu-extent (point) pos))
(setq ee (setnu-extent-at (1- (point)) buf))
(setnu-set-extent-property e 'setnu-prev-extent ee)
(setnu-set-extent-property ee 'setnu-next-extent e)
(setq numstr
(format setnu-line-number-format
(1+ (string-to-int
(setnu-extent-property ee 'line-number)))))
(setnu-set-extent-property e 'line-number numstr)
(setnu-set-extent-begin-glyph e (setnu-number-glyph numstr))
e ))))))
(add-hook 'before-change-functions 'setnu-before-change-function)
(add-hook 'after-change-functions 'setnu-after-change-function)
;; =======================
;; cscope interface
; This is an interface from GNUemacs to Joe Steffen's "cscope" C browser.
; With this code, you can do things like put your cursor on some C
; symbol, hit a couple keys and be transported anyplace special that
; cscope knows about. See the variable cscope-blurb for more general info.
;
; If you use this, I am interested in hearing from you how it went,
; especially if you find bugs or if you use cscope in some way that
; this interface doesn't support (or doesn't support very well).
;
; Bill William_J_Carpenter(a)ATT.COM or
; (908) 576-2932 attmail!bill or att!pegasus!billc
; AT&T Bell Labs / AT&T EasyLink Services LZ 1E-207
;;cscope.el
;;
;;;
;;; LCD Archive Entry:
;;; cscope|Bill Carpenter|William_J_Carpenter(a)ATT.COM
;;; |Interface to cscope browser
;;; |91-11-11|1|archive.cis.ohio-state.edu:/pub/gnu/emacs/elisp-archive/.../cscope.el.Z
;;;
;;; patchlevel 0, 13-Oct-91 (beta)
;;; patchlevel 1, 11-Nov-91 first general release
;;;
;;; As far as I'm concerned, anyone can do anything they want with
;;; this specific piece of code. No warranty or promise of support is
;;; offered. I am interested in hearing reports of bugs or interesting
;;; uses. Suggestions for interesting enhancements are welcome.
;;; My thanks to the beta testers. I am especially appreciative of
;;; the helpful feedback received about earlier versions of this from
;;; Mike Balenger and Neal McBurnett.
(defconst cscope-version "patchlevel 1, 11 Nov 91")
(defvar cscope-bindings-2deep nil
"*If non-nil, then two character bindings are applied when
\"cscope-bind-keys\" is called. The two character bindings are mostly
of the form \"C-c letter\". The reason they are optional is that there
is an elisp coding convention which suggests that those kinds of bindings
should be reserved for users. The binding of \"C-c C-c\" is not controlled
by this user option variable; it is always applied.")
(defvar cscope-bindings-3deep t
"*If non-nil, then three character bindings are applied when
\"cscope-bind-keys\" is called. The three character bindings are mostly
of the form \"C-c C-s letter\".")
(defvar cscope-bind-keys-hook nil
"At the end of the function \"cscope-find-keys\", this hook is run.
This provides an opportunity for custom keybinding schemes as well as any
other buffer-specific set-up. In cscope output buffers, this hook is run
before the extra bindings are applied; however, since those extra bindings
are all in \"cscope-keymap\", they can be modified directly by the user
to affect all cscope output buffers.")
(defvar cscope-quit-hook nil
"Called after a cscope subprocess is told to exit. If called as part of
a command that also kills the buffer, the hook is run before the buffer is
killed.")
(defvar cscope-b-and-f-hook nil
"Run after the user bounces back to the cscope output buffer from a
source file. This hook is run after the cursor has been positoned. It gives
the user an opportunity to use some other cursor positioning strategy instead
of just advancing to the next line.")
(defvar cscope-interpret-output-hook nil
"Run after the user moves from a cscope output line to the referenced
source file. This hook is run after the cursor has been positoned. It gives
the user an opportunity to use some other cursor positioning strategy.")
(defvar cscope-query-hook nil
"Run after a query has been made of the cscope subprocess. Normally, the
cscope interface tries to position the cursor at the first cscope
result line, but it is possible for it to miss. This hook allows an
alternate cursor positioning strategy or any other after-the-query
processing. For example, if you felt like it, you could \"pre-visit\"
all the files mentioned in output lines. More usefully, you might
like to automatically visit a referenced source file
line if there is only one output line from cscope.")
(defvar cscope-file-not-found-hook nil
"If defined, this behaves slightly differently than a standard emacs
hook function. It is run instead of (not in addition to) the normal
action taken if some referenced source file can't be found. Normally,
(if this hook is not defined) the cscope interface will signal an
error and give up looking.")
(defvar cscope-filename-fixxer-raw nil
"If defined as a function, called to generate a filename. The single
argument is a raw filename reference as taken from a cscope output
buffer. The expected return value is something that the cscope
interface will try to resolve into a full pathname (using mechanisms
desribed elsewhere).")
(defvar cscope-filename-fixxer-cooked nil
"If defined as a function, called to generate a filename. The
single argument is a cooked filename reference, meaning that the
cscope interface has already tried to resolve it into a full pathname
(using mechanisms described elsewhere). Since the resolution doesn't
always succeed, the argument might not be a full pathname. The
expected return value is something that the cscope interface will try
to visit with \"find-file\".")
(defvar cscope-blurb nil
"This is an interface from GNUemacs to the line-oriented mode of Joe
Steffen's cscope, a C code browser (cscope itself is available from
the AT&T Toolchest). The interface includes provisions for having
multiple concurrent unrelated cscope sessions. For casual use,
arrange for this file to be loaded and call the function
\"cscope-bind-keys\". See the documentation for \"cscope-bind-keys\"
for more information about that.
If you are inclined to have multiple cscope sessions, possibly with different
invocation command lines or using pre-built databases, then see the
documentation for cscope-master-info-table and cscope-master-info-default.
The general method of using this is to arrange for the cscope-related
bindings to be made, place the cursor over some symbol or filename in
question, and invoke the appropriate cscope function. This will invoke
a cscope subprocess (if it's not already running) and perform the query.
The results of the query are presented in a cscope output buffer. The
user can place the cursor over a cscope reference line and type \"C-c C-c\"
to move to the referenced location. After that, the user can type
\"C-c C-c\" again and move back to the cscope output buffer, automatically
advancing the cursor to the next line. Functions that cause other buffers
to be displayed generally pop them up in another window. If those functions
are called with prefix arguments, then the summoned buffer is put in the
currently selected window.
A good way to arrange for this file to be loaded is via c-mode-hook. This
file \"provides\" cscope, so you can use \"require\" directives
and/or
autoloading. Here's a example:
(autoload 'cscope-bind-keys \"cscope\" nil t)
(defun wjc:c-mode-hook () \"my C mode hook\"
;; only bother doing the bindings first time ... they'll stick
(or (where-is-internal 'cscope-find-c-symbol (current-local-map))
(cscope-bind-keys))
;; (and (boundp 'cscope-blurb) (makunbound 'cscope-blurb))
(local-set-key \"\\M-?\" 'cscope-find-c-symbol))
(setq c-mode-hook 'wjc:c-mode-hook)
If you've seen the information in the description of this user option
variable enough times, you can let emacs reclaim the string space by
doing (makunbound 'cscope-blurb) after the cscope interface is loaded
(shown as a commented line in the above example). Even if you don't
have handy the source file, cscope.el, you'll still be able to read the
docstrings in cscope.elc.")
(defvar cscope-master-info-table nil
"*A list-of-lists telling how to run cscope for a given buffer.
If you're not doing anything fancy with the cscope interface, like browsing
multiple databases concurrently, then you probably don't need to set this.
Each item in \"cscope-master-info-table\" is a list. Trailing nil items from
the sublists may be omitted.
The first item in each sublist is a string which acts as the key for that
sublist. If the value of the buffer-local variable \"cscope-id\" matches
the key, then that sublist is used to decide how to run cscope for that
buffer. If no sublist in the entire table matches \"cscope-id\", then
\"cscope-master-info-default\" is used.
The second item in each sublist is itself a list. It's a list of strings
which comprise the command line and arguments for invoking cscope. See
the cscope man page for valid command line arguments. Don't forget to make
sure that cscope and/or user-specified cscope commands are available via
the PATH environment variable.
The third item in each sublist is an optional \"cd place\". If a non-nil
string, the current directory will be temporarily changed to the directory
named while cscope is being invoked (ie, while the cscope subprocess is
being spawned). After cscope is invoked, the current directory is returned
to whatever it was before.
The fourth item in each sublist is a user-specified path prefix. A
cscope database might only know relative pathnames. Some versions of
cscope can be queried for the path prefix to use with relative
pathnames, but this does not work with all versions. If cscope tells
emacs about a filename that is a relative pathname, the automatically
known path prefix is prepended. If there is no automatically known
path prefix, the user-specified path prefix is used. If there is no
user-specified path prefix, the \"cd place\" is used. Otherwise, the
unprefixed relative pathname is used.
Here's an example of a personal setting for this variable:
(setq cscope-master-info-table
'(
(\"projA\" (\"cscope\" \"-l\" \"-d\"
\"-f\" \"/projA/src/cscope.out\"))
(\"projB\" (\"cscope\" \"-l\" \"-d\"
\"-f\" \"/projB/src/cscope.out\"))
))
The example uses separate pre-built cscope databases for projects
\"projA\" and \"projB\". The last two items in the sublists are nil
(because they're not specified), which is a good clue that the
databases were built knowing full pathnames. For buffers that are not
\"projA\" or \"projB\", the default cscope invocation will be
used.")
(defvar cscope-master-info-default '("CSCOPE" ("cscope"
"-l") nil nil)
"*When a search of \"cscope-master-info-table\" is done and no match
is found, the list specified by this variable is returned instead. See
the documentation for \"cscope-master-info-table\" for an explanation of
the items in the list.")
(defvar cscope-id nil
"*Used as a key into \"cscope-master-info-table\". This is a
buffer-local
variable and could be set manually or by some mode-specific hook function.
If this variable is not explicitly set, it will generally result in the
use of \"cscope-master-info-default\". The value of \"cscope-id\"
follows from buffer to buffer, but will not override any previously
set values. That is, if a given buffer has a cscope-id of \"foo\", a
cscope output buffer for a cscope process started from that buffer
will also get a cscope-id of \"foo\". Any source files newly visited
as a result of cscope queries from that cscope process will also get a
cscope-id of \"foo\". Users can overcome that by explicitly setting
cscope-id via some hook or other means. \"cscope-id\" is
buffer-local, so if you kill-all-local-variables, the value will be
lost.")
(make-variable-buffer-local 'cscope-id)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; most users need not explore below here except to read function
; documentation strings; you can just as well describe-function
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar cscope-output-line-regexp
"\\s-*\\(\\S-+\\)\\s-+\\(\\S-+\\)\\s-+\\([0-9]+\\)"
"*This regular expression is used to recognize valid reference lines of
output from the output of the line-oriented mode of cscope. It must include
subexpressions which obtain the filename, function name, and line number.")
(defvar cscope-output-file-place 1
"*Position number of the \"cscope-output-line-regexp\" subexpression
which locates the filename.")
(defvar cscope-output-func-place 2
"*Position number of the \"cscope-output-line-regexp\" subexpression
which locates the function name.")
(defvar cscope-output-line-place 3
"*Position number of the \"cscope-output-line-regexp\" subexpression
which locates the line number.")
(defvar cscope-c-symbol-regexp "[a-zA-Z0-9_]+"
"*A regular expression specifying a legitimate C symbol. Used for
finding a default symbol for minibuffer prompting. User input need
not conform to this regular expression.")
(defvar cscope-filename-regexp "[a-zA-Z0-9_.-]+"
"*A regular expression specifying a legitimate file name. Used for
finding a default filename for minibuffer prompting. User input need
not conform to this regular expression.")
; macros for pulling items out of sublists from cscope-master-info-table
(defmacro cscope:label-of-list (cl) (list 'nth 0 cl))
(defmacro cscope:command-of-list (cl) (list 'nth 1 cl))
(defmacro cscope:cdplace-of-list (cl) (list 'nth 2 cl))
(defmacro cscope:pathprefix-of-list (cl) (list 'nth 3 cl))
(defun cscope-bind-keys ()
"Establish the key bindings for cscope queries and interactions.
A reasonable thing to do is to call this function from \"c-mode-hook\".
However, if you use a minor mode which changes the keymap, you may
have to take extra steps. For example, \"view-mode\" installs its own
keymap and is often called via \"find-file-hooks\". For that
particular case, it may be helpful to have a line something like this
automatically invoked after \"view-mode\" has been installed:
(if (eq major-mode 'c-mode) (cscope-bind-keys))
Keys bound by invoking this function can be listed by going to a
buffer where the bindings are active and doing \\[describe-bindings].
They usually begin with a C-c C-s prefix. If \"cscope-bindings-2deep\"
is non-nil, then you will see bindings of the form \"C-c letter\". If
\"cscope-bindings-3deep\" is non-nil (the default), you will see
bindings of the form \"C-c C-s letter\". These settings are
independent of one another, and by default the three character
bindings are provided and the two character bindings are not. The
bindings are put in place by modifying whatever keymaps happen to be in
effect whenever you invoke this function. For most users, this will mean
it's a more or less global change (e.g., to \"c-mode-map\").
In any case, the binding of \"C-c C-c\" is provided. After the bindings
have been made, the optional user-supplied \"cscope-bind-keys-hook\" is run.
In cscope output buffers, there are additional single character
bindings (not controlled by any user option variable). Further, the
two and/or three character bindings are provided, depending on the
values of the \"cscope-bindings-2deep\" and \"cscope-bindings-3deep\"
at the time the cscope interface is first loaded. A different binding is
given to \"C-c C-c\" in cscope output buffers.
Within each set of bindings, more than one binding is made for some
functions for convenience. Use \\[describe-bindings] to get a
complete list. The intent of the alternate bindings of
cscope-interpret-output-line and cscope-goback-and-goforth in
different buffer types is so that an interested user can step through
references in a cscope output buffer by repeatedly typing the same
keys."
(interactive)
(if cscope-bindings-2deep (cscope-bind-keys-2deep))
(if cscope-bindings-3deep (cscope-bind-keys-3deep))
(local-set-key "\C-c\C-c" 'cscope-goback-and-goforth)
(run-hooks 'cscope-bind-keys-hook)
)
(defun cscope-bind-keys-2deep ()
(interactive)
"Apply two character cscope bindings to the currently active keymap.
The bindings are of the form \"C-c letter\" See variable
\"cscope-bindings-2deep\"."
(local-set-key "\C-cc" 'cscope-find-c-symbol)
(local-set-key "\C-cC" 'cscope-find-c-symbol)
;; (local-set-key "\C-c\C-c" 'cscope-find-c-symbol)
(local-set-key "\C-cd" 'cscope-find-global-definition)
(local-set-key "\C-cD" 'cscope-find-global-definition)
(local-set-key "\C-c\C-d" 'cscope-find-global-definition)
(local-set-key "\C-cv" 'cscope-find-functions-called)
(local-set-key "\C-cV" 'cscope-find-functions-called)
(local-set-key "\C-c\C-v" 'cscope-find-functions-called)
(local-set-key "\C-c^" 'cscope-find-functions-calling)
(local-set-key "\C-c6" 'cscope-find-functions-calling)
(local-set-key "\C-ct" 'cscope-find-text-string)
(local-set-key "\C-cT" 'cscope-find-text-string)
(local-set-key "\C-c\C-t" 'cscope-find-text-string)
(local-set-key "\C-cg" 'cscope-find-grep-pattern)
(local-set-key "\C-cG" 'cscope-find-grep-pattern)
(local-set-key "\C-c\C-g" 'cscope-find-grep-pattern)
(local-set-key "\C-ce" 'cscope-find-egrep-pattern)
(local-set-key "\C-cE" 'cscope-find-egrep-pattern)
(local-set-key "\C-c\C-e" 'cscope-find-egrep-pattern)
(local-set-key "\C-cf" 'cscope-find-file)
(local-set-key "\C-cF" 'cscope-find-file)
(local-set-key "\C-c\C-f" 'cscope-find-file)
(local-set-key "\C-ci" 'cscope-find-files-including)
(local-set-key "\C-cI" 'cscope-find-files-including)
(local-set-key "\C-c\C-i" 'cscope-find-files-including)
(local-set-key "\C-c#" 'cscope-find-files-including)
(local-set-key "\C-c3" 'cscope-find-files-including)
(local-set-key "\C-c*" 'cscope-find-all)
(local-set-key "\C-c8" 'cscope-find-all)
(local-set-key "\C-ca" 'cscope-admin-toggle-case)
(local-set-key "\C-cA" 'cscope-admin-toggle-case)
(local-set-key "\C-c\C-a" 'cscope-admin-toggle-case)
(local-set-key "\C-cr" 'cscope-admin-rebuild-db)
(local-set-key "\C-cR" 'cscope-admin-rebuild-db)
(local-set-key "\C-c\C-r" 'cscope-admin-rebuild-db)
(local-set-key "\C-cp" 'cscope-query-path-prefix)
(local-set-key "\C-cP" 'cscope-query-path-prefix)
(local-set-key "\C-c\C-p" 'cscope-query-path-prefix)
(local-set-key "\C-cx" 'cscope-admin-quit)
(local-set-key "\C-cX" 'cscope-admin-quit)
(local-set-key "\C-c\C-x" 'cscope-admin-quit)
(local-set-key "\C-cq" 'cscope-admin-quit-and-kill-buffer)
(local-set-key "\C-cQ" 'cscope-admin-quit-and-kill-buffer)
(local-set-key "\C-c\C-q" 'cscope-admin-quit-and-kill-buffer)
)
(defun cscope-bind-keys-3deep ()
(interactive)
"Apply three character cscope bindings to the currently active keymap.
The bindings are of the form \"C-c C-s letter\" See variable
\"cscope-bindings-3deep\"."
(local-set-key "\C-c\C-sc" 'cscope-find-c-symbol)
(local-set-key "\C-c\C-sC" 'cscope-find-c-symbol)
(local-set-key "\C-c\C-s\C-c" 'cscope-find-c-symbol)
(local-set-key "\C-c\C-sd" 'cscope-find-global-definition)
(local-set-key "\C-c\C-sD" 'cscope-find-global-definition)
(local-set-key "\C-c\C-s\C-d" 'cscope-find-global-definition)
(local-set-key "\C-c\C-sv" 'cscope-find-functions-called)
(local-set-key "\C-c\C-sV" 'cscope-find-functions-called)
(local-set-key "\C-c\C-s\C-v" 'cscope-find-functions-called)
(local-set-key "\C-c\C-s^" 'cscope-find-functions-calling)
(local-set-key "\C-c\C-s6" 'cscope-find-functions-calling)
(local-set-key "\C-c\C-st" 'cscope-find-text-string)
(local-set-key "\C-c\C-sT" 'cscope-find-text-string)
(local-set-key "\C-c\C-s\C-t" 'cscope-find-text-string)
(local-set-key "\C-c\C-sg" 'cscope-find-grep-pattern)
(local-set-key "\C-c\C-sG" 'cscope-find-grep-pattern)
(local-set-key "\C-c\C-s\C-g" 'cscope-find-grep-pattern)
(local-set-key "\C-c\C-se" 'cscope-find-egrep-pattern)
(local-set-key "\C-c\C-sE" 'cscope-find-egrep-pattern)
(local-set-key "\C-c\C-s\C-e" 'cscope-find-egrep-pattern)
(local-set-key "\C-c\C-sf" 'cscope-find-file)
(local-set-key "\C-c\C-sF" 'cscope-find-file)
(local-set-key "\C-c\C-s\C-f" 'cscope-find-file)
(local-set-key "\C-c\C-si" 'cscope-find-files-including)
(local-set-key "\C-c\C-sI" 'cscope-find-files-including)
(local-set-key "\C-c\C-s\C-i" 'cscope-find-files-including)
(local-set-key "\C-c\C-s#" 'cscope-find-files-including)
(local-set-key "\C-c\C-s3" 'cscope-find-files-including)
(local-set-key "\C-c\C-s*" 'cscope-find-all)
(local-set-key "\C-c\C-s8" 'cscope-find-all)
(local-set-key "\C-c\C-sa" 'cscope-admin-toggle-case)
(local-set-key "\C-c\C-sA" 'cscope-admin-toggle-case)
(local-set-key "\C-c\C-s\C-a" 'cscope-admin-toggle-case)
(local-set-key "\C-c\C-sr" 'cscope-admin-rebuild-db)
(local-set-key "\C-c\C-sR" 'cscope-admin-rebuild-db)
(local-set-key "\C-c\C-s\C-r" 'cscope-admin-rebuild-db)
(local-set-key "\C-c\C-sp" 'cscope-query-path-prefix)
(local-set-key "\C-c\C-sP" 'cscope-query-path-prefix)
(local-set-key "\C-c\C-s\C-p" 'cscope-query-path-prefix)
(local-set-key "\C-c\C-sx" 'cscope-admin-quit)
(local-set-key "\C-c\C-sX" 'cscope-admin-quit)
(local-set-key "\C-c\C-s\C-x" 'cscope-admin-quit)
(local-set-key "\C-c\C-sq" 'cscope-admin-quit-and-kill-buffer)
(local-set-key "\C-c\C-sQ" 'cscope-admin-quit-and-kill-buffer)
(local-set-key "\C-c\C-s\C-q" 'cscope-admin-quit-and-kill-buffer)
)
(if (not (boundp 'cscope-keymap))
(progn
(setq cscope-keymap (copy-keymap text-mode-map))
(let ((real-keymap (current-local-map)))
(use-local-map cscope-keymap)
(cscope-bind-keys)
(use-local-map real-keymap))
(define-key cscope-keymap "c" 'cscope-find-c-symbol)
(define-key cscope-keymap "C" 'cscope-find-c-symbol)
(define-key cscope-keymap "d" 'cscope-find-global-definition)
(define-key cscope-keymap "D" 'cscope-find-global-definition)
(define-key cscope-keymap "v" 'cscope-find-functions-called)
(define-key cscope-keymap "V" 'cscope-find-functions-called)
(define-key cscope-keymap "^" 'cscope-find-functions-calling)
(define-key cscope-keymap "t" 'cscope-find-text-string)
(define-key cscope-keymap "T" 'cscope-find-text-string)
(define-key cscope-keymap "g" 'cscope-find-grep-pattern)
(define-key cscope-keymap "G" 'cscope-find-grep-pattern)
(define-key cscope-keymap "e" 'cscope-find-egrep-pattern)
(define-key cscope-keymap "E" 'cscope-find-egrep-pattern)
(define-key cscope-keymap "f" 'cscope-find-file)
(define-key cscope-keymap "F" 'cscope-find-file)
(define-key cscope-keymap "i" 'cscope-find-files-including)
(define-key cscope-keymap "I" 'cscope-find-files-including)
(define-key cscope-keymap "#" 'cscope-find-files-including)
(define-key cscope-keymap "*" 'cscope-find-all)
(define-key cscope-keymap "a" 'cscope-admin-toggle-case)
(define-key cscope-keymap "A" 'cscope-admin-toggle-case)
(define-key cscope-keymap "r" 'cscope-admin-rebuild-db)
(define-key cscope-keymap "R" 'cscope-admin-rebuild-db)
(define-key cscope-keymap "p" 'cscope-query-path-prefix)
(define-key cscope-keymap "P" 'cscope-query-path-prefix)
(define-key cscope-keymap "x" 'cscope-admin-quit)
(define-key cscope-keymap "X" 'cscope-admin-quit)
(define-key cscope-keymap "q" 'cscope-admin-quit-and-kill-buffer)
(define-key cscope-keymap "Q" 'cscope-admin-quit-and-kill-buffer)
(define-key cscope-keymap "\C-c\C-c" 'cscope-interpret-output-line)
))
(defun cscope-find-c-symbol (symbol)
"Query cscope for the whereabouts of the given symbol.
When called interactively, the user is prompted for the symbol name,
with a symbol near point being the default. A prefix argument causes
the current window to be used for the output."
(interactive (cscope:gather-c-symbol "0"))
(cscope:query-omnibus "0" symbol))
(defun cscope-find-global-definition (symbol)
"Query cscope for the global definition of the given symbol.
When called interactively, the user is prompted for the symbol name,
with a symbol near point being the default. A prefix argument causes
the current window to be used for the output."
(interactive (cscope:gather-c-symbol "1"))
(cscope:query-omnibus "1" symbol))
(defun cscope-find-functions-called (symbol)
"Query cscope for the names of functions called by a function.
When called interactively, the user is prompted for the function name,
with a symbol near point being the default. A prefix argument causes
the current window to be used for the output."
(interactive (cscope:gather-c-symbol "2"))
(cscope:query-omnibus "2" symbol))
(defun cscope-find-functions-calling (symbol)
"Query cscope for the names of functions calling a function.
When called interactively, the user is prompted for the function name,
with a symbol near point being the default. A prefix argument causes
the current window to be used for the output."
(interactive (cscope:gather-c-symbol "3"))
(cscope:query-omnibus "3" symbol))
(defun cscope-find-text-string (symbol)
"Query cscope for the whereabouts of the given text string.
When called interactively, the user is prompted for the string. A
prefix argument causes the current window to be used for the output."
(interactive (cscope:gather-text-string "4"))
(cscope:query-omnibus "4" symbol))
(defun cscope-find-grep-pattern (symbol)
"Query cscope for the whereabouts of the given grep pattern. When
called interactively, the user is prompted for the pattern. (The
line-oriented mode of cscope does not support changing occurrences of
the given pattern; the full-screen version of cscope does.) A prefix
argument causes the current window to be used for the output."
(interactive (cscope:gather-text-string "5"))
(cscope:query-omnibus "5" symbol))
(defun cscope-find-egrep-pattern (symbol)
"Query cscope for the whereabouts of the given egrep pattern. When
called interactively, the user is prompted for the pattern. A prefix
argument causes the current window to be used for the output."
(interactive (cscope:gather-text-string "6"))
(cscope:query-omnibus "6" symbol))
(defun cscope-find-file (symbol)
"Query cscope for the whereabouts of the given file.
When called interactively, the user is prompted for the file name,
with a symbol near point being the default. A prefix argument causes
the current window to be used for the output."
(interactive (cscope:gather-file-name "7"))
(cscope:query-omnibus "7" symbol))
(defun cscope-find-files-including (symbol)
"Query cscope for the files including a given file.
When called interactively, the user is prompted for the file name,
with a symbol near point being the default. A prefix argument causes
the current window to be used for the output."
(interactive (cscope:gather-file-name "8"))
(cscope:query-omnibus "8" symbol))
(defun cscope-find-all (&rest symbol)
"Query cscope for the definitions of all functions and C++ classes.
Any arguments to this function are ignored. A prefix argument causes
the current window to be used for the output."
(interactive)
(cscope:query-omnibus "9" "fake"))
(defun cscope-admin-toggle-case (&rest symbol)
"Toggle case-folding for subsequent cscope searches. Since
case-folding can also be affected by a command line option when cscope
is invoked, it's up to the user to keep track of the state of the
toggle. Any arguments to this function are ignored. A prefix
argument causes the current window to be used for the output."
(interactive)
(cscope:query-omnibus "c"))
(defun cscope-admin-rebuild-db (&rest symbol)
"Tell the cscope subprocess to rebuild its database.
Any arguments to this function are ignored. A prefix argument causes
the current window to be used for the output."
(interactive)
(cscope:query-omnibus "r"))
(defun cscope-query-path-prefix (&rest symbol)
"Query cscope for the relative filename path prefix. Not all
versions of cscope support this feature; if yours doesn't, it will be
obvious from what you see in the cscope output buffer after running
this command. Any arguments to this function are ignored. A prefix
argument causes the current window to be used for the output."
(interactive)
(cscope:query-omnibus "P"))
(defun cscope-admin-quit (&rest symbol)
"Tell the cscope subprocess to terminate.
Any arguments to this function are ignored. Afterwards, run the
optional user-supplied \"cscope-quit-hook\". A prefix argument causes
the current window to be used for the output."
(interactive)
(prog1 (cscope:query-omnibus "q")
(run-hooks 'cscope-quit-hook)
))
(defun cscope-admin-quit-and-kill-buffer (&rest symbol)
"Tell the cscope subprocess to terminate.
You can achieve the same effect by simply killing the affiliated cscope
output buffer or by exiting emacs. Any arguments to this function are
ignored."
(interactive)
(cscope-admin-quit)
(let* (
(cscope-list (cscope:pick-description-list cscope-id))
(cscope-label (cscope:label-of-list cscope-list))
(cscope-buffer-name (cscope:bname-from-label cscope-label))
)
(if (get-buffer cscope-buffer-name)
(kill-buffer cscope-buffer-name)))
)
(defun cscope-goback-and-goforth ()
"Return to the affiliated cscope buffer and advance the cursor by one line.
The affect of this will usually be to help in stepping through references
in the cscope output buffer. See also \"cscope-interpret-output-line\".
After the cursor has been positioned, the optional user-supplied
\"cscope-b-and-f-hook\" is run. A prefix argument causes
the current window to be used for the cscope output buffer."
(interactive)
(if (and cscope:affiliated-buffer (get-buffer cscope:affiliated-buffer))
(if (and current-prefix-arg
(not (get-buffer-window cscope:affiliated-buffer)))
(switch-to-buffer cscope:affiliated-buffer)
(pop-to-buffer cscope:affiliated-buffer))
(error "CSCOPE: No affiliated cscope output buffer"))
(forward-line)
(run-hooks 'cscope-b-and-f-hook))
(defun cscope-interpret-output-line ()
"Parse the line under the cursor as a cscope output reference line.
Try to visit the named file and place the cursor on the mentioned line number.
After the cursor has been positioned, run the optional user-supplied
\"cscope-interpret-output-hook\". A prefix argument causes
the current window to be used for the visited file."
(interactive)
(beginning-of-line)
(if (not (looking-at cscope-output-line-regexp))
(error "CSCOPE: Line not understood as a cscope reference line")
(let (
(cscope:filename (buffer-substring
(match-beginning cscope-output-file-place)
(match-end cscope-output-file-place)))
(linenumb (buffer-substring
(match-beginning cscope-output-line-place)
(match-end cscope-output-line-place)))
(function (buffer-substring
(match-beginning cscope-output-func-place)
(match-end cscope-output-func-place)))
(find-file-not-found-hooks (list 'cscope:file-not-found))
(affiliated-buffer (buffer-name))
(cscope-id-affiliated cscope-id)
)
(and (fboundp 'cscope-filename-fixxer-raw)
(setq cscope:filename (funcall cscope-filename-fixxer-raw cscope:filename)))
(if (not (file-name-absolute-p cscope:filename))
(setq cscope:filename (cscope:fulfill-relative-path cscope:filename)))
(and (fboundp 'cscope-filename-fixxer-cooked)
(setq cscope:filename (funcall cscope-filename-fixxer-cooked cscope:filename)))
(if current-prefix-arg
(find-file cscope:filename)
(find-file-other-window cscope:filename))
(setq cscope:affiliated-buffer affiliated-buffer)
(if (not cscope-id) (setq cscope-id cscope-id-affiliated))
(goto-line (string-to-int linenumb))
(message "CSCOPE: Function: %s" function)
(run-hooks 'cscope-interpret-output-hook)
))
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; only implementation stuff below here
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; A buffer-local internal variable that is used to navigate back to the
; most recent previous cscope buffer. Used by cscope-goback-and-goforth.
(defvar cscope:affiliated-buffer nil)
(make-variable-buffer-local 'cscope:affiliated-buffer)
; Gets a piece of menu text and strips off the last two characters, "%s"
(defun cscope:get-menu-subtext (menu-item-key)
(substring (cdr (assoc menu-item-key cscope:menu-text-list)) 0 -2))
; Used to pick up buffer contents near point that match regexp.
; Works by backing up until no longer looking at something matching
; the regular expression, then finding the exact bounds by searching
; forward.
(defun cscope:looking-at (regexp)
(let ((fore-marker nil))
(save-excursion
(if (or (looking-at regexp) (re-search-backward regexp nil t))
(progn
(while (and (looking-at regexp) (not (bobp))) (backward-char 1))
(if (re-search-forward regexp nil t)
(buffer-substring (match-beginning 0) (point-marker))
(identity "")))
(identity "")))))
(defun cscope:gather-c-symbol (menu-item-key)
(list (read-string (cscope:get-menu-subtext menu-item-key)
(cscope:looking-at cscope-c-symbol-regexp))))
(defun cscope:gather-file-name (menu-item-key)
(list (read-string (cscope:get-menu-subtext menu-item-key)
(cscope:looking-at cscope-filename-regexp))))
; no default used for text string, grep/egrep patterns
(defun cscope:gather-text-string (menu-item-key)
(list (read-string (cscope:get-menu-subtext menu-item-key))))
; Low-level function for passing queries to the "cscope" subprocess.
; "menu-item-key" and "item-argument" are what "cscope" is
; expecting (see the "cscope" man page).
(defun cscope:query-omnibus (menu-item-key &optional item-argument)
(let* (symbol do-this cscope-process)
(setq symbol (if item-argument item-argument ""))
(setq do-this ;; string to identify (in the cscope buffer) what's asked
(format
(concat (cdr (assoc menu-item-key cscope:menu-text-list)) "\n")
symbol))
(setq cscope-process
(cscope:pname-from-label
(cscope:label-of-list
(cscope:pick-description-list cscope-id))))
(if (or (eq (process-status cscope-process) 'run)
(not (string-equal menu-item-key "q")))
(progn
(setq cscope-process (cscope:guarantee-process do-this))
(process-send-string
cscope-process (concat menu-item-key symbol "\n"))
(accept-process-output cscope-process)
(goto-char (point-min))
(forward-line 1)
(accept-process-output)
(if (looking-at "cscope: ") (forward-line 1))
(run-hooks 'cscope-query-hook)
))))
; Obviously, these are intended to match the text of menu items in
; in the fullscreen version of cscope. I've also added the "admin"
; items available under line-oriented mode. "P" is used automatically
; (and invisibly) by the interface.
(defconst cscope:menu-text-list
'(("0" . "Find this C symbol: %s")
("1" . "Find this global definition: %s")
("2" . "Find functions called by this function: %s")
("3" . "Find functions calling this function: %s")
("4" . "Find this text string: %s")
("5" . "Find this grep pattern: %s")
("6" . "Find this egrep pattern: %s")
("7" . "Find this file: %s")
("8" . "Find files #including this file: %s")
("9" . "Find all functions and C++ classes")
("c" . "Toggle ignore/use letter case when searching")
("r" . "Rebuild the symbol database")
("P" . "Print relative-path prefix")
("q" . "Quit cscope"))
)
; mapping back and forth between label and buffer/process names
(defconst cscope:bname-prefix "cscope: ")
(defconst cscope:bname-prefix-length (length cscope:bname-prefix))
(defconst cscope:bname-suffix " Output")
(defconst cscope:bname-suffix-length (length cscope:bname-suffix))
(defun cscope:bname-from-label (label)
(concat cscope:bname-prefix label cscope:bname-suffix))
(defun cscope:label-from-bname (name)
(substring
(substring name 0 (- cscope:bname-suffix-length))
cscope:bname-prefix-length))
(defconst cscope:pname-prefix "cscope: ")
(defconst cscope:pname-prefix-length (length cscope:pname-prefix))
(defconst cscope:pname-suffix " Process")
(defconst cscope:pname-suffix-length (length cscope:pname-suffix))
(defun cscope:pname-from-label (label)
(concat cscope:pname-prefix label cscope:pname-suffix))
(defun cscope:label-from-pname (name)
(substring
(substring name 0 (- cscope:pname-suffix-length))
cscope:pname-prefix-length))
; if the appropriate cscope subprocess is not already running, start it
; up, initialize buffers, etc; if it is running, just do the buffer biz
(defun cscope:guarantee-process (do-this)
(let* (
(cscope-list (cscope:pick-description-list cscope-id))
(cscope-label (cscope:label-of-list cscope-list))
(cscope-buffer-name (cscope:bname-from-label cscope-label))
(cscope-process-name (cscope:pname-from-label cscope-label))
(cscope-process nil)
(cd-place (if (cscope:cdplace-of-list cscope-list) (cscope:cdplace-of-list cscope-list)
default-directory))
)
(if (eq (process-status cscope-process-name) 'run)
(save-excursion (set-buffer cscope-buffer-name) (erase-buffer))
(message "CSCOPE: Starting process for %s ..." cscope-label)
(and (get-buffer cscope-buffer-name) (kill-buffer cscope-buffer-name))
(setq cscope-process
(let (
(process-connection-type nil) ; use a pipe
(default-directory cd-place))
(apply 'start-process cscope-process-name cscope-buffer-name
(cscope:command-of-list cscope-list))))
(process-kill-without-query cscope-process)
(cscope:figure-out-path-prefix cscope-label cscope-buffer-name cscope-process)
(message "CSCOPE: Starting process for %s ... started" cscope-label)
(run-hooks 'cscope-start-process-hook)
)
(if (and current-prefix-arg
(not (get-buffer-window cscope-buffer-name)))
(switch-to-buffer cscope-buffer-name)
(pop-to-buffer cscope-buffer-name))
(setq cscope-process (get-process cscope-process-name))
(if (not cscope-id) (setq cscope-id cscope-label))
(use-local-map cscope-keymap)
(insert do-this)
(set-marker (process-mark cscope-process) (point-max))
(identity cscope-process)
))
; keep a list of path prefixes that can be discovered by asking cscope
(defvar cscope:path-prefix-table nil)
(defun cscope:figure-out-path-prefix (cscope-label cscope-buffer-name cscope-process)
(set-buffer cscope-buffer-name)
(goto-char (point-min))
(while (and
(eq (process-status cscope-process) 'run)
(not (re-search-forward "^>>" nil t)))
(goto-char (point-min))
(accept-process-output))
(if (not (eq (process-status cscope-process) 'run))
(message "CSCOPE: Dead process for %s" cscope-label)
(erase-buffer)
(process-send-string cscope-process "P\n")
(while (and
(eq (process-status cscope-process) 'run)
(not (re-search-forward "^>>" nil t)))
(goto-char (point-min))
(accept-process-output))
(goto-char (point-min))
(if (not (looking-at ".*cscope.* unknown ")) ;; sometimes no P support
(progn
(end-of-line)
(let* (
(path-prefix (buffer-substring (point-min) (point)))
(list-item
(if cscope:path-prefix-table
(assoc cscope-label cscope:path-prefix-table) nil))
)
(if list-item
(setcdr list-item path-prefix)
(setq cscope:path-prefix-table
(cons '(cscope-label . path-prefix)
cscope:path-prefix-table)))
)))
)
(erase-buffer)
)
(defun cscope:pick-description-list (cscope-id)
(if (and cscope-master-info-table (assoc cscope-id cscope-master-info-table))
(assoc cscope-id cscope-master-info-table)
(identity cscope-master-info-default)))
; catch the file-not-found situation so that a new empty file isn't just
; opened up as a routine matter; instead, give a message
(defun cscope:file-not-found ()
(if cscope-file-not-found-hook
(run-hooks 'cscope-file-not-found-hook)
(kill-buffer (get-file-buffer cscope:filename))
(error "CSCOPE: Can't find file %s" cscope:filename)))
; convert cscope's relative pathnames into absolute pathnames;
; try computed path prefix, user-specified path prefix, and user-specified
; "cd place"
(defun cscope:fulfill-relative-path (filename)
(let* (
(list-item
(if cscope:path-prefix-table
(assoc cscope-id cscope:path-prefix-table) nil))
(prefix (if list-item (cdr list-item) nil))
(cscope-list (cscope:pick-description-list cscope-id))
)
(if (not prefix) (setq prefix (cscope:pathprefix-of-list cscope-list)))
(if (not prefix) (setq prefix (cscope:cdplace-of-list cscope-list)))
(if prefix
(format "%s/%s" prefix filename)
(identity filename))
)
)
(provide 'cscope)