lib-src/be-resources
lib-src/blessmail
lib-src/ctags
-lib-src/ebrowse
lib-src/emacsclient
lib-src/etags
lib-src/hexl
## install emacs very often. See the --help output for more details.
-PUBLIC_LIBSRC_BINARIES='emacsclient etags ctags ebrowse'
+PUBLIC_LIBSRC_BINARIES='emacsclient etags ctags'
AVOID="CVS -DIC README COPYING ChangeLog ~ [.]orig$ [.]rej$ Makefile$ Makefile.in$ makefile$ makefile.w32-in$ stamp-subdir [.]cvsignore [.]arch-ids [{]arch[}] [.][cho]$ make-docfile"
# This is a list of binaries to build and install in lib-src.
LIBSRC_BINARIES = lib-src/etags lib-src/ctags lib-src/emacsclient \
- lib-src/ebrowse lib-src/hexl lib-src/movemail
+ lib-src/hexl lib-src/movemail
CLEAN_SUBDIRS = $(wildcard src lib-src lib etc)
consult the values of the variables @code{ctags-program-name},
@code{etags-program-name}, @code{hexl-program-name},
@code{emacsclient-program-name}, @code{movemail-program-name},
-@code{ebrowse-program-name}, and @code{rcs2log-program-name}.
+and @code{rcs2log-program-name}.
@xref{Subprocess Creation,,, elisp, the Emacs Lisp Reference Manual}.
The @file{/assets} directory containing Emacs start-up files is
produced by the @command{etags} command that is part of an Emacs
distribution, we describe tags tables in more detail here.
-@cindex C++ class browser, tags
-@cindex tags, C++
-@cindex class browser, C++
-@cindex Ebrowse
- The Ebrowse facility is similar to @command{etags} but specifically
-tailored for C++. @xref{Top,, Ebrowse, ebrowse, Ebrowse User's
-Manual}. The Semantic package provides another way to generate and
-use tags, separate from the @command{etags} facility.
-@xref{Semantic}.
-
@menu
* Tag Syntax:: Tag syntax for various types of code and text files.
* Create Tags Table:: Creating and updating tags tables with @command{etags}.
the subcommands of the prefix key of the most recent key sequence. The
prefix described consists of all but the last event of that key
sequence. (The last event is, presumably, the help character.)
-@end deffn
-
- The following two functions are meant for modes that want to provide
-help without relinquishing control, such as the electric modes.
-Their names begin with @samp{Helper} to distinguish them from the
-ordinary help functions.
-
-@deffn Command Helper-describe-bindings
-This command pops up a window displaying a help buffer containing a
-listing of all of the key bindings from both the local and global keymaps.
-It works by calling @code{describe-bindings}.
-@end deffn
-
-@deffn Command Helper-help
-This command provides help for the current mode. It prompts the user
-in the minibuffer with the message @samp{Help (Type ? for further
-options)}, and then provides assistance in finding out what the key
-bindings are, and what the mode is intended for. It returns @code{nil}.
-
-@vindex Helper-help-map
-This can be customized by changing the map @code{Helper-help-map}.
@end deffn
@defvar data-directory
A sparse keymap for the keys following the help character @kbd{C-h}.@*
@xref{Help Functions}.
-@item Helper-help-map
-A full keymap used by the help utility package.@*
-It has the same keymap in its value cell and in its function cell.
-
@item input-decode-map
The keymap for translating keypad and function keys.@*
If there are none, then it contains an empty sparse keymap.
@vindex hexl-program-name
@vindex emacsclient-program-name
@vindex movemail-program-name
-@vindex ebrowse-program-name
@vindex rcs2log-program-name
When starting a program that is part of the Emacs distribution, you
must take into account that the program may have been renamed in order
the value of @code{ctags-program-name} instead. Likewise, instead of
starting @command{movemail}, you must start
@code{movemail-program-name}, and the same goes for @command{etags},
-@command{hexl}, @command{emacsclient}, @code{rcs2log}, and
-@command{ebrowse}.
+@command{hexl}, @command{emacsclient}, and @code{rcs2log}.
@node Shell Arguments
@section Shell Arguments
+++ /dev/null
-.\" See section COPYING for copyright and redistribution information.
-.TH EBROWSE 1 "2008-12-14" "GNU Emacs" "GNU"
-.SH NAME
-ebrowse \- create a class hierarchy database
-.SH SYNOPSIS
-.B ebrowse
-.RI [ options ]
-.RI [ FILES .\|.\|.]
-.SH "DESCRIPTION"
-This manual page documents briefly the
-.BR ebrowse
-command. Full documentation is available in the GNU Info format.
-.PP
-.B ebrowse
-is used to create the database used by the class browser in Emacs.
-.PP
-.SH OPTIONS
-The program follows the usual GNU command line syntax, with long
-options starting with two dashes ("\-").
-.TP
-.B \-a, \-\-append
-append output to existing file
-.TP
-.B \-f, \-\-files=FILES
-read input file names from
-.I FILE
-.TP
-.B \-I, \-\-search-path=LIST
-set search path for input files
-.TP
-.B \-m, \-\-min-regexp-length=N
-set minimum regexp length to
-.I N
-.TP
-.B \-M, \-\-max-regexp-length=N
-set maximum regexp length to
-.I N
-.TP
-.B \-n, \-\-no-nested-classes
-exclude nested classes
-.TP
-.B \-o, \-\-output-file=FILE
-set output file name to
-.I FILE
-.TP
-.B \-p, \-\-position-info
-print info about position in file
-.TP
-.B \-s, \-\-no-structs-or-unions
-don't record structs or unions
-.TP
-.B \-v, \-\-verbose
-be verbose
-.TP
-.B \-V, \-\-very-verbose
-be very verbose
-.TP
-.B \-x, \-\-no-regexps
-don't record regular expressions
-.TP
-.B \-\-help
-display this help
-.TP
-.B \-\-version
-display version info
-.SH "SEE ALSO"
-.BR emacs (1),
-.BR etags (1),
-and the full documentation for
-.B ebrowse
-which is maintained as a Texinfo manual. If the
-.B info
-and
-.B ebrowse
-programs are properly installed at your site, the command
-.IP
-.B info ebrowse
-.PP
-should give you access to the complete manual.
-.SH AUTHOR
-.I Ebrowse
-was written by Gerd Moellmann.
-.
-.SH COPYING
-Copyright 2008-2024 Free Software Foundation, Inc.
-.PP
-Permission is granted to make and distribute verbatim copies of this
-document provided the copyright notice and this permission notice are
-preserved on all copies.
-.PP
-Permission is granted to copy and distribute modified versions of
-this document under the conditions for verbatim copying, provided that
-the entire resulting derived work is distributed under the terms of
-a permission notice identical to this one.
-.PP
-Permission is granted to copy and distribute translations of this
-document into another language, under the above conditions for
-modified versions, except that this permission notice may be stated
-in a translation approved by the Free Software Foundation.
-.
-
-.\" Local Variables:
-.\" time-stamp-pattern: "3/.TH EBROWSE 1 \"%Y-%02m-%02d\" \"GNU Emacs\" \"GNU\"$"
-.\" End:
## Info files to build and install on all platforms.
INFO_COMMON = auth autotype bovine calc ccmode cl dbus dired-x \
- ebrowse ede ediff edt efaq eglot eieio emacs-gnutls \
+ ede ediff edt efaq eglot eieio emacs-gnutls \
emacs-mime epa erc ert eshell eudc eww flymake forms gnus \
htmlfontify idlwave ido info.info mairix-el message mh-e \
modus-themes newsticker nxml-mode octave-mode org pcl-cvs pgg \
+++ /dev/null
-\input texinfo @c -*-texinfo-*-
-
-@comment %**start of header
-@setfilename ../../info/ebrowse.info
-@settitle A Class Browser for C++
-@include docstyle.texi
-@setchapternewpage odd
-@syncodeindex fn cp
-@comment %**end of header
-
-@copying
-This file documents Ebrowse, a C++ class browser for GNU Emacs.
-
-Copyright @copyright{} 2000--2024 Free Software Foundation, Inc.
-
-@quotation
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.3 or
-any later version published by the Free Software Foundation; with no
-Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''
-and with the Back-Cover Texts as in (a) below. A copy of the license
-is included in the section entitled ``GNU Free Documentation License''.
-
-(a) The FSF's Back-Cover Text is: ``You have the freedom to copy and
-modify this GNU manual.''
-@end quotation
-@end copying
-
-@dircategory Emacs misc features
-@direntry
-* Ebrowse: (ebrowse). A C++ class browser for Emacs.
-@end direntry
-
-@titlepage
-@title Ebrowse User's Manual
-@sp 4
-@subtitle Ebrowse/Emacs
-@sp 5
-@author Gerd Moellmann
-@page
-@vskip 0pt plus 1filll
-@insertcopying
-@end titlepage
-
-@contents
-
-@ifnottex
-@node Top
-@top Ebrowse
-
-You can browse C++ class hierarchies from within Emacs by using
-Ebrowse.
-
-@insertcopying
-@end ifnottex
-
-@menu
-* Overview:: What is it and how does it work?
-* Generating browser files:: How to process C++ source files
-* Loading a Tree:: How to start browsing
-* Tree Buffers:: Traversing class hierarchies
-* Member Buffers:: Looking at member information
-* Tags-like Functions:: Finding members from source files
-* GNU Free Documentation License:: The license for this documentation.
-* Concept Index:: An entry for each concept defined
-@end menu
-
-
-
-
-@node Overview
-@chapter Introduction
-
-When working in software projects using C++, I frequently missed
-software support for two things:
-
-@itemize @bullet
-@item
-When you get a new class library, or you have to work on source code you
-haven't written yourself (or written sufficiently long ago), you need a
-tool to let you navigate class hierarchies and investigate
-features of the software. Without such a tool you often end up
-@command{grep}ing through dozens or even hundreds of files.
-
-@item
-Once you are productive, it would be nice to have a tool that knows your
-sources and can help you while you are editing source code. Imagine to
-be able to jump to the definition of an identifier while you are
-editing, or something that can complete long identifier names because it
-knows what identifiers are defined in your program@dots{}.
-@end itemize
-
-The design of Ebrowse reflects these two needs.
-
-How does it work?
-
-@cindex parser for C++ sources
-A fast parser written in C is used to process C++ source files.
-The parser generates a data base containing information about classes,
-members, global functions, defines, types etc.@: found in the sources.
-
-The second part of Ebrowse is a Lisp program. This program reads
-the data base generated by the parser. It displays its contents in
-various forms and allows you to perform operations on it, or do
-something with the help of the knowledge contained in the data base.
-
-@cindex major modes, of Ebrowse buffers
-@dfn{Navigational} use of Ebrowse is centered around two
-types of buffers which define their own major modes:
-
-@cindex tree buffer
-@dfn{Tree buffers} are used to view class hierarchies in tree form.
-They allow you to quickly find classes, find or view class declarations,
-perform operations like query replace on sets of your source files, and
-finally tree buffers are used to produce the second buffer form---member
-buffers. @xref{Tree Buffers}.
-
-@cindex member buffer
-Members are displayed in @dfn{member buffers}. Ebrowse
-distinguishes between six different types of members; each type is
-displayed as a member list of its own:
-
-@itemize @bullet
-@item
-Instance member variables;
-
-@item
-Instance member functions;
-
-@item
-Static member variables;
-
-@item
-Static member functions;
-
-@item
-Friends/Defines. The list of defines is contained in the friends
-list of the pseudo-class @samp{*Globals*};
-
-@item
-Types (@code{enum}s, and @code{typedef}s defined with class
-scope).
-@end itemize
-
-You can switch member buffers from one list to another, or to another
-class. You can include inherited members in the display, you can set
-filters that remove categories of members from the display, and most
-importantly you can find or view member declarations and definitions
-with a keystroke. @xref{Member Buffers}.
-
-These two buffer types and the commands they provide support the
-navigational use of the browser. The second form resembles Emacs's Tags
-package for C and other procedural languages. Ebrowse's commands of
-this type are not confined to special buffers; they are most often used
-while you are editing your source code.
-
-To list just a subset of what you can use the Tags part of Ebrowse for:
-
-@itemize @bullet
-@item
-Jump to the definition or declaration of an identifier in your source
-code, with an electric position stack that lets you easily navigate
-back and forth.
-
-@item
-Complete identifiers in your source with a completion list containing
-identifiers from your source code only.
-
-@item
-Perform search and query replace operations over some or all of your
-source files.
-
-@item
-Show all identifiers matching a regular expression---and jump to one of
-them, if you like.
-@end itemize
-
-
-
-
-@node Generating browser files
-@chapter Processing Source Files
-
-@cindex @command{ebrowse}, the program
-@cindex class data base creation
-Before you can start browsing a class hierarchy, you must run the parser
-@command{ebrowse} on your source files in order to generate a Lisp data
-base describing your program.
-
-@cindex command line for @command{ebrowse}
-The operation of @command{ebrowse} can be tailored with command line
-options. Under normal circumstances it suffices to let the parser use
-its default settings. If you want to do that, call it with a command
-line like:
-
-@example
-ebrowse *.h *.cc
-@end example
-
-@noindent
-or, if your shell doesn't allow all the file names to be specified on
-the command line,
-
-@example
-ebrowse --files=@var{file}
-@end example
-
-@noindent
-where @var{file} contains the names of the files to be parsed, one
-per line.
-
-@findex --help
-When invoked with option @samp{--help}, @command{ebrowse} prints a list of
-available command line options.
-
-@menu
-* Input files:: Specifying which files to parse
-* Output file:: Changing the output file name
-* Structs and unions:: Omitting @code{struct}s and @code{union}s
-* Matching:: Setting regular expression lengths
-* Verbosity:: Getting feedback for lengthy operations
-@end menu
-
-
-
-
-@comment name, next, prev, up
-@node Input files
-@section Specifying Input Files
-
-@table @samp
-@cindex input files, for @command{ebrowse}
-@item file
-Each file name on the command line tells @command{ebrowse} to parse
-that file.
-
-@cindex response files
-@findex --files
-@item --files=@var{file}
-This command line switch specifies that @var{file} contains a list of
-file names to parse. Each line in @var{file} must contain one file
-name. More than one option of this kind is allowed. You might, for
-instance, want to use one file for header files, and another for source
-files.
-
-@cindex standard input, specifying input files
-@item standard input
-When @command{ebrowse} finds no file names on the command line, and no
-@samp{--file} option is specified, it reads file names from standard
-input. This is sometimes convenient when @command{ebrowse} is used as part
-of a command pipe.
-
-@findex --search-path
-@item --search-path=@var{paths}
-This option lets you specify search paths for your input files.
-@var{paths} is a list of directories, separated by
-either a colon or a semicolon, depending on the operating system.
-@end table
-
-@cindex header files
-@cindex friend functions
-It is generally a good idea to specify input files so that header files
-are parsed before source files. This facilitates the parser's work of
-properly identifying friend functions of a class.
-
-
-
-@comment name, next, prev, up
-@node Output file
-@section Changing the Output File Name
-
-@table @samp
-@cindex output file name
-@findex --output-file
-@cindex @file{BROWSE} file
-@item --output-file=@var{file}
-This option instructs @command{ebrowse} to generate a Lisp data base with
-name @var{file}. By default, the data base is named @file{BROWSE}, and
-is written in the directory in which @command{ebrowse} is invoked.
-
-If you regularly use data base names different from the default, you
-might want to add this to your init file:
-
-@lisp
-(add-to-list 'auto-mode-alist '(@var{NAME} . ebrowse-tree-mode))
-@end lisp
-
-@noindent
-where @var{NAME} is the Lisp data base name you are using.
-
-@findex --append
-@cindex appending output to class data base
-@item --append
-By default, each run of @command{ebrowse} erases the old contents of the
-output file when writing to it. You can instruct @command{ebrowse} to
-append its output to an existing file produced by @command{ebrowse}
-with this command line option.
-@end table
-
-
-
-
-@comment name, next, prev, up
-@node Structs and unions
-@section Structs and Unions
-@cindex structs
-@cindex unions
-
-@table @samp
-@findex --no-structs-or-unions
-@item --no-structs-or-unions
-This switch suppresses all classes in the data base declared as
-@code{struct} or @code{union} in the output.
-
-This is mainly useful when you are converting an existing
-C program to C++, and do not want to see the old C structs in a class
-tree.
-@end table
-
-
-
-
-@comment name, next, prev, up
-@node Matching
-@section Regular Expressions
-
-@cindex regular expressions, recording
-The parser @command{ebrowse} normally writes regular expressions to its
-output file that help the Lisp part of Ebrowse to find functions,
-variables etc.@: in their source files.
-
-You can instruct @command{ebrowse} to omit these regular expressions by
-calling it with the command line switch @samp{--no-regexps}.
-
-When you do this, the Lisp part of Ebrowse tries to guess, from member
-or class names, suitable regular expressions to locate that class or
-member in source files. This works fine in most cases, but the
-automatic generation of regular expressions can be too weak if unusual
-coding styles are used.
-
-@table @samp
-@findex --no-regexps
-@item --no-regexps
-This option turns off regular expression recording.
-
-@findex --min-regexp-length
-@cindex minimum regexp length for recording
-@item --min-regexp-length=@var{n}
-The number @var{n} following this option specifies the minimum length of
-the regular expressions recorded to match class and member declarations
-and definitions. The default value is set at compilation time of
-@command{ebrowse}.
-
-The smaller the minimum length, the higher the probability that
-Ebrowse will find a wrong match. The larger the value, the
-larger the output file and therefore the memory consumption once the
-file is read from Emacs.
-
-@findex --max-regexp-length
-@cindex maximum regexp length for recording
-@item --max-regexp-length=@var{n}
-The number following this option specifies the maximum length of the
-regular expressions used to match class and member declarations and
-definitions. The default value is set at compilation time of
-@command{ebrowse}.
-
-The larger the maximum length, the higher the probability that the
-browser will find a correct match, but the larger the value the larger
-the output file and therefore the memory consumption once the data is
-read. As a second effect, the larger the regular expression, the higher
-the probability that it will no longer match after editing the file.
-@end table
-
-
-
-
-@node Verbosity
-@section Verbose Mode
-@cindex verbose operation
-
-@table @samp
-@findex --verbose
-@item --verbose
-When this option is specified on the command line, @command{ebrowse} prints
-a period for each file parsed, and it displays a @samp{+} for each
-class written to the output file.
-
-@findex --very-verbose
-@item --very-verbose
-This option makes @command{ebrowse} print out the names of the files and
-the names of the classes seen.
-@end table
-
-
-
-
-@node Loading a Tree
-@chapter Starting to Browse
-@cindex loading
-@cindex browsing
-
-You start browsing a class hierarchy parsed by @command{ebrowse} by just
-finding the @file{BROWSE} file with @kbd{C-x C-f}.
-
-An example of a tree buffer display is shown below.
-
-@example
-| Collection
-| IndexedCollection
-| Array
-| FixedArray
-| Set
-| Dictionary
-@end example
-
-@cindex mouse highlight in tree buffers
-When you run Emacs on a display which supports colors and the mouse, you
-will notice that certain areas in the tree buffer are highlighted
-when you move the mouse over them. This highlight marks mouse-sensitive
-regions in the buffer. Please notice the help strings in the echo area
-when the mouse moves over a sensitive region.
-
-@cindex context menu
-A click with @kbd{mouse-3} on a mouse-sensitive region opens a context
-menu. In addition to this, each buffer also has a buffer-specific menu
-that is opened with a click with @kbd{mouse-3} somewhere in the buffer
-where no highlight is displayed.
-
-
-
-@comment ****************************************************************
-@comment ***
-@comment *** TREE BUFFERS
-@comment ***
-@comment ****************************************************************
-
-@node Tree Buffers
-@chapter Tree Buffers
-@cindex tree buffer mode
-@cindex class trees
-
-Class trees are displayed in @dfn{tree buffers} which install their own
-major mode. Most Emacs keys work in tree buffers in the usual way,
-e.g., you can move around in the buffer with the usual @kbd{C-f},
-@kbd{C-v} etc., or you can search with @kbd{C-s}.
-
-Tree-specific commands are bound to simple keystrokes, similar to
-@code{Gnus}. You can take a look at the key bindings by entering
-@kbd{?} which calls @code{M-x describe-mode} in both tree and member
-buffers.
-
-@menu
-* Source Display:: Viewing and finding a class declaration
-* Member Display:: Showing members, switching to member buffers
-* Go to Class:: Finding a class
-* Quitting:: Discarding and burying the tree buffer
-* File Name Display:: Showing file names in the tree
-* Expanding and Collapsing:: Expanding and collapsing branches
-* Tree Indentation:: Changing the tree indentation
-* Killing Classes:: Removing class from the tree
-* Saving a Tree:: Saving a modified tree
-* Statistics:: Displaying class tree statistics
-* Marking Classes:: Marking and unmarking classes
-@end menu
-
-
-
-@node Source Display
-@section Viewing and Finding Class Declarations
-@cindex viewing, class
-@cindex finding a class
-@cindex class declaration
-
-You can view or find a class declaration when the cursor is on a class
-name.
-
-@table @kbd
-@item @key{SPC}
-This command views the class declaration if the database
-contains information about it. If you don't parse the entire source
-you are working on, some classes will only be known to exist but the
-location of their declarations and definitions will not be known.
-
-@item @key{RET}
-Works like @kbd{@key{SPC}}, except that it finds the class
-declaration rather than viewing it, so that it is ready for
-editing.
-@end table
-
-The same functionality is available from the menu opened with
-@kbd{mouse-3} on the class name.
-
-
-
-
-@node Member Display
-@section Displaying Members
-@cindex @file{*Members*} buffer
-@cindex @samp{*Globals*}
-@cindex freezing a member buffer
-@cindex member lists, in tree buffers
-
-Ebrowse distinguishes six different kinds of members, each of
-which is displayed as a separate @dfn{member list}: instance variables,
-instance functions, static variables, static functions, friend
-functions, and types.
-
-Each of these lists can be displayed in a member buffer with a command
-starting with @kbd{L} when the cursor is on a class name. By default,
-there is only one member buffer named @dfn{*Members*} that is reused
-each time you display a member list---this has proven to be more
-practical than to clutter up the buffer list with dozens of member
-buffers.
-
-If you want to display more than one member list at a time you can
-@dfn{freeze} its member buffer. Freezing a member buffer prevents it
-from being overwritten the next time you display a member list. You can
-toggle this buffer status at any time.
-
-Every member list display command in the tree buffer can be used with a
-prefix argument (@kbd{C-u}). Without a prefix argument, the command will
-pop to a member buffer displaying the member list. With prefix argument,
-the member buffer will additionally be @dfn{frozen}.
-
-@table @kbd
-@cindex instance member variables, list
-@item L v
-This command displays the list of instance member variables.
-
-@cindex static variables, list
-@item L V
-Display the list of static variables.
-
-@cindex friend functions, list
-@item L d
-Display the list of friend functions. This list is used for defines if
-you are viewing the class @samp{*Globals*} which is a place holder for
-global symbols.
-
-@cindex member functions, list
-@item L f
-Display the list of member functions.
-
-@cindex static member functions, list
-@item L F
-Display the list of static member functions.
-
-@cindex types, list
-@item L t
-Display a list of types.
-@end table
-
-These lists are also available from the class' context menu invoked with
-@kbd{mouse-3} on the class name.
-
-
-
-
-@node Go to Class
-@section Finding a Class
-@cindex locate class
-@cindex expanding branches
-@cindex class location
-
-@table @kbd
-@cindex search for class
-@item /
-This command reads a class name from the minibuffer with completion and
-positions the cursor on the class in the class tree.
-
-If the branch of the class tree containing the class searched for is
-currently collapsed, the class itself and all its base classes are
-recursively made visible. (See also @ref{Expanding and
-Collapsing}.)
-
-This function is also available from the tree buffer's context menu.
-
-@item n
-Repeat the last search done with @kbd{/}. Each tree buffer has its own
-local copy of the regular expression last searched in it.
-@end table
-
-
-
-
-@node Quitting
-@section Burying a Tree Buffer
-@cindex burying tree buffer
-
-@table @kbd
-@item q
-Is a synonym for @kbd{M-x bury-buffer}.
-@end table
-
-
-
-
-@node File Name Display
-@section Displaying File Names
-
-@table @kbd
-@cindex file names in tree buffers
-@item T f
-This command toggles the display of file names in a tree buffer. If
-file name display is switched on, the names of the files containing the
-class declaration are shown to the right of the class names. If the
-file is not known, the string @samp{unknown} is displayed.
-
-This command is also provided in the tree buffer's context menu.
-
-@item s
-Display file names for the current line, or for the number of lines
-given by a prefix argument.
-@end table
-
-Here is an example of a tree buffer with file names displayed.
-
-@example
-| Collection (unknown)
-| IndexedCollection (indexedcltn.h)
-| Array (array.h)
-| FixedArray (fixedarray.h)
-| Set (set.h)
-| Dictionary (dict.h)
-@end example
-
-
-@node Expanding and Collapsing
-@section Expanding and Collapsing a Tree
-@cindex expand tree branch
-@cindex collapse tree branch
-@cindex branches of class tree
-@cindex class tree, collapse or expand
-
-You can expand and collapse parts of a tree to reduce the complexity of
-large class hierarchies. Expanding or collapsing branches of a tree has
-no impact on the functionality of other commands, like @kbd{/}. (See
-also @ref{Go to Class}.)
-
-Collapsed branches are indicated with an ellipsis following the class
-name like in the example below.
-
-@example
-| Collection
-| IndexedCollection...
-| Set
-| Dictionary
-@end example
-
-@table @kbd
-@item -
-This command collapses the branch of the tree starting at the class the
-cursor is on.
-
-@item +
-This command expands the branch of the tree starting at the class the
-cursor is on. Both commands for collapsing and expanding branches are
-also available from the class' object menu.
-
-@item *
-This command expands all collapsed branches in the tree.
-@end table
-
-
-
-
-@node Tree Indentation
-@section Changing the Tree Indentation
-@cindex tree indentation
-@cindex indentation of the tree
-
-@table @kbd
-@item T w
-This command reads a new indentation width from the minibuffer and
-redisplays the tree buffer with the new indentation It is also
-available from the tree buffer's context menu.
-@end table
-
-
-
-
-@node Killing Classes
-@section Removing Classes from the Tree
-@cindex killing classes
-@cindex class, remove from tree
-
-@table @kbd
-@item C-k
-This command removes the class the cursor is on and all its derived
-classes from the tree. The user is asked for confirmation before the
-deletion is actually performed.
-@end table
-
-
-
-
-@node Saving a Tree
-@section Saving a Tree
-@cindex save tree to a file
-@cindex tree, save to a file
-@cindex class tree, save to a file
-
-@table @kbd
-@item C-x C-s
-This command writes a class tree to the file from which it was read.
-This is useful after classes have been deleted from a tree.
-
-@item C-x C-w
-Writes the tree to a file whose name is read from the minibuffer.
-@end table
-
-
-
-
-@node Statistics
-@section Statistics
-@cindex statistics for a tree
-@cindex tree statistics
-@cindex class statistics
-
-@table @kbd
-@item x
-Display statistics for the tree, like number of classes in it, number of
-member functions, etc. This command can also be found in the buffer's
-context menu.
-@end table
-
-
-
-
-@node Marking Classes
-@section Marking Classes
-@cindex marking classes
-@cindex operations on marked classes
-
-Classes can be marked for operations similar to the standard Emacs
-commands @kbd{M-x tags-search} and @kbd{M-x tags-query-replace} (see
-also @pxref{Tags-like Functions}.)
-
-@table @kbd
-@cindex toggle mark
-@item M t
-Toggle the mark of the line point is in or for as many lines as given by
-a prefix command. This command can also be found in the class' context
-menu.
-
-@cindex unmark all
-@item M a
-Unmark all classes. With prefix argument @kbd{C-u}, mark all classes in
-the tree. Since this command operates on the whole buffer, it can also be
-found in the buffer's object menu.
-@end table
-
-Marked classes are displayed with an @code{>} in column one of the tree
-display, like in the following example
-
-@example
-|> Collection
-| IndexedCollection...
-|> Set
-| Dictionary
-@end example
-
-
-
-
-@c ****************************************************************
-@c ***
-@c *** MEMBER BUFFERS
-@c ***
-@c ****************************************************************
-
-@node Member Buffers
-@chapter Member Buffers
-@cindex members
-@cindex member buffer mode
-
-@cindex class members, types
-@cindex types of class members
-@dfn{Member buffers} are used to operate on lists of members of a class.
-Ebrowse distinguishes six kinds of lists:
-
-@itemize @bullet
-@item
-Instance variables (normal member variables);
-@item
-Instance functions (normal member functions);
-@item
-Static variables;
-@item
-Static member functions;
-@item
-Friend functions;
-@item
-Types (@code{enum}s and @code{typedef}s defined with class scope.
-Nested classes will be shown in the class tree like normal classes.
-@end itemize
-
-Like tree buffers, member buffers install their own major mode. Also
-like in tree buffers, menus are provided for certain areas in the
-buffer: members, classes, and the buffer itself.
-
-@menu
-* Switching Member Lists:: Choosing which members to display
-* Finding/Viewing:: Modifying source code
-* Inherited Members:: Display of Inherited Members
-* Searching Members:: Finding members in member buffer
-* Switching to Tree:: Going back to the tree buffer
-* Filters:: Selective member display
-* Attributes:: Display of @code{virtual} etc.
-* Long and Short Display:: Comprehensive and verbose display
-* Regexp Display:: Showing matching regular expressions
-* Switching Classes:: Displaying another class
-* Killing/Burying:: Getting rid of the member buffer
-* Column Width:: Display style
-* Redisplay:: Redrawing the member list
-* Getting Help:: How to get help for key bindings
-@end menu
-
-
-
-
-@node Switching Member Lists
-@section Switching Member Lists
-@cindex member lists, in member buffers
-@cindex static members
-@cindex friends
-@cindex types
-@cindex defines
-
-@table @kbd
-@cindex next member list
-@item L n
-This command switches the member buffer display to the next member list.
-
-@cindex previous member list
-@item L p
-This command switches the member buffer display to the previous member
-list.
-
-@item L f
-Switch to the list of member functions.
-
-@cindex static
-@item L F
-Switch to the list of static member functions.
-
-@item L v
-Switch to the list of member variables.
-
-@item L V
-Switch to the list of static member variables.
-
-@item L d
-Switch to the list of friends or defines.
-
-@item L t
-Switch to the list of types.
-@end table
-
-Both commands cycle through the member list.
-
-Most of the commands are also available from the member buffer's
-context menu.
-
-
-
-
-@node Finding/Viewing
-@section Finding and Viewing Member Source
-@cindex finding members, in member buffers
-@cindex viewing members, in member buffers
-@cindex member definitions, in member buffers
-@cindex member declarations, in member buffers
-@cindex definition of a member, in member buffers
-@cindex declaration of a member, in member buffers
-
-@table @kbd
-@item @key{RET}
-This command finds the definition of the member the cursor is on.
-Finding involves roughly the same as the standard Emacs tags facility
-does---loading the file and searching for a regular expression matching
-the member.
-
-@item f
-This command finds the declaration of the member the cursor is on.
-
-@item @key{SPC}
-This is the same command as @kbd{@key{RET}}, but views the member definition
-instead of finding the member's source file.
-
-@item v
-This is the same command as @kbd{f}, but views the member's declaration
-instead of finding the file the declaration is in.
-@end table
-
-You can install a hook function to perform actions after a member or
-class declaration or definition has been found, or when it is not found.
-
-All the commands described above can also be found in the context menu
-displayed when clicking @kbd{mouse-2} on a member name.
-
-
-
-
-@node Inherited Members
-@section Display of Inherited Members
-@cindex superclasses, members
-@cindex base classes, members
-@cindex inherited members
-
-@table @kbd
-@item D b
-This command toggles the display of inherited members in the member
-buffer. This is also in the buffer's context menu.
-@end table
-
-
-
-
-@node Searching Members
-@section Searching Members
-@cindex searching members
-
-@table @kbd
-@item G v
-Position the cursor on a member whose name is read from the minibuffer;
-only members shown in the current member buffer appear in the completion
-list.
-
-@item G m
-Like the above command, but all members for the current class appear in
-the completion list. If necessary, the current member list is switched
-to the one containing the member.
-
-With a prefix argument (@kbd{C-u}), all members in the class tree,
-i.e., all members the browser knows about appear in the completion
-list. The member display will be switched to the class and member list
-containing the member.
-
-@item G n
-Repeat the last member search.
-@end table
-
-Look into the buffer's context menu for a convenient way to do this with
-a mouse.
-
-
-
-@node Switching to Tree
-@section Switching to Tree Buffer
-@cindex tree buffer, switch to
-@cindex buffer switching
-@cindex switching buffers
-
-@table @kbd
-@item @key{TAB}
-Pop up the tree buffer to which the member buffer belongs.
-
-@item t
-Do the same as @key{TAB} but also position the cursor on the class
-displayed in the member buffer.
-@end table
-
-
-
-
-@node Filters
-@section Filters
-@cindex filters
-
-@table @kbd
-@cindex @code{public} members
-@item F a u
-This command toggles the display of @code{public} members. The
-@samp{a} stands for ``access''.
-
-@cindex @code{protected} members
-@item F a o
-This command toggles the display of @code{protected} members.
-
-@cindex @code{private} members
-@item F a i
-This command toggles the display of @code{private} members.
-
-@cindex @code{virtual} members
-@item F v
-This command toggles the display of @code{virtual} members.
-
-@cindex @code{inline} members
-@item F i
-This command toggles the display of @code{inline} members.
-
-@cindex @code{const} members
-@item F c
-This command toggles the display of @code{const} members.
-
-@cindex pure virtual members
-@item F p
-This command toggles the display of pure virtual members.
-
-@cindex remove filters
-@item F r
-This command removes all filters.
-@end table
-
-These commands are also found in the buffer's context menu.
-
-
-
-
-@node Attributes
-@section Displaying Member Attributes
-@cindex attributes
-@cindex member attribute display
-
-@table @kbd
-@item D a
-Toggle the display of member attributes (default is on).
-
-The nine member attributes Ebrowse knows about are displayed
-as a list a single-characters flags enclosed in angle brackets in front
-the of the member's name. A @samp{-} at a given position means that
-the attribute is false. The list of attributes from left to right is
-
-@table @samp
-@cindex @code{template} attribute
-@item T
-The member is a template.
-
-@cindex @code{extern "C"} attribute
-@item C
-The member is declared @code{extern "C"}.
-
-@cindex @code{virtual} attribute
-@item v
-Means the member is declared @code{virtual}.
-
-@cindex @code{inline}
-@item i
-The member is declared @code{inline}.
-
-@cindex @code{const} attribute
-@item c
-The member is @code{const}.
-
-@cindex pure virtual function attribute
-@item 0
-The member is a pure virtual function.
-
-@cindex @code{mutable} attribute
-@item m
-The member is declared @code{mutable}.
-
-@cindex @code{explicit} attribute
-@item e
-The member is declared @code{explicit}.
-
-@item t
-The member is a function with a throw list.
-@end table
-@end table
-
-This command is also in the buffer's context menu.
-
-
-
-@node Long and Short Display
-@section Long and Short Member Display
-@cindex display form
-@cindex long display
-@cindex short display
-
-@table @kbd
-@item D l
-This command toggles the member buffer between short and long display
-form. The short display form displays member names, only:
-
-@example
-| isEmpty contains hasMember create
-| storeSize hash isEqual restoreGuts
-| saveGuts
-@end example
-
-The long display shows one member per line with member name and regular
-expressions matching the member (if known):
-
-@example
-| isEmpty Bool isEmpty () const...
-| hash unsigned hash () const...
-| isEqual int isEqual (...
-@end example
-
-Regular expressions will only be displayed when the Lisp database has
-not been produced with the @command{ebrowse} option @samp{--no-regexps}.
-@xref{Matching, --no-regexps, Regular Expressions}.
-@end table
-
-
-
-
-@node Regexp Display
-@section Display of Regular Expressions
-@cindex regular expression display
-
-@table @kbd
-@item D r
-This command toggles the long display form from displaying the regular
-expressions matching the member declarations to those expressions
-matching member definitions.
-@end table
-
-Regular expressions will only be displayed when the Lisp database has
-not been produced with the @command{ebrowse} option @samp{--no-regexps},
-see @ref{Matching, --no-regexps, Regular Expressions}.
-
-
-
-
-@node Switching Classes
-@section Displaying Another Class
-@cindex base class, display
-@cindex derived class, display
-@cindex superclass, display
-@cindex subclass, display
-@cindex class display
-
-@table @kbd
-@item C c
-This command lets you switch the member buffer to another class. It
-reads the name of the new class from the minibuffer with completion.
-
-@item C b
-This is the same command as @kbd{C c} but restricts the classes shown in
-the completion list to immediate base classes, only. If only one base
-class exists, this one is immediately shown in the minibuffer.
-
-@item C d
-Same as @kbd{C b}, but for derived classes.
-
-@item C p
-Switch to the previous class in the class hierarchy on the same level as
-the class currently displayed.
-
-@item C n
-Switch to the next sibling of the class in the class tree.
-@end table
-
-
-
-
-@node Killing/Burying
-@section Burying a Member Buffer
-@cindex burying member buffers
-
-@table @kbd
-@item q
-This command is a synonym for @kbd{M-x bury-buffer}.
-@end table
-
-
-
-
-@node Column Width
-@section Setting the Column Width
-@cindex column width
-@cindex member indentation
-@cindex indentation, member
-
-@table @kbd
-@item D w
-This command sets the column width depending on the display form used
-(long or short display).
-@end table
-
-
-
-
-@node Redisplay
-@section Forced Redisplay
-@cindex redisplay of member buffers
-
-@table @kbd
-@item C-l
-This command forces a redisplay of the member buffer. If the width
-of the window displaying the member buffer is changed this command
-redraws the member list with the appropriate column widths and number of
-columns.
-@end table
-
-
-
-
-@node Getting Help
-@section Getting Help
-@cindex help
-
-@table @kbd
-@item ?
-This key is bound to @code{describe-mode}.
-@end table
-
-
-
-
-@comment **************************************************************
-@comment *** TAGS LIKE FUNCTIONS
-@comment **************************************************************
-
-@node Tags-like Functions
-@chapter Tags-like Functions
-
-Ebrowse provides tags functions similar to those of the standard
-Emacs Tags facility, but better suited to the needs of C++ programmers.
-
-@menu
-* Finding and Viewing:: Going to a member declaration/definition
-* Position Stack:: Moving to previous locations
-* Search & Replace:: Searching and replacing over class tree files
-* Members in Files:: Listing all members in a given file
-* Apropos:: Listing members matching a regular expression
-* Symbol Completion:: Completing names while editing
-* Member Buffer Display:: Quickly display a member buffer for some
- identifier
-@end menu
-
-
-
-@node Finding and Viewing
-@section Finding and Viewing Members
-@cindex finding class member, in C++ source
-@cindex viewing class member, in C++ source
-@cindex tags
-@cindex member definition, finding, in C++ source
-@cindex member declaration, finding, in C++ source
-
-The functions in this section are similar to those described in
-@ref{Source Display}, and also in @ref{Finding/Viewing}, except that
-they work in a C++ source buffer, not in member and tree buffers created
-by Ebrowse.
-
-@table @kbd
-@item C-c C-m f
-Find the definition of the member around point. If you invoke this
-function with a prefix argument, the declaration is searched.
-
-If more than one class contains a member with the given name you can
-select the class with completion. If there is a scope declaration in
-front of the member name, this class name is used as initial input for
-the completion.
-
-@item C-c C-m F
-Find the declaration of the member around point.
-
-@item C-c C-m v
-View the definition of the member around point.
-
-@item C-c C-m V
-View the declaration of the member around point.
-
-@item C-c C-m 4 f
-Find a member's definition in another window.
-
-@item C-c C-m 4 F
-Find a member's declaration in another window.
-
-@item C-c C-m 4 v
-View a member's definition in another window.
-
-@item C-c C-m 4 V
-View a member's declaration in another window.
-
-@item C-c C-m 5 f
-Find a member's definition in another frame.
-
-@item C-c C-m 5 F
-Find a member's declaration in another frame.
-
-@item C-c C-m 5 v
-View a member's definition in another frame.
-
-@item C-c C-m 5 V
-View a member's declaration in another frame.
-@end table
-
-
-
-@node Position Stack
-@section The Position Stack
-@cindex position stack
-
-When jumping to a member declaration or definition with one of
-Ebrowse's commands, the position from where you performed the
-jump and the position where you jumped to are recorded in a
-@dfn{position stack}. There are several ways in which you can quickly
-move to positions in the stack:
-
-@table @kbd
-@cindex return to original position
-@item C-c C-m -
-This command sets point to the previous position in the position stack.
-Directly after you performed a jump, this will put you back to the
-position where you came from.
-
-The stack is not popped, i.e., you can always switch back and forth
-between positions in the stack. To avoid letting the stack grow to
-infinite size there is a maximum number of positions defined. When this
-number is reached, older positions are discarded when new positions are
-pushed on the stack.
-
-@item C-c C-m +
-This command moves forward in the position stack, setting point to
-the next position stored in the position stack.
-
-@item C-c C-m p
-Displays an electric buffer showing all positions saved in the stack.
-You can select a position by pressing @kbd{@key{SPC}} in a line. You can
-view a position with @kbd{v}.
-@end table
-
-
-
-
-@node Search & Replace
-@section Searching and Replacing
-@cindex searching multiple C++ files
-@cindex replacing in multiple C++ files
-@cindex restart tags-operation
-
-Ebrowse allows you to perform operations on all or a subset of the files
-mentioned in a class tree. When you invoke one of the following
-functions and more than one class tree is loaded, you must choose a
-class tree to use from an electric tree menu. If the selected tree
-contains marked classes, the following commands operate on the files
-mentioned in the marked classes only. Otherwise all files in the class
-tree are used.
-
-@table @kbd
-@item C-c C-m s
-This function performs a regular expression search in the chosen set of
-files.
-
-@item C-c C-m u
-This command performs a search for calls of a given member which is
-selected in the usual way with completion.
-
-@item C-c C-m %
-Perform a query replace over the set of files.
-
-@item C-c C-m ,
-All three operations above stop when finding a match. You can restart
-the operation with this command.
-
-@item C-c C-m n
-This restarts the last tags operation with the next file in the list.
-@end table
-
-
-
-
-@node Members in Files
-@section Members in Files
-@cindex files
-@cindex members in file, listing
-@cindex list class members in a file
-@cindex file, members
-
-The command @kbd{C-c C-m l}, lists all members in a given file. The file
-name is read from the minibuffer with completion.
-
-
-
-
-@node Apropos
-@section Member Apropos
-@cindex apropos on class members
-@cindex members, matching regexp
-
-The command @kbd{C-c C-m a} can be used to display all members matching a
-given regular expression. This command can be very useful if you
-remember only part of a member name, and not its beginning.
-
-A special buffer is popped up containing all identifiers matching the
-regular expression, and what kind of symbol it is (e.g., a member
-function, or a type). You can then switch to this buffer, and use the
-command @kbd{C-c C-m f}, for example, to jump to a specific member.
-
-
-
-
-@node Symbol Completion
-@section Symbol Completion
-@cindex completion
-@cindex symbol completion
-
-The command @kbd{C-c C-m @key{TAB}} completes the symbol in front of point.
-
-
-
-
-@node Member Buffer Display
-@section Quick Member Display
-@cindex member buffer, for member at point
-
-You can quickly display a member buffer containing the member the cursor
-in on with the command @kbd{C-c C-m m}.
-
-
-@node GNU Free Documentation License
-@appendix GNU Free Documentation License
-@include doclicense.texi
-
-
-@node Concept Index
-@unnumbered Concept Index
-@printindex cp
-
-@bye
CROSS_SRC_BINS := $(top_builddir)/cross/src/android-emacs
CROSS_LIBSRC_BINS := $(top_builddir)/cross/lib-src/ctags \
$(top_builddir)/cross/lib-src/hexl \
- $(top_builddir)/cross/lib-src/ebrowse \
$(top_builddir)/cross/lib-src/emacsclient \
$(top_builddir)/cross/lib-src/etags
CROSS_LIBSRC_BINS_MOVEMAIL := $(top_builddir)/cross/lib-src/movemail
CLIENTW = @CLIENTW@
# Things that a user might actually run, which should be installed in bindir.
-INSTALLABLES = etags${EXEEXT} ctags${EXEEXT} emacsclient${EXEEXT} $(CLIENTW) \
- ebrowse${EXEEXT}
+INSTALLABLES = etags${EXEEXT} ctags${EXEEXT} emacsclient${EXEEXT} $(CLIENTW)
# Things that Emacs runs internally, or during the build process,
# which should not be installed in bindir.
asset-directory-tool${EXEEXT}: ${srcdir}/asset-directory-tool.c $(config_h)
$(AM_V_CCLD)$(CC) ${ALL_CFLAGS} $< $(LOADLIBES) -o $@
-ebrowse${EXEEXT}: ${srcdir}/ebrowse.c ${srcdir}/../lib/min-max.h $(NTLIB) \
- $(config_h)
- $(AM_V_CCLD)$(CC) ${ALL_CFLAGS} -o $@ $< $(NTLIB) $(LOADLIBES)
-
make-docfile${EXEEXT}: ${srcdir}/make-docfile.c $(NTLIB) $(config_h)
$(AM_V_CCLD)$(CC) ${ALL_CFLAGS} $< $(NTLIB) $(LOADLIBES) -o $@
+++ /dev/null
-/* ebrowse.c --- parsing files for the ebrowse C++ browser
-
-Copyright (C) 1992-2024 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs 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 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs 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 GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
-
-
-#include <config.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-#include <getopt.h>
-
-#include <attribute.h>
-#include <flexmember.h>
-#include <min-max.h>
-#include <unlocked-io.h>
-
-/* Files are read in chunks of this number of bytes. */
-
-enum { READ_CHUNK_SIZE = 100 * 1024 };
-
-/* Value is true if strings X and Y compare equal. */
-
-static bool
-streq (char const *x, char const *y)
-{
- return strcmp (x, y) == 0;
-}
-
-static bool
-filename_eq (char const *x, char const *y)
-{
-#ifdef __MSDOS__
- return strcasecmp (x, y) == 0;
-#elif defined WINDOWSNT
- return stricmp (x, y) == 0;
-#else
- return streq (x, y);
-#endif
-}
-
-/* The default output file name. */
-
-#define DEFAULT_OUTFILE "BROWSE"
-
-/* A version string written to the output file. Change this whenever
- the structure of the output file changes. */
-
-#define EBROWSE_FILE_VERSION "ebrowse 5.0"
-
-/* The output file consists of a tree of Lisp objects, with major
- nodes built out of Lisp structures. These are the heads of the
- Lisp structs with symbols identifying their type. */
-
-#define TREE_HEADER_STRUCT "[ebrowse-hs "
-#define TREE_STRUCT "[ebrowse-ts "
-#define MEMBER_STRUCT "[ebrowse-ms "
-#define CLASS_STRUCT "[ebrowse-cs "
-
-/* The name of the symbol table entry for global functions, variables,
- defines etc. This name also appears in the browser display. */
-
-#define GLOBALS_NAME "*Globals*"
-
-/* Token definitions. */
-
-enum token
-{
- YYEOF = 0, /* end of file */
- CSTRING = 256, /* string constant */
- CCHAR, /* character constant */
- CINT, /* integral constant */
- CFLOAT, /* real constant */
-
- ELLIPSIS, /* ... */
- LSHIFTASGN, /* <<= */
- RSHIFTASGN, /* >>= */
- ARROWSTAR, /* ->* */
- IDENT, /* identifier */
- DIVASGN, /* /= */
- INC, /* ++ */
- ADDASGN, /* += */
- DEC, /* -- */
- ARROW, /* -> */
- SUBASGN, /* -= */
- MULASGN, /* *= */
- MODASGN, /* %= */
- LOR, /* || */
- ORASGN, /* |= */
- LAND, /* && */
- ANDASGN, /* &= */
- XORASGN, /* ^= */
- POINTSTAR, /* .* */
- DCOLON, /* :: */
- EQ, /* == */
- NE, /* != */
- LE, /* <= */
- LSHIFT, /* << */
- GE, /* >= */
- RSHIFT, /* >> */
-
-/* Keywords. The undef's are there because these
- three symbols are very likely to be defined somewhere. */
-#undef BOOL
-#undef TRUE
-#undef FALSE
-
- ASM, /* asm */
- AUTO, /* auto */
- BREAK, /* break */
- CASE, /* case */
- CATCH, /* catch */
- CHAR, /* char */
- CLASS, /* class */
- CONST, /* const */
- CONTINUE, /* continue */
- DEFAULT, /* default */
- DELETE, /* delete */
- DO, /* do */
- DOUBLE, /* double */
- ELSE, /* else */
- ENUM, /* enum */
- EXTERN, /* extern */
- FLOAT, /* float */
- FOR, /* for */
- FRIEND, /* friend */
- GOTO, /* goto */
- IF, /* if */
- T_INLINE, /* inline */
- INT, /* int */
- LONG, /* long */
- NEW, /* new */
- OPERATOR, /* operator */
- PRIVATE, /* private */
- PROTECTED, /* protected */
- PUBLIC, /* public */
- REGISTER, /* register */
- RETURN, /* return */
- SHORT, /* short */
- SIGNED, /* signed */
- SIZEOF, /* sizeof */
- STATIC, /* static */
- STRUCT, /* struct */
- SWITCH, /* switch */
- TEMPLATE, /* template */
- THIS, /* this */
- THROW, /* throw */
- TRY, /* try */
- TYPEDEF, /* typedef */
- UNION, /* union */
- UNSIGNED, /* unsigned */
- VIRTUAL, /* virtual */
- VOID, /* void */
- VOLATILE, /* volatile */
- WHILE, /* while */
- MUTABLE, /* mutable */
- BOOL, /* bool */
- TRUE, /* true */
- FALSE, /* false */
- SIGNATURE, /* signature (GNU extension) */
- NAMESPACE, /* namespace */
- EXPLICIT, /* explicit */
- TYPENAME, /* typename */
- CONST_CAST, /* const_cast */
- DYNAMIC_CAST, /* dynamic_cast */
- REINTERPRET_CAST, /* reinterpret_cast */
- STATIC_CAST, /* static_cast */
- TYPEID, /* typeid */
- USING, /* using */
- WCHAR, /* wchar_t */
- FINAL /* final */
-};
-
-/* Storage classes, in a wider sense. */
-
-enum sc
-{
- SC_UNKNOWN,
- SC_MEMBER, /* Is an instance member. */
- SC_STATIC, /* Is static member. */
- SC_FRIEND, /* Is friend function. */
- SC_TYPE /* Is a type definition. */
-};
-
-/* Member visibility. */
-
-enum visibility
-{
- V_PUBLIC,
- V_PROTECTED,
- V_PRIVATE
-};
-
-/* Member flags. */
-
-#define F_VIRTUAL 1 /* Is virtual function. */
-#define F_INLINE 2 /* Is inline function. */
-#define F_CONST 4 /* Is const. */
-#define F_PURE 8 /* Is pure virtual function. */
-#define F_MUTABLE 16 /* Is mutable. */
-#define F_TEMPLATE 32 /* Is a template. */
-#define F_EXPLICIT 64 /* Is explicit constructor. */
-#define F_THROW 128 /* Has a throw specification. */
-#define F_EXTERNC 256 /* Is declared extern "C". */
-#define F_DEFINE 512 /* Is a #define. */
-
-/* Set and test a bit in an int. */
-
-static void
-set_flag (int *f, int flag)
-{
- *f |= flag;
-}
-
-static bool
-has_flag (int f, int flag)
-{
- return (f & flag) != 0;
-}
-
-/* Structure describing a class member. */
-
-struct member
-{
- struct member *next; /* Next in list of members. */
- struct member *anext; /* Collision chain in member_table. */
- struct member **list; /* Pointer to list in class. */
- unsigned param_hash; /* Hash value for parameter types. */
- int vis; /* Visibility (public, ...). */
- int flags; /* See F_* above. */
- char *regexp; /* Matching regular expression. */
- const char *filename; /* Don't free this shared string. */
- int pos; /* Buffer position of occurrence. */
- char *def_regexp; /* Regular expression matching definition. */
- const char *def_filename; /* File name of definition. */
- int def_pos; /* Buffer position of definition. */
- char name[FLEXIBLE_ARRAY_MEMBER]; /* Member name. */
-};
-
-/* Structures of this type are used to connect class structures with
- their super and subclasses. */
-
-struct link
-{
- struct sym *sym; /* The super or subclass. */
- struct link *next; /* Next in list or NULL. */
-};
-
-/* Structure used to record namespace aliases. */
-
-struct alias
-{
- struct alias *next; /* Next in list. */
- struct sym *namesp; /* Namespace in which defined. */
- struct link *aliasee; /* List of aliased namespaces (A::B::C...). */
- char name[FLEXIBLE_ARRAY_MEMBER]; /* Alias name. */
-};
-
-/* The structure used to describe a class in the symbol table,
- or a namespace in all_namespaces. */
-
-struct sym
-{
- int flags; /* Is class a template class?. */
- unsigned char visited; /* Used to find circles. */
- struct sym *next; /* Hash collision list. */
- struct link *subs; /* List of subclasses. */
- struct link *supers; /* List of superclasses. */
- struct member *vars; /* List of instance variables. */
- struct member *fns; /* List of instance functions. */
- struct member *static_vars; /* List of static variables. */
- struct member *static_fns; /* List of static functions. */
- struct member *friends; /* List of friend functions. */
- struct member *types; /* List of local types. */
- char *regexp; /* Matching regular expression. */
- int pos; /* Buffer position. */
- const char *filename; /* File in which it can be found. */
- const char *sfilename; /* File in which members can be found. */
- struct sym *namesp; /* Namespace in which defined. . */
- char name[FLEXIBLE_ARRAY_MEMBER]; /* Name of the class. */
-};
-
-/* Experimental: Print info for `--position-info'. We print
- '(CLASS-NAME SCOPE MEMBER-NAME). */
-
-#define P_DEFN 1
-#define P_DECL 2
-
-static int info_where;
-static struct sym *info_cls = NULL;
-static struct member *info_member = NULL;
-
-/* Experimental. For option `--position-info', the buffer position we
- are interested in. When this position is reached, print out
- information about what we know about that point. */
-
-static int info_position = -1;
-
-/* Command line options structure for getopt_long. */
-
-static struct option const options[] =
-{
- {"append", no_argument, NULL, 'a'},
- {"files", required_argument, NULL, 'f'},
- {"help", no_argument, NULL, -2},
- {"min-regexp-length", required_argument, NULL, 'm'},
- {"max-regexp-length", required_argument, NULL, 'M'},
- {"no-nested-classes", no_argument, NULL, 'n'},
- {"no-regexps", no_argument, NULL, 'x'},
- {"no-structs-or-unions", no_argument, NULL, 's'},
- {"output-file", required_argument, NULL, 'o'},
- {"position-info", required_argument, NULL, 'p'},
- {"search-path", required_argument, NULL, 'I'},
- {"verbose", no_argument, NULL, 'v'},
- {"version", no_argument, NULL, -3},
- {"very-verbose", no_argument, NULL, 'V'},
- {NULL, 0, NULL, 0}
-};
-
-/* Semantic values of tokens. Set by yylex.. */
-
-static unsigned yyival; /* Set for token CINT. */
-static char *yytext; /* Set for token IDENT. */
-static char *yytext_end;
-
-/* Output file. */
-
-static FILE *yyout;
-
-/* Current line number. */
-
-static int yyline;
-
-/* The name of the current input file. */
-
-static const char *filename;
-
-/* Three character class vectors, and macros to test membership
- of characters. */
-
-static char is_ident[255];
-static char is_digit[255];
-static char is_white[255];
-
-#define IDENTP(C) is_ident[(unsigned char) (C)]
-#define DIGITP(C) is_digit[(unsigned char) (C)]
-#define WHITEP(C) is_white[(unsigned char) (C)]
-
-/* Command line flags. */
-
-static int f_append;
-static int f_verbose;
-static int f_very_verbose;
-static int f_structs = 1;
-static int f_regexps = 1;
-static int f_nested_classes = 1;
-
-/* Maximum and minimum lengths of regular expressions matching a
- member, class etc., for writing them to the output file. These are
- overridable from the command line. */
-
-static int min_regexp = 5;
-static int max_regexp = 50;
-
-/* Input buffer. */
-
-static char *inbuffer;
-static char *in;
-static size_t inbuffer_size;
-
-/* Return the current buffer position in the input file. */
-
-#define BUFFER_POS() (in - inbuffer)
-
-/* If current lookahead is CSTRING, the following points to the
- first character in the string constant. Used for recognizing
- extern "C". */
-
-static char *string_start;
-
-/* The size of the hash tables for classes.and members. Should be
- prime. */
-
-#define TABLE_SIZE 1001
-
-/* The hash table for class symbols. */
-
-static struct sym *class_table[TABLE_SIZE];
-
-/* Hash table containing all member structures. This is generally
- faster for member lookup than traversing the member lists of a
- `struct sym'. */
-
-static struct member *member_table[TABLE_SIZE];
-
-/* Hash table for namespace aliases */
-
-static struct alias *namespace_alias_table[TABLE_SIZE];
-
-/* The special class symbol used to hold global functions,
- variables etc. */
-
-static struct sym *global_symbols;
-
-/* The current namespace. */
-
-static struct sym *current_namespace;
-
-/* The list of all known namespaces. */
-
-static struct sym *all_namespaces;
-
-/* Stack of namespaces we're currently nested in, during the parse. */
-
-static struct sym **namespace_stack;
-static int namespace_stack_size;
-static int namespace_sp;
-
-/* The current lookahead token. */
-
-static int tk = -1;
-
-/* Structure describing a keyword. */
-
-struct kw
-{
- const char *name; /* Spelling. */
- int tk; /* Token value. */
- struct kw *next; /* Next in collision chain. */
-};
-
-/* Keywords are lookup up in a hash table of their own. */
-
-#define KEYWORD_TABLE_SIZE 1001
-static struct kw *keyword_table[KEYWORD_TABLE_SIZE];
-
-/* Search path. */
-
-struct search_path
-{
- char *path;
- struct search_path *next;
-};
-
-static struct search_path *search_path;
-static struct search_path *search_path_tail;
-
-/* Function prototypes. */
-
-static char *matching_regexp (void);
-static struct sym *add_sym (const char *, struct sym *);
-static void add_global_defn (char *, char *, int, unsigned, int, int, int);
-static void add_global_decl (char *, char *, int, unsigned, int, int, int);
-static struct member *add_member (struct sym *, char *, int, int, unsigned);
-static void class_definition (struct sym *, const char *, int, int, int);
-static char *operator_name (int *);
-static void parse_qualified_param_ident_or_type (char **);
-\f
-/***********************************************************************
- Utilities
- ***********************************************************************/
-
-/* Print an error in a printf-like style with the current input file
- name and line number. */
-
-static void
-yyerror (const char *format, const char *s)
-{
- fprintf (stderr, "%s:%d: ", filename, yyline);
- fprintf (stderr, format, s);
- putc ('\n', stderr);
-}
-
-
-/* Like malloc but print an error and exit if not enough memory is
- available. */
-
-static void * ATTRIBUTE_MALLOC
-xmalloc (size_t nbytes)
-{
- void *p = malloc (nbytes);
- if (p == NULL)
- {
- yyerror ("out of memory", NULL);
- exit (EXIT_FAILURE);
- }
- return p;
-}
-
-
-/* Like realloc but print an error and exit if out of memory. */
-
-static void *
-xrealloc (void *p, size_t sz)
-{
- p = realloc (p, sz);
- if (p == NULL)
- {
- yyerror ("out of memory", NULL);
- exit (EXIT_FAILURE);
- }
- return p;
-}
-
-
-/* Like strdup, but print an error and exit if not enough memory is
- available.. If S is null, return null. */
-
-static char *
-xstrdup (char *s)
-{
- if (s)
- return strcpy (xmalloc (strlen (s) + 1), s);
- return s;
-}
-
-
-\f
-/***********************************************************************
- Symbols
- ***********************************************************************/
-
-/* Initialize the symbol table. This currently only sets up the
- special symbol for globals (`*Globals*'). */
-
-static void
-init_sym (void)
-{
- global_symbols = add_sym (GLOBALS_NAME, NULL);
-}
-
-
-/* Add a symbol for class NAME to the symbol table. NESTED_IN_CLASS
- is the class in which class NAME was found. If it is null,
- this means the scope of NAME is the current namespace.
-
- If a symbol for NAME already exists, return that. Otherwise
- create a new symbol and set it to default values. */
-
-static struct sym *
-add_sym (const char *name, struct sym *nested_in_class)
-{
- struct sym *sym;
- unsigned h;
- const char *s;
- struct sym *scope = nested_in_class ? nested_in_class : current_namespace;
-
- for (s = name, h = 0; *s; ++s)
- h = (h << 1) ^ *s;
- h %= TABLE_SIZE;
-
- for (sym = class_table[h]; sym; sym = sym->next)
- if (streq (name, sym->name)
- && ((!sym->namesp && !scope)
- || (sym->namesp && scope
- && streq (sym->namesp->name, scope->name))))
- break;
-
- if (sym == NULL)
- {
- if (f_very_verbose)
- {
- putchar ('\t');
- puts (name);
- }
-
- sym = xmalloc (FLEXSIZEOF (struct sym, name, strlen (name) + 1));
- memset (sym, 0, offsetof (struct sym, name));
- strcpy (sym->name, name);
- sym->namesp = scope;
- sym->next = class_table[h];
- class_table[h] = sym;
- }
-
- return sym;
-}
-
-
-/* Add links between superclass SUPER and subclass SUB. */
-
-static void
-add_link (struct sym *super, struct sym *sub)
-{
- struct link *lnk, *lnk2, *p, *prev;
-
- /* See if a link already exists. */
- for (p = super->subs, prev = NULL;
- p && strcmp (sub->name, p->sym->name) > 0;
- prev = p, p = p->next)
- ;
-
- /* Avoid duplicates. */
- if (p == NULL || p->sym != sub)
- {
- lnk = (struct link *) xmalloc (sizeof *lnk);
- lnk2 = (struct link *) xmalloc (sizeof *lnk2);
-
- lnk->sym = sub;
- lnk->next = p;
-
- if (prev)
- prev->next = lnk;
- else
- super->subs = lnk;
-
- lnk2->sym = super;
- lnk2->next = sub->supers;
- sub->supers = lnk2;
- }
-}
-
-
-/* Find in class CLS member NAME.
-
- VAR non-zero means look for a member variable; otherwise a function
- is searched. SC specifies what kind of member is searched---a
- static, or per-instance member etc. HASH is a hash code for the
- parameter types of functions. Value is a pointer to the member
- found or null if not found. */
-
-static struct member *
-find_member (struct sym *cls, char *name, int var, int sc, unsigned int hash)
-{
- struct member **list;
- struct member *p;
- unsigned name_hash = 0;
- char *s;
- int i;
-
- switch (sc)
- {
- case SC_FRIEND:
- list = &cls->friends;
- break;
-
- case SC_TYPE:
- list = &cls->types;
- break;
-
- case SC_STATIC:
- list = var ? &cls->static_vars : &cls->static_fns;
- break;
-
- default:
- list = var ? &cls->vars : &cls->fns;
- break;
- }
-
- for (s = name; *s; ++s)
- name_hash = (name_hash << 1) ^ *s;
- i = name_hash % TABLE_SIZE;
-
- for (p = member_table[i]; p; p = p->anext)
- if (p->list == list && p->param_hash == hash && streq (name, p->name))
- break;
-
- return p;
-}
-
-
-/* Add to class CLS information for the declaration of member NAME.
- REGEXP is a regexp matching the declaration, if non-null. POS is
- the position in the source where the declaration is found. HASH is
- a hash code for the parameter list of the member, if it's a
- function. VAR non-zero means member is a variable or type. SC
- specifies the type of member (instance member, static, ...). VIS
- is the member's visibility (public, protected, private). FLAGS is
- a bit set giving additional information about the member (see the
- F_* defines). */
-
-static void
-add_member_decl (struct sym *cls, char *name, char *regexp, int pos, unsigned int hash, int var, int sc, int vis, int flags)
-{
- struct member *m;
-
- m = find_member (cls, name, var, sc, hash);
- if (m == NULL)
- m = add_member (cls, name, var, sc, hash);
-
- /* Have we seen a new filename? If so record that. */
- if (!cls->filename || !filename_eq (cls->filename, filename))
- m->filename = filename;
-
- m->regexp = regexp;
- m->pos = pos;
- m->flags = flags;
-
- switch (vis)
- {
- case PRIVATE:
- m->vis = V_PRIVATE;
- break;
-
- case PROTECTED:
- m->vis = V_PROTECTED;
- break;
-
- case PUBLIC:
- m->vis = V_PUBLIC;
- break;
- }
-
- info_where = P_DECL;
- info_cls = cls;
- info_member = m;
-}
-
-
-/* Add to class CLS information for the definition of member NAME.
- REGEXP is a regexp matching the declaration, if non-null. POS is
- the position in the source where the declaration is found. HASH is
- a hash code for the parameter list of the member, if it's a
- function. VAR non-zero means member is a variable or type. SC
- specifies the type of member (instance member, static, ...). VIS
- is the member's visibility (public, protected, private). FLAGS is
- a bit set giving additional information about the member (see the
- F_* defines). */
-
-static void
-add_member_defn (struct sym *cls, char *name, char *regexp, int pos, unsigned int hash, int var, int sc, int flags)
-{
- struct member *m;
-
- if (sc == SC_UNKNOWN)
- {
- m = find_member (cls, name, var, SC_MEMBER, hash);
- if (m == NULL)
- {
- m = find_member (cls, name, var, SC_STATIC, hash);
- if (m == NULL)
- m = add_member (cls, name, var, sc, hash);
- }
- }
- else
- {
- m = find_member (cls, name, var, sc, hash);
- if (m == NULL)
- m = add_member (cls, name, var, sc, hash);
- }
-
- if (!cls->sfilename)
- cls->sfilename = filename;
-
- if (!filename_eq (cls->sfilename, filename))
- m->def_filename = filename;
-
- m->def_regexp = regexp;
- m->def_pos = pos;
- m->flags |= flags;
-
- info_where = P_DEFN;
- info_cls = cls;
- info_member = m;
-}
-
-
-/* Add a symbol for a define named NAME to the symbol table.
- REGEXP is a regular expression matching the define in the source,
- if it is non-null. POS is the position in the file. */
-
-static void
-add_define (char *name, char *regexp, int pos)
-{
- add_global_defn (name, regexp, pos, 0, 1, SC_FRIEND, F_DEFINE);
- add_global_decl (name, regexp, pos, 0, 1, SC_FRIEND, F_DEFINE);
-}
-
-
-/* Add information for the global definition of NAME.
- REGEXP is a regexp matching the declaration, if non-null. POS is
- the position in the source where the declaration is found. HASH is
- a hash code for the parameter list of the member, if it's a
- function. VAR non-zero means member is a variable or type. SC
- specifies the type of member (instance member, static, ...). VIS
- is the member's visibility (public, protected, private). FLAGS is
- a bit set giving additional information about the member (see the
- F_* defines). */
-
-static void
-add_global_defn (char *name, char *regexp, int pos, unsigned int hash, int var, int sc, int flags)
-{
- int i;
- struct sym *sym;
-
- /* Try to find out for which classes a function is a friend, and add
- what we know about it to them. */
- if (!var)
- for (i = 0; i < TABLE_SIZE; ++i)
- for (sym = class_table[i]; sym; sym = sym->next)
- if (sym != global_symbols && sym->friends)
- if (find_member (sym, name, 0, SC_FRIEND, hash))
- add_member_defn (sym, name, regexp, pos, hash, 0,
- SC_FRIEND, flags);
-
- /* Add to global symbols. */
- add_member_defn (global_symbols, name, regexp, pos, hash, var, sc, flags);
-}
-
-
-/* Add information for the global declaration of NAME.
- REGEXP is a regexp matching the declaration, if non-null. POS is
- the position in the source where the declaration is found. HASH is
- a hash code for the parameter list of the member, if it's a
- function. VAR non-zero means member is a variable or type. SC
- specifies the type of member (instance member, static, ...). VIS
- is the member's visibility (public, protected, private). FLAGS is
- a bit set giving additional information about the member (see the
- F_* defines). */
-
-static void
-add_global_decl (char *name, char *regexp, int pos, unsigned int hash, int var, int sc, int flags)
-{
- /* Add declaration only if not already declared. Header files must
- be processed before source files for this to have the right effect.
- I do not want to handle implicit declarations at the moment. */
- struct member *m;
- struct member *found;
-
- m = found = find_member (global_symbols, name, var, sc, hash);
- if (m == NULL)
- m = add_member (global_symbols, name, var, sc, hash);
-
- /* Definition already seen => probably last declaration implicit.
- Override. This means that declarations must always be added to
- the symbol table before definitions. */
- if (!found)
- {
- if (!global_symbols->filename
- || !filename_eq (global_symbols->filename, filename))
- m->filename = filename;
-
- m->regexp = regexp;
- m->pos = pos;
- m->vis = V_PUBLIC;
- m->flags = flags;
-
- info_where = P_DECL;
- info_cls = global_symbols;
- info_member = m;
- }
-}
-
-
-/* Add a symbol for member NAME to class CLS.
- VAR non-zero means it's a variable. SC specifies the kind of
- member. HASH is a hash code for the parameter types of a function.
- Value is a pointer to the member's structure. */
-
-static struct member *
-add_member (struct sym *cls, char *name, int var, int sc, unsigned int hash)
-{
- struct member *m = xmalloc (FLEXSIZEOF (struct member, name,
- strlen (name) + 1));
- struct member **list;
- struct member *p;
- struct member *prev;
- unsigned name_hash = 0;
- int i;
- char *s;
-
- strcpy (m->name, name);
- m->param_hash = hash;
-
- m->vis = 0;
- m->flags = 0;
- m->regexp = NULL;
- m->filename = NULL;
- m->pos = 0;
- m->def_regexp = NULL;
- m->def_filename = NULL;
- m->def_pos = 0;
-
- assert (cls != NULL);
-
- switch (sc)
- {
- case SC_FRIEND:
- list = &cls->friends;
- break;
-
- case SC_TYPE:
- list = &cls->types;
- break;
-
- case SC_STATIC:
- list = var ? &cls->static_vars : &cls->static_fns;
- break;
-
- default:
- list = var ? &cls->vars : &cls->fns;
- break;
- }
-
- for (s = name; *s; ++s)
- name_hash = (name_hash << 1) ^ *s;
- i = name_hash % TABLE_SIZE;
- m->anext = member_table[i];
- member_table[i] = m;
- m->list = list;
-
- /* Keep the member list sorted. It's cheaper to do it here than to
- sort them in Lisp. */
- for (prev = NULL, p = *list;
- p && strcmp (name, p->name) > 0;
- prev = p, p = p->next)
- ;
-
- m->next = p;
- if (prev)
- prev->next = m;
- else
- *list = m;
- return m;
-}
-
-
-/* Given the root R of a class tree, step through all subclasses
- recursively, marking functions as virtual that are declared virtual
- in base classes. */
-
-static void
-mark_virtual (struct sym *r)
-{
- struct link *p;
- struct member *m, *m2;
-
- for (p = r->subs; p; p = p->next)
- {
- for (m = r->fns; m; m = m->next)
- if (has_flag (m->flags, F_VIRTUAL))
- {
- for (m2 = p->sym->fns; m2; m2 = m2->next)
- if (m->param_hash == m2->param_hash && streq (m->name, m2->name))
- set_flag (&m2->flags, F_VIRTUAL);
- }
-
- mark_virtual (p->sym);
- }
-}
-
-
-/* For all roots of the class tree, mark functions as virtual that
- are virtual because of a virtual declaration in a base class. */
-
-static void
-mark_inherited_virtual (void)
-{
- struct sym *r;
- int i;
-
- for (i = 0; i < TABLE_SIZE; ++i)
- for (r = class_table[i]; r; r = r->next)
- if (r->supers == NULL)
- mark_virtual (r);
-}
-
-
-/* Create and return a symbol for a namespace with name NAME. */
-
-static struct sym *
-make_namespace (char *name, struct sym *context)
-{
- struct sym *s = xmalloc (FLEXSIZEOF (struct sym, name, strlen (name) + 1));
- memset (s, 0, offsetof (struct sym, name));
- strcpy (s->name, name);
- s->next = all_namespaces;
- s->namesp = context;
- all_namespaces = s;
- return s;
-}
-
-
-/* Find the symbol for namespace NAME. If not found, return NULL */
-
-static struct sym *
-check_namespace (char *name, struct sym *context)
-{
- struct sym *p = NULL;
-
- for (p = all_namespaces; p; p = p->next)
- {
- if (streq (p->name, name) && (p->namesp == context))
- break;
- }
-
- return p;
-}
-
-/* Find the symbol for namespace NAME. If not found, add a new symbol
- for NAME to all_namespaces. */
-
-static struct sym *
-find_namespace (char *name, struct sym *context)
-{
- struct sym *p = check_namespace (name, context);
-
- if (p == NULL)
- p = make_namespace (name, context);
-
- return p;
-}
-
-
-/* Find namespace alias with name NAME. If not found return NULL. */
-
-static struct link *
-check_namespace_alias (char *name)
-{
- struct link *p = NULL;
- struct alias *al;
- unsigned h;
- char *s;
-
- for (s = name, h = 0; *s; ++s)
- h = (h << 1) ^ *s;
- h %= TABLE_SIZE;
-
- for (al = namespace_alias_table[h]; al; al = al->next)
- if (streq (name, al->name) && (al->namesp == current_namespace))
- {
- p = al->aliasee;
- break;
- }
-
- return p;
-}
-
-/* Register the name NEW_NAME as an alias for namespace list OLD_NAME. */
-
-static void
-register_namespace_alias (char *new_name, struct link *old_name)
-{
- unsigned h;
- char *s;
- struct alias *al;
-
- for (s = new_name, h = 0; *s; ++s)
- h = (h << 1) ^ *s;
- h %= TABLE_SIZE;
-
-
- /* Is it already in the table of aliases? */
- for (al = namespace_alias_table[h]; al; al = al->next)
- if (streq (new_name, al->name) && (al->namesp == current_namespace))
- return;
-
- al = xmalloc (FLEXSIZEOF (struct alias, name, strlen (new_name) + 1));
- strcpy (al->name, new_name);
- al->next = namespace_alias_table[h];
- al->namesp = current_namespace;
- al->aliasee = old_name;
- namespace_alias_table[h] = al;
-}
-
-
-/* Enter namespace with name NAME. */
-
-static void
-enter_namespace (char *name)
-{
- struct sym *p = find_namespace (name, current_namespace);
-
- if (namespace_sp == namespace_stack_size)
- {
- int size = max (10, 2 * namespace_stack_size);
- namespace_stack
- = (struct sym **) xrealloc ((void *)namespace_stack,
- size * sizeof *namespace_stack);
- namespace_stack_size = size;
- }
-
- namespace_stack[namespace_sp++] = current_namespace;
- current_namespace = p;
-}
-
-
-/* Leave the current namespace. */
-
-static void
-leave_namespace (void)
-{
- assert (namespace_sp > 0);
- current_namespace = namespace_stack[--namespace_sp];
-}
-
-
-\f
-/***********************************************************************
- Writing the Output File
- ***********************************************************************/
-
-/* Write string S to the output file FP in a Lisp-readable form.
- If S is null, write out `()'. */
-
-static void
-putstr (const char *s, FILE *fp)
-{
- if (!s)
- {
- putc ('(', fp);
- putc (')', fp);
- putc (' ', fp);
- }
- else
- {
- putc ('"', fp);
- fputs (s, fp);
- putc ('"', fp);
- putc (' ', fp);
- }
-}
-
-/* A dynamically allocated buffer for constructing a scope name. */
-
-static char *scope_buffer;
-static int scope_buffer_size;
-static int scope_buffer_len;
-
-
-/* Make sure scope_buffer has enough room to add LEN chars to it. */
-
-static void
-ensure_scope_buffer_room (int len)
-{
- if (scope_buffer_len + len >= scope_buffer_size)
- {
- int new_size = max (2 * scope_buffer_size, scope_buffer_len + len);
- scope_buffer = (char *) xrealloc (scope_buffer, new_size);
- scope_buffer_size = new_size;
- }
-}
-
-
-/* Recursively add the scope names of symbol P and the scopes of its
- namespaces to scope_buffer. Value is a pointer to the complete
- scope name constructed. */
-
-static char *
-sym_scope_1 (struct sym *p)
-{
- int len;
-
- if (p->namesp)
- sym_scope_1 (p->namesp);
-
- if (*scope_buffer)
- {
- ensure_scope_buffer_room (3);
- strcpy (scope_buffer + scope_buffer_len, "::");
- scope_buffer_len += 2;
- }
-
- len = strlen (p->name);
- ensure_scope_buffer_room (len + 1);
- strcpy (scope_buffer + scope_buffer_len, p->name);
- scope_buffer_len += len;
-
- if (has_flag (p->flags, F_TEMPLATE))
- {
- ensure_scope_buffer_room (3);
- strcpy (scope_buffer + scope_buffer_len, "<>");
- scope_buffer_len += 2;
- }
-
- return scope_buffer;
-}
-
-
-/* Return the scope of symbol P in printed representation, i.e.
- as it would appear in a C*+ source file. */
-
-static char *
-sym_scope (struct sym *p)
-{
- if (!scope_buffer)
- {
- scope_buffer_size = 1024;
- scope_buffer = (char *) xmalloc (scope_buffer_size);
- }
-
- *scope_buffer = '\0';
- scope_buffer_len = 0;
-
- if (p->namesp)
- sym_scope_1 (p->namesp);
-
- return scope_buffer;
-}
-
-
-/* Dump the list of members M to file FP. */
-
-static void
-dump_members (FILE *fp, struct member *m)
-{
- putc ('(', fp);
-
- for (; m; m = m->next)
- {
- fputs (MEMBER_STRUCT, fp);
- putstr (m->name, fp);
- putstr (NULL, fp); /* FIXME? scope for globals */
- fprintf (fp, "%u ", (unsigned) m->flags);
- putstr (m->filename, fp);
- putstr (m->regexp, fp);
- fprintf (fp, "%u ", (unsigned) m->pos);
- fprintf (fp, "%u ", (unsigned) m->vis);
- putc (' ', fp);
- putstr (m->def_filename, fp);
- putstr (m->def_regexp, fp);
- fprintf (fp, "%u", (unsigned) m->def_pos);
- putc (']', fp);
- putc ('\n', fp);
- }
-
- putc (')', fp);
- putc ('\n', fp);
-}
-
-
-/* Dump class ROOT to stream FP. */
-
-static void
-dump_sym (FILE *fp, struct sym *root)
-{
- fputs (CLASS_STRUCT, fp);
- putstr (root->name, fp);
-
- /* Print scope, if any. */
- if (root->namesp)
- putstr (sym_scope (root), fp);
- else
- putstr (NULL, fp);
-
- /* Print flags. */
- fprintf (fp, "%d", root->flags);
- putstr (root->filename, fp);
- putstr (root->regexp, fp);
- fprintf (fp, "%u", (unsigned) root->pos);
- putstr (root->sfilename, fp);
- putc (']', fp);
- putc ('\n', fp);
-}
-
-
-/* Dump class ROOT and its subclasses to file FP. */
-
-static void
-dump_tree (FILE *fp, struct sym *root)
-{
- dump_sym (fp, root);
-
- if (f_verbose)
- {
- putchar ('+');
- fflush (stdout);
- }
-
- putc ('(', fp);
-
- for (struct link *lk = root->subs; lk; lk = lk->next)
- {
- fputs (TREE_STRUCT, fp);
- dump_tree (fp, lk->sym);
- putc (']', fp);
- }
-
- putc (')', fp);
-
- dump_members (fp, root->vars);
- dump_members (fp, root->fns);
- dump_members (fp, root->static_vars);
- dump_members (fp, root->static_fns);
- dump_members (fp, root->friends);
- dump_members (fp, root->types);
-
- /* Superclasses. */
- putc ('(', fp);
- putc (')', fp);
-
- /* Mark slot. */
- putc ('(', fp);
- putc (')', fp);
-
- putc ('\n', fp);
-}
-
-
-/* Dump the entire class tree to file FP. */
-
-static void
-dump_roots (FILE *fp)
-{
- /* Output file header containing version string, command line
- options etc. */
- if (!f_append)
- {
- fputs (TREE_HEADER_STRUCT, fp);
- putstr (EBROWSE_FILE_VERSION, fp);
-
- putc ('\"', fp);
- if (!f_structs)
- fputs (" -s", fp);
- if (f_regexps)
- fputs (" -x", fp);
- putc ('\"', fp);
- fputs (" ()", fp);
- fputs (" ()", fp);
- putc (']', fp);
- }
-
- /* Mark functions as virtual that are so because of functions
- declared virtual in base classes. */
- mark_inherited_virtual ();
-
- /* Dump the roots of the graph. */
- for (int i = 0; i < TABLE_SIZE; ++i)
- for (struct sym *r = class_table[i]; r; r = r->next)
- if (!r->supers)
- {
- fputs (TREE_STRUCT, fp);
- dump_tree (fp, r);
- putc (']', fp);
- }
-
- if (f_verbose)
- putchar ('\n');
-}
-
-
-\f
-/***********************************************************************
- Scanner
- ***********************************************************************/
-
-#ifdef DEBUG
-#define INCREMENT_LINENO \
-do { \
- if (f_very_verbose) \
- { \
- ++yyline; \
- printf ("%d:\n", yyline); \
- } \
- else \
- ++yyline; \
-} while (0)
-#else
-#define INCREMENT_LINENO ++yyline
-#endif
-
-/* Define two macros for accessing the input buffer (current input
- file). GET(C) sets C to the next input character and advances the
- input pointer. UNGET retracts the input pointer. */
-
-#define GET(C) ((C) = *in++)
-#define UNGET() (--in)
-
-
-/* Process a preprocessor line. Value is the next character from the
- input buffer not consumed. */
-
-static int
-process_pp_line (void)
-{
- int in_comment = 0, in_string = 0;
- int c;
- char *p = yytext;
-
- /* Skip over white space. The `#' has been consumed already. */
- while (WHITEP (GET (c)))
- ;
-
- /* Read the preprocessor command (if any). */
- while (IDENTP (c))
- {
- *p++ = c;
- GET (c);
- }
-
- /* Is it a `define'? */
- *p = '\0';
-
- if (*yytext && streq (yytext, "define"))
- {
- p = yytext;
- while (WHITEP (c))
- GET (c);
- while (IDENTP (c))
- {
- *p++ = c;
- GET (c);
- }
-
- *p = '\0';
-
- if (*yytext)
- {
- char *regexp = matching_regexp ();
- int pos = BUFFER_POS ();
- add_define (yytext, regexp, pos);
- }
- }
-
- while (c && (c != '\n' || in_comment || in_string))
- {
- if (c == '\\')
- GET (c);
- else if (c == '/' && !in_comment)
- {
- if (GET (c) == '*')
- in_comment = 1;
- }
- else if (c == '*' && in_comment)
- {
- if (GET (c) == '/')
- in_comment = 0;
- }
- else if (c == '"')
- in_string = !in_string;
-
- if (c == '\n')
- INCREMENT_LINENO;
-
- GET (c);
- }
-
- return c;
-}
-
-
-/* Value is the next token from the input buffer. */
-
-static int
-yylex (void)
-{
- int c;
- char end_char;
- char *p;
-
- for (;;)
- {
- while (WHITEP (GET (c)))
- ;
-
- switch (c)
- {
- case '\n':
- INCREMENT_LINENO;
- break;
-
- case '\r':
- break;
-
- case 0:
- /* End of file. */
- return YYEOF;
-
- case '\\':
- GET (c);
- break;
-
- case '"':
- case '\'':
- /* String and character constants. */
- end_char = c;
- string_start = in;
- while (GET (c) && c != end_char)
- {
- switch (c)
- {
- case '\\':
- /* Escape sequences. */
- if (!GET (c))
- {
- if (end_char == '\'')
- yyerror ("EOF in character constant", NULL);
- else
- yyerror ("EOF in string constant", NULL);
- goto end_string;
- }
- else switch (c)
- {
- case '\n':
- INCREMENT_LINENO;
- case 'a':
- case 'b':
- case 'f':
- case 'n':
- case 'r':
- case 't':
- case 'v':
- break;
-
- case 'x':
- {
- /* Hexadecimal escape sequence. */
- int i;
- for (i = 0; i < 2; ++i)
- {
- GET (c);
-
- if (c >= '0' && c <= '7')
- ;
- else if (c >= 'a' && c <= 'f')
- ;
- else if (c >= 'A' && c <= 'F')
- ;
- else
- {
- UNGET ();
- break;
- }
- }
- }
- break;
-
- case '0':
- {
- /* Octal escape sequence. */
- int i;
- for (i = 0; i < 3; ++i)
- {
- GET (c);
-
- if (c >= '0' && c <= '7')
- ;
- else
- {
- UNGET ();
- break;
- }
- }
- }
- break;
-
- default:
- break;
- }
- break;
-
- case '\n':
- if (end_char == '\'')
- yyerror ("newline in character constant", NULL);
- else
- yyerror ("newline in string constant", NULL);
- INCREMENT_LINENO;
- break;
-
- default:
- break;
- }
- }
-
- end_string:
- return end_char == '\'' ? CCHAR : CSTRING;
- case 'R':
- if (GET (c) == '"')
- {
- /* C++11 rstrings. */
-
-#define RSTRING_EOF_CHECK \
- do { \
- if (c == '\0') \
- { \
- yyerror ("unterminated c++11 rstring", NULL); \
- UNGET (); \
- return CSTRING; \
- } \
- } while (0)
-
- char *rstring_prefix_start = in;
-
- while (GET (c) != '(')
- {
- RSTRING_EOF_CHECK;
- if (c == '"')
- {
- yyerror ("malformed c++11 rstring", NULL);
- return CSTRING;
- }
- }
- char *rstring_prefix_end = in - 1;
- while (TRUE)
- {
- switch (GET (c))
- {
- default:
- RSTRING_EOF_CHECK;
- break;
- case '\n':
- INCREMENT_LINENO;
- break;
- case ')':
- {
- char *in_saved = in;
- char *prefix = rstring_prefix_start;
- while (prefix != rstring_prefix_end && GET (c) == *prefix)
- {
- RSTRING_EOF_CHECK;
- prefix++;
- }
- if (prefix == rstring_prefix_end)
- {
- if (GET (c) == '"')
- return CSTRING;
- RSTRING_EOF_CHECK;
- }
- in = in_saved;
- }
- }
- }
- }
-
- UNGET ();
- /* Fall through to identifiers and keywords. */
- FALLTHROUGH;
-
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
- case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
- case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
- case 'v': case 'w': case 'x': case 'y': case 'z':
- case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
- case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
- case 'O': case 'P': case 'Q': case 'S': case 'T': case 'U':
- case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_':
- {
- /* Identifier and keywords. */
- unsigned hash;
- struct kw *k;
-
- p = yytext;
- *p++ = hash = c;
-
- while (IDENTP (GET (*p)))
- {
- hash = (hash << 1) ^ *p++;
- if (p == yytext_end - 1)
- {
- int size = yytext_end - yytext;
- yytext = (char *) xrealloc (yytext, 2 * size);
- yytext_end = yytext + 2 * size;
- p = yytext + size - 1;
- }
- }
-
- UNGET ();
- *p = 0;
-
- for (k = keyword_table[hash % KEYWORD_TABLE_SIZE]; k; k = k->next)
- if (streq (k->name, yytext))
- return k->tk;
-
- return IDENT;
- }
-
- case '/':
- /* C and C++ comments, '/' and '/='. */
- switch (GET (c))
- {
- case '*':
- while (GET (c))
- {
- switch (c)
- {
- case '*':
- if (GET (c) == '/')
- goto comment_end;
- UNGET ();
- break;
- case '\\':
- GET (c);
- break;
- case '\n':
- INCREMENT_LINENO;
- break;
- }
- }
- comment_end:;
- break;
-
- case '=':
- return DIVASGN;
-
- case '/':
- while (GET (c) && c != '\n')
- ;
- /* Don't try to read past the end of the input buffer if
- the file ends in a C++ comment without a newline. */
- if (c == 0)
- return YYEOF;
-
- INCREMENT_LINENO;
- break;
-
- default:
- UNGET ();
- return '/';
- }
- break;
-
- case '+':
- if (GET (c) == '+')
- return INC;
- else if (c == '=')
- return ADDASGN;
- UNGET ();
- return '+';
-
- case '-':
- switch (GET (c))
- {
- case '-':
- return DEC;
- case '>':
- if (GET (c) == '*')
- return ARROWSTAR;
- UNGET ();
- return ARROW;
- case '=':
- return SUBASGN;
- }
- UNGET ();
- return '-';
-
- case '*':
- if (GET (c) == '=')
- return MULASGN;
- UNGET ();
- return '*';
-
- case '%':
- if (GET (c) == '=')
- return MODASGN;
- UNGET ();
- return '%';
-
- case '|':
- if (GET (c) == '|')
- return LOR;
- else if (c == '=')
- return ORASGN;
- UNGET ();
- return '|';
-
- case '&':
- if (GET (c) == '&')
- return LAND;
- else if (c == '=')
- return ANDASGN;
- UNGET ();
- return '&';
-
- case '^':
- if (GET (c) == '=')
- return XORASGN;
- UNGET ();
- return '^';
-
- case '.':
- if (GET (c) == '*')
- return POINTSTAR;
- else if (c == '.')
- {
- if (GET (c) != '.')
- yyerror ("invalid token '..' ('...' assumed)", NULL);
- UNGET ();
- return ELLIPSIS;
- }
- else if (!DIGITP (c))
- {
- UNGET ();
- return '.';
- }
- goto mantissa;
-
- case ':':
- if (GET (c) == ':')
- return DCOLON;
- UNGET ();
- return ':';
-
- case '=':
- if (GET (c) == '=')
- return EQ;
- UNGET ();
- return '=';
-
- case '!':
- if (GET (c) == '=')
- return NE;
- UNGET ();
- return '!';
-
- case '<':
- switch (GET (c))
- {
- case '=':
- return LE;
- case '<':
- if (GET (c) == '=')
- return LSHIFTASGN;
- UNGET ();
- return LSHIFT;
- }
- UNGET ();
- return '<';
-
- case '>':
- switch (GET (c))
- {
- case '=':
- return GE;
- case '>':
- if (GET (c) == '=')
- return RSHIFTASGN;
- UNGET ();
- return RSHIFT;
- }
- UNGET ();
- return '>';
-
- case '#':
- c = process_pp_line ();
- if (c == 0)
- return YYEOF;
- break;
-
- case '(': case ')': case '[': case ']': case '{': case '}':
- case ';': case ',': case '?': case '~':
- return c;
-
- case '0':
- yyival = 0;
-
- if (GET (c) == 'x' || c == 'X')
- {
- while (GET (c))
- {
- if (DIGITP (c))
- yyival = yyival * 16 + c - '0';
- else if (c >= 'a' && c <= 'f')
- yyival = yyival * 16 + c - 'a' + 10;
- else if (c >= 'A' && c <= 'F')
- yyival = yyival * 16 + c - 'A' + 10;
- else
- break;
- }
-
- goto int_suffixes;
- }
- else if (c == '.')
- goto mantissa;
-
- while (c >= '0' && c <= '7')
- {
- yyival = (yyival << 3) + c - '0';
- GET (c);
- }
-
- int_suffixes:
- /* Integer suffixes. */
- while (isalpha (c))
- GET (c);
- UNGET ();
- return CINT;
-
- case '1': case '2': case '3': case '4': case '5': case '6':
- case '7': case '8': case '9':
- /* Integer or floating constant, part before '.'. */
- yyival = c - '0';
-
- while (GET (c) && DIGITP (c))
- yyival = 10 * yyival + c - '0';
-
- if (c != '.')
- goto int_suffixes;
-
- mantissa:
- /* Digits following '.'. */
- while (DIGITP (c))
- GET (c);
-
- /* Optional exponent. */
- if (c == 'E' || c == 'e')
- {
- if (GET (c) == '-' || c == '+')
- GET (c);
-
- while (DIGITP (c))
- GET (c);
- }
-
- /* Optional type suffixes. */
- while (isalpha (c))
- GET (c);
- UNGET ();
- return CFLOAT;
-
- default:
- break;
- }
- }
-}
-
-
-/* Actually local to matching_regexp. These variables must be in
- global scope for the case that `static' gets defined away. */
-
-static char *matching_regexp_buffer, *matching_regexp_end_buf;
-
-
-/* Value is the string from the start of the line to the current
- position in the input buffer, or maybe a bit more if that string is
- shorter than min_regexp. */
-
-static char *
-matching_regexp (void)
-{
- char *p;
- char *s;
- char *t;
-
- if (!f_regexps)
- return NULL;
-
- if (matching_regexp_buffer == NULL)
- {
- matching_regexp_buffer = (char *) xmalloc (max_regexp);
- matching_regexp_end_buf = &matching_regexp_buffer[max_regexp] - 1;
- }
-
- /* Scan back to previous newline of buffer start. */
- for (p = in - 1; p > inbuffer && *p != '\n'; --p)
- ;
-
- if (*p == '\n')
- {
- while (in - p < min_regexp && p > inbuffer)
- {
- /* Line probably not significant enough */
- for (--p; p > inbuffer && *p != '\n'; --p)
- ;
- }
- if (*p == '\n')
- ++p;
- }
-
- /* Copy from end to make sure significant portions are included.
- This implies that in the browser a regular expressing of the form
- `^.*{regexp}' has to be used. */
- for (s = matching_regexp_end_buf - 1, t = in;
- s > matching_regexp_buffer && t > p;)
- {
- *--s = *--t;
-
- if (*s == '"' || *s == '\\')
- {
- if (s > matching_regexp_buffer)
- *--s = '\\';
- else
- {
- s++;
- break;
- }
- }
- }
-
- *(matching_regexp_end_buf - 1) = '\0';
- return xstrdup (s);
-}
-
-
-/* Return a printable representation of token T. */
-
-static const char *
-token_string (int t)
-{
- static char b[3];
-
- switch (t)
- {
- case CSTRING: return "string constant";
- case CCHAR: return "char constant";
- case CINT: return "int constant";
- case CFLOAT: return "floating constant";
- case ELLIPSIS: return "...";
- case LSHIFTASGN: return "<<=";
- case RSHIFTASGN: return ">>=";
- case ARROWSTAR: return "->*";
- case IDENT: return "identifier";
- case DIVASGN: return "/=";
- case INC: return "++";
- case ADDASGN: return "+=";
- case DEC: return "--";
- case ARROW: return "->";
- case SUBASGN: return "-=";
- case MULASGN: return "*=";
- case MODASGN: return "%=";
- case LOR: return "||";
- case ORASGN: return "|=";
- case LAND: return "&&";
- case ANDASGN: return "&=";
- case XORASGN: return "^=";
- case POINTSTAR: return ".*";
- case DCOLON: return "::";
- case EQ: return "==";
- case NE: return "!=";
- case LE: return "<=";
- case LSHIFT: return "<<";
- case GE: return ">=";
- case RSHIFT: return ">>";
- case ASM: return "asm";
- case AUTO: return "auto";
- case BREAK: return "break";
- case CASE: return "case";
- case CATCH: return "catch";
- case CHAR: return "char";
- case CLASS: return "class";
- case CONST: return "const";
- case CONTINUE: return "continue";
- case DEFAULT: return "default";
- case DELETE: return "delete";
- case DO: return "do";
- case DOUBLE: return "double";
- case ELSE: return "else";
- case ENUM: return "enum";
- case EXTERN: return "extern";
- case FLOAT: return "float";
- case FOR: return "for";
- case FRIEND: return "friend";
- case GOTO: return "goto";
- case IF: return "if";
- case T_INLINE: return "inline";
- case INT: return "int";
- case LONG: return "long";
- case NEW: return "new";
- case OPERATOR: return "operator";
- case PRIVATE: return "private";
- case PROTECTED: return "protected";
- case PUBLIC: return "public";
- case REGISTER: return "register";
- case RETURN: return "return";
- case SHORT: return "short";
- case SIGNED: return "signed";
- case SIZEOF: return "sizeof";
- case STATIC: return "static";
- case STRUCT: return "struct";
- case SWITCH: return "switch";
- case TEMPLATE: return "template";
- case THIS: return "this";
- case THROW: return "throw";
- case TRY: return "try";
- case TYPEDEF: return "typedef";
- case UNION: return "union";
- case UNSIGNED: return "unsigned";
- case VIRTUAL: return "virtual";
- case VOID: return "void";
- case VOLATILE: return "volatile";
- case WHILE: return "while";
- case MUTABLE: return "mutable";
- case BOOL: return "bool";
- case TRUE: return "true";
- case FALSE: return "false";
- case SIGNATURE: return "signature";
- case NAMESPACE: return "namespace";
- case EXPLICIT: return "explicit";
- case TYPENAME: return "typename";
- case CONST_CAST: return "const_cast";
- case DYNAMIC_CAST: return "dynamic_cast";
- case REINTERPRET_CAST: return "reinterpret_cast";
- case STATIC_CAST: return "static_cast";
- case TYPEID: return "typeid";
- case USING: return "using";
- case WCHAR: return "wchar_t";
- case YYEOF: return "EOF";
- case FINAL: return "final";
-
- default:
- if (t < 255)
- {
- b[0] = t;
- b[1] = '\0';
- return b;
- }
- else
- return "???";
- }
-}
-
-
-/* Reinitialize the scanner for a new input file. */
-
-static void
-re_init_scanner (void)
-{
- in = inbuffer;
- yyline = 1;
-
- if (yytext == NULL)
- {
- int size = 256;
- yytext = (char *) xmalloc (size * sizeof *yytext);
- yytext_end = yytext + size;
- }
-}
-
-
-/* Insert a keyword NAME with token value TKV into the keyword hash
- table. */
-
-static void
-insert_keyword (const char *name, int tkv)
-{
- const char *s;
- unsigned h = 0;
- struct kw *k = (struct kw *) xmalloc (sizeof *k);
-
- for (s = name; *s; ++s)
- h = (h << 1) ^ *s;
-
- h %= KEYWORD_TABLE_SIZE;
- k->name = name;
- k->tk = tkv;
- k->next = keyword_table[h];
- keyword_table[h] = k;
-}
-
-
-/* Initialize the scanner for the first file. This sets up the
- character class vectors and fills the keyword hash table. */
-
-static void
-init_scanner (void)
-{
- int i;
-
- /* Allocate the input buffer */
- inbuffer_size = READ_CHUNK_SIZE + 1;
- inbuffer = in = (char *) xmalloc (inbuffer_size);
- yyline = 1;
-
- /* Set up character class vectors. */
- for (i = 0; i < sizeof is_ident; ++i)
- {
- if (i == '_' || isalnum (i))
- is_ident[i] = 1;
-
- if (i >= '0' && i <= '9')
- is_digit[i] = 1;
-
- if (i == ' ' || i == '\t' || i == '\f' || i == '\v')
- is_white[i] = 1;
- }
-
- /* Fill keyword hash table. */
- insert_keyword ("and", LAND);
- insert_keyword ("and_eq", ANDASGN);
- insert_keyword ("asm", ASM);
- insert_keyword ("auto", AUTO);
- insert_keyword ("bitand", '&');
- insert_keyword ("bitor", '|');
- insert_keyword ("bool", BOOL);
- insert_keyword ("break", BREAK);
- insert_keyword ("case", CASE);
- insert_keyword ("catch", CATCH);
- insert_keyword ("char", CHAR);
- insert_keyword ("class", CLASS);
- insert_keyword ("compl", '~');
- insert_keyword ("const", CONST);
- insert_keyword ("const_cast", CONST_CAST);
- insert_keyword ("continue", CONTINUE);
- insert_keyword ("default", DEFAULT);
- insert_keyword ("delete", DELETE);
- insert_keyword ("do", DO);
- insert_keyword ("double", DOUBLE);
- insert_keyword ("dynamic_cast", DYNAMIC_CAST);
- insert_keyword ("else", ELSE);
- insert_keyword ("enum", ENUM);
- insert_keyword ("explicit", EXPLICIT);
- insert_keyword ("extern", EXTERN);
- insert_keyword ("false", FALSE);
- insert_keyword ("final", FINAL);
- insert_keyword ("float", FLOAT);
- insert_keyword ("for", FOR);
- insert_keyword ("friend", FRIEND);
- insert_keyword ("goto", GOTO);
- insert_keyword ("if", IF);
- insert_keyword ("inline", T_INLINE);
- insert_keyword ("int", INT);
- insert_keyword ("long", LONG);
- insert_keyword ("mutable", MUTABLE);
- insert_keyword ("namespace", NAMESPACE);
- insert_keyword ("new", NEW);
- insert_keyword ("not", '!');
- insert_keyword ("not_eq", NE);
- insert_keyword ("operator", OPERATOR);
- insert_keyword ("or", LOR);
- insert_keyword ("or_eq", ORASGN);
- insert_keyword ("private", PRIVATE);
- insert_keyword ("protected", PROTECTED);
- insert_keyword ("public", PUBLIC);
- insert_keyword ("register", REGISTER);
- insert_keyword ("reinterpret_cast", REINTERPRET_CAST);
- insert_keyword ("return", RETURN);
- insert_keyword ("short", SHORT);
- insert_keyword ("signed", SIGNED);
- insert_keyword ("sizeof", SIZEOF);
- insert_keyword ("static", STATIC);
- insert_keyword ("static_cast", STATIC_CAST);
- insert_keyword ("struct", STRUCT);
- insert_keyword ("switch", SWITCH);
- insert_keyword ("template", TEMPLATE);
- insert_keyword ("this", THIS);
- insert_keyword ("throw", THROW);
- insert_keyword ("true", TRUE);
- insert_keyword ("try", TRY);
- insert_keyword ("typedef", TYPEDEF);
- insert_keyword ("typeid", TYPEID);
- insert_keyword ("typename", TYPENAME);
- insert_keyword ("union", UNION);
- insert_keyword ("unsigned", UNSIGNED);
- insert_keyword ("using", USING);
- insert_keyword ("virtual", VIRTUAL);
- insert_keyword ("void", VOID);
- insert_keyword ("volatile", VOLATILE);
- insert_keyword ("wchar_t", WCHAR);
- insert_keyword ("while", WHILE);
- insert_keyword ("xor", '^');
- insert_keyword ("xor_eq", XORASGN);
-}
-
-
-\f
-/***********************************************************************
- Parser
- ***********************************************************************/
-
-/* Match the current lookahead token and set it to the next token. */
-
-#define MATCH() (tk = yylex ())
-
-/* Return the lookahead token. If current lookahead token is cleared,
- read a new token. */
-
-#define LA1 (tk == -1 ? (tk = yylex ()) : tk)
-
-/* Is the current lookahead equal to the token T? */
-
-#define LOOKING_AT(T) (tk == (T))
-
-/* Is the current lookahead one of T1 or T2? */
-
-#define LOOKING_AT2(T1, T2) (tk == (T1) || tk == (T2))
-
-/* Is the current lookahead one of T1, T2 or T3? */
-
-#define LOOKING_AT3(T1, T2, T3) (tk == (T1) || tk == (T2) || tk == (T3))
-
-/* Is the current lookahead one of T1...T4? */
-
-#define LOOKING_AT4(T1, T2, T3, T4) \
- (tk == (T1) || tk == (T2) || tk == (T3) || tk == (T4))
-
-/* Match token T if current lookahead is T. */
-
-#define MATCH_IF(T) if (LOOKING_AT (T)) MATCH (); else ((void) 0)
-
-/* Skip to matching token if current token is T. */
-
-#define SKIP_MATCHING_IF(T) \
- if (LOOKING_AT (T)) skip_matching (); else ((void) 0)
-
-
-/* Skip forward until a given token TOKEN or YYEOF is seen and return
- the current lookahead token after skipping. */
-
-static int
-skip_to (int token)
-{
- while (!LOOKING_AT2 (YYEOF, token))
- MATCH ();
- return tk;
-}
-
-/* Skip over pairs of tokens (parentheses, square brackets,
- angle brackets, curly brackets) matching the current lookahead. */
-
-static void
-skip_matching (void)
-{
- int open, close, n;
-
- switch (open = LA1)
- {
- case '{':
- close = '}';
- break;
-
- case '(':
- close = ')';
- break;
-
- case '<':
- close = '>';
- break;
-
- case '[':
- close = ']';
- break;
-
- default:
- abort ();
- }
-
- for (n = 0;;)
- {
- if (LOOKING_AT (open))
- ++n;
- else if (LOOKING_AT (close))
- --n;
- else if (LOOKING_AT (YYEOF))
- break;
-
- MATCH ();
-
- if (n == 0)
- break;
- }
-}
-
-static void
-skip_initializer (void)
-{
- for (;;)
- {
- switch (LA1)
- {
- case ';':
- case ',':
- case YYEOF:
- return;
-
- case '{':
- case '[':
- case '(':
- skip_matching ();
- break;
-
- default:
- MATCH ();
- break;
- }
- }
-}
-
-/* Build qualified namespace alias (A::B::c) and return it. */
-
-static struct link *
-match_qualified_namespace_alias (void)
-{
- struct link *head = NULL;
- struct link *cur = NULL;
- struct link *tmp = NULL;
-
- for (;;)
- {
- MATCH ();
- switch (LA1)
- {
- case IDENT:
- tmp = (struct link *) xmalloc (sizeof *cur);
- tmp->sym = find_namespace (yytext, cur ? cur->sym : NULL);
- tmp->next = NULL;
- if (head)
- {
- cur = cur->next = tmp;
- }
- else
- {
- head = cur = tmp;
- }
- break;
- case DCOLON:
- /* Just skip */
- break;
- default:
- return head;
- break;
- }
- }
-}
-
-/* Re-initialize the parser by resetting the lookahead token. */
-
-static void
-re_init_parser (void)
-{
- tk = -1;
-}
-
-
-/* Parse a parameter list, including the const-specifier,
- pure-specifier, and throw-list that may follow a parameter list.
- Return in FLAGS what was seen following the parameter list.
- Returns a hash code for the parameter types. This value is used to
- distinguish between overloaded functions. */
-
-static unsigned
-parm_list (int *flags)
-{
- unsigned hash = 0;
- int type_seen = 0;
-
- while (!LOOKING_AT2 (YYEOF, ')'))
- {
- switch (LA1)
- {
- /* Skip over grouping parens or parameter lists in parameter
- declarations. */
- case '(':
- skip_matching ();
- break;
-
- /* Next parameter. */
- case ',':
- MATCH ();
- type_seen = 0;
- break;
-
- /* Ignore the scope part of types, if any. This is because
- some types need scopes when defined outside of a class body,
- and don't need them inside the class body. This means that
- we have to look for the last IDENT in a sequence of
- IDENT::IDENT::... */
- case IDENT:
- if (!type_seen)
- {
- char *last_id;
- unsigned ident_type_hash = 0;
-
- parse_qualified_param_ident_or_type (&last_id);
- if (last_id)
- {
- /* LAST_ID null means something like `X::*'. */
- for (; *last_id; ++last_id)
- ident_type_hash = (ident_type_hash << 1) ^ *last_id;
- hash = (hash << 1) ^ ident_type_hash;
- type_seen = 1;
- }
- }
- else
- MATCH ();
- break;
-
- case VOID:
- /* This distinction is made to make `func (void)' equivalent
- to `func ()'. */
- type_seen = 1;
- MATCH ();
- if (!LOOKING_AT (')'))
- hash = (hash << 1) ^ VOID;
- break;
-
- case BOOL: case CHAR: case CLASS: case CONST:
- case DOUBLE: case ENUM: case FLOAT: case INT:
- case LONG: case SHORT: case SIGNED: case STRUCT:
- case UNION: case UNSIGNED: case VOLATILE: case WCHAR:
- case ELLIPSIS:
- type_seen = 1;
- hash = (hash << 1) ^ LA1;
- MATCH ();
- break;
-
- case '*': case '&': case '[': case ']':
- hash = (hash << 1) ^ LA1;
- MATCH ();
- break;
-
- default:
- MATCH ();
- break;
- }
- }
-
- if (LOOKING_AT (')'))
- {
- MATCH ();
-
- if (LOOKING_AT (CONST))
- {
- /* We can overload the same function on `const' */
- hash = (hash << 1) ^ CONST;
- set_flag (flags, F_CONST);
- MATCH ();
- }
-
- if (LOOKING_AT (THROW))
- {
- MATCH ();
- SKIP_MATCHING_IF ('(');
- set_flag (flags, F_THROW);
- }
-
- if (LOOKING_AT ('='))
- {
- MATCH ();
- if (LOOKING_AT (CINT) && yyival == 0)
- {
- MATCH ();
- set_flag (flags, F_PURE);
- }
- }
- }
-
- return hash;
-}
-
-
-/* Print position info to stdout. */
-
-static void
-print_info (void)
-{
- if (info_position >= 0 && BUFFER_POS () <= info_position)
- if (info_cls)
- printf ("(\"%s\" \"%s\" \"%s\" %d)\n",
- info_cls->name, sym_scope (info_cls),
- info_member->name, info_where);
-}
-
-
-/* Parse a member declaration within the class body of CLS. VIS is
- the access specifier for the member (private, protected,
- public). */
-
-static void
-member (struct sym *cls, int vis)
-{
- char *id = NULL;
- int sc = SC_MEMBER;
- char *regexp = NULL;
- int pos;
- int is_constructor;
- int flags = 0;
- int class_tag;
- char *class_name;
- int type_seen = 0;
- int paren_seen = 0;
- unsigned hash = 0;
- int tilde = 0;
-
- while (!LOOKING_AT4 (';', '{', '}', YYEOF))
- {
- switch (LA1)
- {
- default:
- MATCH ();
- break;
-
- /* A function or class may follow. */
- case TEMPLATE:
- MATCH ();
- set_flag (&flags, F_TEMPLATE);
- /* Skip over template argument list */
- SKIP_MATCHING_IF ('<');
- break;
-
- case EXPLICIT:
- set_flag (&flags, F_EXPLICIT);
- goto typeseen;
-
- case MUTABLE:
- set_flag (&flags, F_MUTABLE);
- goto typeseen;
-
- case T_INLINE:
- set_flag (&flags, F_INLINE);
- goto typeseen;
-
- case VIRTUAL:
- set_flag (&flags, F_VIRTUAL);
- goto typeseen;
-
- case '[':
- skip_matching ();
- break;
-
- case ENUM:
- sc = SC_TYPE;
- goto typeseen;
-
- case TYPEDEF:
- sc = SC_TYPE;
- goto typeseen;
-
- case FRIEND:
- sc = SC_FRIEND;
- goto typeseen;
-
- case STATIC:
- sc = SC_STATIC;
- goto typeseen;
-
- case '~':
- tilde = 1;
- MATCH ();
- break;
-
- case IDENT:
- /* Remember IDENTS seen so far. Among these will be the member
- name. */
- id = (char *) xrealloc (id, strlen (yytext) + 2);
- if (tilde)
- {
- *id = '~';
- strcpy (id + 1, yytext);
- }
- else
- strcpy (id, yytext);
- MATCH ();
- break;
-
- case OPERATOR:
- {
- char *s = operator_name (&sc);
- id = (char *) xrealloc (id, strlen (s) + 1);
- strcpy (id, s);
- }
- break;
-
- case '(':
- /* Most probably the beginning of a parameter list. */
- MATCH ();
- paren_seen = 1;
-
- if (id && cls)
- {
- if (!(is_constructor = streq (id, cls->name)))
- regexp = matching_regexp ();
- }
- else
- is_constructor = 0;
-
- pos = BUFFER_POS ();
- hash = parm_list (&flags);
-
- if (is_constructor)
- regexp = matching_regexp ();
-
- if (id && cls != NULL)
- add_member_decl (cls, id, regexp, pos, hash, 0, sc, vis, flags);
-
- while (!LOOKING_AT3 (';', '{', YYEOF))
- MATCH ();
-
- if (LOOKING_AT ('{') && id && cls)
- add_member_defn (cls, id, regexp, pos, hash, 0, sc, flags);
-
- free (id);
- id = NULL;
- sc = SC_MEMBER;
- break;
-
- case STRUCT: case UNION: case CLASS:
- /* Nested class */
- class_tag = LA1;
- type_seen = 1;
- MATCH ();
- class_name = NULL;
-
- /* More than one ident here to allow for MS-DOS specialties
- like `_export class' etc. The last IDENT seen counts
- as the class name. */
- while (!LOOKING_AT4 (YYEOF, ';', ':', '{'))
- {
- if (LOOKING_AT (IDENT))
- {
- if (class_name)
- {
- int size = strlen (yytext);
-
- if(strlen (class_name) < size)
- {
- class_name = (char *) xrealloc(class_name, size + 1);
- }
-
- memcpy(class_name, yytext, size + 1);
- }
- else
- {
- class_name = xstrdup(yytext);
- }
- }
-
- MATCH ();
- }
-
- if (LOOKING_AT2 (':', '{'))
- class_definition (class_name ? cls : NULL, class_name ? class_name : yytext, class_tag, flags, 1);
- else
- skip_to (';');
-
- free(class_name);
- break;
-
- case INT: case CHAR: case LONG: case UNSIGNED:
- case SIGNED: case CONST: case DOUBLE: case VOID:
- case SHORT: case VOLATILE: case BOOL: case WCHAR:
- case TYPENAME:
- typeseen:
- type_seen = 1;
- MATCH ();
- break;
- }
- }
-
- if (LOOKING_AT (';'))
- {
- /* The end of a member variable, a friend declaration or an access
- declaration. We don't want to add friend classes as members. */
- if (id && sc != SC_FRIEND && cls)
- {
- regexp = matching_regexp ();
- pos = BUFFER_POS ();
-
- if (cls != NULL)
- {
- if (type_seen || !paren_seen)
- add_member_decl (cls, id, regexp, pos, 0, 1, sc, vis, 0);
- else
- add_member_decl (cls, id, regexp, pos, hash, 0, sc, vis, 0);
- }
- }
-
- MATCH ();
- print_info ();
- }
- else if (LOOKING_AT ('{'))
- {
- /* A named enum. */
- if (sc == SC_TYPE && id && cls)
- {
- regexp = matching_regexp ();
- pos = BUFFER_POS ();
-
- if (cls != NULL)
- {
- add_member_decl (cls, id, regexp, pos, 0, 1, sc, vis, 0);
- add_member_defn (cls, id, regexp, pos, 0, 1, sc, 0);
- }
- }
-
- skip_matching ();
- print_info ();
- }
-
- free (id);
-}
-
-
-/* Parse the body of class CLS. TAG is the tag of the class (struct,
- union, class). */
-
-static void
-class_body (struct sym *cls, int tag)
-{
- int vis = tag == CLASS ? PRIVATE : PUBLIC;
- int temp;
-
- while (!LOOKING_AT2 (YYEOF, '}'))
- {
- switch (LA1)
- {
- case PRIVATE: case PROTECTED: case PUBLIC:
- temp = LA1;
- MATCH ();
-
- if (LOOKING_AT (':'))
- {
- vis = temp;
- MATCH ();
- }
- else
- {
- /* Probably conditional compilation for inheritance list.
- We don't known whether there comes more of this.
- This is only a crude fix that works most of the time. */
- do
- {
- MATCH ();
- }
- while (LOOKING_AT2 (IDENT, ',')
- || LOOKING_AT3 (PUBLIC, PROTECTED, PRIVATE));
- }
- break;
-
- case TYPENAME:
- case USING:
- skip_to (';');
- break;
-
- /* Try to synchronize */
- case CHAR: case CLASS: case CONST:
- case DOUBLE: case ENUM: case FLOAT: case INT:
- case LONG: case SHORT: case SIGNED: case STRUCT:
- case UNION: case UNSIGNED: case VOID: case VOLATILE:
- case TYPEDEF: case STATIC: case T_INLINE: case FRIEND:
- case VIRTUAL: case TEMPLATE: case IDENT: case '~':
- case BOOL: case WCHAR: case EXPLICIT: case MUTABLE:
- member (cls, vis);
- break;
-
- default:
- MATCH ();
- break;
- }
- }
-}
-
-
-/* Parse a qualified identifier. Current lookahead is IDENT. A
- qualified ident has the form `X<..>::Y<...>::T<...>. Returns a
- symbol for that class. */
-
-static struct sym *
-parse_classname (void)
-{
- struct sym *last_class = NULL;
-
- while (LOOKING_AT (IDENT))
- {
- last_class = add_sym (yytext, last_class);
- MATCH ();
-
- if (LOOKING_AT ('<'))
- {
- skip_matching ();
- set_flag (&last_class->flags, F_TEMPLATE);
- }
-
- if (!LOOKING_AT (DCOLON))
- break;
-
- MATCH ();
- }
-
- return last_class;
-}
-
-
-/* Parse an operator name. Add the `static' flag to *SC if an
- implicitly static operator has been parsed. Value is a pointer to
- a static buffer holding the constructed operator name string. */
-
-static char *
-operator_name (int *sc)
-{
- static size_t id_size = 0;
- static char *id = NULL;
- const char *s;
- size_t len;
-
- MATCH ();
-
- if (LOOKING_AT2 (NEW, DELETE))
- {
- /* `new' and `delete' are implicitly static. */
- if (*sc != SC_FRIEND)
- *sc = SC_STATIC;
-
- s = token_string (LA1);
- MATCH ();
-
- ptrdiff_t slen = strlen (s);
- len = slen + 10;
- if (len > id_size)
- {
- size_t new_size = max (len, 2 * id_size);
- id = (char *) xrealloc (id, new_size);
- id_size = new_size;
- }
- char *z = stpcpy (id, s);
-
- /* Vector new or delete? */
- if (LOOKING_AT ('['))
- {
- z = stpcpy (z, "[");
- MATCH ();
-
- if (LOOKING_AT (']'))
- {
- strcpy (z, "]");
- MATCH ();
- }
- }
- }
- else
- {
- size_t tokens_matched = 0;
-
- len = 20;
- if (len > id_size)
- {
- int new_size = max (len, 2 * id_size);
- id = (char *) xrealloc (id, new_size);
- id_size = new_size;
- }
- char *z = stpcpy (id, "operator");
-
- /* Beware access declarations of the form "X::f;" Beware of
- `operator () ()'. Yet another difficulty is found in
- GCC 2.95's STL: `operator == __STL_NULL_TMPL_ARGS (...'. */
- while (!(LOOKING_AT ('(') && tokens_matched)
- && !LOOKING_AT2 (';', YYEOF))
- {
- s = token_string (LA1);
- len += strlen (s) + 2;
- if (len > id_size)
- {
- ptrdiff_t idlen = z - id;
- size_t new_size = max (len, 2 * id_size);
- id = (char *) xrealloc (id, new_size);
- id_size = new_size;
- z = id + idlen;
- }
-
- if (*s != ')' && *s != ']')
- *z++ = ' ';
- z = stpcpy (z, s);
- MATCH ();
-
- /* If this is a simple operator like `+', stop now. */
- if (!isalpha ((unsigned char) *s) && *s != '(' && *s != '[')
- break;
-
- ++tokens_matched;
- }
- }
-
- return id;
-}
-
-
-/* This one consumes the last IDENT of a qualified member name like
- `X::Y::z'. This IDENT is returned in LAST_ID. Value is the
- symbol structure for the ident. */
-
-static struct sym *
-parse_qualified_ident_or_type (char **last_id)
-{
- struct sym *cls = NULL;
- char *id = NULL;
- size_t id_size = 0;
- int enter = 0;
-
- while (LOOKING_AT (IDENT))
- {
- int len = strlen (yytext) + 1;
- if (len > id_size)
- {
- id = (char *) xrealloc (id, len);
- id_size = len;
- }
- strcpy (id, yytext);
- *last_id = id;
- MATCH ();
-
- SKIP_MATCHING_IF ('<');
-
- if (LOOKING_AT (DCOLON))
- {
- struct sym *pcn = NULL;
- struct link *pna = check_namespace_alias (id);
- if (pna)
- {
- do
- {
- enter_namespace (pna->sym->name);
- enter++;
- pna = pna->next;
- }
- while (pna);
- }
- else if ((pcn = check_namespace (id, current_namespace)))
- {
- enter_namespace (pcn->name);
- enter++;
- }
- else
- cls = add_sym (id, cls);
-
- *last_id = NULL;
- free (id);
- id = NULL;
- id_size = 0;
- MATCH ();
- }
- else
- break;
- }
-
- while (enter--)
- leave_namespace ();
-
- return cls;
-}
-
-
-/* This one consumes the last IDENT of a qualified member name like
- `X::Y::z'. This IDENT is returned in LAST_ID. Value is the
- symbol structure for the ident. */
-
-static void
-parse_qualified_param_ident_or_type (char **last_id)
-{
- struct sym *cls = NULL;
- static char *id = NULL;
- static int id_size = 0;
-
- assert (LOOKING_AT (IDENT));
-
- do
- {
- int len = strlen (yytext) + 1;
- if (len > id_size)
- {
- id = (char *) xrealloc (id, len);
- id_size = len;
- }
- strcpy (id, yytext);
- *last_id = id;
- MATCH ();
-
- SKIP_MATCHING_IF ('<');
-
- if (LOOKING_AT (DCOLON))
- {
- cls = add_sym (id, cls);
- *last_id = NULL;
- MATCH ();
- }
- else
- break;
- }
- while (LOOKING_AT (IDENT));
-}
-
-
-/* Parse a class definition.
-
- CONTAINING is the class containing the class being parsed or null.
- This may also be null if NESTED != 0 if the containing class is
- anonymous. TAG is the tag of the class (struct, union, class).
- NESTED is non-zero if we are parsing a nested class.
-
- Current lookahead is the class name. */
-
-static void
-class_definition (struct sym *containing, const char *class_name, int tag, int flags, int nested)
-{
- struct sym *current;
- struct sym *base_class;
-
- /* Set CURRENT to null if no entry has to be made for the class
- parsed. This is the case for certain command line flag
- settings. */
- if ((tag != CLASS && !f_structs) || (nested && !f_nested_classes))
- current = NULL;
- else
- {
- current = add_sym (class_name, containing);
- current->pos = BUFFER_POS ();
- current->regexp = matching_regexp ();
- current->filename = filename;
- current->flags = flags;
- }
-
- /* If at ':', base class list follows. */
- if (LOOKING_AT (':'))
- {
- int done = 0;
- MATCH ();
-
- while (!done)
- {
- switch (LA1)
- {
- case VIRTUAL: case PUBLIC: case PROTECTED: case PRIVATE:
- MATCH ();
- break;
-
- case IDENT:
- base_class = parse_classname ();
- if (base_class && current && base_class != current)
- add_link (base_class, current);
- break;
-
- /* The `,' between base classes or the end of the base
- class list. Add the previously found base class.
- It's done this way to skip over sequences of
- `A::B::C' until we reach the end.
-
- FIXME: it is now possible to handle `class X : public B::X'
- because we have enough information. */
- case ',':
- MATCH ();
- break;
-
- default:
- /* A syntax error, possibly due to preprocessor constructs
- like
-
- #ifdef SOMETHING
- class A : public B
- #else
- class A : private B.
-
- MATCH until we see something like `;' or `{'. */
- while (!LOOKING_AT3 (';', YYEOF, '{'))
- MATCH ();
- FALLTHROUGH;
- case '{':
- done = 1;
- break;
- }
- }
- }
-
- /* Parse the class body if there is one. */
- if (LOOKING_AT ('{'))
- {
- if (tag != CLASS && !f_structs)
- skip_matching ();
- else
- {
- MATCH ();
- class_body (current, tag);
-
- if (LOOKING_AT ('}'))
- {
- MATCH ();
- if (LOOKING_AT (';') && !nested)
- MATCH ();
- }
- }
- }
-}
-
-/* Add to class *CLS information for the declaration of variable or
- type *ID. If *CLS is null, this means a global declaration. SC is
- the storage class of *ID. FLAGS is a bit set giving additional
- information about the member (see the F_* defines). */
-
-static void
-add_declarator (struct sym **cls, char **id, int flags, int sc)
-{
- if (LOOKING_AT2 (';', ','))
- {
- /* The end of a member variable or of an access declaration
- `X::f'. To distinguish between them we have to know whether
- type information has been seen. */
- if (*id)
- {
- char *regexp = matching_regexp ();
- int pos = BUFFER_POS ();
-
- if (*cls)
- add_member_defn (*cls, *id, regexp, pos, 0, 1, SC_UNKNOWN, flags);
- else
- add_global_defn (*id, regexp, pos, 0, 1, sc, flags);
- }
-
- MATCH ();
- print_info ();
- }
- else if (LOOKING_AT ('{'))
- {
- if (sc == SC_TYPE && *id)
- {
- /* A named enumeration. */
- char *regexp = matching_regexp ();
- int pos = BUFFER_POS ();
- add_global_defn (*id, regexp, pos, 0, 1, sc, flags);
- }
-
- skip_matching ();
- print_info ();
- }
-
- free (*id);
- *id = NULL;
- *cls = NULL;
-}
-
-/* Parse a declaration. */
-
-static void
-declaration (int flags)
-{
- char *id = NULL;
- struct sym *cls = NULL;
- char *regexp = NULL;
- int pos = 0;
- unsigned hash = 0;
- int is_constructor;
- int sc = 0;
-
- while (!LOOKING_AT3 (';', '{', YYEOF))
- {
- switch (LA1)
- {
- default:
- MATCH ();
- break;
-
- case '[':
- skip_matching ();
- break;
-
- case ENUM:
- case TYPEDEF:
- sc = SC_TYPE;
- MATCH ();
- break;
-
- case STATIC:
- sc = SC_STATIC;
- MATCH ();
- break;
-
- case INT: case CHAR: case LONG: case UNSIGNED:
- case SIGNED: case CONST: case DOUBLE: case VOID:
- case SHORT: case VOLATILE: case BOOL: case WCHAR:
- MATCH ();
- break;
-
- case CLASS: case STRUCT: case UNION:
- /* This is for the case `STARTWRAP class X : ...' or
- `declare (X, Y)\n class A : ...'. */
- if (id)
- {
- free (id);
- return;
- }
- FALLTHROUGH;
- case '=':
- /* Assumed to be the start of an initialization in this
- context. */
- skip_initializer ();
- break;
-
- case ',':
- add_declarator (&cls, &id, flags, sc);
- break;
-
- case OPERATOR:
- {
- char *s = operator_name (&sc);
- id = (char *) xrealloc (id, strlen (s) + 1);
- strcpy (id, s);
- }
- break;
-
- case T_INLINE:
- set_flag (&flags, F_INLINE);
- MATCH ();
- break;
-
- case '~':
- MATCH ();
- if (LOOKING_AT (IDENT))
- {
- id = (char *) xrealloc (id, strlen (yytext) + 2);
- *id = '~';
- strcpy (id + 1, yytext);
- MATCH ();
- }
- break;
-
- case IDENT:
- cls = parse_qualified_ident_or_type (&id);
- break;
-
- case '(':
- /* Most probably the beginning of a parameter list. */
- if (cls)
- {
- MATCH ();
-
- if (id && cls)
- {
- if (!(is_constructor = streq (id, cls->name)))
- regexp = matching_regexp ();
- }
- else
- is_constructor = 0;
-
- pos = BUFFER_POS ();
- hash = parm_list (&flags);
-
- if (is_constructor)
- regexp = matching_regexp ();
-
- if (id && cls)
- add_member_defn (cls, id, regexp, pos, hash, 0,
- SC_UNKNOWN, flags);
- }
- else
- {
- /* This may be a C functions, but also a macro
- call of the form `declare (A, B)' --- such macros
- can be found in some class libraries. */
- MATCH ();
-
- if (id)
- {
- regexp = matching_regexp ();
- pos = BUFFER_POS ();
- hash = parm_list (&flags);
- add_global_decl (id, regexp, pos, hash, 0, sc, flags);
- }
-
- /* This is for the case that the function really is
- a macro with no `;' following it. If a CLASS directly
- follows, we would miss it otherwise. */
- if (LOOKING_AT3 (CLASS, STRUCT, UNION))
- return;
- }
-
- while (!LOOKING_AT3 (';', '{', YYEOF))
- MATCH ();
-
- if (!cls && id && LOOKING_AT ('{'))
- add_global_defn (id, regexp, pos, hash, 0, sc, flags);
-
- free (id);
- id = NULL;
- break;
- }
- }
-
- add_declarator (&cls, &id, flags, sc);
-}
-
-
-/* Parse a list of top-level declarations/definitions. START_FLAGS
- says in which context we are parsing. If it is F_EXTERNC, we are
- parsing in an `extern "C"' block. Value is 1 if EOF is reached, 0
- otherwise. */
-
-static int
-globals (int start_flags)
-{
- int class_tk;
- char *class_name;
- int flags = start_flags;
-
- for (;;)
- {
- char *prev_in = in;
-
- switch (LA1)
- {
- case NAMESPACE:
- {
- MATCH ();
-
- if (LOOKING_AT (IDENT))
- {
- char *namespace_name = xstrdup (yytext);
- MATCH ();
-
- if (LOOKING_AT ('='))
- {
- struct link *qna = match_qualified_namespace_alias ();
- if (qna)
- register_namespace_alias (namespace_name, qna);
-
- if (skip_to (';') == ';')
- MATCH ();
- }
- else if (LOOKING_AT ('{'))
- {
- MATCH ();
- enter_namespace (namespace_name);
- globals (0);
- leave_namespace ();
- MATCH_IF ('}');
- }
-
- free (namespace_name);
- }
- }
- break;
-
- case EXTERN:
- MATCH ();
- if (LOOKING_AT (CSTRING) && *string_start == 'C'
- && *(string_start + 1) == '"')
- {
- /* This is `extern "C"'. */
- MATCH ();
-
- if (LOOKING_AT ('{'))
- {
- MATCH ();
- globals (F_EXTERNC);
- MATCH_IF ('}');
- }
- else
- set_flag (&flags, F_EXTERNC);
- }
- break;
-
- case TEMPLATE:
- MATCH ();
- SKIP_MATCHING_IF ('<');
- set_flag (&flags, F_TEMPLATE);
- break;
-
- case CLASS: case STRUCT: case UNION:
- class_tk = LA1;
- MATCH ();
- class_name = NULL;
-
- /* More than one ident here to allow for MS-DOS and OS/2
- specialties like `far', `_Export' etc. Some C++ libs
- have constructs like `_OS_DLLIMPORT(_OS_CLIENT)' in front
- of the class name. */
- while (!LOOKING_AT4 (YYEOF, ';', ':', '{'))
- {
- if (LOOKING_AT (IDENT))
- {
- if (class_name)
- {
- int size = strlen (yytext);
-
- if(strlen (class_name) < size)
- {
- class_name = (char *) xrealloc(class_name, size + 1);
- }
-
- memcpy(class_name, yytext, size + 1);
- }
- else
- {
- class_name = xstrdup(yytext);
- }
- }
-
- MATCH ();
- }
-
- /* Don't add anonymous unions. */
- if (LOOKING_AT2 (':', '{') && class_name)
- class_definition (NULL, class_name, class_tk, flags, 0);
- else
- {
- if (skip_to (';') == ';')
- MATCH ();
- }
-
- free(class_name);
- flags = start_flags;
- break;
-
- case YYEOF:
- return 1;
-
- case '}':
- return 0;
-
- default:
- declaration (flags);
- flags = start_flags;
- break;
- }
-
- if (prev_in == in)
- yyerror ("parse error", NULL);
- }
-}
-
-
-/* Parse the current input file. */
-
-static void
-yyparse (void)
-{
- while (globals (0) == 0)
- MATCH_IF ('}');
-}
-
-
-\f
-/***********************************************************************
- Main Program
- ***********************************************************************/
-
-/* Add the list of paths PATH_LIST to the current search path for
- input files. */
-
-static void
-add_search_path (char *path_list)
-{
- while (*path_list)
- {
- char *start = path_list;
- struct search_path *p;
-
- while (*path_list && *path_list != SEPCHAR)
- ++path_list;
-
- p = (struct search_path *) xmalloc (sizeof *p);
- p->path = (char *) xmalloc (path_list - start + 1);
- memcpy (p->path, start, path_list - start);
- p->path[path_list - start] = '\0';
- p->next = NULL;
-
- if (search_path_tail)
- {
- search_path_tail->next = p;
- search_path_tail = p;
- }
- else
- search_path = search_path_tail = p;
-
- while (*path_list == SEPCHAR)
- ++path_list;
- }
-}
-
-
-/* Open FILE and return a file handle for it, or -1 if FILE cannot be
- opened. Try to find FILE in search_path first, then try the
- unchanged file name. */
-
-static FILE *
-open_file (char *file)
-{
- FILE *fp = NULL;
- static char *buffer;
- static int buffer_size;
- struct search_path *path;
- int flen = strlen (file) + 1; /* +1 for the slash */
-
- filename = xstrdup (file);
-
- for (path = search_path; path && fp == NULL; path = path->next)
- {
- int len = strlen (path->path) + flen;
-
- if (len + 1 >= buffer_size)
- {
- buffer_size = max (len + 1, 2 * buffer_size);
- buffer = (char *) xrealloc (buffer, buffer_size);
- }
-
- char *z = stpcpy (buffer, path->path);
- *z++ = '/';
- strcpy (z, file);
- fp = fopen (buffer, "r");
- }
-
- /* Try the original file name. */
- if (fp == NULL)
- fp = fopen (file, "r");
-
- if (fp == NULL)
- yyerror ("cannot open", NULL);
-
- return fp;
-}
-
-
-/* Display usage information and exit program. */
-
-static char const *const usage_message[] =
- {
- "\
-Usage: ebrowse [options] {files}\n\
-\n\
- -a, --append append output to existing file\n\
- -f, --files=FILES read input file names from FILE\n\
- -I, --search-path=LIST set search path for input files\n\
- -m, --min-regexp-length=N set minimum regexp length to N\n\
- -M, --max-regexp-length=N set maximum regexp length to N\n\
-",
- "\
- -n, --no-nested-classes exclude nested classes\n\
- -o, --output-file=FILE set output file name to FILE\n\
- -p, --position-info print info about position in file\n\
- -s, --no-structs-or-unions don't record structs or unions\n\
- -v, --verbose be verbose\n\
- -V, --very-verbose be very verbose\n\
- -x, --no-regexps don't record regular expressions\n\
- --help display this help\n\
- --version display version info\n\
-\n\
-"
- };
-
-static _Noreturn void
-usage (int error)
-{
- int i;
- for (i = 0; i < sizeof usage_message / sizeof *usage_message; i++)
- fputs (usage_message[i], stdout);
- exit (error ? EXIT_FAILURE : EXIT_SUCCESS);
-}
-
-
-/* Display version and copyright info. */
-
-static _Noreturn void
-version (void)
-{
- fputs (("ebrowse " PACKAGE_VERSION "\n"
- COPYRIGHT "\n"
- "This program is distributed under the same terms as Emacs.\n"),
- stdout);
- exit (EXIT_SUCCESS);
-}
-
-
-/* Parse one input file FILE, adding classes and members to the symbol
- table. */
-
-static void
-process_file (char *file)
-{
- FILE *fp;
-
- fp = open_file (file);
- if (fp)
- {
- size_t nread, nbytes;
-
- /* Give a progress indication if needed. */
- if (f_very_verbose)
- {
- puts (filename);
- fflush (stdout);
- }
- else if (f_verbose)
- {
- putchar ('.');
- fflush (stdout);
- }
-
- /* Read file to inbuffer. */
- for (nread = 0;;)
- {
- if (nread + READ_CHUNK_SIZE >= inbuffer_size)
- {
- inbuffer_size = nread + READ_CHUNK_SIZE + 1;
- inbuffer = (char *) xrealloc (inbuffer, inbuffer_size);
- }
-
- nbytes = fread (inbuffer + nread, 1, READ_CHUNK_SIZE, fp);
- if (nbytes == 0)
- break;
- nread += nbytes;
- }
- inbuffer[nread] = '\0';
-
- /* Reinitialize scanner and parser for the new input file. */
- re_init_scanner ();
- re_init_parser ();
-
- /* Parse it and close the file. */
- yyparse ();
- fclose (fp);
- }
-}
-
-
-/* Read a line from stream FP and return a pointer to a static buffer
- containing its contents without the terminating newline. Value
- is null when EOF is reached. */
-
-static char *
-read_line (FILE *fp)
-{
- static char *buffer;
- static int buffer_size;
- int i = 0, c;
-
- while ((c = getc (fp)) != EOF && c != '\n')
- {
- if (i >= buffer_size)
- {
- buffer_size = max (100, buffer_size * 2);
- buffer = (char *) xrealloc (buffer, buffer_size);
- }
-
- buffer[i++] = c;
- }
-
- if (c == EOF && i == 0)
- return NULL;
-
- if (i == buffer_size)
- {
- buffer_size = max (100, buffer_size * 2);
- buffer = (char *) xrealloc (buffer, buffer_size);
- }
-
- buffer[i] = '\0';
- if (i > 0 && buffer[i - 1] == '\r')
- buffer[i - 1] = '\0';
- return buffer;
-}
-
-
-/* Main entry point. */
-
-int
-main (int argc, char **argv)
-{
- int i;
- int any_inputfiles = 0;
- static const char *out_filename = DEFAULT_OUTFILE;
- static char **input_filenames = NULL;
- static int input_filenames_size = 0;
- static int n_input_files;
-
- filename = "command line";
- yyout = stdout;
-
- while ((i = getopt_long (argc, argv, "af:I:m:M:no:p:svVx",
- options, NULL)) != EOF)
- {
- switch (i)
- {
- /* Experimental. */
- case 'p':
- info_position = atoi (optarg);
- break;
-
- case 'n':
- f_nested_classes = 0;
- break;
-
- case 'x':
- f_regexps = 0;
- break;
-
- /* Add the name of a file containing more input files. */
- case 'f':
- if (n_input_files == input_filenames_size)
- {
- input_filenames_size = max (10, 2 * input_filenames_size);
- input_filenames = xrealloc (input_filenames,
- (input_filenames_size
- * sizeof *input_filenames));
- }
- input_filenames[n_input_files++] = xstrdup (optarg);
- break;
-
- /* Append new output to output file instead of truncating it. */
- case 'a':
- f_append = 1;
- break;
-
- /* Include structs in the output */
- case 's':
- f_structs = 0;
- break;
-
- /* Be verbose (give a progress indication). */
- case 'v':
- f_verbose = 1;
- break;
-
- /* Be very verbose (print file names as they are processed). */
- case 'V':
- f_verbose = 1;
- f_very_verbose = 1;
- break;
-
- /* Change the name of the output file. */
- case 'o':
- out_filename = optarg;
- break;
-
- /* Set minimum length for regular expression strings
- when recorded in the output file. */
- case 'm':
- min_regexp = atoi (optarg);
- break;
-
- /* Set maximum length for regular expression strings
- when recorded in the output file. */
- case 'M':
- max_regexp = atoi (optarg);
- break;
-
- /* Add to search path. */
- case 'I':
- add_search_path (optarg);
- break;
-
- /* Display help */
- case -2:
- usage (0);
- break;
-
- case -3:
- version ();
- break;
- }
- }
-
- /* Call init_scanner after command line flags have been processed to be
- able to add keywords depending on command line (not yet
- implemented). */
- init_scanner ();
- init_sym ();
-
- /* Open output file */
- if (*out_filename)
- {
- if (f_append)
- {
- /* Check that the file to append to exists, and is not
- empty. More specifically, it should be a valid file
- produced by a previous run of ebrowse, but that's too
- difficult to check. */
- FILE *fp;
- int rc;
-
- fp = fopen (out_filename, "r");
- if (fp == NULL)
- {
- yyerror ("file '%s' must exist for --append", out_filename);
- exit (EXIT_FAILURE);
- }
-
- rc = fseek (fp, 0, SEEK_END);
- if (rc == -1)
- {
- yyerror ("error seeking in file '%s'", out_filename);
- exit (EXIT_FAILURE);
- }
-
- rc = ftell (fp);
- if (rc == -1)
- {
- yyerror ("error getting size of file '%s'", out_filename);
- exit (EXIT_FAILURE);
- }
-
- else if (rc == 0)
- {
- yyerror ("file '%s' is empty", out_filename);
- /* It may be ok to use an empty file for appending.
- exit (EXIT_FAILURE); */
- }
-
- fclose (fp);
- }
-
- yyout = fopen (out_filename, f_append ? "a" : "w");
- if (yyout == NULL)
- {
- yyerror ("cannot open output file '%s'", out_filename);
- exit (EXIT_FAILURE);
- }
- }
-
- /* Process input files specified on the command line. */
- while (optind < argc)
- {
- process_file (argv[optind++]);
- any_inputfiles = 1;
- }
-
- /* Process files given on stdin if no files specified. */
- if (!any_inputfiles && n_input_files == 0)
- {
- char *file;
- while ((file = read_line (stdin)) != NULL)
- process_file (file);
- }
- else
- {
- /* Process files from `--files=FILE'. Every line in FILE names
- one input file to process. */
- for (i = 0; i < n_input_files; ++i)
- {
- FILE *fp = fopen (input_filenames[i], "r");
-
- if (fp == NULL)
- yyerror ("cannot open input file '%s'", input_filenames[i]);
- else
- {
- char *file;
- while ((file = read_line (fp)) != NULL)
- process_file (file);
- fclose (fp);
- }
- }
- }
-
- /* Write output file. */
- dump_roots (yyout);
-
- /* Close output file. */
- if (yyout != stdout)
- fclose (yyout);
-
- return EXIT_SUCCESS;
-}
-
-/* ebrowse.c ends here */
(make-obsolete-variable 'semantic-version 'emacs-version "29.1")
(declare-function inversion-test "inversion")
-(declare-function semanticdb-load-ebrowse-caches "semantic/db-ebrowse")
(defun semantic-require-version (major minor &optional beta)
"Non-nil if this version of Semantic does not satisfy a specific version.
(and (memq mode semantic-default-submodes)
(fboundp mode)
(funcall mode 1)))
- (unless semantic-load-system-cache-loaded
- (setq semantic-load-system-cache-loaded t)
- (when (and (boundp 'semanticdb-default-system-save-directory)
- (stringp semanticdb-default-system-save-directory)
- (file-exists-p semanticdb-default-system-save-directory))
- (require 'semantic/db-ebrowse)
- (semanticdb-load-ebrowse-caches)))
(add-hook 'mode-local-init-hook #'semantic-new-buffer-fcn)
;; Add semantic-ia-complete-symbol to
;; completion-at-point-functions, so that it is run from
#'semantic-change-function)
(define-key cedet-menu-map [cedet-menu-separator] nil)
(define-key cedet-menu-map [semantic-options-separator] nil)
- ;; FIXME: handle semanticdb-load-ebrowse-caches
(dolist (mode semantic-submode-list)
(if (and (boundp mode) (symbol-value mode))
(funcall mode -1)))
+++ /dev/null
-;;; semantic/db-ebrowse.el --- Semanticdb backend using ebrowse. -*- lexical-binding: t; -*-
-
-;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
-
-;; Authors: Eric M. Ludlam <zappo@gnu.org>
-;; Joakim Verona
-;; Keywords: tags
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs 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 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs 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 GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-;;
-;; This program was started by Eric Ludlam, and Joakim Verona finished
-;; the implementation by adding searches and fixing bugs.
-;;
-;; Read in custom-created ebrowse BROWSE files into a semanticdb back
-;; end.
-;;
-;; Add these databases to the 'system' search.
-;; Possibly use ebrowse for local parsing too.
-;;
-;; When real details are needed out of the tag system from ebrowse,
-;; we will need to delve into the originating source and parse those
-;; files the usual way.
-;;
-;; COMMANDS:
-;; `semanticdb-create-ebrowse-database' - Call EBROWSE to create a
-;; system database for some directory. In general, use this for
-;; system libraries, such as /usr/include, or include directories
-;; large software projects.
-;; Customize `semanticdb-ebrowse-file-match' to make sure the correct
-;; file extensions are matched.
-;;
-;; `semanticdb-load-ebrowse-caches' - Load all the EBROWSE caches from
-;; your semanticdb system database directory. Once they are
-;; loaded, they become searchable as omnipotent databases for
-;; all C++ files. This is called automatically by semantic-load.
-;; Call it a second time to refresh the Emacs DB with the file.
-;;
-
-(require 'ebrowse)
-(require 'semantic)
-(require 'semantic/db-file)
-
-(eval-when-compile
- ;; For generic function searching.
- (require 'eieio)
- (require 'eieio-opt)
- (require 'semantic/find))
-
-(declare-function semantic-add-system-include "semantic/dep")
-
-;;; Code:
-(defvar semanticdb-ebrowse-default-file-name "BROWSE"
- "The EBROWSE file name used for system caches.")
-
-(defcustom semanticdb-ebrowse-file-match "\\.\\(hh?\\|HH?\\|hpp\\)"
- "Regular expression matching file names for ebrowse to parse.
-This expression should exclude C++ headers that have no extension.
-By default, include only headers since the semantic use of EBrowse
-is only for searching via semanticdb, and thus only headers would
-be searched."
- :group 'semanticdb
- :type 'regexp)
-
-;;; SEMANTIC Database related Code
-;;; Classes:
-(defclass semanticdb-table-ebrowse (semanticdb-table)
- ((major-mode :initform #'c++-mode)
- (ebrowse-tree :initform nil
- :initarg :ebrowse-tree
- :documentation
- "The raw ebrowse tree for this file."
- )
- (global-extract :initform nil
- :initarg :global-extract
- :documentation
- "Table of ebrowse tags specific to this file.
-This table is composited from the ebrowse *Globals* section.")
- )
- "A table for returning search results from ebrowse.")
-
-(defclass semanticdb-project-database-ebrowse
- (semanticdb-project-database)
- ((new-table-class :initform 'semanticdb-table-ebrowse
- :type class
- :documentation
- "New tables created for this database are of this class.")
- (system-include-p :initform nil
- :initarg :system-include
- :documentation
- "Flag indicating this database represents a system include directory.")
- (ebrowse-struct :initform nil
- :initarg :ebrowse-struct
- )
- )
- "Semantic Database deriving tags using the EBROWSE tool.
-EBROWSE is a C/C++ parser for use with `ebrowse' Emacs program.")
-
-
-(defun semanticdb-ebrowse-C-file-p (file)
- "Is FILE a C or C++ file?"
- (or (string-match semanticdb-ebrowse-file-match file)
- (and (string-match "/\\w+$" file)
- (not (file-directory-p file))
- (let ((tmp (get-buffer-create "*semanticdb-ebrowse-tmp*")))
- (with-current-buffer tmp
- (condition-case nil
- (insert-file-contents file nil 0 100 t)
- (error (insert-file-contents file nil nil nil t)))
- (goto-char (point-min))
- (looking-at "\\s-*/\\(\\*\\|/\\)")
- ))
- )))
-
-(defun semanticdb-create-ebrowse-database (dir)
- "Create an EBROWSE database for directory DIR.
-The database file is stored in ~/.semanticdb, or whichever directory
-is specified by `semanticdb-default-save-directory'."
- (interactive "DDirectory: ")
- (setq dir (file-name-as-directory dir)) ;; for / on end
- (let* ((savein (semanticdb-ebrowse-file-for-directory dir))
- (filebuff (get-buffer-create "*SEMANTICDB EBROWSE TMP*"))
- (files (directory-files (expand-file-name dir) t))
- ;; (mma auto-mode-alist)
- ;; (regexp nil)
- )
- ;; Create the input to the ebrowse command
- (with-current-buffer filebuff
- (buffer-disable-undo filebuff)
- (setq default-directory (expand-file-name dir))
-
- ;;; @TODO - convert to use semanticdb-collect-matching-filenames
- ;; to get the file names.
-
-
- (mapc (lambda (f)
- (when (semanticdb-ebrowse-C-file-p f)
- (insert f)
- (insert "\n")))
- files)
- ;; Cleanup the ebrowse output buffer.
- (with-current-buffer (get-buffer-create "*EBROWSE OUTPUT*")
- (erase-buffer))
- ;; Call the EBROWSE command.
- (message "Creating ebrowse file: %s ..." savein)
- (call-process-region (point-min) (point-max)
- ebrowse-program-name
- nil "*EBROWSE OUTPUT*" nil
- (concat "--output-file=" savein)
- "--very-verbose")
- )
- ;; Create a short LOADER program for loading in this database.
- (let* ((lfn (concat savein "-load.el"))
- (lf (find-file-noselect lfn)))
- (with-current-buffer lf
- (erase-buffer)
- (insert "(semanticdb-ebrowse-load-helper \""
- (expand-file-name dir)
- "\")\n")
- (save-buffer)
- (kill-buffer (current-buffer)))
- (message "Creating ebrowse file: %s ... done" savein)
- ;; Reload that database
- (load lfn nil t)
- )))
-
-(defun semanticdb-load-ebrowse-caches ()
- "Load all semanticdb controlled EBROWSE caches."
- (interactive)
- (let ((f (directory-files semanticdb-default-save-directory
- t (concat (regexp-quote
- semanticdb-ebrowse-default-file-name)
- "-load\\.el\\'")
- t)))
- (while f
- (load (car f) nil t)
- (setq f (cdr f)))
- ))
-
-(defun semanticdb-ebrowse-load-helper (directory)
- "Create the semanticdb database via ebrowse for directory.
-If DIRECTORY is found to be defunct, it won't load the DB, and will
-warn instead."
- (if (file-directory-p directory)
- (semanticdb-create-database 'semanticdb-project-database-ebrowse
- directory)
- (let* ((BF (semanticdb-ebrowse-file-for-directory directory))
- (BFL (concat BF "-load.el"))
- (BFLB (concat BF "-load.el~")))
- (save-window-excursion
- (with-output-to-temp-buffer "*FILES TO DELETE*"
- (princ "The following BROWSE files are obsolete.\n\n")
- (princ BF)
- (princ "\n")
- (princ BFL)
- (princ "\n")
- (when (file-exists-p BFLB)
- (princ BFLB)
- (princ "\n"))
- )
- (when (y-or-n-p (format
- "Warning: Obsolete BROWSE file for: %s\nDelete? "
- directory))
- (delete-file BF)
- (delete-file BFL)
- (when (file-exists-p BFLB)
- (delete-file BFLB))
- )))))
-
-;JAVE this just instantiates a default empty ebrowse struct?
-; how would new instances wind up here?
-; the ebrowse class isn't singleton, unlike the Emacs Lisp one
-(defvar-mode-local c++-mode semanticdb-project-system-databases
- ()
- "Search Ebrowse for symbols.")
-
-(cl-defmethod semanticdb-needs-refresh-p ((_table semanticdb-table-ebrowse))
- "EBROWSE database do not need to be refreshed.
-
-JAVE: stub for needs-refresh, because, how do we know if BROWSE files
- are out of date?
-
-EML: Our database should probably remember the timestamp/checksum of
- the most recently read EBROWSE file, and use that."
- nil
-)
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-
-;;; EBROWSE code
-;;
-;; These routines deal with part of the ebrowse interface.
-(defun semanticdb-ebrowse-file-for-directory (dir)
- "Return the file name for DIR where the ebrowse BROWSE file is.
-This file should reside in `semanticdb-default-save-directory'."
- (let* ((semanticdb-default-save-directory
- semanticdb-default-save-directory)
- (B (semanticdb-file-name-directory
- 'semanticdb-project-database-file
- (concat (expand-file-name dir)
- semanticdb-ebrowse-default-file-name)))
- )
- B))
-
-(defun semanticdb-ebrowse-get-ebrowse-structure (dir)
- "Return the ebrowse structure for directory DIR.
-This assumes semantic manages the BROWSE files, so they are assumed to live
-where semantic cache files live, depending on your settings.
-
-For instance: /home/<username>/.semanticdb/!usr!include!BROWSE"
- (let* ((B (semanticdb-ebrowse-file-for-directory dir))
- (buf (get-buffer-create "*semanticdb ebrowse*")))
- (message "semanticdb-ebrowse %s" B)
- (when (file-exists-p B)
- (set-buffer buf)
- (buffer-disable-undo buf)
- (erase-buffer)
- (insert-file-contents B)
- (let ((ans nil)
- (efcn (symbol-function 'ebrowse-show-progress)))
- (fset 'ebrowse-show-progress (lambda (&rest _junk) nil))
- (unwind-protect ; Protect against errors with ebrowse
- (setq ans (list B (ebrowse-read)))
- ;; These items must always happen
- (erase-buffer)
- (fset 'ebrowse-show-fcn efcn)
- )
- ans))))
-
-;;; Methods for creating a database or tables
-;;
-(cl-defmethod semanticdb-create-database ((dbeC (subclass semanticdb-project-database-ebrowse))
- directory)
- "Create a new semantic database for DIRECTORY based on ebrowse.
-If there is no database for DIRECTORY available, then
-{not implemented yet} create one. Return nil if that is not possible."
- ;; MAKE SURE THAT THE FILE LOADED DOESN'T ALREADY EXIST.
- (require 'semantic/dep)
- (let ((dbs semanticdb-database-list)
- (found nil))
- (while (and (not found) dbs)
- (when (semanticdb-project-database-ebrowse-p (car dbs))
- (when (string= (oref (car dbs) reference-directory) directory)
- (setq found (car dbs))))
- (setq dbs (cdr dbs)))
- ;;STATIC means DBE can't be used as object, only as a class
- (let* ((ebrowse-data (semanticdb-ebrowse-get-ebrowse-structure directory))
- (dat (car (cdr ebrowse-data)))
- (ebd (car dat))
- (db nil)
- (default-directory directory)
- )
- (if found
- (setq db found)
- (setq db (make-instance
- dbeC
- directory
- :ebrowse-struct ebd
- ))
- (oset db reference-directory directory))
-
- ;; Once we recycle or make a new DB, refresh the
- ;; contents from the BROWSE file.
- (oset db tables nil)
- ;; only possible after object creation, tables inited to nil.
- (semanticdb-ebrowse-strip-trees db dat)
-
- ;; Once our database is loaded, if we are a system DB, we
- ;; add ourselves to the include list for C++.
- (semantic-add-system-include directory 'c++-mode)
- (semantic-add-system-include directory 'c-mode)
-
- db)))
-
-(cl-defmethod semanticdb-ebrowse-strip-trees ((dbe semanticdb-project-database-ebrowse)
- data)
- "For the ebrowse database DBE, strip all tables from DATA."
-;JAVE what it actually seems to do is split the original tree in "tables" associated with files
-; im not sure it actually works:
-; the filename slot sometimes gets to be nil,
-; apparently for classes which definition can't be found, yet needs to be included in the tree
-; like library baseclasses
-; a file can define several classes
- (let ((T (car (cdr data))));1st comes a header, then the tree
- (while T
-
- (let* ((tree (car T))
- ;;(class (ebrowse-ts-class tree)); root class of tree
- ;; Something funny going on with this file thing...
- ;; (filename (or (ebrowse-cs-source-file class)
- ;; (ebrowse-cs-file class)))
- )
- (cond
- ((ebrowse-globals-tree-p tree)
- ;; We have the globals tree.. save this special.
- (semanticdb-ebrowse-add-globals-to-table dbe tree)
- )
- (t
- ;; ebrowse will collect all the info from multiple files
- ;; into one tree. Semantic wants all the bits to be tied
- ;; into different files. We need to do a full dissociation
- ;; into semantic parsable tables.
- (semanticdb-ebrowse-add-tree-to-table dbe tree)
- ))
- (setq T (cdr T))))
- ))
-
-;;; Filename based methods
-;;
-(defun semanticdb-ebrowse-add-globals-to-table (_dbe tree)
- "For database DBE, add the ebrowse TREE into the table."
- (if (or (not (ebrowse-ts-p tree))
- (not (ebrowse-globals-tree-p tree)))
- (signal 'wrong-type-argument (list 'ebrowse-ts-p tree)))
-
- (let* ((class (ebrowse-ts-class tree))
- ;; (fname (or (ebrowse-cs-source-file class)
- ;; (ebrowse-cs-file class)
- ;; ;; Not def'd here, assume our current
- ;; ;; file
- ;; (concat default-directory "/unknown-proxy.hh")))
- (vars (ebrowse-ts-member-functions tree))
- (fns (ebrowse-ts-member-variables tree))
- (toks nil)
- )
- (while vars
- (let ((nt (semantic-tag (ebrowse-ms-name (car vars))
- 'variable))
- (defpoint (ebrowse-bs-point class)))
- (when defpoint
- (semantic--tag-set-overlay nt
- (vector defpoint defpoint)))
- (setq toks (cons nt toks)))
- (setq vars (cdr vars)))
- (while fns
- (let ((nt (semantic-tag (ebrowse-ms-name (car fns))
- 'function))
- (defpoint (ebrowse-bs-point class)))
- (when defpoint
- (semantic--tag-set-overlay nt
- (vector defpoint defpoint)))
- (setq toks (cons nt toks)))
- (setq fns (cdr fns)))
-
- ))
-
-(defun semanticdb-ebrowse-add-tree-to-table (dbe tree &optional fname baseclasses)
- "For database DBE, add the ebrowse TREE into the table for FNAME.
-Optional argument BASECLASSES specifies a baseclass to the tree being provided."
- (if (not (ebrowse-ts-p tree))
- (signal 'wrong-type-argument (list 'ebrowse-ts-p tree)))
-
- ;; Strategy overview:
- ;; 1) Calculate the filename for this tree.
- ;; 2) Find a matching namespace in TAB, or create a new one.
- ;; 3) Fabricate a tag proxy for CLASS
- ;; 4) Add it to the namespace
- ;; 5) Add subclasses
-
- ;; 1 - Find the filename
- (if (not fname)
- (setq fname (or (ebrowse-cs-source-file (ebrowse-ts-class tree))
- (ebrowse-cs-file (ebrowse-ts-class tree))
- ;; Not def'd here, assume our current
- ;; file
- (concat default-directory "/unknown-proxy.hh"))))
-
- (let* ((tab (or (semanticdb-file-table dbe fname)
- (semanticdb-create-table dbe fname)))
- (class (ebrowse-ts-class tree))
- (scope (ebrowse-cs-scope class))
- (ns (when scope (split-string scope ":" t)))
- (nst nil)
- (cls nil)
- )
-
- ;; 2 - Get the namespace tag
- (when ns
- (let ((taglst (if (slot-boundp tab 'tags) (oref tab tags) nil)))
- (setq nst (semantic-find-first-tag-by-name (car ns) taglst))
- (when (not nst)
- (setq nst (semantic-tag (car ns) 'type :type "namespace"))
- (oset tab tags (cons nst taglst))
- )))
-
- ;; 3 - Create a proxy tg.
- (setq cls (semantic-tag (ebrowse-cs-name class)
- 'type
- :type "class"
- :superclasses baseclasses
- :faux t
- :filename fname
- ))
- (let ((defpoint (ebrowse-bs-point class)))
- (when defpoint
- (semantic--tag-set-overlay cls
- (vector defpoint defpoint))))
-
- ;; 4 - add to namespace
- (if nst
- (semantic-tag-put-attribute
- nst :members (cons cls (semantic-tag-get-attribute nst :members)))
- (oset tab tags (cons cls (when (slot-boundp tab 'tags)
- (oref tab tags)))))
-
- ;; 5 - Subclasses
- (let* ((subclass (ebrowse-ts-subclasses tree))
- (pname (ebrowse-cs-name class)))
- (when (ebrowse-cs-scope class)
- (setq pname (concat (mapconcat (lambda (a) a) (cdr ns) "::") "::" pname)))
-
- (while subclass
- (let* ((scc (ebrowse-ts-class (car subclass)))
- (fname (or (ebrowse-cs-source-file scc)
- (ebrowse-cs-file scc)
- ;; Not def'd here, assume our current
- ;; file
- fname
- )))
- (when fname
- (semanticdb-ebrowse-add-tree-to-table
- dbe (car subclass) fname pname)))
- (setq subclass (cdr subclass))))
- ))
-
-;;;
-;; Overload for converting the simple faux tag into something better.
-;;
-(cl-defmethod semanticdb-normalize-tags ((obj semanticdb-table-ebrowse) tags)
- "Convert in Ebrowse database OBJ a list of TAGS into a complete tag.
-The default tag provided by searches exclude many features of a
-semantic parsed tag. Look up the file for OBJ, and match TAGS
-against a semantic parsed tag that has all the info needed, and
-return that."
- (let ((tagret nil)
- )
- ;; SemanticDB will automatically create a regular database
- ;; on top of the file just loaded by ebrowse during the set
- ;; buffer. Fetch that table, and use it's tag list to look
- ;; up the tag we just got, and thus turn it into a full semantic
- ;; tag.
- (while tags
- (let ((tag (car tags)))
- (save-excursion
- (semanticdb-set-buffer obj)
- (let ((ans nil))
- ;; Gee, it would be nice to do this, but ebrowse LIES. Oi.
- (when (semantic-tag-with-position-p tag)
- (goto-char (semantic-tag-start tag))
- (let ((foundtag (semantic-current-tag)))
- ;; Make sure the discovered tag is the same as what we started with.
- (when (string= (semantic-tag-name tag)
- (semantic-tag-name foundtag))
- ;; We have a winner!
- (setq ans foundtag))))
- ;; Sometimes ebrowse lies. Do a generic search
- ;; to find it within this file.
- (when (not ans)
- ;; We might find multiple hits for this tag, and we have no way
- ;; of knowing which one the user wanted. Return the first one.
- (setq ans (semantic-deep-find-tags-by-name
- (semantic-tag-name tag)
- (semantic-fetch-tags))))
- (if (semantic-tag-p ans)
- (setq tagret (cons ans tagret))
- (setq tagret (append ans tagret)))
- ))
- (setq tags (cdr tags))))
- tagret))
-
-(cl-defmethod semanticdb-normalize-one-tag ((obj semanticdb-table-ebrowse) tag)
- "Convert in Ebrowse database OBJ one TAG into a complete tag.
-The default tag provided by searches exclude many features of a
-semantic parsed tag. Look up the file for OBJ, and match TAG
-against a semantic parsed tag that has all the info needed, and
-return that."
- (let ((tagret nil)
- (objret nil))
- ;; SemanticDB will automatically create a regular database
- ;; on top of the file just loaded by ebrowse during the set
- ;; buffer. Fetch that table, and use it's tag list to look
- ;; up the tag we just got, and thus turn it into a full semantic
- ;; tag.
- (save-excursion
- (semanticdb-set-buffer obj)
- (setq objret semanticdb-current-table)
- (when (not objret)
- ;; What to do??
- (debug))
- (let ((ans nil))
- ;; Gee, it would be nice to do this, but ebrowse LIES. Oi.
- (when (semantic-tag-with-position-p tag)
- (goto-char (semantic-tag-start tag))
- (let ((foundtag (semantic-current-tag)))
- ;; Make sure the discovered tag is the same as what we started with.
- (when (string= (semantic-tag-name tag)
- (semantic-tag-name foundtag))
- ;; We have a winner!
- (setq ans foundtag))))
- ;; Sometimes ebrowse lies. Do a generic search
- ;; to find it within this file.
- (when (not ans)
- ;; We might find multiple hits for this tag, and we have no way
- ;; of knowing which one the user wanted. Return the first one.
- (setq ans (semantic-deep-find-tags-by-name
- (semantic-tag-name tag)
- (semantic-fetch-tags))))
- (if (semantic-tag-p ans)
- (setq tagret ans)
- (setq tagret (car ans)))
- ))
- (cons objret tagret)))
-
-;;; Search Overrides
-;;
-;; NOTE WHEN IMPLEMENTING: Be sure to add doc-string updates explaining
-;; how your new search routines are implemented.
-;;
-(cl-defmethod semanticdb-find-tags-by-name-method
- ((_table semanticdb-table-ebrowse) _name &optional tags)
- "Find all tags named NAME in TABLE.
-Return a list of tags."
- ;;(message "semanticdb-find-tags-by-name-method name -- %s" name)
- (if tags
- ;; If TAGS are passed in, then we don't need to do work here.
- (cl-call-next-method)
- ;; If we ever need to do something special, add here.
- ;; Since ebrowse tags are converted into semantic tags, we can
- ;; get away with this sort of thing.
- (cl-call-next-method)
- )
- )
-
-(cl-defmethod semanticdb-find-tags-by-name-regexp-method
- ((_table semanticdb-table-ebrowse) _regex &optional tags)
- "Find all tags with name matching REGEX in TABLE.
-Optional argument TAGS is a list of tags to search.
-Return a list of tags."
- (if tags (cl-call-next-method)
- ;; YOUR IMPLEMENTATION HERE
- (cl-call-next-method)
- ))
-
-(cl-defmethod semanticdb-find-tags-for-completion-method
- ((_table semanticdb-table-ebrowse) _prefix &optional tags)
- "In TABLE, find all occurrences of tags matching PREFIX.
-Optional argument TAGS is a list of tags to search.
-Returns a table of all matching tags."
- (if tags (cl-call-next-method)
- ;; YOUR IMPLEMENTATION HERE
- (cl-call-next-method)
- ))
-
-(cl-defmethod semanticdb-find-tags-by-class-method
- ((_table semanticdb-table-ebrowse) _class &optional tags)
- "In TABLE, find all occurrences of tags of CLASS.
-Optional argument TAGS is a list of tags to search.
-Returns a table of all matching tags."
- (if tags (cl-call-next-method)
- (cl-call-next-method)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;; Deep Searches
-;;
-;; If your language does not have a `deep' concept, these can be left
-;; alone, otherwise replace with implementations similar to those
-;; above.
-;;
-
-(cl-defmethod semanticdb-deep-find-tags-by-name-method
- ((_table semanticdb-table-ebrowse) _name &optional _tags)
- "Find all tags name NAME in TABLE.
-Optional argument TAGS is a list of tags to search.
-Like `semanticdb-find-tags-by-name-method' for ebrowse."
- ;;(semanticdb-find-tags-by-name-method table name tags)
- (cl-call-next-method))
-
-(cl-defmethod semanticdb-deep-find-tags-by-name-regexp-method
- ((_table semanticdb-table-ebrowse) _regex &optional _tags)
- "Find all tags with name matching REGEX in TABLE.
-Optional argument TAGS is a list of tags to search.
-Like `semanticdb-find-tags-by-name-method' for ebrowse."
- ;;(semanticdb-find-tags-by-name-regexp-method table regex tags)
- (cl-call-next-method))
-
-(cl-defmethod semanticdb-deep-find-tags-for-completion-method
- ((_table semanticdb-table-ebrowse) _prefix &optional _tags)
- "In TABLE, find all occurrences of tags matching PREFIX.
-Optional argument TAGS is a list of tags to search.
-Like `semanticdb-find-tags-for-completion-method' for ebrowse."
- ;;(semanticdb-find-tags-for-completion-method table prefix tags)
- (cl-call-next-method))
-
-;;; Advanced Searches
-;;
-(cl-defmethod semanticdb-find-tags-external-children-of-type-method
- ((_table semanticdb-table-ebrowse) _type &optional tags)
- "Find all nonterminals which are child elements of TYPE
-Optional argument TAGS is a list of tags to search.
-Return a list of tags."
- (if tags (cl-call-next-method)
- ;; Ebrowse collects all this type of stuff together for us.
- ;; but we can't use it.... yet.
- nil
- ))
-
-(provide 'semantic/db-ebrowse)
-
-;; Local variables:
-;; generated-autoload-load-name: "semantic/db-ebrowse"
-;; End:
-
-;;; semantic/db-ebrowse.el ends here
(edit-and-eval-command "Redo: " what))))
(defcustom default-command-history-filter-garbage
- '(command-history-mode
- list-command-history
- electric-command-history)
+ '(command-history-mode list-command-history)
"A list of symbols to be ignored by `default-command-history-filter'.
If that function is given a list whose car is an element of this list,
then it will return non-nil (indicating the list should be discarded from
(define-key map "\e" nil)
(define-key map "\C-z" #'suspend-frame)
(define-key map "v" #'Electric-buffer-menu-mode-view-buffer)
- (define-key map (char-to-string help-char) #'Helper-help)
- (define-key map "?" #'Helper-describe-bindings)
(define-key map "\C-c" nil)
(define-key map "\C-c\C-c" #'Electric-buffer-menu-quit)
(define-key map "\C-]" #'Electric-buffer-menu-quit)
(put 'Electric-buffer-menu-quit :advertised-binding "\C-c\C-c")
(put 'Electric-buffer-menu-select :advertised-binding " ")
-(put 'Helper-help :advertised-binding (char-to-string help-char))
-(put 'Helper-describe-bindings :advertised-binding "?")
(defvar electric-buffer-menu-mode-hook nil
"Normal hook run by `electric-buffer-menu-mode'.")
(recenter -1))))
(electric-buffer-update-highlight))
-(defvar Helper-return-blurb)
-
(define-derived-mode electric-buffer-menu-mode Buffer-menu-mode
"Electric Buffer Menu"
"Toggle Electric Buffer Menu mode in this buffer.
Electric Buffer Menu mode is a minor mode which is automatically
enabled and disabled by the \\[electric-buffer-list] command.
See the documentation of `electric-buffer-list' for details."
- (setq mode-line-buffer-identification "Electric Buffer List")
- (setq-local Helper-return-blurb "return to buffer editing"))
+ (setq mode-line-buffer-identification "Electric Buffer List"))
;; generally the same as Buffer-menu-mode-map
;; (except we don't indirect to global-map)
(message "%s"
(substitute-command-keys "\
Type \\[Electric-buffer-menu-quit] to exit, \
-\\[Electric-buffer-menu-select] to select, \
-\\[Helper-help] for help, \\[Helper-describe-bindings] for commands."))
+\\[Electric-buffer-menu-select] to select."))
(sit-for 4))
(defun Electric-buffer-menu-mode-view-buffer ()
+++ /dev/null
-;;; echistory.el --- Electric Command History Mode -*- lexical-binding: t -*-
-
-;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
-
-;; Author: K. Shane Hartman
-;; Maintainer: emacs-devel@gnu.org
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs 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 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs 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 GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'electric) ; command loop
-(require 'chistory) ; history lister
-
-;; Dynamically bound in electric-command-history
-(defvar electric-history-in-progress)
-
-;;;###autoload
-(defun Electric-command-history-redo-expression (&optional noconfirm)
- "Edit current history line in minibuffer and execute result.
-With prefix arg NOCONFIRM, execute current line as-is without editing."
- (interactive "P")
- (let (todo)
- (with-current-buffer "*Command History*"
- (beginning-of-line)
- (setq todo (read (current-buffer)))
- (if (boundp 'electric-history-in-progress)
- (if todo (throw 'electric-history-quit (list noconfirm todo)))))))
-
-(defvar electric-history-map
- (let ((map (make-sparse-keymap)))
- (define-key map [t] #'Electric-history-undefined)
- (define-key map "\e" (make-sparse-keymap))
- (define-key map [?\e t] #'Electric-history-undefined)
- (define-key map "\C-u" #'universal-argument)
- (define-key map " " #'Electric-command-history-redo-expression)
- (define-key map "!" #'Electric-command-history-redo-expression)
- (define-key map "\e\C-d" #'down-list)
- (define-key map "\e\C-u" #'backward-up-list)
- (define-key map "\e\C-b" #'backward-sexp)
- (define-key map "\e\C-f" #'forward-sexp)
- (define-key map "\e\C-a" #'beginning-of-defun)
- (define-key map "\e\C-e" #'end-of-defun)
- (define-key map "\e\C-n" #'forward-list)
- (define-key map "\e\C-p" #'backward-list)
- (define-key map "q" #'Electric-history-quit)
- (define-key map "\C-c" nil)
- (define-key map "\C-c\C-c" #'Electric-history-quit)
- (define-key map "\C-]" #'Electric-history-quit)
- (define-key map "\C-z" #'suspend-frame)
- (define-key map (char-to-string help-char) #'Helper-help)
- (define-key map "?" #'Helper-describe-bindings)
- (define-key map "\e>" #'end-of-buffer)
- (define-key map "\e<" #'beginning-of-buffer)
- (define-key map "\n" #'next-line)
- (define-key map "\r" #'next-line)
- (define-key map "\177" #'previous-line)
- (define-key map "\C-n" #'next-line)
- (define-key map "\C-p" #'previous-line)
- (define-key map "\ev" #'scroll-down)
- (define-key map "\C-v" #'scroll-up)
- (define-key map [home] #'beginning-of-buffer)
- (define-key map [down] #'next-line)
- (define-key map [up] #'previous-line)
- (define-key map [prior] #'scroll-down)
- (define-key map [next] #'scroll-up)
- (define-key map "\C-l" #'recenter)
- (define-key map "\e\C-v" #'scroll-other-window)
- map)
- "Keymap for Electric Command History mode.")
-
-(defvar electric-command-history-hook nil
- "If non-nil, its value is called by `electric-command-history'.")
-
-(defvar Helper-return-blurb) ; from helper.el
-
-(defun electric-command-history ()
- "\\<electric-history-map>Major mode for examining and redoing commands from `command-history'.
-This pops up a window with the Command History listing.
-The number of command listed is controlled by `list-command-history-max'.
-The command history is filtered by `list-command-history-filter' if non-nil.
-Combines typeout Command History list window with menu like selection
-of an expression from the history for re-evaluation in the *original* buffer.
-
-The history displayed is filtered by `list-command-history-filter' if non-nil.
-
-Like Emacs-Lisp mode except that characters do not insert themselves and
-Tab and Linefeed do not indent. Instead these commands are provided:
-\\{electric-history-map}
-
-Calls the value of `electric-command-history-hook' if that is non-nil.
-The Command History listing is recomputed each time this mode is invoked."
- (interactive)
- (let ((electric-history-in-progress t)
- (old-buffer (current-buffer))
- (todo))
- (unwind-protect
- (setq todo
- (catch 'electric-history-quit
- (save-window-excursion
- (save-window-excursion
- (list-command-history)
- (set-buffer "*Command History*")
- (setq major-mode 'electric-command-history)
- (setq mode-name "Electric History")
- (use-local-map electric-history-map))
- (Electric-pop-up-window "*Command History*")
- (run-hooks 'electric-command-history-hook)
- (if (eobp)
- (progn (ding)
- (message "No command history.")
- (throw 'electric-history-quit nil))
- (let ((Helper-return-blurb "return to History"))
- (Electric-command-loop 'electric-history-quit
- "->" t))))))
- (set-buffer "*Command History*")
- (command-history-mode)
- (bury-buffer (current-buffer)))
- (if (consp todo)
- (progn (set-buffer old-buffer)
- (if (car todo)
- (apply (car (car (cdr todo))) (cdr (car (cdr todo))))
- (edit-and-eval-command "Redo: " (car (cdr todo))))))))
-
-(defun Electric-history-undefined ()
- (interactive)
- (ding)
- (message "%s" (substitute-command-keys "Type \\[Helper-help] for help, \
-\\[Helper-describe-bindings] for commands, \\[Electric-history-quit] to quit, \
-\\[Electric-command-history-redo-expression] to execute"))
- (sit-for 4))
-
-(defun Electric-history-quit ()
- "Quit Electric Command History, restoring previous window configuration."
- (interactive)
- (if (boundp 'electric-history-in-progress)
- (progn (message "")
- (throw 'electric-history-quit nil))))
-
-(provide 'echistory)
-
-;;; echistory.el ends here
("\\.\\(?:PDF\\|EPUB\\|CBZ\\|FB2\\|O?XPS\\|DVI\\|OD[FGPST]\\|DOCX\\|XLSX?\\|PPTX?\\|pdf\\|epub\\|cbz\\|fb2\\|o?xps\\|djvu\\|dvi\\|od[fgpst]\\|docx\\|xlsx?\\|pptx?\\)\\'" . doc-view-mode-maybe)
("configure\\.\\(ac\\|in\\)\\'" . autoconf-mode)
("\\.s\\(v\\|iv\\|ieve\\)\\'" . sieve-mode)
- ("BROWSE\\'" . ebrowse-tree-mode)
- ("\\.ebrowse\\'" . ebrowse-tree-mode)
("#\\*mail\\*" . mail-mode)
("\\.g\\'" . antlr-mode)
("\\.mod\\'" . m2-mode)
(defcustom Info-url-alist
'((("auth" "autotype" "bovine" "calc" "ccmode" "cl" "dbus" "dired-x"
- "ebrowse" "ede" "ediff" "edt" "efaq" "efaq-w32" "eglot" "eieio"
+ "ede" "ediff" "edt" "efaq" "efaq-w32" "eglot" "eieio"
"eintr" "elisp" "emacs" "emacs-gnutls" "emacs-mime" "epa" "erc"
"ert" "eshell" "eudc" "eww" "flymake" "forms" "gnus"
"htmlfontify" "idlwave" "ido" "info" "mairix-el" "message"
("tempo" . "autotype") ("hippie-expand" . "autotype")
("cvs" . "pcl-cvs") ("ada" . "ada-mode") "calc"
("calcAlg" . "calc") ("calcDigit" . "calc") ("calcVar" . "calc")
- "ebrowse" "eshell" "cl" "reftex" "speedbar" "widget" "woman"
+ "eshell" "cl" "reftex" "speedbar" "widget" "woman"
("mail-header" . "emacs-mime") ("mail-content" . "emacs-mime")
("mail-encode" . "emacs-mime") ("mail-decode" . "emacs-mime")
("rfc2045" . "emacs-mime")
(defconst org-info-emacs-documents
'("ada-mode" "auth" "autotype" "bovine" "calc" "ccmode" "cl" "dbus" "dired-x"
- "ebrowse" "ede" "ediff" "edt" "efaq-w32" "efaq" "eglot" "eieio" "eintr"
+ "ede" "ediff" "edt" "efaq-w32" "efaq" "eglot" "eieio" "eintr"
"elisp" "emacs-gnutls" "emacs-mime" "emacs" "epa" "erc" "ert" "eshell"
"eudc" "eww" "flymake" "forms" "gnus" "htmlfontify" "idlwave" "ido" "info"
"mairix-el" "message" "mh-e" "modus-themes" "newsticker" "nxml-mode" "octave-mode"
+++ /dev/null
-;;; ebrowse.el --- Emacs C++ class browser & tags facility -*- lexical-binding:t -*-
-
-;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
-
-;; Author: Gerd Moellmann <gerd@gnu.org>
-;; Maintainer: emacs-devel@gnu.org
-;; Keywords: C++ tags tools
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs 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 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs 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 GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; This package implements
-
-;; - A class browser for C++
-;; - A complete set of tags-like functions working on class trees
-;; - An electric buffer list showing class browser buffers only
-
-;; Documentation is found in a separate Info file.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'seq)
-(require 'view)
-(require 'ebuff-menu)
-
-(eval-when-compile
- (require 'helper))
-
-\f
-;;; User-options
-
-(defgroup ebrowse nil
- "Settings for the C++ class browser."
- :group 'tools)
-
-(defcustom ebrowse-search-path nil
- "List of directories to search for source files in a class tree.
-Elements should be directory names; nil as an element means to try
-to find source files relative to the location of the BROWSE file loaded."
- :type '(repeat (choice (const :tag "Default" nil)
- (string :tag "Directory"))))
-
-
-(defcustom ebrowse-view/find-hook nil
- "Hooks run after finding or viewing a member or class."
- :type 'hook)
-
-
-(defcustom ebrowse-not-found-hook nil
- "Hooks run when finding or viewing a member or class was not successful."
- :type 'hook)
-
-
-(defcustom ebrowse-electric-list-mode-hook nil
- "Hook called by `ebrowse-electric-position-mode'."
- :type 'hook)
-
-
-(defcustom ebrowse-max-positions 50
- "Number of markers saved on electric position stack."
- :type 'integer)
-
-
-\f
-(defgroup ebrowse-tree nil
- "Settings for class tree buffers."
- :group 'ebrowse)
-
-
-(defcustom ebrowse-tree-mode-hook nil
- "Hook run in each new tree buffer."
- :type 'hook)
-
-
-(defcustom ebrowse-tree-buffer-name "*Tree*"
- "The default name of class tree buffers."
- :type 'string)
-
-
-(defcustom ebrowse--indentation 4
- "The amount by which subclasses are indented in the tree."
- :type 'integer)
-
-
-(defcustom ebrowse-source-file-column 40
- "The column in which source file names are displayed in the tree."
- :type 'integer)
-
-
-(defcustom ebrowse-tree-left-margin 2
- "Amount of space left at the left side of the tree display.
-This space is used to display markers."
- :type 'integer)
-
-
-\f
-(defgroup ebrowse-member nil
- "Settings for member buffers."
- :group 'ebrowse)
-
-
-(defcustom ebrowse-default-declaration-column 25
- "The column in which member declarations are displayed in member buffers."
- :type 'integer)
-
-
-(defcustom ebrowse-default-column-width 25
- "The width of the columns in member buffers (short display form)."
- :type 'integer)
-
-
-(defcustom ebrowse-member-buffer-name "*Members*"
- "The name of the buffer for member display."
- :type 'string)
-
-
-(defcustom ebrowse-member-mode-hook nil
- "Run in each new member buffer."
- :type 'hook)
-
-
-\f
-(defgroup ebrowse-faces nil
- "Faces used by Ebrowse."
- :group 'ebrowse)
-
-(defface ebrowse-tree-mark
- '((((min-colors 88)) :foreground "red1")
- (t :foreground "red"))
- "Face for the mark character in the Ebrowse tree.")
-
-(defface ebrowse-root-class
- '((((min-colors 88)) :weight bold :foreground "blue1")
- (t :weight bold :foreground "blue"))
- "Face for root classes in the Ebrowse tree.")
-
-(defface ebrowse-file-name '((t :slant italic))
- "Face for filenames in the Ebrowse tree.")
-
-(defface ebrowse-default '((t))
- "Face for items in the Ebrowse tree which do not have other faces.")
-
-(defface ebrowse-member-attribute
- '((((min-colors 88)) :foreground "red1")
- (t :foreground "red"))
- "Face for member attributes.")
-
-(defface ebrowse-member-class
- '((t :foreground "purple"))
- "Face used to display the class title in member buffers.")
-
-(defface ebrowse-progress
- '((((min-colors 88)) :background "blue1")
- (t :background "blue"))
- "Face for progress indicator.")
-
-\f
-;;; Utilities.
-
-(define-obsolete-function-alias 'ebrowse-some #'seq-some "28.1")
-
-
-(define-obsolete-function-alias 'ebrowse-every #'seq-every-p "28.1")
-
-
-(defun ebrowse-position (item list &optional test)
- "Return the position of ITEM in LIST or nil if not found.
-Compare items with `eq' or TEST if specified."
- (declare (obsolete seq-position "28.1"))
- (seq-position list item (or test #'eql)))
-
-
-(defmacro ebrowse-ignoring-completion-case (&rest body)
- "Eval BODY with `completion-ignore-case' bound to t."
- (declare (indent 0) (debug t))
- `(let ((completion-ignore-case t))
- ,@body))
-
-(defmacro ebrowse-for-all-trees (spec &rest body)
- "For all trees in SPEC, eval BODY."
- (declare (indent 1) (debug ((sexp form) body)))
- (let ((spec-var (car spec))
- (array (cadr spec)))
- `(maphash (lambda (_k ,spec-var)
- (when ,spec-var
- (cl-assert (cl-typep ,spec-var 'ebrowse-ts))
- ,@body))
- ,array)))
-
-(defsubst ebrowse-set-face (start end face)
- "Set face of a region START END to FACE."
- (overlay-put (make-overlay start end) 'face face))
-
-
-(defun ebrowse-completing-read-value (prompt table initial-input)
- "Read a string in the minibuffer, with completion.
-Case is ignored in completions.
-
-PROMPT is a string to prompt with; normally it ends in a colon and a space.
-TABLE is a completion table.
-If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.
-If it is (STRING . POSITION), the initial input
-is STRING, but point is placed POSITION characters into the string."
- (ebrowse-ignoring-completion-case
- (completing-read prompt table nil t initial-input)))
-
-(defun ebrowse-rename-buffer (new-name)
- "Rename current buffer to NEW-NAME.
-If a buffer with name NEW-NAME already exists, delete it first."
- (let ((old-buffer (get-buffer new-name)))
- (unless (eq old-buffer (current-buffer))
- (when old-buffer
- (save-excursion (kill-buffer old-buffer)))
- (rename-buffer new-name))))
-
-
-(defun ebrowse-trim-string (string)
- "Return a copy of STRING with leading white space removed.
-Replace sequences of newlines with a single space."
- (when (string-match "^[ \t\n]+" string)
- (setq string (substring string (match-end 0))))
- (cl-loop while (string-match "[\n]+" string)
- finally return string do
- (setq string (replace-match " " nil t string))))
-
-
-(defun ebrowse-width-of-drawable-area ()
- "Return the width of the display area for the current buffer.
-If buffer is displayed in a window, use that window's width,
-otherwise use the current frame's width."
- (let ((window (get-buffer-window (current-buffer))))
- (if window
- (window-width window)
- (frame-width))))
-
-\f
-;;; Structure definitions
-
-;; Note: These use `(:type vector) :named' in order to match the
-;; format used in src/BROWSE.
-
-(cl-defstruct (ebrowse-hs (:type vector) :named)
- "Header structure found at the head of BROWSE files."
- ;; A version string that is compared against the version number of
- ;; the Lisp package when the file is loaded. This is done to
- ;; detect file format changes.
- version
- ;; Command line options used for producing the BROWSE file.
- command-line-options
- ;; The following slot is currently not used. It's kept to keep
- ;; the file format compatible.
- unused
- ;; A slot that is filled out after the tree is loaded. This slot is
- ;; set to a hash table mapping members to lists of classes in which
- ;; they are defined.
- member-table)
-
-
-(cl-defstruct (ebrowse-ts (:type vector) :named)
- "Tree structure.
-Following the header structure, a BROWSE file contains a number
-of `ebrowse-ts' structures, each one describing one root class of
-the class hierarchy with all its subclasses."
- ;; A `ebrowse-cs' structure describing the root class.
- class
- ;; A list of `ebrowse-ts' structures for all subclasses.
- subclasses
- ;; Lists of `ebrowse-ms' structures for each member in a group of
- ;; members.
- member-variables member-functions static-variables static-functions
- friends types
- ;; List of `ebrowse-ts' structures for base classes. This slot is
- ;; filled at load time.
- base-classes
- ;; A marker slot used in the tree buffer (can be saved back to disk.
- mark)
-
-
-(cl-defstruct (ebrowse-bs (:type vector) :named)
- "Common sub-structure.
-A common structure defining an occurrence of some name in the
-source files."
- ;; The class or member name as a string constant
- name
- ;; An optional string for the scope of nested classes or for
- ;; namespaces.
- scope
- ;; Various flags describing properties of classes/members, e.g. is
- ;; template, is const etc.
- flags
- ;; File in which the entity is found. If this is part of a
- ;; `ebrowse-ms' member description structure, and FILE is nil, then
- ;; search for the name in the SOURCE-FILE of the members class.
- file
- ;; Regular expression to search for. This slot can be a number in
- ;; which case the number is the file position at which the regular
- ;; expression is found in a separate regexp file (see the header
- ;; structure). This slot can be nil in which case the regular
- ;; expression will be generated from the class/member name.
- pattern
- ;; The buffer position at which the search for the class or member
- ;; will start.
- point)
-
-
-(cl-defstruct (ebrowse-cs (:include ebrowse-bs) (:type vector) :named)
- "Class structure.
-This is the structure stored in the CLASS slot of a `ebrowse-ts'
-structure. It describes the location of the class declaration."
- source-file)
-
-
-(cl-defstruct (ebrowse-ms (:include ebrowse-bs) (:type vector) :named)
- "Member structure.
-This is the structure describing a single member. The `ebrowse-ts'
-structure contains various lists for the different types of
-members."
- ;; Public, protected, private
- visibility
- ;; The file in which the member's definition can be found.
- definition-file
- ;; Same as PATTERN above, but for the member definition.
- definition-pattern
- ;; Same as POINT above but for member definition.
- definition-point)
-
-
-\f
-;;; Some macros to access the FLAGS slot of a MEMBER.
-
-(defsubst ebrowse-member-bit-set-p (member bit)
- "Value is non-nil if MEMBER's bit BIT is set."
- (/= 0 (logand (ebrowse-bs-flags member) bit)))
-
-
-(defsubst ebrowse-virtual-p (member)
- "Value is non-nil if MEMBER is virtual."
- (ebrowse-member-bit-set-p member 1))
-
-
-(defsubst ebrowse-inline-p (member)
- "Value is non-nil if MEMBER is inline."
- (ebrowse-member-bit-set-p member 2))
-
-
-(defsubst ebrowse-const-p (member)
- "Value is non-nil if MEMBER is const."
- (ebrowse-member-bit-set-p member 4))
-
-
-(defsubst ebrowse-pure-virtual-p (member)
- "Value is non-nil if MEMBER is a pure virtual function."
- (ebrowse-member-bit-set-p member 8))
-
-
-(defsubst ebrowse-mutable-p (member)
- "Value is non-nil if MEMBER is mutable."
- (ebrowse-member-bit-set-p member 16))
-
-
-(defsubst ebrowse-template-p (member)
- "Value is non-nil if MEMBER is a template."
- (ebrowse-member-bit-set-p member 32))
-
-
-(defsubst ebrowse-explicit-p (member)
- "Value is non-nil if MEMBER is explicit."
- (ebrowse-member-bit-set-p member 64))
-
-
-(defsubst ebrowse-throw-list-p (member)
- "Value is non-nil if MEMBER has a throw specification."
- (ebrowse-member-bit-set-p member 128))
-
-
-(defsubst ebrowse-extern-c-p (member)
- "Value is non-nil if MEMBER is `extern \"C\"'."
- (ebrowse-member-bit-set-p member 256))
-
-
-(defsubst ebrowse-define-p (member)
- "Value is non-nil if MEMBER is a define."
- (ebrowse-member-bit-set-p member 512))
-
-
-(defconst ebrowse-version-string "ebrowse 5.0"
- "Version string expected in BROWSE files.")
-
-
-(defconst ebrowse-globals-name "*Globals*"
- "The name used for the surrogate class.containing global entities.
-This must be the same that `ebrowse' uses.")
-
-
-(defvar-local ebrowse--last-regexp nil
- "Last regular expression searched for in tree and member buffers.
-Each tree and member buffer maintains its own search history.")
-
-(defconst ebrowse-member-list-accessors
- (list #'ebrowse-ts-member-variables
- #'ebrowse-ts-member-functions
- #'ebrowse-ts-static-variables
- #'ebrowse-ts-static-functions
- #'ebrowse-ts-friends
- #'ebrowse-ts-types)
- "List of accessors for member lists.
-Each element is the symbol of an accessor function.
-The nth element must be the accessor for the nth member list
-in an `ebrowse-ts' structure.")
-
-
-;;; FIXME: Add more doc strings for the buffer-local variables below.
-
-(defvar ebrowse--tree-table nil
- "Hash-table holding all `ebrowse-ts' structures of a class tree.
-Buffer-local in Ebrowse buffers.")
-
-
-(defvar ebrowse--tags-file-name nil
- "File from which BROWSE file was loaded.
-Buffer-local in Ebrowse buffers.")
-
-
-(defvar ebrowse--header nil
- "Header structure of type `ebrowse-hs' of a class tree.
-Buffer-local in Ebrowse buffers.")
-
-
-(defvar ebrowse--frozen-flag nil
- "Non-nil means an Ebrowse buffer won't be reused.
-Buffer-local in Ebrowse buffers.")
-
-
-(defvar ebrowse--show-file-names-flag nil
- "Non-nil means show file names in a tree buffer.
-Buffer-local in Ebrowse tree buffers.")
-
-
-(defvar ebrowse--long-display-flag nil
- "Non-nil means show members in long display form.
-Buffer-local in Ebrowse member buffers.")
-
-
-(defvar ebrowse--n-columns nil
- "Number of columns to display for short member display form.
-Buffer-local in Ebrowse member buffers.")
-
-
-(defvar ebrowse--column-width nil
- "Width of a columns to display for short member display form.
-Buffer-local in Ebrowse member buffers.")
-
-
-(defvar ebrowse--virtual-display-flag nil
- "Non-nil means display virtual members in a member buffer.
-Buffer-local in Ebrowse member buffers.")
-
-
-(defvar ebrowse--inline-display-flag nil
- "Non-nil means display inline members in a member buffer.
-Buffer-local in Ebrowse member buffers.")
-
-
-(defvar ebrowse--const-display-flag nil
- "Non-nil means display const members in a member buffer.
-Buffer-local in Ebrowse member buffers.")
-
-
-(defvar ebrowse--pure-display-flag nil
- "Non-nil means display pure virtual members in a member buffer.
-Buffer-local in Ebrowse member buffers.")
-
-
-(defvar ebrowse--filters nil
- "Filter for display of public, protected, and private members.
-This is a vector of three elements. An element nil means the
-corresponding members are not shown.
-Buffer-local in Ebrowse member buffers.")
-
-
-(defvar ebrowse--show-inherited-flag nil
- "Non-nil means display inherited members in a member buffer.
-Buffer-local in Ebrowse member buffers.")
-
-
-(defvar ebrowse--attributes-flag nil
- "Non-nil means display member attributes in a member buffer.
-Buffer-local in Ebrowse member buffers.")
-
-
-(defvar ebrowse--source-regexp-flag nil
- "Non-nil means display member regexps in a member buffer.
-Buffer-local in Ebrowse member buffers.")
-
-
-(defvar ebrowse--displayed-class nil
- "Class displayed in a member buffer, a `ebrowse-ts' structure.
-Buffer-local in Ebrowse member buffers.")
-
-
-(defvar ebrowse--accessor nil
- "Member list displayed in a member buffer.
-This is a symbol whose function definition is an accessor for the
-member list in `ebrowse-cs' structures.
-Buffer-local in Ebrowse member buffers.")
-
-
-(defvar ebrowse--member-list nil
- "The list of `ebrowse-ms' structures displayed in a member buffer.
-Buffer-local in Ebrowse member buffers.")
-
-
-(defvar ebrowse--decl-column nil
- "Column in which declarations are displayed in member buffers.
-Buffer-local in Ebrowse member buffers.")
-
-
-(defvar ebrowse--frame-configuration nil
- "Frame configuration saved when viewing a class/member in another frame.
-Buffer-local in Ebrowse buffers.")
-
-
-(defvar ebrowse--view-exit-action nil
- "Action to perform after viewing a class/member.
-Either `kill-buffer' or nil.
-Buffer-local in Ebrowse buffers.")
-
-
-(defvar ebrowse--tree nil
- "Class tree.
-Buffer-local in Ebrowse buffers.")
-
-
-;;; Temporaries used to communicate with `ebrowse-find-pattern'.
-
-(defvar ebrowse-temp-position-to-view nil)
-(defvar ebrowse-temp-info-to-view nil)
-
-
-(defvar ebrowse-tree-mode-map ()
- "The keymap used in tree mode buffers.")
-
-
-(defvar ebrowse--member-mode-strings nil
- "Strings displayed in the mode line of member buffers.")
-
-
-(defvar ebrowse-member-mode-map ()
- "The keymap used in the member buffers.")
-
-
-;;; Define mode line titles for each member list.
-
-(put 'ebrowse-ts-member-variables 'ebrowse-title "Member Variables")
-(put 'ebrowse-ts-member-functions 'ebrowse-title "Member Functions")
-(put 'ebrowse-ts-static-variables 'ebrowse-title "Static Variables")
-(put 'ebrowse-ts-static-functions 'ebrowse-title "Static Functions")
-(put 'ebrowse-ts-friends 'ebrowse-title "Friends")
-(put 'ebrowse-ts-types 'ebrowse-title "Types")
-
-(put 'ebrowse-ts-member-variables 'ebrowse-global-title "Global Variables")
-(put 'ebrowse-ts-member-functions 'ebrowse-global-title "Global Functions")
-(put 'ebrowse-ts-static-variables 'ebrowse-global-title "Static Variables")
-(put 'ebrowse-ts-static-functions 'ebrowse-global-title "Static Functions")
-(put 'ebrowse-ts-friends 'ebrowse-global-title "Defines")
-(put 'ebrowse-ts-types 'ebrowse-global-title "Types")
-
-
-\f
-;;; Operations on `ebrowse-ts' structures
-
-(defun ebrowse-files-table (&optional marked-only)
- "Return a hash table containing all files mentioned in the current tree.
-The tree is expected in the buffer-local variable `ebrowse--tree-table'.
-MARKED-ONLY non-nil means include marked classes only."
- (let ((files (make-hash-table :test 'equal))
- (i -1))
- (ebrowse-for-all-trees (tree ebrowse--tree-table)
- (when (or (not marked-only) (ebrowse-ts-mark tree))
- (let ((class (ebrowse-ts-class tree)))
- (when (zerop (% (cl-incf i) 20))
- (ebrowse-show-progress "Preparing file list" (zerop i)))
- ;; Add files mentioned in class description
- (let ((source-file (ebrowse-cs-source-file class))
- (file (ebrowse-cs-file class)))
- (when source-file
- (puthash source-file source-file files))
- (when file
- (puthash file file files))
- ;; For all member lists in this class
- (dolist (accessor ebrowse-member-list-accessors)
- (cl-loop for m in (funcall accessor tree)
- for file = (ebrowse-ms-file m)
- for def-file = (ebrowse-ms-definition-file m) do
- (when file
- (puthash file file files))
- (when def-file
- (puthash def-file def-file files))))))))
- files))
-
-
-(defun ebrowse-files-list (&optional marked-only)
- "Return a list containing all files mentioned in a tree.
-MARKED-ONLY non-nil means include marked classes only."
- (let (list)
- (maphash (lambda (file _dummy) (push file list))
- (ebrowse-files-table marked-only))
- list))
-
-
-(cl-defun ebrowse-marked-classes-p ()
- "Value is non-nil if any class in the current class tree is marked."
- (ebrowse-for-all-trees (tree ebrowse--tree-table)
- (when (ebrowse-ts-mark tree)
- (cl-return-from ebrowse-marked-classes-p tree))))
-
-
-(defsubst ebrowse-globals-tree-p (tree)
- "Return t if TREE is the one for global entities."
- (string= (ebrowse-bs-name (ebrowse-ts-class tree))
- ebrowse-globals-name))
-
-
-(defsubst ebrowse-qualified-class-name (class)
- "Return the name of CLASS with scope prepended, if any."
- (if (ebrowse-cs-scope class)
- (concat (ebrowse-cs-scope class) "::" (ebrowse-cs-name class))
- (ebrowse-cs-name class)))
-
-
-(defun ebrowse-tree-table-as-alist (&optional qualified-names-p)
- "Return an alist describing all classes in a tree.
-Each elements in the list has the form (CLASS-NAME . TREE).
-CLASS-NAME is the name of the class. TREE is the
-class tree whose root is QUALIFIED-CLASS-NAME.
-QUALIFIED-NAMES-P non-nil means return qualified names as CLASS-NAME.
-The class tree is found in the buffer-local variable `ebrowse--tree-table'."
- (let (alist)
- (if qualified-names-p
- (ebrowse-for-all-trees (tree ebrowse--tree-table)
- (setq alist
- (cl-acons (ebrowse-qualified-class-name
- (ebrowse-ts-class tree))
- tree alist)))
- (ebrowse-for-all-trees (tree ebrowse--tree-table)
- (setq alist
- (cl-acons (ebrowse-cs-name (ebrowse-ts-class tree))
- tree alist))))
- alist))
-
-
-(defun ebrowse-sort-tree-list (list)
- "Sort a LIST of `ebrowse-ts' structures by qualified class names."
- (sort list
- (lambda (a b)
- (string< (ebrowse-qualified-class-name (ebrowse-ts-class a))
- (ebrowse-qualified-class-name (ebrowse-ts-class b))))))
-
-
-(defun ebrowse-class-in-tree (class tree)
- "Search for a class with name CLASS in TREE.
-If CLASS is found, return the tail of TREE starting at CLASS. This function
-is used during the load phase where classes appended to a file replace older
-class information."
- (let ((tclass (ebrowse-ts-class class))
- found)
- (while (and tree (not found))
- (let ((root-ptr tree))
- (when (string= (ebrowse-qualified-class-name (ebrowse-ts-class (car root-ptr)))
- (ebrowse-qualified-class-name tclass))
- (setq found root-ptr))
- (setq tree (cdr tree))))
- found))
-
-
-(defun ebrowse-base-classes (tree)
- "Return list of base-classes of TREE by searching subclass lists.
-This function must be used instead of the struct slot
-`base-classes' to access the base-class list directly because it
-computes this information lazily."
- (or (ebrowse-ts-base-classes tree)
- (setf (ebrowse-ts-base-classes tree)
- (cl-loop with to-search = (list tree)
- with result = nil
- as search = (pop to-search)
- while search finally return result
- do (ebrowse-for-all-trees (ti ebrowse--tree-table)
- (when (memq search (ebrowse-ts-subclasses ti))
- (unless (memq ti result)
- (setq result (nconc result (list ti))))
- (push ti to-search)))))))
-
-
-(defun ebrowse-direct-base-classes (tree)
- "Return the list of direct super classes of TREE."
- (let (result)
- (dolist (s (ebrowse-base-classes tree))
- (when (memq tree (ebrowse-ts-subclasses s))
- (setq result (cons s result))))
- result))
-
-
-\f
-;;; Operations on MEMBER structures/lists
-
-(defun ebrowse-name/accessor-alist (tree accessor)
- "Return an alist containing all members of TREE in group ACCESSOR.
-ACCESSOR is the accessor function for the member list.
-Elements of the result have the form (NAME . ACCESSOR), where NAME
-is the member name."
- (cl-loop for member in (funcall accessor tree)
- collect (cons (ebrowse-ms-name member) accessor)))
-
-
-(defun ebrowse-name/accessor-alist-for-visible-members ()
- "Return an alist describing all members visible in the current buffer.
-Each element of the list has the form (MEMBER-NAME . ACCESSOR),
-where MEMBER-NAME is the member's name, and ACCESSOR is the struct
-accessor with which the member's list can be accessed in an `ebrowse-ts'
-structure. The list includes inherited members if these are visible."
- (let* ((list (ebrowse-name/accessor-alist ebrowse--displayed-class
- ebrowse--accessor)))
- (if ebrowse--show-inherited-flag
- (nconc list
- (cl-loop for tree in (ebrowse-base-classes
- ebrowse--displayed-class)
- nconc (ebrowse-name/accessor-alist
- tree ebrowse--accessor)))
- list)))
-
-
-(defun ebrowse-name/accessor-alist-for-class-members ()
- "Like `ebrowse-name/accessor-alist-for-visible-members'.
-This function includes members of base classes if base class members
-are visible in the buffer."
- (let (list)
- (dolist (func ebrowse-member-list-accessors list)
- (setq list (nconc list (ebrowse-name/accessor-alist
- ebrowse--displayed-class func)))
- (when ebrowse--show-inherited-flag
- (dolist (class (ebrowse-base-classes ebrowse--displayed-class))
- (setq list
- (nconc list (ebrowse-name/accessor-alist class func))))))))
-
-\f
-;;; Progress indication
-
-(defvar ebrowse-n-boxes 0)
-(defconst ebrowse-max-boxes 60)
-
-(defun ebrowse-show-progress (title &optional start)
- "Display a progress indicator.
-TITLE is the title of the progress message. START non-nil means
-this is the first progress message displayed."
- (let (message-log-max)
- (when start (setq ebrowse-n-boxes 0))
- (setq ebrowse-n-boxes (mod (1+ ebrowse-n-boxes) ebrowse-max-boxes))
- (message "%s: %s" title
- (propertize (make-string ebrowse-n-boxes
- (if (display-color-p) ?\ ?+))
- 'face 'ebrowse-progress))))
-
-\f
-;;; Reading a tree from disk
-
-(defun ebrowse-read ()
- "Read `ebrowse-hs' and `ebrowse-ts' structures in the current buffer.
-Return a list (HEADER TREE) where HEADER is the file header read
-and TREE is a list of `ebrowse-ts' structures forming the class tree."
- (let ((header (condition-case nil
- (read (current-buffer))
- (error (error "No Ebrowse file header found"))))
- tree)
- ;; Check file format.
- (unless (ebrowse-hs-p header)
- (error "No Ebrowse file header found"))
- (unless (string= (ebrowse-hs-version header) ebrowse-version-string)
- (error "File has wrong version `%s' (`%s' expected)"
- (ebrowse-hs-version header) ebrowse-version-string))
- ;; Read Lisp objects. Temporarily increase `gc-cons-threshold' to
- ;; prevent a GC that would not free any memory.
- (let ((gc-cons-threshold (max gc-cons-threshold 2000000)))
- (while (not (progn (skip-chars-forward " \t\n") (eobp)))
- (let* ((root (read (current-buffer)))
- (old-root-ptr (ebrowse-class-in-tree root tree)))
- (ebrowse-show-progress "Reading data" (null tree))
- (if old-root-ptr
- (setcar old-root-ptr root)
- (push root tree)))))
- (garbage-collect)
- (list header tree)))
-
-
-(defun ebrowse-revert-tree-buffer-from-file (_ignore-auto-save noconfirm)
- "Function installed as `revert-buffer-function' in tree buffers.
-See that variable's documentation for the meaning of IGNORE-AUTO-SAVE and
-NOCONFIRM."
- (when (or noconfirm (yes-or-no-p "Revert tree from disk? "))
- (mapc #'kill-buffer (ebrowse-same-tree-member-buffer-list))
- (erase-buffer)
- (with-no-warnings
- (insert-file (or buffer-file-name ebrowse--tags-file-name)))
- (ebrowse-tree-mode)
- (current-buffer)))
-
-
-(defun ebrowse-create-tree-buffer (tree tags-file header classes pop)
- "Create a new tree buffer for tree TREE.
-The tree was loaded from file TAGS-FILE.
-HEADER is the header structure of the file.
-CLASSES is a hash-table with an entry for each class in the tree.
-POP non-nil means popup the buffer up at the end.
-Return the buffer created."
- (let ((name ebrowse-tree-buffer-name))
- (set-buffer (get-buffer-create name))
- (ebrowse-tree-mode)
- (setq ebrowse--tree tree
- ebrowse--tags-file-name tags-file
- ebrowse--tree-table classes
- ebrowse--header header
- ebrowse--frozen-flag nil)
- (ebrowse-redraw-tree)
- (set-buffer-modified-p nil)
- (pcase pop
- ('switch (switch-to-buffer name))
- ('pop (pop-to-buffer name)))
- (current-buffer)))
-
-
-\f
-;;; Operations for member tables
-
-(defun ebrowse-fill-member-table ()
- "Return a hash table holding all members of all classes in the current tree.
-
-For each member, a symbol is added to the table. Members are
-extracted from the buffer-local tree `ebrowse--tree-table'.
-
-Each symbol has its property `ebrowse-info' set to a list (TREE MEMBER-LIST
-MEMBER) where TREE is the tree in which the member is defined,
-MEMBER-LIST is a symbol describing the member list in which the member
-is found, and MEMBER is a MEMBER structure describing the member.
-
-The slot `member-table' of the buffer-local header structure of
-type `ebrowse-hs' is set to the resulting table."
- (let ((members (make-hash-table :test 'equal))
- (i -1))
- (setf (ebrowse-hs-member-table ebrowse--header) nil)
- (garbage-collect)
- ;; For all classes...
- (ebrowse-for-all-trees (c ebrowse--tree-table)
- (when (zerop (% (cl-incf i) 10))
- (ebrowse-show-progress "Preparing member lookup" (zerop i)))
- (dolist (f ebrowse-member-list-accessors)
- (dolist (m (funcall f c))
- (push (list c f m) (gethash (ebrowse-ms-name m) members)))))
- (setf (ebrowse-hs-member-table ebrowse--header) members)))
-
-
-(defun ebrowse-member-table (header)
- "Return the member table. Build it if it hasn't been set up yet.
-HEADER is the tree header structure of the class tree."
- (when (null (ebrowse-hs-member-table header))
- (cl-loop for buffer in (ebrowse-browser-buffer-list)
- until (eq header (buffer-local-value 'ebrowse--header buffer))
- finally do
- (with-current-buffer buffer
- (ebrowse-fill-member-table))))
- (ebrowse-hs-member-table header))
-
-
-\f
-;;; Operations on TREE tables
-
-(defun ebrowse-build-tree-table (tree)
- "Make sure every class in TREE is represented by a unique object.
-Build hash table of all classes in TREE."
- (let ((classes (make-hash-table :test #'equal)))
- ;; Add root classes...
- (cl-loop for root in tree
- do (let ((name (ebrowse-qualified-class-name
- (ebrowse-ts-class root))))
- (unless (gethash name classes)
- (setf (gethash name classes) root))))
- ;; Process subclasses
- (ebrowse-insert-supers tree classes)
- classes))
-
-
-(defun ebrowse-insert-supers (tree classes)
- "Build base class lists in class tree TREE.
-CLASSES is an obarray used to collect classes.
-
-Helper function for `ebrowse-build-tree-table'. Base classes should
-be ordered so that immediate base classes come first, then the base
-class of the immediate base class and so on. This means that we must
-construct the base-class list top down with adding each level at the
-beginning of the base-class list.
-
-We have to be cautious here not to end up in an infinite recursion
-if for some reason a circle is in the inheritance graph."
- (cl-loop for class in tree
- as subclasses = (ebrowse-ts-subclasses class) do
- ;; Make sure every class is represented by a unique object
- (cl-loop for subclass on subclasses
- do
- (let ((name (ebrowse-qualified-class-name
- (ebrowse-ts-class (car subclass)))))
- ;; Replace the subclass tree with the one found in
- ;; CLASSES if there is already an entry for that class
- ;; in it. Otherwise make a new entry.
- ;;
- ;; CAVEAT: If by some means (e.g., use of the
- ;; preprocessor in class declarations, a name is marked
- ;; as a subclass of itself on some path, we would end up
- ;; in an endless loop. We have to omit subclasses from
- ;; the recursion that already have been processed.
- (if (gethash name classes)
- (setf (car subclass) (gethash name classes))
- (setf (gethash name classes) (car subclass)))))
- ;; Process subclasses
- (ebrowse-insert-supers subclasses classes)))
-
-\f
-;;; Tree buffers
-
-(unless ebrowse-tree-mode-map
- (let ((map (make-keymap)))
- (setf ebrowse-tree-mode-map map)
- (suppress-keymap map)
-
- (when (display-mouse-p)
- (define-key map [down-mouse-3] 'ebrowse-mouse-3-in-tree-buffer)
- (define-key map [mouse-2] 'ebrowse-mouse-2-in-tree-buffer)
- (define-key map [down-mouse-1] 'ebrowse-mouse-1-in-tree-buffer))
-
- (let ((map1 (make-sparse-keymap)))
- (suppress-keymap map1 t)
- (define-key map "L" map1)
- (define-key map1 "d" 'ebrowse-tree-command:show-friends)
- (define-key map1 "f" 'ebrowse-tree-command:show-member-functions)
- (define-key map1 "F" 'ebrowse-tree-command:show-static-member-functions)
- (define-key map1 "t" 'ebrowse-tree-command:show-types)
- (define-key map1 "v" 'ebrowse-tree-command:show-member-variables)
- (define-key map1 "V" 'ebrowse-tree-command:show-static-member-variables))
-
- (let ((map1 (make-sparse-keymap)))
- (suppress-keymap map1 t)
- (define-key map "M" map1)
- (define-key map1 "a" 'ebrowse-mark-all-classes)
- (define-key map1 "t" 'ebrowse-toggle-mark-at-point))
-
- (let ((map1 (make-sparse-keymap)))
- (suppress-keymap map1 t)
- (define-key map "T" map1)
- (define-key map1 "f" 'ebrowse-toggle-file-name-display)
- (define-key map1 "s" 'ebrowse-show-file-name-at-point)
- (define-key map1 "w" 'ebrowse-set-tree-indentation)
- (define-key map "x" 'ebrowse-statistics))
-
- (define-key map "n" 'ebrowse-repeat-member-search)
- (define-key map "q" 'bury-buffer)
- (define-key map "*" 'ebrowse-expand-all)
- (define-key map "+" 'ebrowse-expand-branch)
- (define-key map "-" 'ebrowse-collapse-branch)
- (define-key map "/" 'ebrowse-read-class-name-and-go)
- (define-key map " " 'ebrowse-view-class-declaration)
- (define-key map "?" 'describe-mode)
- (define-key map "\C-i" 'ebrowse-pop/switch-to-member-buffer-for-same-tree)
- (define-key map "\C-k" 'ebrowse-remove-class-at-point)
- (define-key map "\C-l" 'ebrowse-redraw-tree)
- (define-key map "\C-m" 'ebrowse-find-class-declaration)))
-
-
-\f
-;;; Tree-mode - mode for tree buffers
-
-;;;###autoload
-(define-derived-mode ebrowse-tree-mode special-mode "Ebrowse-Tree"
- "Major mode for Ebrowse class tree buffers.
-Each line corresponds to a class in a class tree.
-Letters do not insert themselves, they are commands.
-File operations in the tree buffer work on class tree data structures.
-E.g. \\[save-buffer] writes the tree to the file it was loaded from.
-
-Tree mode key bindings:
-\\{ebrowse-tree-mode-map}"
- (let* ((ident (propertized-buffer-identification "C++ Tree"))
- (inhibit-read-only t)
- header tree)
-
- (buffer-disable-undo)
-
- (unless (zerop (buffer-size))
- (goto-char (point-min))
- (cl-multiple-value-setq (header tree) (cl-values-list (ebrowse-read)))
- (message "Sorting. Please be patient...")
- (setq tree (ebrowse-sort-tree-list tree))
- (erase-buffer)
- (message nil))
-
- (setq-local ebrowse--show-file-names-flag nil)
- (setq-local ebrowse--frozen-flag nil)
- (setq mode-line-buffer-identification ident)
- (setq buffer-read-only t)
- (add-to-invisibility-spec '(ebrowse . t))
- (setq-local revert-buffer-function #'ebrowse-revert-tree-buffer-from-file)
- (setq-local ebrowse--header header)
- (setq-local ebrowse--tree tree)
- (setq-local ebrowse--tags-file-name buffer-file-name)
- (setq-local ebrowse--tree-table (and tree (ebrowse-build-tree-table tree)))
- (setq-local ebrowse--frozen-flag nil)
-
- (add-hook 'write-file-functions #'ebrowse-write-file-hook-fn nil t)
- (modify-syntax-entry ?_ (char-to-string (char-syntax ?a)))
- (when tree
- (ebrowse-redraw-tree)
- (set-buffer-modified-p nil))))
-
-
-
-(defun ebrowse-update-tree-buffer-mode-line ()
- "Update the tree buffer mode line."
- (ebrowse-rename-buffer (if ebrowse--frozen-flag
- (ebrowse-frozen-tree-buffer-name
- ebrowse--tags-file-name)
- ebrowse-tree-buffer-name))
- (force-mode-line-update))
-
-
-\f
-;;; Removing classes from trees
-
-(defun ebrowse-remove-class-and-kill-member-buffers (tree class)
- "Remove from TREE class CLASS.
-Kill all member buffers still containing a reference to the class."
- (setf tree (delq class tree)
- (gethash (ebrowse-cs-name (ebrowse-ts-class class))
- ebrowse--tree-table)
- nil)
- (dolist (root tree)
- (setf (ebrowse-ts-subclasses root)
- (delq class (ebrowse-ts-subclasses root))
- (ebrowse-ts-base-classes root) nil)
- (ebrowse-remove-class-and-kill-member-buffers
- (ebrowse-ts-subclasses root) class))
- (ebrowse-kill-member-buffers-displaying class)
- tree)
-
-
-(defun ebrowse-remove-class-at-point (forced)
- "Remove the class point is on from the class tree.
-Do not ask for confirmation if FORCED is non-nil."
- (interactive "P")
- (let* ((class (ebrowse-tree-at-point))
- (class-name (ebrowse-cs-name (ebrowse-ts-class class)))
- (subclasses (ebrowse-ts-subclasses class)))
- (cond ((or forced
- (y-or-n-p (concat "Delete class " class-name "? ")))
- (setf ebrowse--tree (ebrowse-remove-class-and-kill-member-buffers
- ebrowse--tree class))
- (set-buffer-modified-p t)
- (message "%s %sdeleted." class-name
- (if subclasses "and derived classes " ""))
- (ebrowse-redraw-tree))
- (t (message "Aborted")))))
-
-
-\f
-;;; Marking classes in the tree buffer
-
-(defun ebrowse-toggle-mark-at-point (&optional n-times)
- "Toggle mark for class cursor is on.
-If given a numeric N-TIMES argument, mark that many classes."
- (interactive "p")
- (let (to-change)
- ;; Get the classes whose mark must be toggled. Note that
- ;; ebrowse-tree-at-point might issue an error.
- (ignore-errors
- (cl-loop repeat (or n-times 1)
- as tree = (ebrowse-tree-at-point)
- do (progn
- (setf (ebrowse-ts-mark tree) (not (ebrowse-ts-mark tree)))
- (forward-line 1)
- (push tree to-change))))
- (save-excursion
- ;; For all these classes, reverse the mark char in the display
- ;; by a regexp replace over the whole buffer. The reason for this
- ;; is that classes might have multiple base classes. If this is
- ;; the case, they are displayed more than once in the tree.
- (with-silent-modifications
- (cl-loop
- for tree in to-change
- as regexp = (concat "^.*\\b"
- (regexp-quote
- (ebrowse-cs-name (ebrowse-ts-class tree)))
- "\\b")
- do
- (goto-char (point-min))
- (while (re-search-forward regexp nil t)
- (goto-char (match-beginning 0))
- (delete-char 1)
- (insert-char (if (ebrowse-ts-mark tree) ?> ? ) 1)
- (ebrowse-set-mark-props (1- (point)) (point) tree)
- (goto-char (match-end 0))))))))
-
-
-(defun ebrowse-mark-all-classes (prefix)
- "Unmark, with PREFIX mark, all classes in the tree."
- (interactive "P")
- (ebrowse-for-all-trees (tree ebrowse--tree-table)
- (setf (ebrowse-ts-mark tree) prefix))
- (ebrowse-redraw-marks (point-min) (point-max)))
-
-
-(defun ebrowse-redraw-marks (start end)
- "Display class marker signs in the tree between START and END."
- (interactive "r")
- (save-excursion
- (with-silent-modifications
- (catch 'end
- (goto-char (point-min))
- (dolist (root ebrowse--tree)
- (ebrowse-draw-marks-fn root start end))))
- (ebrowse-update-tree-buffer-mode-line)))
-
-
-(defun ebrowse-draw-marks-fn (tree start end)
- "Display class marker signs in TREE between START and END."
- (when (>= (point) start)
- (delete-char 1)
- (insert (if (ebrowse-ts-mark tree) ?> ? ))
- (ebrowse-set-mark-props (1- (point)) (point) tree))
- (forward-line 1)
- (when (> (point) end)
- (throw 'end nil))
- (dolist (sub (ebrowse-ts-subclasses tree))
- (ebrowse-draw-marks-fn sub start end)))
-
-
-\f
-;;; File name display in tree buffers
-
-(defun ebrowse-show-file-name-at-point (prefix)
- "Show filename in the line point is in.
-With PREFIX, insert that many filenames."
- (interactive "p")
- (unless ebrowse--show-file-names-flag
- (with-silent-modifications
- (dotimes (_ prefix)
- (let ((tree (ebrowse-tree-at-point))
- start
- file-name-existing)
- (beginning-of-line)
- (skip-chars-forward " \t*a-zA-Z0-9_")
- (setq start (point)
- file-name-existing (looking-at "("))
- (delete-region start (line-end-position))
- (unless file-name-existing
- (indent-to ebrowse-source-file-column)
- (insert "(" (or (ebrowse-cs-file
- (ebrowse-ts-class tree))
- "unknown")
- ")"))
- (ebrowse-set-face start (point) 'ebrowse-file-name)
- (beginning-of-line)
- (forward-line 1))))))
-
-
-(defun ebrowse-toggle-file-name-display ()
- "Toggle display of filenames in tree buffer."
- (interactive)
- (setf ebrowse--show-file-names-flag (not ebrowse--show-file-names-flag))
- (let ((old-line (count-lines (point-min) (point))))
- (ebrowse-redraw-tree)
- (goto-char (point-min))
- (forward-line (1- old-line))))
-
-
-\f
-;;; General member and tree buffer functions
-
-(defun ebrowse-member-buffer-p (buffer)
- "Value is non-nil if BUFFER is a member buffer."
- ;; FIXME: Why not (buffer-local-value 'major-mode buffer)?
- (eq (cdr (assoc 'major-mode (buffer-local-variables buffer)))
- 'ebrowse-member-mode))
-
-
-(defun ebrowse-tree-buffer-p (buffer)
- "Value is non-nil if BUFFER is a class tree buffer."
- (eq (cdr (assoc 'major-mode (buffer-local-variables buffer)))
- 'ebrowse-tree-mode))
-
-
-(defun ebrowse-buffer-p (buffer)
- "Value is non-nil if BUFFER is a tree or member buffer."
- (memq (cdr (assoc 'major-mode (buffer-local-variables buffer)))
- '(ebrowse-tree-mode ebrowse-member-mode)))
-
-
-(defun ebrowse-browser-buffer-list ()
- "Return a list of all tree or member buffers."
- (cl-delete-if-not #'ebrowse-buffer-p (buffer-list)))
-
-
-(defun ebrowse-member-buffer-list ()
- "Return a list of all member buffers."
- (cl-delete-if-not #'ebrowse-member-buffer-p (buffer-list)))
-
-
-(defun ebrowse-tree-buffer-list ()
- "Return a list of all tree buffers."
- (cl-delete-if-not #'ebrowse-tree-buffer-p (buffer-list)))
-
-
-(defun ebrowse-known-class-trees-buffer-list ()
- "Return a list of buffers containing class trees.
-The list will contain, for each class tree loaded,
-one buffer. Prefer tree buffers over member buffers."
- (let ((buffers (nconc (ebrowse-tree-buffer-list)
- (ebrowse-member-buffer-list)))
- (set (make-hash-table))
- result)
- (dolist (buffer buffers)
- (let ((tree (buffer-local-value 'ebrowse--tree buffer)))
- (unless (gethash tree set)
- (push buffer result))
- (puthash tree t set)))
- result))
-
-
-(defun ebrowse-same-tree-member-buffer-list ()
- "Return a list of members buffers with same tree as current buffer."
- (cl-delete-if-not
- (lambda (buffer)
- (eq (buffer-local-value 'ebrowse--tree buffer)
- ebrowse--tree))
- (ebrowse-member-buffer-list)))
-
-
-\f
-(defun ebrowse-pop/switch-to-member-buffer-for-same-tree (arg)
- "Pop to the buffer displaying members.
-Switch to buffer if prefix ARG.
-If no member buffer exists, make one."
- (interactive "P")
- (let ((buf (or (cl-first (ebrowse-same-tree-member-buffer-list))
- (get-buffer ebrowse-member-buffer-name)
- (ebrowse-tree-command:show-member-functions))))
- (when buf
- (if arg
- (switch-to-buffer buf)
- (pop-to-buffer buf)))
- buf))
-
-
-(defun ebrowse-switch-to-next-member-buffer ()
- "Switch to next member buffer."
- (interactive)
- (let* ((list (ebrowse-member-buffer-list))
- (next-list (cdr (memq (current-buffer) list)))
- (next-buffer (if next-list (car next-list) (car list))))
- (if (eq next-buffer (current-buffer))
- (error "No next buffer")
- (bury-buffer)
- (switch-to-buffer next-buffer))))
-
-
-(defun ebrowse-kill-member-buffers-displaying (tree)
- "Kill all member buffers displaying TREE."
- (cl-loop for buffer in (ebrowse-member-buffer-list)
- as class = (buffer-local-value 'ebrowse--displayed-class buffer)
- when (eq class tree) do (kill-buffer buffer)))
-
-
-(defun ebrowse-frozen-tree-buffer-name (tags-file)
- "Return the buffer name of a tree which is associated TAGS-FILE."
- (concat ebrowse-tree-buffer-name " (" tags-file ")"))
-
-
-(defun ebrowse-pop-to-browser-buffer (arg)
- "Pop to a browser buffer from any other buffer.
-Pop to member buffer if no prefix ARG, to tree buffer otherwise."
- (interactive "P")
- (let ((buffer (get-buffer (if arg
- ebrowse-tree-buffer-name
- ebrowse-member-buffer-name))))
- (unless buffer
- (setq buffer
- (get-buffer (if arg
- ebrowse-member-buffer-name
- ebrowse-tree-buffer-name))))
- (unless buffer
- (error "No browser buffer found"))
- (pop-to-buffer buffer)))
-
-
-\f
-;;; Functions to hide/unhide text
-
-(defun ebrowse--hidden-p (&optional pos)
- (eq (get-char-property (or pos (point)) 'invisible) 'ebrowse))
-
-(defun ebrowse--hide (start end)
- (put-text-property start end 'invisible 'ebrowse))
-
-(defun ebrowse--unhide (start end)
- ;; FIXME: This also removes other invisible properties!
- (remove-text-properties start end '(invisible nil)))
-
-;;; Misc tree buffer commands
-
-(defun ebrowse-set-tree-indentation ()
- "Set the indentation width of the tree display."
- (interactive)
- (let ((width (string-to-number (read-string
- (format-prompt
- "Indentation"
- (int-to-string ebrowse--indentation))
- nil nil ebrowse--indentation))))
- (when (cl-plusp width)
- (setq-local ebrowse--indentation width)
- (ebrowse-redraw-tree))))
-
-
-(defun ebrowse-read-class-name-and-go (&optional class)
- "Position cursor on CLASS.
-Read a class name from the minibuffer if CLASS is nil."
- (interactive)
- (ebrowse-ignoring-completion-case
- ;; If no class specified, read the class name from mini-buffer
- (unless class
- (setf class
- (completing-read "Goto class: "
- (ebrowse-tree-table-as-alist) nil t)))
- (goto-char (point-min))
- (widen)
- (setq ebrowse--last-regexp (concat "\\b" class "\\b"))
- (if (re-search-forward ebrowse--last-regexp nil t)
- (progn
- (goto-char (match-beginning 0))
- (ebrowse-unhide-base-classes))
- (error "Not found"))))
-
-
-\f
-;;; Showing various kinds of member buffers
-
-(defun ebrowse-tree-command:show-member-variables (arg)
- "Display member variables; with prefix ARG in frozen member buffer."
- (interactive "P")
- (ebrowse-display-member-buffer #'ebrowse-ts-member-variables arg))
-
-
-(defun ebrowse-tree-command:show-member-functions (&optional arg)
- "Display member functions; with prefix ARG in frozen member buffer."
- (interactive "P")
- (ebrowse-display-member-buffer #'ebrowse-ts-member-functions arg))
-
-
-(defun ebrowse-tree-command:show-static-member-variables (arg)
- "Display static member variables; with prefix ARG in frozen member buffer."
- (interactive "P")
- (ebrowse-display-member-buffer #'ebrowse-ts-static-variables arg))
-
-
-(defun ebrowse-tree-command:show-static-member-functions (arg)
- "Display static member functions; with prefix ARG in frozen member buffer."
- (interactive "P")
- (ebrowse-display-member-buffer #'ebrowse-ts-static-functions arg))
-
-
-(defun ebrowse-tree-command:show-friends (arg)
- "Display friend functions; with prefix ARG in frozen member buffer."
- (interactive "P")
- (ebrowse-display-member-buffer #'ebrowse-ts-friends arg))
-
-
-(defun ebrowse-tree-command:show-types (arg)
- "Display types defined in a class; with prefix ARG in frozen member buffer."
- (interactive "P")
- (ebrowse-display-member-buffer #'ebrowse-ts-types arg))
-
-
-\f
-;;; Viewing or finding a class declaration
-
-(defun ebrowse-tree-at-point ()
- "Return the class structure for the class point is on."
- (or (get-text-property (point) 'ebrowse-tree)
- (error "Not on a class")))
-
-
-(cl-defun ebrowse-view/find-class-declaration (&key view where)
- "View or find the declarator of the class point is on.
-VIEW non-nil means view it. WHERE is additional position info."
- (let* ((class (ebrowse-ts-class (ebrowse-tree-at-point)))
- (file (ebrowse-cs-file class))
- (browse-struct (make-ebrowse-bs
- :name (ebrowse-cs-name class)
- :pattern (ebrowse-cs-pattern class)
- :flags (ebrowse-cs-flags class)
- :file (ebrowse-cs-file class)
- :point (ebrowse-cs-point class))))
- (ebrowse-view/find-file-and-search-pattern
- browse-struct
- (list ebrowse--header class nil)
- file
- ebrowse--tags-file-name
- view
- where)))
-
-
-(defun ebrowse-find-class-declaration (prefix)
- "Find a class declaration and position cursor on it.
-PREFIX 4 means find it in another window.
-PREFIX 5 means find it in another frame."
- (interactive "p")
- (ebrowse-view/find-class-declaration
- :view nil
- :where (cond ((= prefix 4) 'other-window)
- ((= prefix 5) 'other-frame)
- (t 'this-window))))
-
-
-(defun ebrowse-view-class-declaration (prefix)
- "View class declaration and position cursor on it.
-PREFIX 4 means view it in another window.
-PREFIX 5 means view it in another frame."
- (interactive "p")
- (ebrowse-view/find-class-declaration
- :view 'view
- :where (cond ((= prefix 4) 'other-window)
- ((= prefix 5) 'other-frame)
- (t 'this-window))))
-
-
-\f
-;;; The FIND engine
-
-(defun ebrowse-find-source-file (file tags-file)
- "Find source file FILE.
-Source files are searched for (a) relative to TAGS-FILE
-which is the path of the BROWSE file from which the class tree was loaded,
-and (b) in the directories named in `ebrowse-search-path'."
- (let (file-name
- (try-file (expand-file-name file
- (file-name-directory tags-file))))
- (if (file-readable-p try-file)
- (setq file-name try-file)
- (let ((search-in ebrowse-search-path))
- (while (and search-in
- (null file-name))
- (let ((try-file (expand-file-name file (car search-in))))
- (if (file-readable-p try-file)
- (setq file-name try-file))
- (setq search-in (cdr search-in))))))
- (unless file-name
- (error "File `%s' not found" file))
- file-name))
-
-
-(defun ebrowse-view-exit-fn (buffer)
- "Function called when exiting View mode in BUFFER.
-Restore frame configuration active before viewing the file,
-and possibly kill the viewed buffer."
- (let (exit-action original-frame-configuration)
- (with-current-buffer buffer
- (setq original-frame-configuration ebrowse--frame-configuration
- exit-action ebrowse--view-exit-action))
- ;; Delete the frame in which we viewed.
- (mapc #'delete-frame
- (cl-loop for frame in (frame-list)
- when (not (assq frame original-frame-configuration))
- collect frame))
- (when exit-action
- (funcall exit-action buffer))))
-
-
-(defun ebrowse-view-file-other-frame (file)
- "View FILE in another frame.
-The new frame is deleted when you quit viewing the file in that frame."
- (interactive "fIn other frame view file: ")
- (let ((old-frame-configuration (current-frame-configuration))
- (had-a-buf (get-file-buffer file))
- (buf-to-view (find-file-noselect file)))
- (switch-to-buffer-other-frame buf-to-view)
- (setq-local ebrowse--frame-configuration
- old-frame-configuration)
- (setq-local ebrowse--view-exit-action
- (and (not had-a-buf)
- (not (buffer-modified-p buf-to-view))
- #'kill-buffer))
- (view-mode-enter (cons (selected-window) (cons (selected-window) t))
- 'ebrowse-view-exit-fn)))
-
-(defun ebrowse-view/find-file-and-search-pattern
- (struc info file tags-file &optional view where)
- "Find or view a member or class.
-STRUC is an `ebrowse-bs' structure (or a structure including that)
-describing what to search.
-INFO is a list (HEADER MEMBER-OR-CLASS ACCESSOR). HEADER is the
-header structure of a class tree. MEMBER-OR-CLASS is either an
-`ebrowse-ms' or `ebrowse-cs' structure depending on what is searched.
-ACCESSOR is an accessor function for the member list of a member
-if MEMBER-OR-CLASS is an `ebrowse-ms'.
-FILE is the file to search the member in.
-FILE is not taken out of STRUC here because the filename in STRUC
-may be nil in which case the filename of the class description is used.
-TAGS-FILE is the name of the BROWSE file from which the
-tree was loaded.
-If VIEW is non-nil, view file else find the file.
-WHERE is either `other-window', `other-frame' or `this-window' and
-specifies where to find/view the result."
- (unless file
- (error "Sorry, no file information available for %s"
- (ebrowse-bs-name struc)))
- ;; Get the source file to view or find.
- (setf file (ebrowse-find-source-file file tags-file))
- ;; If current window is dedicated, use another frame.
- (when (window-dedicated-p)
- (setf where 'other-window))
- (cond (view
- (setf ebrowse-temp-position-to-view struc
- ebrowse-temp-info-to-view info)
- (add-hook 'view-mode-hook #'ebrowse-find-pattern)
- (pcase where
- ('other-window (view-file-other-window file))
- ('other-frame (ebrowse-view-file-other-frame file))
- (_ (view-file file))))
- (t
- (pcase where
- ('other-window (find-file-other-window file))
- ('other-frame (find-file-other-frame file))
- (_ (find-file file)))
- (ebrowse-find-pattern struc info))))
-
-
-(defun ebrowse-symbol-regexp (name)
- "Generate a suitable regular expression for a member or class NAME.
-This is `regexp-quote' for most symbols, except for operator names
-which may contain whitespace. For these symbols, replace white
-space in the symbol name (generated by BROWSE) with a regular
-expression matching any number of whitespace characters."
- (cl-loop with regexp = (regexp-quote name)
- with start = 0
- finally return regexp
- while (string-match "[ \t]+" regexp start)
- do (setq regexp (concat (substring regexp 0 (match-beginning 0))
- "[ \t]*"
- (substring regexp (match-end 0)))
- start (+ (match-beginning 0) 5))))
-
-
-(defun ebrowse-class-declaration-regexp (name)
- "Construct a regexp for a declaration of class NAME."
- (concat "^[ \t]*\\(template[ \t\n]*<.*>\\)?"
- "[ \t\n]*\\(class\\|struct\\|union\\).*\\S_"
- (ebrowse-symbol-regexp name)
- "\\S_"))
-
-
-(defun ebrowse-variable-declaration-regexp (name)
- "Construct a regexp for matching a variable NAME."
- (concat "\\S_" (ebrowse-symbol-regexp name) "\\S_"))
-
-
-(defun ebrowse-function-declaration/definition-regexp (name)
- "Construct a regexp for matching a function NAME."
- (concat "^[a-zA-Z0-9_:*&<>, \t]*\\S_"
- (ebrowse-symbol-regexp name)
- "[ \t\n]*("))
-
-
-(defun ebrowse-pp-define-regexp (name)
- "Construct a regexp matching a define of NAME."
- (concat "^[ \t]*#[ \t]*define[ \t]+" (regexp-quote name)))
-
-
-(cl-defun ebrowse-find-pattern (&optional position info &aux viewing)
- "Find a pattern.
-
-This is a kluge: Ebrowse allows you to find or view a file containing
-a pattern. To be able to do a search in a viewed buffer,
-`view-mode-hook' is temporarily set to this function;
-`ebrowse-temp-position-to-view' holds what to search for.
-
-INFO is a list (TREE-HEADER TREE-OR-MEMBER MEMBER-LIST)."
- (unless position
- (remove-hook 'view-mode-hook #'ebrowse-find-pattern)
- (setf viewing t
- position ebrowse-temp-position-to-view
- info ebrowse-temp-info-to-view))
- (widen)
- (let* ((pattern (ebrowse-bs-pattern position))
- (start (ebrowse-bs-point position))
- (offset 100)
- found)
- (pcase-let ((`(,_header ,class-or-member ,member-list) info))
- ;; If no pattern is specified, construct one from the member name.
- (when (stringp pattern)
- (setq pattern (concat "^.*" (regexp-quote pattern))))
- ;; Construct a regular expression if none given.
- (unless pattern
- (cl-typecase class-or-member
- (ebrowse-ms
- (setf pattern
- (pcase member-list
- ((or 'ebrowse-ts-member-variables
- 'ebrowse-ts-static-variables
- 'ebrowse-ts-types)
- (ebrowse-variable-declaration-regexp
- (ebrowse-bs-name position)))
- (_
- (if (ebrowse-define-p class-or-member)
- (ebrowse-pp-define-regexp (ebrowse-bs-name position))
- (ebrowse-function-declaration/definition-regexp
- (ebrowse-bs-name position)))))))
- (ebrowse-cs
- (setf pattern (ebrowse-class-declaration-regexp
- (ebrowse-bs-name position))))))
- ;; Begin searching some OFFSET from the original point where the
- ;; regular expression was found by the parse, and step forward.
- ;; When there is no regular expression in the database and a
- ;; member definition/declaration was not seen by the parser,
- ;; START will be 0.
- (when (and (boundp 'ebrowse-debug)
- (symbol-value 'ebrowse-debug))
- (y-or-n-p (format "start = %d? " start))
- (y-or-n-p pattern))
- (setf found
- (cl-loop do (goto-char (max (point-min) (- start offset)))
- when (re-search-forward pattern (+ start offset) t)
- return t
- never (bobp)
- do (cl-incf offset offset)))
- (cond (found
- (beginning-of-line)
- (run-hooks 'ebrowse-view/find-hook))
- ((numberp (ebrowse-bs-pattern position))
- (goto-char start)
- (if ebrowse-not-found-hook
- (run-hooks 'ebrowse-not-found-hook)
- (message "Not found")
- (sit-for 2)))
- (t
- (if ebrowse-not-found-hook
- (run-hooks 'ebrowse-not-found-hook)
- (unless viewing
- (error "Not found"))
- (message "Not found")
- (sit-for 2)))))))
-
-\f
-;;; Drawing the tree
-
-(defun ebrowse-redraw-tree (&optional quietly)
- "Redisplay the complete tree.
-QUIETLY non-nil means don't display progress messages."
- (interactive)
- (or quietly (message "Displaying..."))
- (save-excursion
- (with-silent-modifications
- (erase-buffer)
- (ebrowse-draw-tree-fn)))
- (ebrowse-update-tree-buffer-mode-line)
- (or quietly (message nil)))
-
-
-(defun ebrowse-set-mark-props (start end tree)
- "Set text properties for class marker signs between START and END.
-TREE denotes the class shown."
- (add-text-properties
- start end
- `(mouse-face highlight ebrowse-what mark ebrowse-tree ,tree
- help-echo "double-mouse-1: mark/unmark"))
- (ebrowse-set-face start end 'ebrowse-tree-mark))
-
-
-(cl-defun ebrowse-draw-tree-fn (&aux stack1 stack2 start)
- "Display a single class and recursively its subclasses.
-This function may look weird, but this is faster than recursion."
- (setq stack1 (make-list (length ebrowse--tree) 0)
- stack2 (copy-sequence ebrowse--tree))
- (cl-loop while stack2
- as level = (pop stack1)
- as tree = (pop stack2)
- as class = (ebrowse-ts-class tree) do
- (let ((start-of-line (point))
- start-of-class-name end-of-class-name)
- ;; Insert mark
- (insert (if (ebrowse-ts-mark tree) ">" " "))
-
- ;; Indent and insert class name
- (indent-to (+ (* level ebrowse--indentation)
- ebrowse-tree-left-margin))
- (setq start (point))
- (insert (ebrowse-qualified-class-name class))
-
- ;; If template class, add <>
- (when (ebrowse-template-p class)
- (insert "<>"))
- (ebrowse-set-face start (point) (if (zerop level)
- 'ebrowse-root-class
- 'ebrowse-default))
- (setf start-of-class-name start
- end-of-class-name (point))
- ;; If filenames are to be displayed...
- (when ebrowse--show-file-names-flag
- (indent-to ebrowse-source-file-column)
- (setq start (point))
- (insert "("
- (or (ebrowse-cs-file class)
- "unknown")
- ")")
- (ebrowse-set-face start (point) 'ebrowse-file-name))
- (ebrowse-set-mark-props start-of-line (1+ start-of-line) tree)
- (add-text-properties
- start-of-class-name end-of-class-name
- `(mouse-face highlight ebrowse-what class-name
- ebrowse-tree ,tree
- help-echo "double-mouse-1: (un)expand tree; mouse-2: member functions, mouse-3: menu"))
- (insert "\n"))
- ;; Push subclasses, if any.
- (when (ebrowse-ts-subclasses tree)
- (setq stack2
- (nconc (copy-sequence (ebrowse-ts-subclasses tree)) stack2)
- stack1
- (nconc (make-list (length (ebrowse-ts-subclasses tree))
- (1+ level))
- stack1)))))
-
-
-\f
-;;; Expanding/ collapsing tree branches
-
-(defun ebrowse-expand-branch (arg)
- "Expand a sub-tree that has been previously collapsed.
-With prefix ARG, expand all sub-trees."
- (interactive "P")
- (if arg
- (ebrowse-expand-all arg)
- (ebrowse-collapse-fn nil)))
-
-
-(defun ebrowse-collapse-branch (arg)
- "Fold (do no longer display) the subclasses of the current class.
-\(The class cursor is on.) With prefix ARG, fold all trees in the buffer."
- (interactive "P")
- (if arg
- (ebrowse-expand-all (not arg))
- (ebrowse-collapse-fn t)))
-
-
-(defun ebrowse-expand-all (collapse)
- "Expand or fold all trees in the buffer.
-COLLAPSE non-nil means fold them."
- (interactive "P")
- (with-silent-modifications
- (if (not collapse)
- (ebrowse--unhide (point-min) (point-max))
- (save-excursion
- (goto-char (point-min))
- (while (progn (end-of-line) (not (eobp)))
- (when (looking-at "\n ")
- (ebrowse--hide (point) (line-end-position 2)))
- (skip-chars-forward "\n "))))))
-
-
-(defun ebrowse-unhide-base-classes ()
- "Unhide the line the cursor is on and all base classes."
- (with-silent-modifications
- (save-excursion
- (let (indent last-indent)
- (forward-line 0)
- (when (not (looking-at "\n[^ \t]"))
- (skip-chars-forward "\n \t")
- (while (and (or (null last-indent) ;first time
- (> indent 1)) ;not root class
- (re-search-backward "\n[ \t]*" nil t))
- (setf indent (- (match-end 0)
- (match-beginning 0)))
- (when (or (null last-indent)
- (< indent last-indent))
- (setf last-indent indent)
- (when (ebrowse--hidden-p)
- (ebrowse--unhide (point) (line-end-position 2))))))))))
-
-
-(defun ebrowse-hide-line (collapse)
- "Hide/show a single line in the tree.
-COLLAPSE non-nil means hide."
- (with-silent-modifications
- (funcall (if collapse #'ebrowse--hide #'ebrowse--unhide)
- (line-end-position) (line-end-position 2))))
-
-
-(defun ebrowse-collapse-fn (collapse)
- "Collapse or expand a branch of the tree.
-COLLAPSE non-nil means collapse the branch."
- (with-silent-modifications
- (save-excursion
- (beginning-of-line)
- (skip-chars-forward "> \t")
- (let ((indentation (current-column)))
- (while (and (not (eobp))
- (save-excursion
- (forward-line 1)
- (skip-chars-forward "> \t")
- (> (current-column) indentation)))
- (ebrowse-hide-line collapse)
- (forward-line 1))))))
-
-\f
-;;; Electric tree selection
-
-(defvar ebrowse-electric-list-mode-map ()
- "Keymap used in electric Ebrowse buffer list window.")
-
-
-(unless ebrowse-electric-list-mode-map
- (let ((map (make-keymap))
- (submap (make-keymap)))
- (setq ebrowse-electric-list-mode-map map)
- (fillarray (car (cdr map)) 'ebrowse-electric-list-undefined)
- (fillarray (car (cdr submap)) 'ebrowse-electric-list-undefined)
- (define-key map "\e" submap)
- (define-key map "\C-z" 'suspend-frame)
- (define-key map "\C-h" 'Helper-help)
- (define-key map "?" 'Helper-describe-bindings)
- (define-key map "\C-c" nil)
- (define-key map "\C-c\C-c" 'ebrowse-electric-list-quit)
- (define-key map "q" 'ebrowse-electric-list-quit)
- (define-key map " " 'ebrowse-electric-list-select)
- (define-key map "\C-l" 'recenter)
- (define-key map "\C-u" 'universal-argument)
- (define-key map "\C-p" 'previous-line)
- (define-key map "\C-n" 'next-line)
- (define-key map "p" 'previous-line)
- (define-key map "n" 'next-line)
- (define-key map "v" 'ebrowse-electric-view-buffer)
- (define-key map "\C-v" 'scroll-up-command)
- (define-key map "\ev" 'scroll-down-command)
- (define-key map "\e\C-v" 'scroll-other-window)
- (define-key map "\e>" 'end-of-buffer)
- (define-key map "\e<" 'beginning-of-buffer)
- (define-key map "\e>" 'end-of-buffer)))
-
-(put 'ebrowse-electric-list-mode 'mode-class 'special)
-(put 'ebrowse-electric-list-undefined 'suppress-keymap t)
-
-
-(define-derived-mode ebrowse-electric-list-mode
- fundamental-mode "Electric Position Menu"
- "Mode for electric tree list mode."
- (setq mode-line-buffer-identification "Electric Tree Menu")
- (when (memq 'mode-name mode-line-format)
- (setq mode-line-format (copy-sequence mode-line-format))
- (setcar (memq 'mode-name mode-line-format) "Tree Buffers"))
- (setq-local Helper-return-blurb "return to buffer editing")
- (setq truncate-lines t
- buffer-read-only t))
-
-
-(defun ebrowse-list-tree-buffers ()
- "Display a list of all tree buffers."
- (set-buffer (get-buffer-create "*Tree Buffers*"))
- (setq buffer-read-only nil)
- (erase-buffer)
- (insert "Tree\n" "----\n")
- (dolist (buffer (ebrowse-known-class-trees-buffer-list))
- (insert (buffer-name buffer) "\n"))
- (setq buffer-read-only t))
-
-
-;;;###autoload
-(defun ebrowse-electric-choose-tree ()
- "Return a buffer containing a tree or nil if no tree found or canceled."
- (interactive)
- (unless (car (ebrowse-known-class-trees-buffer-list))
- (error "No tree buffers"))
- (let (select buffer window)
- (save-window-excursion
- (save-window-excursion (ebrowse-list-tree-buffers))
- (setq window (Electric-pop-up-window "*Tree Buffers*")
- buffer (window-buffer window))
- (shrink-window-if-larger-than-buffer window)
- (unwind-protect
- (progn
- (set-buffer buffer)
- (ebrowse-electric-list-mode)
- (setq select
- (catch 'ebrowse-electric-list-select
- (message "<<< Press Space to bury the list >>>")
- (let ((first (progn (goto-char (point-min))
- (forward-line 2)
- (point)))
- (last (progn (goto-char (point-max))
- (forward-line -1)
- (point)))
- (goal-column 0))
- (goto-char first)
- (Electric-command-loop 'ebrowse-electric-list-select
- nil
- t
- 'ebrowse-electric-list-looper
- (cons first last))))))
- (set-buffer buffer)
- (bury-buffer buffer)
- (message nil)))
- (when select
- (set-buffer buffer)
- (setq select (ebrowse-electric-get-buffer select)))
- (kill-buffer buffer)
- select))
-
-
-(defun ebrowse-electric-list-looper (state condition)
- "Prevent cursor from moving beyond the buffer end.
-Don't let it move into the title lines.
-See `Electric-command-loop' for a description of STATE and CONDITION."
- (cond ((and condition
- (not (memq (car condition)
- '(buffer-read-only end-of-buffer
- beginning-of-buffer))))
- (signal (car condition) (cdr condition)))
- ((< (point) (car state))
- (goto-char (point-min))
- (forward-line 2))
- ((> (point) (cdr state))
- (goto-char (point-max))
- (forward-line -1)
- (if (pos-visible-in-window-p (point-max))
- (recenter -1)))))
-
-
-(defun ebrowse-electric-list-undefined ()
- "Function called for keys that are undefined."
- (interactive)
- (message "Type C-h for help, ? for commands, q to quit, Space to select.")
- (sit-for 4))
-
-
-(defun ebrowse-electric-list-quit ()
- "Discard the buffer list."
- (interactive)
- (throw 'ebrowse-electric-list-select nil))
-
-
-(defun ebrowse-electric-list-select ()
- "Select a buffer from the buffer list."
- (interactive)
- (throw 'ebrowse-electric-list-select (point)))
-
-
-(defun ebrowse-electric-get-buffer (point)
- "Get a buffer corresponding to the line POINT is in."
- (let ((index (- (count-lines (point-min) point) 2)))
- (nth index (ebrowse-known-class-trees-buffer-list))))
-
-
-;;; View a buffer for a tree.
-
-(defun ebrowse-electric-view-buffer ()
- "View buffer point is on."
- (interactive)
- (let ((buffer (ebrowse-electric-get-buffer (point))))
- (cond (buffer
- (view-buffer buffer))
- (t
- (error "Buffer no longer exists")))))
-
-
-(defun ebrowse-choose-from-browser-buffers ()
- "Read a browser buffer name from the minibuffer and return that buffer."
- (let* ((buffers (ebrowse-known-class-trees-buffer-list)))
- (if buffers
- (if (not (cl-second buffers))
- (cl-first buffers)
- (or (ebrowse-electric-choose-tree) (error "No tree buffer")))
- (let* ((insert-default-directory t)
- (file (read-file-name "Find tree: " nil nil t)))
- (save-excursion
- (find-file file))
- (find-buffer-visiting file)))))
-
-\f
-;;; Member buffers
-
-(unless ebrowse-member-mode-map
- (let ((map (make-keymap)))
- (setf ebrowse-member-mode-map map)
- (suppress-keymap map)
-
- (when (display-mouse-p)
- (define-key map [down-mouse-3] 'ebrowse-member-mouse-3)
- (define-key map [mouse-2] 'ebrowse-member-mouse-2))
-
- (let ((map1 (make-sparse-keymap)))
- (suppress-keymap map1 t)
- (define-key map "C" map1)
- (define-key map1 "b" 'ebrowse-switch-member-buffer-to-base-class)
- (define-key map1 "c" 'ebrowse-switch-member-buffer-to-any-class)
- (define-key map1 "d" 'ebrowse-switch-member-buffer-to-derived-class)
- (define-key map1 "n" 'ebrowse-switch-member-buffer-to-next-sibling-class)
- (define-key map1 "p" 'ebrowse-switch-member-buffer-to-previous-sibling-class))
-
- (let ((map1 (make-sparse-keymap)))
- (suppress-keymap map1 t)
- (define-key map "D" map1)
- (define-key map1 "a" 'ebrowse-toggle-member-attributes-display)
- (define-key map1 "b" 'ebrowse-toggle-base-class-display)
- (define-key map1 "f" 'ebrowse-freeze-member-buffer)
- (define-key map1 "l" 'ebrowse-toggle-long-short-display)
- (define-key map1 "r" 'ebrowse-toggle-regexp-display)
- (define-key map1 "w" 'ebrowse-set-member-buffer-column-width))
-
- (let ((map1 (make-sparse-keymap)))
- (suppress-keymap map1 t)
- (define-key map "F" map1)
- (let ((map2 (make-sparse-keymap)))
- (suppress-keymap map2 t)
- (define-key map1 "a" map2)
- (define-key map2 "i" 'ebrowse-toggle-private-member-filter)
- (define-key map2 "o" 'ebrowse-toggle-protected-member-filter)
- (define-key map2 "u" 'ebrowse-toggle-public-member-filter))
- (define-key map1 "c" 'ebrowse-toggle-const-member-filter)
- (define-key map1 "i" 'ebrowse-toggle-inline-member-filter)
- (define-key map1 "p" 'ebrowse-toggle-pure-member-filter)
- (define-key map1 "r" 'ebrowse-remove-all-member-filters)
- (define-key map1 "v" 'ebrowse-toggle-virtual-member-filter))
-
- (let ((map1 (make-sparse-keymap)))
- (suppress-keymap map1 t)
- (define-key map "L" map1)
- (define-key map1 "d" 'ebrowse-display-friends-member-list)
- (define-key map1 "f" 'ebrowse-display-function-member-list)
- (define-key map1 "F" 'ebrowse-display-static-functions-member-list)
- (define-key map1 "n" 'ebrowse-display-next-member-list)
- (define-key map1 "p" 'ebrowse-display-previous-member-list)
- (define-key map1 "t" 'ebrowse-display-types-member-list)
- (define-key map1 "v" 'ebrowse-display-variables-member-list)
- (define-key map1 "V" 'ebrowse-display-static-variables-member-list))
-
- (let ((map1 (make-sparse-keymap)))
- (suppress-keymap map1 t)
- (define-key map "G" map1)
- (define-key map1 "m" 'ebrowse-goto-visible-member/all-member-lists)
- (define-key map1 "n" 'ebrowse-repeat-member-search)
- (define-key map1 "v" 'ebrowse-goto-visible-member))
-
- (define-key map "f" 'ebrowse-find-member-declaration)
- (define-key map "m" 'ebrowse-switch-to-next-member-buffer)
- (define-key map "q" 'bury-buffer)
- (define-key map "t" 'ebrowse-show-displayed-class-in-tree)
- (define-key map "v" 'ebrowse-view-member-declaration)
- (define-key map " " 'ebrowse-view-member-definition)
- (define-key map "?" 'describe-mode)
- (define-key map "\C-i" 'ebrowse-pop-from-member-to-tree-buffer)
- (define-key map "\C-l" 'ebrowse-redisplay-member-buffer)
- (define-key map "\C-m" 'ebrowse-find-member-definition)))
-
-
-\f
-;;; Member mode
-
-;;;###autoload
-(define-derived-mode ebrowse-member-mode special-mode "Ebrowse-Members"
- "Major mode for Ebrowse member buffers."
- (mapc #'make-local-variable
- '(ebrowse--n-columns ;number of short columns
- ebrowse--accessor ;vars, functions, friends
- ebrowse--displayed-class ;class displayed
- ebrowse--member-list ;list of members displayed
- ebrowse--tree ;the class tree
- ebrowse--member-mode-strings ;part of mode line
- ebrowse--tags-file-name ;
- ebrowse--header
- ebrowse--tree-table
- ebrowse--frozen-flag)) ;buffer not automagically reused
- (setq-local
- mode-line-buffer-identification
- (propertized-buffer-identification "C++ Members")
- buffer-read-only t
- ebrowse--long-display-flag nil ;display with regexps?
- ebrowse--attributes-flag t ;show `virtual' and `inline'
- ebrowse--show-inherited-flag t ;include inherited members?
- ebrowse--source-regexp-flag nil ;show source regexp?
- ebrowse--filters [0 1 2] ;public, protected, private
- ebrowse--decl-column ebrowse-default-declaration-column ;display column
- ebrowse--column-width ebrowse-default-column-width ;width of columns above
- ebrowse--virtual-display-flag nil
- ebrowse--inline-display-flag nil
- ebrowse--const-display-flag nil
- ebrowse--pure-display-flag nil)
- (modify-syntax-entry ?_ (char-to-string (char-syntax ?a))))
-
-
-\f
-;;; Member mode mode line
-
-(defsubst ebrowse-class-name-displayed-in-member-buffer ()
- "Return the name of the class displayed in the member buffer."
- (ebrowse-cs-name (ebrowse-ts-class ebrowse--displayed-class)))
-
-
-(defsubst ebrowse-member-list-name ()
- "Return a string describing what is displayed in the member buffer."
- (get ebrowse--accessor (if (ebrowse-globals-tree-p ebrowse--displayed-class)
- 'ebrowse-global-title
- 'ebrowse-title)))
-
-
-(defun ebrowse-update-member-buffer-mode-line ()
- "Update the mode line of member buffers."
- (let* ((name (when ebrowse--frozen-flag
- (concat (ebrowse-class-name-displayed-in-member-buffer)
- " ")))
- (ident (concat name (ebrowse-member-list-name))))
- (setq mode-line-buffer-identification
- (propertized-buffer-identification ident))
- (ebrowse-rename-buffer (if name ident ebrowse-member-buffer-name))
- (force-mode-line-update)))
-
-
-;;; Misc member buffer commands
-
-(defun ebrowse-freeze-member-buffer ()
- "Toggle frozen status of current buffer."
- (interactive)
- (setq ebrowse--frozen-flag (not ebrowse--frozen-flag))
- (ebrowse-redisplay-member-buffer))
-
-
-(defun ebrowse-show-displayed-class-in-tree (arg)
- "Show the currently displayed class in the tree window.
-With prefix ARG, switch to the tree buffer else pop to it."
- (interactive "P")
- (let ((class-name (ebrowse-class-name-displayed-in-member-buffer)))
- (when (ebrowse-pop-from-member-to-tree-buffer arg)
- (ebrowse-read-class-name-and-go class-name))))
-
-
-(defun ebrowse-set-member-buffer-column-width ()
- "Set the column width of the member display.
-The new width is read from the minibuffer."
- (interactive)
- (let ((width (string-to-number
- (read-from-minibuffer
- (concat "Column width ("
- (int-to-string (if ebrowse--long-display-flag
- ebrowse--decl-column
- ebrowse--column-width))
- "): ")))))
- (when (cl-plusp width)
- (if ebrowse--long-display-flag
- (setq ebrowse--decl-column width)
- (setq ebrowse--column-width width))
- (ebrowse-redisplay-member-buffer))))
-
-
-(defun ebrowse-pop-from-member-to-tree-buffer (arg)
- "Pop from a member buffer to the matching tree buffer.
-Switch to the buffer if prefix ARG. If no tree buffer exists,
-make one."
- (interactive "P")
- (let ((buf (or (get-buffer (ebrowse-frozen-tree-buffer-name
- ebrowse--tags-file-name))
- (get-buffer ebrowse-tree-buffer-name)
- (ebrowse-create-tree-buffer ebrowse--tree
- ebrowse--tags-file-name
- ebrowse--header
- ebrowse--tree-table
- 'pop))))
- (and buf
- (funcall (if arg #'switch-to-buffer #'pop-to-buffer) buf))
- buf))
-
-
-\f
-;;; Switching between member lists
-
-(defun ebrowse-display-member-list-for-accessor (accessor)
- "Switch the member buffer to display the member list for ACCESSOR."
- (setf ebrowse--accessor accessor
- ebrowse--member-list (funcall accessor ebrowse--displayed-class))
- (ebrowse-redisplay-member-buffer))
-
-
-(defun ebrowse-cyclic-display-next/previous-member-list (incr)
- "Switch buffer to INCR'th next/previous list of members."
- (let ((index (seq-position ebrowse-member-list-accessors
- ebrowse--accessor
- #'eql)))
- (setf ebrowse--accessor
- (cond ((cl-plusp incr)
- (or (nth (1+ index)
- ebrowse-member-list-accessors)
- (cl-first ebrowse-member-list-accessors)))
- ((cl-minusp incr)
- (or (and (>= (cl-decf index) 0)
- (nth index
- ebrowse-member-list-accessors))
- (cl-first (last ebrowse-member-list-accessors))))))
- (ebrowse-display-member-list-for-accessor ebrowse--accessor)))
-
-
-(defun ebrowse-display-next-member-list ()
- "Switch buffer to next member list."
- (interactive)
- (ebrowse-cyclic-display-next/previous-member-list 1))
-
-
-(defun ebrowse-display-previous-member-list ()
- "Switch buffer to previous member list."
- (interactive)
- (ebrowse-cyclic-display-next/previous-member-list -1))
-
-
-(defun ebrowse-display-function-member-list ()
- "Display the list of member functions."
- (interactive)
- (ebrowse-display-member-list-for-accessor #'ebrowse-ts-member-functions))
-
-
-(defun ebrowse-display-variables-member-list ()
- "Display the list of member variables."
- (interactive)
- (ebrowse-display-member-list-for-accessor #'ebrowse-ts-member-variables))
-
-
-(defun ebrowse-display-static-variables-member-list ()
- "Display the list of static member variables."
- (interactive)
- (ebrowse-display-member-list-for-accessor #'ebrowse-ts-static-variables))
-
-
-(defun ebrowse-display-static-functions-member-list ()
- "Display the list of static member functions."
- (interactive)
- (ebrowse-display-member-list-for-accessor #'ebrowse-ts-static-functions))
-
-
-(defun ebrowse-display-friends-member-list ()
- "Display the list of friends."
- (interactive)
- (ebrowse-display-member-list-for-accessor #'ebrowse-ts-friends))
-
-
-(defun ebrowse-display-types-member-list ()
- "Display the list of types."
- (interactive)
- (ebrowse-display-member-list-for-accessor #'ebrowse-ts-types))
-
-
-\f
-;;; Filters and other display attributes
-
-(defun ebrowse-toggle-member-attributes-display ()
- "Toggle display of `virtual', `inline', `const' etc."
- (interactive)
- (setq ebrowse--attributes-flag (not ebrowse--attributes-flag))
- (ebrowse-redisplay-member-buffer))
-
-
-(defun ebrowse-toggle-base-class-display ()
- "Toggle the display of members inherited from base classes."
- (interactive)
- (setf ebrowse--show-inherited-flag (not ebrowse--show-inherited-flag))
- (ebrowse-redisplay-member-buffer))
-
-
-(defun ebrowse-toggle-pure-member-filter ()
- "Toggle display of pure virtual members."
- (interactive)
- (setf ebrowse--pure-display-flag (not ebrowse--pure-display-flag))
- (ebrowse-redisplay-member-buffer))
-
-
-(defun ebrowse-toggle-const-member-filter ()
- "Toggle display of const members."
- (interactive)
- (setf ebrowse--const-display-flag (not ebrowse--const-display-flag))
- (ebrowse-redisplay-member-buffer))
-
-
-(defun ebrowse-toggle-inline-member-filter ()
- "Toggle display of inline members."
- (interactive)
- (setf ebrowse--inline-display-flag (not ebrowse--inline-display-flag))
- (ebrowse-redisplay-member-buffer))
-
-
-(defun ebrowse-toggle-virtual-member-filter ()
- "Toggle display of virtual members."
- (interactive)
- (setf ebrowse--virtual-display-flag (not ebrowse--virtual-display-flag))
- (ebrowse-redisplay-member-buffer))
-
-
-(defun ebrowse-remove-all-member-filters ()
- "Remove all filters."
- (interactive)
- (dotimes (i 3)
- (aset ebrowse--filters i i))
- (setq ebrowse--pure-display-flag nil
- ebrowse--const-display-flag nil
- ebrowse--virtual-display-flag nil
- ebrowse--inline-display-flag nil)
- (ebrowse-redisplay-member-buffer))
-
-
-(defun ebrowse-toggle-public-member-filter ()
- "Toggle visibility of public members."
- (interactive)
- (ebrowse-set-member-access-visibility 0)
- (ebrowse-redisplay-member-buffer))
-
-
-(defun ebrowse-toggle-protected-member-filter ()
- "Toggle visibility of protected members."
- (interactive)
- (ebrowse-set-member-access-visibility 1)
- (ebrowse-redisplay-member-buffer))
-
-
-(defun ebrowse-toggle-private-member-filter ()
- "Toggle visibility of private members."
- (interactive)
- (ebrowse-set-member-access-visibility 2)
- (ebrowse-redisplay-member-buffer))
-
-
-(defun ebrowse-set-member-access-visibility (vis)
- (setf (aref ebrowse--filters vis)
- (if (aref ebrowse--filters vis) nil vis)))
-
-
-(defun ebrowse-toggle-long-short-display ()
- "Toggle between long and short display form of member buffers."
- (interactive)
- (setf ebrowse--long-display-flag (not ebrowse--long-display-flag))
- (ebrowse-redisplay-member-buffer))
-
-
-(defun ebrowse-toggle-regexp-display ()
- "Toggle declaration/definition regular expression display.
-Used in member buffers showing the long display form."
- (interactive)
- (setf ebrowse--source-regexp-flag (not ebrowse--source-regexp-flag))
- (ebrowse-redisplay-member-buffer))
-
-
-\f
-;;; Viewing/finding members
-
-(defun ebrowse-find-member-definition (&optional prefix)
- "Find the file containing a member definition.
-With PREFIX 4. find file in another window, with prefix 5
-find file in another frame."
- (interactive "p")
- (ebrowse-view/find-member-declaration/definition prefix nil t))
-
-
-(defun ebrowse-view-member-definition (prefix)
- "View the file containing a member definition.
-With PREFIX 4. find file in another window, with prefix 5
-find file in another frame."
- (interactive "p")
- (ebrowse-view/find-member-declaration/definition prefix t t))
-
-
-(defun ebrowse-find-member-declaration (prefix)
- "Find the file containing a member's declaration.
-With PREFIX 4. find file in another window, with prefix 5
-find file in another frame."
- (interactive "p")
- (ebrowse-view/find-member-declaration/definition prefix nil))
-
-
-(defun ebrowse-view-member-declaration (prefix)
- "View the file containing a member's declaration.
-With PREFIX 4. find file in another window, with prefix 5
-find file in another frame."
- (interactive "p")
- (ebrowse-view/find-member-declaration/definition prefix t))
-
-
-(cl-defun ebrowse-view/find-member-declaration/definition
- (prefix view &optional definition info header tags-file)
- "Find or view a member declaration or definition.
-With PREFIX 4. find file in another window, with prefix 5
-find file in another frame.
-DEFINITION non-nil means find the definition, otherwise find the
-declaration.
-INFO is a list (TREE ACCESSOR MEMBER) describing the member to
-search.
-TAGS-FILE is the file name of the BROWSE file."
- (unless header
- (setq header ebrowse--header))
- (unless tags-file
- (setq tags-file ebrowse--tags-file-name))
- (let (tree member accessor file on-class
- (where (if (= prefix 4) 'other-window
- (if (= prefix 5) 'other-frame 'this-window))))
- ;; If not given as parameters, get the necessary information
- ;; out of the member buffer.
- (if info
- (setq tree (cl-first info)
- accessor (cl-second info)
- member (cl-third info))
- (cl-multiple-value-setq (tree member on-class)
- (cl-values-list (ebrowse-member-info-from-point)))
- (setq accessor ebrowse--accessor))
- ;; View/find class if on a line containing a class name.
- (when on-class
- (cl-return-from ebrowse-view/find-member-declaration/definition
- (ebrowse-view/find-file-and-search-pattern
- (ebrowse-ts-class tree)
- (list ebrowse--header (ebrowse-ts-class tree) nil)
- (ebrowse-cs-file (ebrowse-ts-class tree))
- tags-file view where)))
- ;; For some member lists, it doesn't make sense to search for
- ;; a definition. If this is requested, silently search for the
- ;; declaration.
- (when (and definition
- (eq accessor 'ebrowse-ts-member-variables))
- (setq definition nil))
- ;; Construct a suitable `browse' struct for definitions.
- (when definition
- (setf member (make-ebrowse-ms
- :name (ebrowse-ms-name member)
- :file (ebrowse-ms-definition-file member)
- :pattern (ebrowse-ms-definition-pattern
- member)
- :flags (ebrowse-ms-flags member)
- :point (ebrowse-ms-definition-point
- member))))
- ;; When no file information in member, use that of the class
- (setf file (or (ebrowse-ms-file member)
- (if definition
- (ebrowse-cs-source-file (ebrowse-ts-class tree))
- (ebrowse-cs-file (ebrowse-ts-class tree)))))
- ;; When we have no regular expressions in the database the only
- ;; indication that the parser hasn't seen a definition/declaration
- ;; is that the search start point will be zero.
- (if (or (null file) (zerop (ebrowse-ms-point member)))
- (if (y-or-n-p (concat "No information about "
- (if definition "definition" "declaration")
- ". Search for "
- (if definition "declaration" "definition")
- " of `"
- (ebrowse-ms-name member)
- "'? "))
- (progn
- (message nil)
- ;; Recurse with new info.
- (ebrowse-view/find-member-declaration/definition
- prefix view (not definition) info header tags-file))
- (error "Search canceled"))
- ;; Find that thing.
- (ebrowse-view/find-file-and-search-pattern
- (make-ebrowse-bs :name (ebrowse-ms-name member)
- :pattern (ebrowse-ms-pattern member)
- :file (ebrowse-ms-file member)
- :flags (ebrowse-ms-flags member)
- :point (ebrowse-ms-point member))
- (list header member accessor)
- file
- tags-file
- view
- where))))
-
-
-\f
-;;; Drawing the member buffer
-
-(defun ebrowse-redisplay-member-buffer ()
- "Force buffer redisplay."
- (interactive)
- (let ((display-fn (if ebrowse--long-display-flag
- #'ebrowse-draw-member-long-fn
- #'ebrowse-draw-member-short-fn)))
- (with-silent-modifications
- (erase-buffer)
- ;; Show this class
- (ebrowse-draw-member-buffer-class-line)
- (funcall display-fn ebrowse--member-list ebrowse--displayed-class)
- ;; Show inherited members if corresponding switch is on
- (when ebrowse--show-inherited-flag
- (dolist (super (ebrowse-base-classes ebrowse--displayed-class))
- (goto-char (point-max))
- (insert (if (bolp) "\n\n" "\n"))
- (ebrowse-draw-member-buffer-class-line super)
- (funcall display-fn (funcall ebrowse--accessor super) super)))
- (ebrowse-update-member-buffer-mode-line))))
-
-
-(defun ebrowse-draw-member-buffer-class-line (&optional class)
- "Display the title line for a class section in the member buffer.
-CLASS non-nil means display that class' title. Otherwise use
-the class cursor is on."
- (let ((start (point))
- (tree (or class ebrowse--displayed-class))
- class-name-start
- class-name-end)
- (insert "class ")
- (setq class-name-start (point))
- (insert (ebrowse-qualified-class-name (ebrowse-ts-class tree)))
- (when (ebrowse-template-p (ebrowse-ts-class tree))
- (insert "<>"))
- (setq class-name-end (point))
- (insert ":\n\n")
- (ebrowse-set-face start (point) 'ebrowse-member-class)
- (add-text-properties
- class-name-start class-name-end
- '(ebrowse-what class-name
- mouse-face highlight
- help-echo "mouse-3: menu"))
- (put-text-property start class-name-end 'ebrowse-tree tree)))
-
-
-(defun ebrowse-display-member-buffer (list &optional stand-alone class)
- "Start point for member buffer creation.
-LIST is the member list to display. STAND-ALONE non-nil
-means the member buffer is standalone. CLASS is its class."
- (let* ((classes ebrowse--tree-table)
- (tree ebrowse--tree)
- (tags-file ebrowse--tags-file-name)
- (header ebrowse--header)
- temp-buffer-setup-hook
- (temp-buffer (get-buffer ebrowse-member-buffer-name)))
- ;; Get the class description from the name the cursor
- ;; is on if not specified as an argument.
- (unless class
- (setq class (ebrowse-tree-at-point)))
- (save-selected-window
- (if temp-buffer
- (pop-to-buffer temp-buffer)
- (pop-to-buffer (get-buffer-create ebrowse-member-buffer-name))
- ;; If new buffer, set the mode and initial values of locals
- (ebrowse-member-mode))
- ;; Set local variables
- (setq ebrowse--member-list (funcall list class)
- ebrowse--displayed-class class
- ebrowse--accessor list
- ebrowse--tree-table classes
- ebrowse--frozen-flag stand-alone
- ebrowse--tags-file-name tags-file
- ebrowse--header header
- ebrowse--tree tree
- buffer-read-only t)
- (ebrowse-redisplay-member-buffer)
- (current-buffer))))
-
-
-(defun ebrowse-member-display-p (member)
- "Check if MEMBER must be displayed under the current filter settings.
-If so, return MEMBER; otherwise return nil."
- (if (and (aref ebrowse--filters (ebrowse-ms-visibility member))
- (or (null ebrowse--const-display-flag)
- (ebrowse-const-p member))
- (or (null ebrowse--inline-display-flag)
- (ebrowse-inline-p member))
- (or (null ebrowse--pure-display-flag)
- (ebrowse-bs-p member))
- (or (null ebrowse--virtual-display-flag)
- (ebrowse-virtual-p member)))
- member))
-
-
-(defun ebrowse-draw-member-attributes (member)
- "Insert a string for the attributes of MEMBER."
- (insert (if (ebrowse-template-p member) "T" "-")
- (if (ebrowse-extern-c-p member) "C" "-")
- (if (ebrowse-virtual-p member) "v" "-")
- (if (ebrowse-inline-p member) "i" "-")
- (if (ebrowse-const-p member) "c" "-")
- (if (ebrowse-pure-virtual-p member) "0" "-")
- (if (ebrowse-mutable-p member) "m" "-")
- (if (ebrowse-explicit-p member) "e" "-")
- (if (ebrowse-throw-list-p member) "t" "-")))
-
-
-(defun ebrowse-draw-member-regexp (member-struc)
- "Insert a string for the regular expression matching MEMBER-STRUC."
- (let ((pattern (if ebrowse--source-regexp-flag
- (ebrowse-ms-definition-pattern
- member-struc)
- (ebrowse-ms-pattern member-struc))))
- (cond ((stringp pattern)
- (insert (ebrowse-trim-string pattern) "...\n")
- (beginning-of-line 0)
- (move-to-column (+ 4 ebrowse--decl-column))
- (while (re-search-forward "[ \t]+" nil t)
- (delete-region (match-beginning 0) (match-end 0))
- (insert " "))
- (beginning-of-line 2))
- (t
- (insert "[not recorded or unknown]\n")))))
-
-
-(defun ebrowse-draw-member-long-fn (member-list tree)
- "Display member buffer for MEMBER-LIST in long form.
-TREE is the class tree of MEMBER-LIST."
- (dolist (member-struc (mapcar #'ebrowse-member-display-p member-list))
- (when member-struc
- (let ((name (ebrowse-ms-name member-struc))
- (start (point)))
- ;; Insert member name truncated to the right length
- (insert (substring name
- 0
- (min (length name)
- (1- ebrowse--decl-column))))
- (add-text-properties
- start (point)
- `(mouse-face highlight ebrowse-what member-name
- ebrowse-member ,member-struc
- ebrowse-tree ,tree
- help-echo "mouse-2: view definition; mouse-3: menu"))
- ;; Display virtual, inline, and const status
- (setf start (point))
- (indent-to ebrowse--decl-column)
- (put-text-property start (point) 'mouse-face nil)
- (when ebrowse--attributes-flag
- (let ((start (point)))
- (insert "<")
- (ebrowse-draw-member-attributes member-struc)
- (insert ">")
- (ebrowse-set-face start (point)
- 'ebrowse-member-attribute)))
- (insert " ")
- (ebrowse-draw-member-regexp member-struc))))
- (insert "\n")
- (goto-char (point-min)))
-
-
-(defun ebrowse-draw-member-short-fn (member-list tree)
- "Display MEMBER-LIST in short form.
-TREE is the class tree in which the members are found."
- (let ((i 0)
- (column-width (+ ebrowse--column-width
- (if ebrowse--attributes-flag 12 0))))
- ;; Get the number of columns to draw.
- (setq ebrowse--n-columns
- (max 1 (/ (ebrowse-width-of-drawable-area) column-width)))
- (dolist (member (mapcar #'ebrowse-member-display-p member-list))
- (when member
- (let ((name (ebrowse-ms-name member))
- start-of-entry
- (start-of-column (point))
- start-of-name)
- (indent-to (* i column-width))
- (put-text-property start-of-column (point) 'mouse-face nil)
- (setq start-of-entry (point))
- ;; Show various attributes
- (when ebrowse--attributes-flag
- (insert "<")
- (ebrowse-draw-member-attributes member)
- (insert "> ")
- (ebrowse-set-face start-of-entry (point)
- 'ebrowse-member-attribute))
- ;; insert member name truncated to column width
- (setq start-of-name (point))
- (insert (substring name 0
- (min (length name)
- (1- ebrowse--column-width))))
- ;; set text properties
- (add-text-properties
- start-of-name (point)
- `(ebrowse-what member-name
- ebrowse-member ,member
- mouse-face highlight
- ebrowse-tree ,tree
- help-echo "mouse-2: view definition; mouse-3: menu"))
- (cl-incf i)
- (when (>= i ebrowse--n-columns)
- (setf i 0)
- (insert "\n")))))
- (when (cl-plusp i)
- (insert "\n"))
- (goto-char (point-min))))
-
-
-\f
-;;; Killing members from tree
-
-(defun ebrowse-member-info-from-point ()
- "Ger information about the member at point.
-The result has the form (TREE MEMBER NULL-P). TREE is the tree
-we're in, MEMBER is the member we're on. NULL-P is t if MEMBER
-is nil."
- (let ((tree (or (get-text-property (point) 'ebrowse-tree)
- (error "No information at point")))
- (member (get-text-property (point) 'ebrowse-member)))
- (list tree member (null member))))
-
-
-\f
-;;; Switching member buffer to display a selected member
-
-(defun ebrowse-goto-visible-member/all-member-lists (_prefix)
- "Position cursor on a member read from the minibuffer.
-With PREFIX, search all members in the tree. Otherwise consider
-only members visible in the buffer."
- (interactive "p")
- (ebrowse-ignoring-completion-case
- (let* ((completion-list (ebrowse-name/accessor-alist-for-class-members))
- (member (completing-read "Goto member: " completion-list nil t))
- (accessor (cdr (assoc member completion-list))))
- (unless accessor
- (error "`%s' not found" member))
- (unless (eq accessor ebrowse--accessor)
- (setf ebrowse--accessor accessor
- ebrowse--member-list (funcall accessor ebrowse--displayed-class))
- (ebrowse-redisplay-member-buffer))
- (ebrowse-move-point-to-member member))))
-
-
-(defun ebrowse-goto-visible-member (repeat)
- "Position point on a member.
-Read the member's name from the minibuffer. Consider only members
-visible in the member buffer.
-REPEAT non-nil means repeat the search that number of times."
- (interactive "p")
- (ebrowse-ignoring-completion-case
- ;; Read member name
- (let* ((completion-list (ebrowse-name/accessor-alist-for-visible-members))
- (member (completing-read "Goto member: " completion-list nil t)))
- (ebrowse-move-point-to-member member repeat))))
-
-
-\f
-;;; Searching a member in the member buffer
-
-(defun ebrowse-repeat-member-search (repeat)
- "Repeat the last regular expression search.
-REPEAT, if specified, says repeat the search REPEAT times."
- (interactive "p")
- (unless ebrowse--last-regexp
- (error "No regular expression remembered"))
- ;; Skip over word the point is on
- (skip-chars-forward "^ \t\n")
- ;; Search for regexp from point
- (if (re-search-forward ebrowse--last-regexp nil t repeat)
- (progn
- (goto-char (match-beginning 0))
- (skip-chars-forward " \t\n"))
- ;; If not found above, repeat search from buffer start
- (goto-char (point-min))
- (if (re-search-forward ebrowse--last-regexp nil t)
- (progn
- (goto-char (match-beginning 0))
- (skip-chars-forward " \t\n"))
- (error "Not found"))))
-
-
-(cl-defun ebrowse-move-point-to-member (name &optional count &aux member)
- "Set point on member NAME in the member buffer.
-COUNT, if specified, says search the COUNT'th member with the same name."
- (goto-char (point-min))
- (widen)
- (setq member
- (substring name 0 (min (length name) (1- ebrowse--column-width)))
- ebrowse--last-regexp
- (concat "[ \t\n]" (regexp-quote member) "[ \n\t]"))
- (if (re-search-forward ebrowse--last-regexp nil t count)
- (goto-char (1+ (match-beginning 0)))
- (error "Not found")))
-
-
-\f
-;;; Switching member buffer to another class.
-
-(defun ebrowse-switch-member-buffer-to-other-class (title compl-list)
- "Switch member buffer to a class read from the minibuffer.
-Use TITLE as minibuffer prompt.
-COMPL-LIST is a completion list to use."
- (let* ((initial (unless (cl-second compl-list)
- (cl-first (cl-first compl-list))))
- (class (or (ebrowse-completing-read-value title compl-list initial)
- (error "Not found"))))
- (setf ebrowse--displayed-class class
- ebrowse--member-list (funcall ebrowse--accessor
- ebrowse--displayed-class))
- (ebrowse-redisplay-member-buffer)))
-
-
-(defun ebrowse-switch-member-buffer-to-any-class ()
- "Switch member buffer to a class read from the minibuffer."
- (interactive)
- (ebrowse-switch-member-buffer-to-other-class
- "Goto class: "
- ;; FIXME: Why not use the hash-table as-is?
- (ebrowse-tree-table-as-alist)))
-
-
-(defun ebrowse-switch-member-buffer-to-base-class (arg)
- "Switch buffer to ARG'th base class."
- (interactive "P")
- (let ((supers (or (ebrowse-direct-base-classes ebrowse--displayed-class)
- (error "No base classes"))))
- (if (and arg (cl-second supers))
- (let ((alist (cl-loop for s in supers
- collect (cons (ebrowse-qualified-class-name
- (ebrowse-ts-class s))
- s))))
- (ebrowse-switch-member-buffer-to-other-class
- "Goto base class: " alist))
- (setq ebrowse--displayed-class (cl-first supers)
- ebrowse--member-list
- (funcall ebrowse--accessor ebrowse--displayed-class))
- (ebrowse-redisplay-member-buffer))))
-
-(defun ebrowse-switch-member-buffer-to-next-sibling-class (arg)
- "Move to ARG'th next sibling."
- (interactive "p")
- (ebrowse-switch-member-buffer-to-sibling-class arg))
-
-
-(defun ebrowse-switch-member-buffer-to-previous-sibling-class (arg)
- "Move to ARG'th previous sibling."
- (interactive "p")
- (ebrowse-switch-member-buffer-to-sibling-class (- arg)))
-
-
-(defun ebrowse-switch-member-buffer-to-sibling-class (inc)
- "Switch member display to nth sibling class.
-Prefix arg INC specifies which one."
- (interactive "p")
- (let ((containing-list ebrowse--tree)
- index cls
- (supers (ebrowse-direct-base-classes ebrowse--displayed-class)))
- (cl-flet ((trees-alist (trees)
- (cl-loop for tr in trees
- collect (cons (ebrowse-cs-name
- (ebrowse-ts-class tr))
- tr))))
- (when supers
- (let ((tree (if (cl-second supers)
- (ebrowse-completing-read-value
- "Relative to base class: "
- (trees-alist supers) nil)
- (cl-first supers))))
- (unless tree (error "Not found"))
- (setq containing-list (ebrowse-ts-subclasses tree)))))
- (setq index (+ inc (seq-position containing-list
- ebrowse--displayed-class
- #'eql)))
- (cond ((cl-minusp index) (message "No previous class"))
- ((null (nth index containing-list)) (message "No next class")))
- (setq index (max 0 (min index (1- (length containing-list)))))
- (setq cls (nth index containing-list))
- (setf ebrowse--displayed-class cls
- ebrowse--member-list (funcall ebrowse--accessor cls))
- (ebrowse-redisplay-member-buffer)))
-
-
-(defun ebrowse-switch-member-buffer-to-derived-class (arg)
- "Switch member display to nth derived class.
-Prefix arg ARG says which class should be displayed. Default is
-the first derived class."
- (interactive "P")
- (cl-flet ((ebrowse-tree-table-as-alist ()
- (cl-loop for s in (ebrowse-ts-subclasses
- ebrowse--displayed-class)
- collect (cons (ebrowse-cs-name (ebrowse-ts-class s))
- s))))
- (let ((subs (or (ebrowse-ts-subclasses ebrowse--displayed-class)
- (error "No derived classes"))))
- (if (and arg (cl-second subs))
- (ebrowse-switch-member-buffer-to-other-class
- "Goto derived class: " (ebrowse-tree-table-as-alist))
- (setq ebrowse--displayed-class (cl-first subs)
- ebrowse--member-list
- (funcall ebrowse--accessor ebrowse--displayed-class))
- (ebrowse-redisplay-member-buffer)))))
-
-
-\f
-;;; Member buffer mouse functions
-
-(defun ebrowse-displaying-functions ()
- (eq ebrowse--accessor 'ebrowse-ts-member-functions))
-(defun ebrowse-displaying-variables ()
- (eq ebrowse--accessor 'ebrowse-ts-member-variables))
-(defun ebrowse-displaying-static-functions ()
- )
-(defun ebrowse-displaying-static-variables ()
- )
-(defun ebrowse-displaying-types ()
- (eq ebrowse--accessor 'ebrowse-ts-types))
-(defun ebrowse-displaying-friends ()
- (eq ebrowse--accessor 'ebrowse-ts-friends))
-
-(easy-menu-define
- ebrowse-member-buffer-object-menu ebrowse-member-mode-map
- "Object menu for the member buffer itself."
- '("Members"
- ("Members List"
- ["Functions" ebrowse-display-function-member-list
- :help "Show the list of member functions"
- :style radio
- :selected (eq ebrowse--accessor 'ebrowse-ts-member-functions)
- :active t]
- ["Variables" ebrowse-display-variables-member-list
- :help "Show the list of member variables"
- :style radio
- :selected (eq ebrowse--accessor 'ebrowse-ts-member-variables)
- :active t]
- ["Static Functions" ebrowse-display-static-functions-member-list
- :help "Show the list of static member functions"
- :style radio
- :selected (eq ebrowse--accessor 'ebrowse-ts-static-functions)
- :active t]
- ["Static Variables" ebrowse-display-static-variables-member-list
- :help "Show the list of static member variables"
- :style radio
- :selected (eq ebrowse--accessor 'ebrowse-ts-static-variables)
- :active t]
- ["Types" ebrowse-display-types-member-list
- :help "Show the list of nested types"
- :style radio
- :selected (eq ebrowse--accessor 'ebrowse-ts-types)
- :active t]
- ["Friends/Defines" ebrowse-display-friends-member-list
- :help "Show the list of friends or defines"
- :style radio
- :selected (eq ebrowse--accessor 'ebrowse-ts-friends)
- :active t])
- ("Class"
- ["Up" ebrowse-switch-member-buffer-to-base-class
- :help "Show the base class of this class"
- :active t]
- ["Down" ebrowse-switch-member-buffer-to-derived-class
- :help "Show a derived class of this class"
- :active t]
- ["Next Sibling" ebrowse-switch-member-buffer-to-next-sibling-class
- :help "Show the next sibling class"
- :active t]
- ["Previous Sibling" ebrowse-switch-member-buffer-to-previous-sibling-class
- :help "Show the previous sibling class"
- :active t])
- ("Member"
- ["Show in Tree" ebrowse-show-displayed-class-in-tree
- :help "Show this class in the class tree"
- :active t]
- ["Find in this Class" ebrowse-goto-visible-member
- :help "Search for a member of this class"
- :active t]
- ["Find in Tree" ebrowse-goto-visible-member/all-member-lists
- :help "Search for a member in any class"
- :active t])
- ("Display"
- ["Inherited" ebrowse-toggle-base-class-display
- :help "Toggle display of inherited members"
- :style toggle
- :selected ebrowse--show-inherited-flag
- :active t]
- ["Attributes" ebrowse-toggle-member-attributes-display
- :help "Show member attributes"
- :style toggle
- :selected ebrowse--attributes-flag
- :active t]
- ["Long Display" ebrowse-toggle-long-short-display
- :help "Toggle the member display format"
- :style toggle
- :selected ebrowse--long-display-flag
- :active t]
- ["Column Width" ebrowse-set-member-buffer-column-width
- :help "Set the display's column width"
- :active t])
- ("Filter"
- ["Public" ebrowse-toggle-public-member-filter
- :help "Toggle the visibility of public members"
- :style toggle
- :selected (not (aref ebrowse--filters 0))
- :active t]
- ["Protected" ebrowse-toggle-protected-member-filter
- :help "Toggle the visibility of protected members"
- :style toggle
- :selected (not (aref ebrowse--filters 1))
- :active t]
- ["Private" ebrowse-toggle-private-member-filter
- :help "Toggle the visibility of private members"
- :style toggle
- :selected (not (aref ebrowse--filters 2))
- :active t]
- ["Virtual" ebrowse-toggle-virtual-member-filter
- :help "Toggle the visibility of virtual members"
- :style toggle
- :selected ebrowse--virtual-display-flag
- :active t]
- ["Inline" ebrowse-toggle-inline-member-filter
- :help "Toggle the visibility of inline members"
- :style toggle
- :selected ebrowse--inline-display-flag
- :active t]
- ["Const" ebrowse-toggle-const-member-filter
- :help "Toggle the visibility of const members"
- :style toggle
- :selected ebrowse--const-display-flag
- :active t]
- ["Pure" ebrowse-toggle-pure-member-filter
- :help "Toggle the visibility of pure virtual members"
- :style toggle
- :selected ebrowse--pure-display-flag
- :active t]
- "-----------------"
- ["Show all" ebrowse-remove-all-member-filters
- :help "Remove any display filters"
- :active t])
- ("Buffer"
- ["Tree" ebrowse-pop-from-member-to-tree-buffer
- :help "Pop to the class tree buffer"
- :active t]
- ["Next Member Buffer" ebrowse-switch-to-next-member-buffer
- :help "Switch to the next member buffer of this class tree"
- :active t]
- ["Freeze" ebrowse-freeze-member-buffer
- :help "Freeze (do not reuse) this member buffer"
- :active t])))
-
-
-(defun ebrowse-on-class-name ()
- "Value is non-nil if point is on a class name."
- (eq (get-text-property (point) 'ebrowse-what) 'class-name))
-
-
-(defun ebrowse-on-member-name ()
- "Value is non-nil if point is on a member name."
- (eq (get-text-property (point) 'ebrowse-what) 'member-name))
-
-
-(easy-menu-define
- ebrowse-member-class-name-object-menu ebrowse-member-mode-map
- "Object menu for class names in member buffer."
- '("Class"
- ["Find" ebrowse-find-member-definition
- :help "Find this class in the source files"
- :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
- ["View" ebrowse-view-member-definition
- :help "View this class in the source files"
- :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]))
-
-
-(easy-menu-define
- ebrowse-member-name-object-menu ebrowse-member-mode-map
- "Object menu for member names."
- '("Ebrowse"
- ["Find Definition" ebrowse-find-member-definition
- :help "Find this member's definition in the source files"
- :active (ebrowse-on-member-name)]
- ["Find Declaration" ebrowse-find-member-declaration
- :help "Find this member's declaration in the source files"
- :active (ebrowse-on-member-name)]
- ["View Definition" ebrowse-view-member-definition
- :help "View this member's definition in the source files"
- :active (ebrowse-on-member-name)]
- ["View Declaration" ebrowse-view-member-declaration
- :help "View this member's declaration in the source files"
- :active (ebrowse-on-member-name)]))
-
-
-(defun ebrowse-member-mouse-3 (event)
- "Handle `mouse-3' events in member buffers.
-EVENT is the mouse event."
- (interactive "e")
- (mouse-set-point event)
- (pcase (event-click-count event)
- (2 (ebrowse-find-member-definition))
- (1 (pcase (get-text-property (posn-point (event-start event))
- 'ebrowse-what)
- ('member-name
- (ebrowse-popup-menu ebrowse-member-name-object-menu event))
- ('class-name
- (ebrowse-popup-menu ebrowse-member-class-name-object-menu event))
- (_
- (ebrowse-popup-menu ebrowse-member-buffer-object-menu event))))))
-
-
-(defun ebrowse-member-mouse-2 (event)
- "Handle `mouse-2' events in member buffers.
-EVENT is the mouse event."
- (interactive "e")
- (mouse-set-point event)
- (pcase (event-click-count event)
- (2 (ebrowse-find-member-definition))
- (1 (pcase (get-text-property (posn-point (event-start event))
- 'ebrowse-what)
- ('member-name
- (ebrowse-view-member-definition 0))))))
-
-
-\f
-;;; Tags view/find
-
-(defun ebrowse-class-alist-for-member (tree-header name)
- "Return information about a member in a class tree.
-TREE-HEADER is the header structure of the class tree.
-NAME is the name of the member.
-Value is an alist of elements (CLASS-NAME . (CLASS LIST NAME)),
-where each element describes one occurrence of member NAME in the tree.
-CLASS-NAME is the qualified name of the class in which the
-member was found. The CDR of the acons is described in function
-`ebrowse-class/index/member-for-member'."
- (let ((table (ebrowse-member-table tree-header))
- known-classes
- alist)
- (when name
- (dolist (info (gethash name table) alist)
- (unless (memq (cl-first info) known-classes)
- (setf alist (cl-acons (ebrowse-qualified-class-name
- (ebrowse-ts-class (cl-first info)))
- info alist)
- known-classes (cons (cl-first info) known-classes)))))))
-
-
-(defun ebrowse-choose-tree ()
- "Choose a class tree to use.
-If there's more than one class tree loaded, let the user choose
-the one he wants. Value is (TREE HEADER BUFFER), with TREE being
-the class tree, HEADER the header structure of the tree, and BUFFER
-being the tree or member buffer containing the tree."
- (let* ((buffer (ebrowse-choose-from-browser-buffers)))
- (if buffer (list (buffer-local-value 'ebrowse--tree buffer)
- (buffer-local-value 'ebrowse--header buffer)
- buffer))))
-
-
-(defun ebrowse-tags-read-name (header prompt)
- "Read a C++ identifier from the minibuffer.
-HEADER is the `ebrowse-hs' structure of the class tree.
-Prompt with PROMPT. Insert into the minibuffer a C++ identifier read
-from point as default. Value is a list (CLASS-NAME MEMBER-NAME)."
- (save-excursion
- (let ((members (ebrowse-member-table header)))
- (cl-multiple-value-bind (class-name member-name)
- (cl-values-list (ebrowse-tags-read-member+class-name))
- (unless member-name
- (error "No member name at point"))
- (if members
- (let* ((name (ebrowse-ignoring-completion-case
- (completing-read prompt members nil nil member-name)))
- ;; (completion-result (try-completion name members))
- )
- ;; Cannot rely on `try-completion' returning t for exact
- ;; matches! It returns the name as a string.
- (unless (gethash name members)
- (if (y-or-n-p "No exact match found. Try substrings? ")
- (setq name
- (or (cl-first (ebrowse-list-of-matching-members
- members (regexp-quote name) name))
- (error "Sorry, nothing found")))
- (error "Canceled")))
- (list class-name name))
- (list class-name (read-from-minibuffer prompt member-name)))))))
-
-
-(defun ebrowse-tags-read-member+class-name ()
- "Read a C++ identifier from point.
-Value is (CLASS-NAME MEMBER-NAME).
-CLASS-NAME is the name of the class if the identifier was qualified.
-It is nil otherwise.
-MEMBER-NAME is the name of the member found."
- (save-excursion
- (skip-chars-backward "a-zA-Z0-9_")
- (let* ((start (point))
- (name (progn (skip-chars-forward "a-zA-Z0-9_")
- (buffer-substring start (point))))
- ) ;; class
- (list nil name)))) ;; class
-
-
-(defun ebrowse-tags-choose-class (_tree header name initial-class-name)
- "Read a class name for a member from the minibuffer.
-TREE is the class tree we operate on.
-HEADER is its header structure.
-NAME is the name of the member.
-INITIAL-CLASS-NAME is an initial class name to insert in the minibuffer.
-Value is a list (TREE ACCESSOR MEMBER) for the member."
- (let ((alist (or (ebrowse-class-alist-for-member header name)
- (error "No classes with member `%s' found" name))))
- (ebrowse-ignoring-completion-case
- (if (null (cl-second alist))
- (cdr (cl-first alist))
- (push ?\? unread-command-events)
- (cdr (assoc (completing-read "In class: "
- alist nil t initial-class-name)
- alist))))))
-
-
-(cl-defun ebrowse-tags-view/find-member-decl/defn
- (prefix &key view definition member-name)
- "If VIEW is t, view, else find an occurrence of MEMBER-NAME.
-
-If DEFINITION is t, find or view the member definition else its
-declaration. This function reads the member's name from the
-current buffer like FIND-TAG. It then prepares a completion list
-of all classes containing a member with the given name and lets
-the user choose the class to use. As a last step, a tags search
-is performed that positions point on the member declaration or
-definition."
- (cl-multiple-value-bind
- (tree header tree-buffer) (cl-values-list (ebrowse-choose-tree))
- (unless tree (error "No class tree"))
- (let* ((marker (point-marker))
- class-name
- (name member-name)
- info)
- (unless name
- (cl-multiple-value-setq (class-name name)
- (cl-values-list
- (ebrowse-tags-read-name
- header
- (concat (if view "View" "Find") " member "
- (if definition "definition" "declaration") ": ")))))
- (setq info (ebrowse-tags-choose-class tree header name class-name))
- (ebrowse-push-position marker info)
- ;; Goto the occurrence of the member
- (ebrowse-view/find-member-declaration/definition
- prefix view definition info
- header
- (buffer-local-value 'ebrowse--tags-file-name tree-buffer))
- ;; Record position jumped to
- (ebrowse-push-position (point-marker) info t))))
-
-
-;;;###autoload
-(defun ebrowse-tags-view-declaration ()
- "View declaration of member at point."
- (interactive)
- (ebrowse-tags-view/find-member-decl/defn 0 :view t :definition nil))
-
-
-;;;###autoload
-(defun ebrowse-tags-find-declaration ()
- "Find declaration of member at point."
- (interactive)
- (ebrowse-tags-view/find-member-decl/defn 0 :view nil :definition nil))
-
-
-;;;###autoload
-(defun ebrowse-tags-view-definition ()
- "View definition of member at point."
- (interactive)
- (ebrowse-tags-view/find-member-decl/defn 0 :view t :definition t))
-
-
-;;;###autoload
-(defun ebrowse-tags-find-definition ()
- "Find definition of member at point."
- (interactive)
- (ebrowse-tags-view/find-member-decl/defn 0 :view nil :definition t))
-
-
-(defun ebrowse-tags-view-declaration-other-window ()
- "View declaration of member at point in other window."
- (interactive)
- (ebrowse-tags-view/find-member-decl/defn 4 :view t :definition nil))
-
-
-;;;###autoload
-(defun ebrowse-tags-find-declaration-other-window ()
- "Find declaration of member at point in other window."
- (interactive)
- (ebrowse-tags-view/find-member-decl/defn 4 :view nil :definition nil))
-
-
-;;;###autoload
-(defun ebrowse-tags-view-definition-other-window ()
- "View definition of member at point in other window."
- (interactive)
- (ebrowse-tags-view/find-member-decl/defn 4 :view t :definition t))
-
-
-;;;###autoload
-(defun ebrowse-tags-find-definition-other-window ()
- "Find definition of member at point in other window."
- (interactive)
- (ebrowse-tags-view/find-member-decl/defn 4 :view nil :definition t))
-
-
-(defun ebrowse-tags-view-declaration-other-frame ()
- "View definition of member at point in other frame."
- (interactive)
- (ebrowse-tags-view/find-member-decl/defn 5 :view t :definition nil))
-
-
-;;;###autoload
-(defun ebrowse-tags-find-declaration-other-frame ()
- "Find definition of member at point in other frame."
- (interactive)
- (ebrowse-tags-view/find-member-decl/defn 5 :view nil :definition nil))
-
-
-;;;###autoload
-(defun ebrowse-tags-view-definition-other-frame ()
- "View definition of member at point in other frame."
- (interactive)
- (ebrowse-tags-view/find-member-decl/defn 5 :view t :definition t))
-
-
-;;;###autoload
-(defun ebrowse-tags-find-definition-other-frame ()
- "Find definition of member at point in other frame."
- (interactive)
- (ebrowse-tags-view/find-member-decl/defn 5 :view nil :definition t))
-
-
-(defun ebrowse-tags-select/create-member-buffer (tree-buffer info)
- "Select or create member buffer.
-TREE-BUFFER specifies the tree to use. INFO describes the member.
-It is a list (TREE ACCESSOR MEMBER)."
- (let ((buffer (get-buffer ebrowse-member-buffer-name)))
- (cond ((null buffer)
- (set-buffer tree-buffer)
- (switch-to-buffer (ebrowse-display-member-buffer
- (cl-second info) nil (cl-first info))))
- (t
- (switch-to-buffer buffer)
- (setq ebrowse--displayed-class (cl-first info)
- ebrowse--accessor (cl-second info)
- ebrowse--member-list (funcall ebrowse--accessor
- ebrowse--displayed-class))
- (ebrowse-redisplay-member-buffer)))
- (ebrowse-move-point-to-member (ebrowse-ms-name (cl-third info)))))
-
-
-(defun ebrowse-tags-display-member-buffer (&optional fix-name)
- "Display a member buffer for a member.
-FIX-NAME non-nil means display the buffer for that member.
-Otherwise read a member name from point."
- (interactive)
- (cl-multiple-value-bind
- (tree header tree-buffer) (cl-values-list (ebrowse-choose-tree))
- (unless tree (error "No class tree"))
- (let* ((marker (point-marker)) class-name (name fix-name) info)
- (unless name
- (cl-multiple-value-setq (class-name name)
- (cl-values-list
- (ebrowse-tags-read-name header
- (concat "Find member list of: ")))))
- (setq info (ebrowse-tags-choose-class tree header name class-name))
- (ebrowse-push-position marker info)
- (ebrowse-tags-select/create-member-buffer tree-buffer info))))
-
-
-(defun ebrowse-list-of-matching-members (members regexp &optional name)
- "Return a list of members in table MEMBERS matching REGEXP or NAME.
-Both NAME and REGEXP may be nil in which case exact or regexp matches
-are not performed."
- (let (list)
- (when (or name regexp)
- (maphash (lambda (member-name _info)
- (when (or (and name (string= name member-name))
- (and regexp (string-match regexp member-name)))
- (setq list (cons member-name list))))
- members))
- list))
-
-
-(defun ebrowse-tags-apropos ()
- "Display a list of members matching a regexp read from the minibuffer."
- (interactive)
- (let* ((buffer (or (ebrowse-choose-from-browser-buffers)
- (error "No tree buffer")))
- (header (buffer-local-value 'ebrowse--header buffer))
- (members (ebrowse-member-table header))
- temp-buffer-setup-hook
- (regexp (read-from-minibuffer "List members matching regexp: ")))
- (with-output-to-temp-buffer (concat "*Apropos Members*")
- (set-buffer standard-output)
- (erase-buffer)
- (insert (format-message "Members matching `%s'\n\n" regexp))
- (cl-loop for s in (ebrowse-list-of-matching-members members regexp) do
- (cl-loop for info in (gethash s members) do
- (ebrowse-draw-file-member-info info))))))
-
-
-(defun ebrowse-tags-list-members-in-file ()
- "Display a list of members found in a file.
-The file name is read from the minibuffer."
- (interactive)
- (let* ((buffer (or (ebrowse-choose-from-browser-buffers)
- (error "No tree buffer")))
- (files (with-current-buffer buffer (ebrowse-files-table)))
- (file (completing-read "List members in file: " files nil t))
- (header (buffer-local-value 'ebrowse--header buffer))
- temp-buffer-setup-hook
- (members (ebrowse-member-table header)))
- (with-output-to-temp-buffer (concat "*Members in file " file "*")
- (set-buffer standard-output)
- (maphash
- (lambda (_member-name list)
- (cl-loop for info in list
- as member = (cl-third info)
- as class = (ebrowse-ts-class (cl-first info))
- when (or (and (null (ebrowse-ms-file member))
- (string= (ebrowse-cs-file class) file))
- (string= file (ebrowse-ms-file member)))
- do (ebrowse-draw-file-member-info info "decl.")
- when (or (and (null (ebrowse-ms-definition-file member))
- (string= (ebrowse-cs-source-file class) file))
- (string= file (ebrowse-ms-definition-file member)))
- do (ebrowse-draw-file-member-info info "defn.")))
- members))))
-
-
-(cl-defun ebrowse-draw-file-member-info (info &optional (kind ""))
- "Display a line in the members info buffer.
-INFO describes the member. It has the form (TREE ACCESSOR MEMBER).
-TREE is the class of the member to display.
-ACCESSOR is the accessor symbol of its member list.
-MEMBER is the member structure.
-KIND is an additional string printed in the buffer."
- (let* ((tree (cl-first info))
- (globals-p (ebrowse-globals-tree-p tree)))
- (unless globals-p
- (insert (ebrowse-cs-name (ebrowse-ts-class tree))))
- (insert "::" (ebrowse-ms-name (cl-third info)))
- (indent-to 40)
- (insert kind)
- (indent-to 50)
- (insert (pcase (cl-second info)
- ('ebrowse-ts-member-functions "member function")
- ('ebrowse-ts-member-variables "member variable")
- ('ebrowse-ts-static-functions "static function")
- ('ebrowse-ts-static-variables "static variable")
- ('ebrowse-ts-friends (if globals-p "define" "friend"))
- ('ebrowse-ts-types "type")
- (_ "unknown"))
- "\n")))
-
-(defvar-local ebrowse-last-completion nil
- "Text inserted by the last completion operation.")
-
-
-(defvar-local ebrowse-last-completion-start nil
- "String which was the basis for the last completion operation.")
-
-
-(defvar-local ebrowse-last-completion-location nil
- "Buffer position at which the last completion operation was initiated.")
-
-
-(defvar-local ebrowse-last-completion-table nil
- "Member used in last completion operation.")
-\f
-(defun ebrowse-some-member-table ()
- "Return a hash table containing all members of a tree.
-If there's only one tree loaded, use that. Otherwise let the
-use choose a tree."
- (let* ((buffers (ebrowse-known-class-trees-buffer-list))
- (buffer (cond ((and (cl-first buffers) (not (cl-second buffers)))
- (cl-first buffers))
- (t (or (ebrowse-electric-choose-tree)
- (error "No tree buffer")))))
- (header (buffer-local-value 'ebrowse--header buffer)))
- (ebrowse-member-table header)))
-
-
-(defun ebrowse-cyclic-successor-in-string-list (string list)
- "Return the item following STRING in LIST.
-If STRING is the last element, return the first element as successor."
- (or (nth (1+ (seq-position list string #'string=)) list)
- (cl-first list)))
-
-\f
-;;; Symbol completion
-
-;;;###autoload
-(cl-defun ebrowse-tags-complete-symbol (prefix)
- "Perform completion on the C++ symbol preceding point.
-A second call of this function without changing point inserts the next match.
-A call with prefix PREFIX reads the symbol to insert from the minibuffer with
-completion."
- (interactive "P")
- (let* ((end (point))
- (begin (save-excursion (skip-chars-backward "a-zA-Z_0-9") (point)))
- (pattern (buffer-substring begin end))
- list completion)
- (cond
- ;; With prefix, read name from minibuffer with completion.
- (prefix
- (let* ((members (ebrowse-some-member-table))
- (completion (completing-read "Insert member: "
- members nil t pattern)))
- (when completion
- (setf ebrowse-last-completion-location nil)
- (delete-region begin end)
- (insert completion))))
- ;; If this function is called at the same point the last
- ;; expansion ended, insert the next expansion.
- ((eq (point) ebrowse-last-completion-location)
- (setf list (all-completions ebrowse-last-completion-start
- ebrowse-last-completion-table)
- completion (ebrowse-cyclic-successor-in-string-list
- ebrowse-last-completion list))
- (cond ((null completion)
- (error "No completion"))
- ((string= completion pattern)
- (error "No further completion"))
- (t
- (delete-region begin end)
- (insert completion)
- (setf ebrowse-last-completion completion
- ebrowse-last-completion-location (point)))))
- ;; First time the function is called at some position in the
- ;; buffer: Start new completion.
- (t
- (let* ((members (ebrowse-some-member-table))
- (completion (cl-first (all-completions pattern members))))
- (cond ((eq completion t))
- ((null completion)
- (error "Can't find completion for `%s'" pattern))
- (t
- (delete-region begin end)
- (insert completion)
-
- (setf ebrowse-last-completion-location (point)
- ebrowse-last-completion-start pattern
- ebrowse-last-completion completion
- ebrowse-last-completion-table members))))))))
-
-\f
-;;; Tags query replace & search
-
-(defvar ebrowse-tags-loop-call '(ignore)
- "Function call for `ebrowse-tags-loop-continue'.
-Passed to `apply' for each file in the tree. If it returns nil, proceed
-with the next file.")
-
-(defvar ebrowse-tags-next-file-list ()
- "A list of files to be processed.")
-
-
-(defvar ebrowse-tags-next-file-path nil
- "The path relative to which files have to be searched.")
-
-
-(defvar ebrowse-tags-loop-last-file nil
- "The last file visited via `ebrowse-tags-loop'.")
-
-
-(defun ebrowse-tags-next-file (&optional initialize tree-buffer)
- "Select next file among files in current tag table.
-Non-nil argument INITIALIZE (prefix arg, if interactive) initializes
-to the beginning of the list of files in the tag table.
-TREE-BUFFER specifies the class tree we operate on."
- (interactive "P")
- ;; Call with INITIALIZE non-nil initializes the files list.
- ;; If more than one tree buffer is loaded, let the user choose
- ;; on which tree (s)he wants to operate.
- (when initialize
- (let ((buffer (or tree-buffer (ebrowse-choose-from-browser-buffers))))
- (with-current-buffer buffer
- (setq ebrowse-tags-next-file-list
- (ebrowse-files-list (ebrowse-marked-classes-p))
- ebrowse-tags-loop-last-file
- nil
- ebrowse-tags-next-file-path
- (file-name-directory ebrowse--tags-file-name)))))
- ;; End of the loop if the stack of files is empty.
- (unless ebrowse-tags-next-file-list
- (error "All files processed"))
- ;; ebrowse-tags-loop-last-file is the last file that was visited due
- ;; to a call to BROWSE-LOOP (see below). If that file is still
- ;; in memory, and it wasn't modified, throw its buffer away to
- ;; prevent cluttering up the buffer list.
- (when ebrowse-tags-loop-last-file
- (let ((buffer (get-file-buffer ebrowse-tags-loop-last-file)))
- (when (and buffer
- (not (buffer-modified-p buffer)))
- (kill-buffer buffer))))
- ;; Remember this buffer file name for later deletion, if it
- ;; wasn't visited by other means.
- (let ((file (expand-file-name (car ebrowse-tags-next-file-list)
- ebrowse-tags-next-file-path)))
- (setq ebrowse-tags-loop-last-file (if (get-file-buffer file) nil file))
- ;; Find the file and pop the file list. Pop has to be done
- ;; before the file is loaded because FIND-FILE might encounter
- ;; an error, and we want to be able to proceed with the next
- ;; file in this case.
- (pop ebrowse-tags-next-file-list)
- (find-file file)))
-
-
-;;;###autoload
-(defun ebrowse-tags-loop-continue (&optional first-time tree-buffer)
- "Repeat last operation on files in tree.
-FIRST-TIME non-nil means this is not a repetition, but the first time.
-TREE-BUFFER if indirectly specifies which files to loop over."
- (interactive)
- (when first-time
- (ebrowse-tags-next-file first-time tree-buffer)
- (goto-char (point-min)))
- (while (not (apply ebrowse-tags-loop-call))
- (ebrowse-tags-next-file)
- (message "Scanning file `%s'..." buffer-file-name)
- (goto-char (point-min))))
-
-
-;;;###autoload
-(defun ebrowse-tags-search (regexp)
- "Search for REGEXP in all files in a tree.
-If marked classes exist, process marked classes, only.
-If regular expression is nil, repeat last search."
- (interactive "sTree search (regexp): ")
- (if (and (string= regexp "")
- (eq (car ebrowse-tags-loop-call) #'re-search-forward))
- (ebrowse-tags-loop-continue)
- (setq ebrowse-tags-loop-call `(re-search-forward ,regexp nil t))
- (ebrowse-tags-loop-continue 'first-time)))
-
-
-;;;###autoload
-(defun ebrowse-tags-query-replace (from to)
- "Query replace FROM with TO in all files of a class tree.
-With prefix arg, process files of marked classes only.
-
-As each match is found, the user must type a character saying
-what to do with it. Type SPC or `y' to replace the match,
-DEL or `n' to skip and go to the next match. For more directions,
-type \\[help-command] at that time."
- (interactive
- "sTree query replace (regexp): \nsTree query replace %s by: ")
- (setq ebrowse-tags-loop-call
- (list (lambda ()
- (and (save-excursion
- (re-search-forward from nil t))
- (not (perform-replace from to t t nil))))))
- (ebrowse-tags-loop-continue 'first-time))
-
-
-;;;###autoload
-(defun ebrowse-tags-search-member-use (&optional fix-name)
- "Search for call sites of a member.
-If FIX-NAME is specified, search uses of that member.
-Otherwise, read a member name from the minibuffer.
-Searches in all files mentioned in a class tree for something that
-looks like a function call to the member."
- (interactive)
- ;; Choose the tree to use if there is more than one.
- (cl-multiple-value-bind (tree header tree-buffer)
- (cl-values-list (ebrowse-choose-tree))
- (unless tree
- (error "No class tree"))
- ;; Get the member name NAME (class-name is ignored).
- (let ((name fix-name) class-name regexp)
- (unless name
- (ignore class-name) ;Can't use an underscore to silence the warning :-(!
- (cl-multiple-value-setq (class-name name)
- (cl-values-list (ebrowse-tags-read-name header "Find calls of: "))))
- ;; Set tags loop form to search for member and begin loop.
- (setq regexp (concat "\\<" name "[ \t]*(")
- ebrowse-tags-loop-call `(re-search-forward ,regexp nil t))
- (ebrowse-tags-loop-continue 'first-time tree-buffer))))
-
-
-\f
-;;; Tags position management
-
-;;; Structures of this kind are the elements of the position stack.
-
-(cl-defstruct (ebrowse-position)
- file-name ; in which file
- point ; point in file
- target ; t if target of a jump
- info) ; (CLASS FUNC MEMBER) jumped to
-
-
-(defvar ebrowse-position-stack ()
- "Stack of `ebrowse-position' structured.")
-
-
-(defvar ebrowse-position-index 0
- "Current position in position stack.")
-
-
-(defun ebrowse-position-name (position)
- "Return an identifying string for POSITION.
-The string is printed in the electric position list buffer."
- (let ((info (ebrowse-position-info position)))
- (concat (if (ebrowse-position-target position) "at " "to ")
- (ebrowse-cs-name (ebrowse-ts-class (cl-first info)))
- "::" (ebrowse-ms-name (cl-third info)))))
-
-
-(defun ebrowse-view/find-position (position &optional view)
- "Position point on POSITION.
-If VIEW is non-nil, view the position, otherwise find it."
- (cond ((not view)
- (find-file (ebrowse-position-file-name position))
- (goto-char (ebrowse-position-point position)))
- (t
- (let ((fn (lambda ()
- (goto-char (ebrowse-position-point position)))))
- (unwind-protect
- (progn
- (add-hook 'view-mode-hook fn)
- (view-file (ebrowse-position-file-name position)))
- (remove-hook 'view-mode-hook fn))))))
-
-
-(defun ebrowse-push-position (marker info &optional target)
- "Push current position on position stack.
-MARKER is the marker to remember as position.
-INFO is a list (CLASS FUNC MEMBER) specifying what we jumped to.
-TARGET non-nil means we performed a jump.
-Positions in buffers that have no file names are not saved."
- (when (buffer-file-name (marker-buffer marker))
- (let ((too-much (- (length ebrowse-position-stack)
- ebrowse-max-positions)))
- ;; Do not let the stack grow to infinity.
- (when (cl-plusp too-much)
- (setq ebrowse-position-stack
- (butlast ebrowse-position-stack too-much)))
- ;; Push the position.
- (push (make-ebrowse-position
- :file-name (buffer-file-name (marker-buffer marker))
- :point (marker-position marker)
- :target target
- :info info)
- ebrowse-position-stack))))
-
-
-(defun ebrowse-move-in-position-stack (increment)
- "Move by INCREMENT in the position stack."
- (let ((length (length ebrowse-position-stack)))
- (when (zerop length)
- (error "No positions remembered"))
- (setq ebrowse-position-index
- (mod (+ increment ebrowse-position-index) length))
- (message "Position %d of %d " ebrowse-position-index length)
- (ebrowse-view/find-position (nth ebrowse-position-index
- ebrowse-position-stack))))
-
-
-;;;###autoload
-(defun ebrowse-back-in-position-stack (arg)
- "Move backward in the position stack.
-Prefix arg ARG says how much."
- (interactive "p")
- (ebrowse-move-in-position-stack (max 1 arg)))
-
-
-;;;###autoload
-(defun ebrowse-forward-in-position-stack (arg)
- "Move forward in the position stack.
-Prefix arg ARG says how much."
- (interactive "p")
- (ebrowse-move-in-position-stack (min -1 (- arg))))
-
-
-\f
-;;; Electric position list
-
-(defvar ebrowse-electric-position-mode-map
- (let ((map (make-keymap))
- (submap (make-keymap)))
- ;; FIXME: Yuck!
- (fillarray (car (cdr map)) 'ebrowse-electric-position-undefined)
- (fillarray (car (cdr submap)) 'ebrowse-electric-position-undefined)
- (define-key map "\e" submap)
- (define-key map "\C-z" 'suspend-frame)
- (define-key map "\C-h" 'Helper-help)
- (define-key map "?" 'Helper-describe-bindings)
- (define-key map "\C-c" nil)
- (define-key map "\C-c\C-c" 'ebrowse-electric-position-quit)
- (define-key map "q" 'ebrowse-electric-position-quit)
- (define-key map " " 'ebrowse-electric-select-position)
- (define-key map "\C-l" 'recenter)
- (define-key map "\C-u" 'universal-argument)
- (define-key map "\C-p" 'previous-line)
- (define-key map "\C-n" 'next-line)
- (define-key map "p" 'previous-line)
- (define-key map "n" 'next-line)
- (define-key map "v" 'ebrowse-electric-view-position)
- (define-key map "\C-v" 'scroll-up-command)
- (define-key map "\ev" 'scroll-down-command)
- (define-key map "\e\C-v" 'scroll-other-window)
- (define-key map "\e>" 'end-of-buffer)
- (define-key map "\e<" 'beginning-of-buffer)
- (define-key map "\e>" 'end-of-buffer)
- map)
- "Keymap used in electric position stack window.")
-
-
-(defvar ebrowse-electric-position-mode-hook nil
- "If non-nil, its value is called by `ebrowse-electric-position-mode'.")
-
-(put 'ebrowse-electric-position-undefined 'suppress-keymap t)
-
-
-(define-derived-mode ebrowse-electric-position-mode
- special-mode "Electric Position Menu"
- "Mode for electric position buffers.
-Runs the hook `ebrowse-electric-position-mode-hook'."
- (setq mode-line-buffer-identification "Electric Position Menu")
- (when (memq 'mode-name mode-line-format)
- (setq mode-line-format (copy-sequence mode-line-format))
- ;; FIXME: Why not set `mode-name' to "Positions"?
- (setcar (memq 'mode-name mode-line-format) "Positions"))
- (setq-local Helper-return-blurb "return to buffer editing")
- (setq truncate-lines t
- buffer-read-only t))
-
-
-(defun ebrowse-draw-position-buffer ()
- "Display positions in buffer *Positions*."
- (set-buffer (get-buffer-create "*Positions*"))
- (setq buffer-read-only nil)
- (erase-buffer)
- (insert "File Point Description\n"
- "---- ----- -----------\n")
- (dolist (position ebrowse-position-stack)
- (insert (file-name-nondirectory (ebrowse-position-file-name position)))
- (indent-to 15)
- (insert (int-to-string (ebrowse-position-point position)))
- (indent-to 22)
- (insert (ebrowse-position-name position) "\n"))
- (setq buffer-read-only t))
-
-
-;;;###autoload
-(defun ebrowse-electric-position-menu ()
- "List positions in the position stack in an electric buffer."
- (interactive)
- (unless ebrowse-position-stack
- (error "No positions remembered"))
- (let (select buffer window)
- (save-window-excursion
- (save-window-excursion (ebrowse-draw-position-buffer))
- (setq window (Electric-pop-up-window "*Positions*")
- buffer (window-buffer window))
- (shrink-window-if-larger-than-buffer window)
- (unwind-protect
- (progn
- (set-buffer buffer)
- (ebrowse-electric-position-mode)
- (setq select
- (catch 'ebrowse-electric-select-position
- (message "<<< Press Space to bury the list >>>")
- (let ((first (progn (goto-char (point-min))
- (forward-line 2)
- (point)))
- (last (progn (goto-char (point-max))
- (forward-line -1)
- (point)))
- (goal-column 0))
- (goto-char first)
- (Electric-command-loop 'ebrowse-electric-select-position
- nil t
- 'ebrowse-electric-position-looper
- (cons first last))))))
- (set-buffer buffer)
- (bury-buffer buffer)
- (message nil)))
- (when select
- (set-buffer buffer)
- (ebrowse-electric-find-position select))
- (kill-buffer buffer)))
-
-
-(defun ebrowse-electric-position-looper (state condition)
- "Prevent moving point on invalid lines.
-Called from `Electric-command-loop'. See there for the meaning
-of STATE and CONDITION."
- (cond ((and condition
- (not (memq (car condition) '(buffer-read-only
- end-of-buffer
- beginning-of-buffer))))
- (signal (car condition) (cdr condition)))
- ((< (point) (car state))
- (goto-char (point-min))
- (forward-line 2))
- ((> (point) (cdr state))
- (goto-char (point-max))
- (forward-line -1)
- (if (pos-visible-in-window-p (point-max))
- (recenter -1)))))
-
-
-(defun ebrowse-electric-position-undefined ()
- "Function called for undefined keys."
- (interactive)
- (message "Type C-h for help, ? for commands, q to quit, Space to execute")
- (sit-for 4))
-
-
-(defun ebrowse-electric-position-quit ()
- "Leave the electric position list."
- (interactive)
- (throw 'ebrowse-electric-select-position nil))
-
-
-(defun ebrowse-electric-select-position ()
- "Select a position from the list."
- (interactive)
- (throw 'ebrowse-electric-select-position (point)))
-
-
-(defun ebrowse-electric-find-position (point &optional view)
- "View/find what is described by the line at POINT.
-If VIEW is non-nil, view else find source files."
- (let ((index (- (count-lines (point-min) point) 2)))
- (ebrowse-view/find-position (nth index
- ebrowse-position-stack) view)))
-
-
-(defun ebrowse-electric-view-position ()
- "View the position described by the line point is in."
- (interactive)
- (ebrowse-electric-find-position (point) t))
-
-
-\f
-;;; Saving trees to disk
-
-(defun ebrowse-write-file-hook-fn ()
- "Write current buffer as a class tree.
-Added to `write-file-functions'."
- (ebrowse-save-tree)
- t)
-
-
-;;;###autoload
-(defun ebrowse-save-tree ()
- "Save current tree in same file it was loaded from."
- (interactive)
- (ebrowse-save-tree-as (or buffer-file-name ebrowse--tags-file-name)))
-
-
-;;;###autoload
-(defun ebrowse-save-tree-as (&optional file-name)
- "Write the current tree data structure to a file.
-Read the file name from the minibuffer if interactive.
-Otherwise, FILE-NAME specifies the file to save the tree in."
- (interactive "FSave tree as: ")
- (let ((temp-buffer (get-buffer-create "*Tree Output"))
- (old-standard-output standard-output)
- (header (copy-ebrowse-hs ebrowse--header))
- (tree ebrowse--tree))
- (unwind-protect
- (with-current-buffer (setq standard-output temp-buffer)
- (erase-buffer)
- (setf (ebrowse-hs-member-table header) nil)
- (insert (prin1-to-string header) " ")
- (mapc #'ebrowse-save-class tree)
- (write-file file-name)
- (message "Tree written to file `%s'" file-name))
- (kill-buffer temp-buffer)
- (set-buffer-modified-p nil)
- (ebrowse-update-tree-buffer-mode-line)
- (setq standard-output old-standard-output))))
-
-
-(defun ebrowse-save-class (class)
- "Write single class CLASS to current buffer."
- (message "%s..." (ebrowse-cs-name (ebrowse-ts-class class)))
- (insert "[ebrowse-ts ")
- (prin1 (ebrowse-ts-class class)) ;class name
- (insert "(") ;list of subclasses
- (mapc #'ebrowse-save-class (ebrowse-ts-subclasses class))
- (insert ")")
- (dolist (func ebrowse-member-list-accessors)
- (prin1 (funcall func class))
- (insert "\n"))
- (insert "()") ;base-classes slot
- (prin1 (ebrowse-ts-mark class))
- (insert "]\n"))
-
-
-\f
-;;; Statistics
-
-;;;###autoload
-(defun ebrowse-statistics ()
- "Display statistics for a class tree."
- (interactive)
- (let ((tree-file (buffer-file-name))
- temp-buffer-setup-hook)
- (with-output-to-temp-buffer "*Tree Statistics*"
- (cl-multiple-value-bind (classes member-functions member-variables
- static-functions static-variables)
- (cl-values-list (ebrowse-gather-statistics))
- (set-buffer standard-output)
- (erase-buffer)
- (insert "STATISTICS FOR TREE " (or tree-file "unknown") ":\n\n")
- (ebrowse-print-statistics-line "Number of classes:" classes)
- (ebrowse-print-statistics-line "Number of member functions:"
- member-functions)
- (ebrowse-print-statistics-line "Number of member variables:"
- member-variables)
- (ebrowse-print-statistics-line "Number of static functions:"
- static-functions)
- (ebrowse-print-statistics-line "Number of static variables:"
- static-variables)))))
-
-
-(defun ebrowse-print-statistics-line (title value)
- "Print a line in the statistics buffer.
-TITLE is the title of the line, VALUE is a number to be printed
-after that."
- (insert title)
- (indent-to 40)
- (insert (format "%d\n" value)))
-
-
-(defun ebrowse-gather-statistics ()
- "Return statistics for a class tree.
-The result is a list (NUMBER-OF-CLASSES NUMBER-OF-MEMBER-FUNCTIONS
-NUMBER-OF-INSTANCE-VARIABLES NUMBER-OF-STATIC-FUNCTIONS
-NUMBER-OF-STATIC-VARIABLES:"
- (let ((classes 0) (member-functions 0) (member-variables 0)
- (static-functions 0) (static-variables 0))
- (ebrowse-for-all-trees (tree ebrowse--tree-table)
- (cl-incf classes)
- (cl-incf member-functions (length (ebrowse-ts-member-functions tree)))
- (cl-incf member-variables (length (ebrowse-ts-member-variables tree)))
- (cl-incf static-functions (length (ebrowse-ts-static-functions tree)))
- (cl-incf static-variables (length (ebrowse-ts-static-variables tree))))
- (list classes member-functions member-variables
- static-functions static-variables)))
-
-
-\f
-;;; Global key bindings
-
-;; The following can be used to bind key sequences starting with
-;; prefix `\C-c\C-m' to browse commands.
-
-(defvar ebrowse-global-map nil
- "Keymap for Ebrowse commands.")
-
-(defvar ebrowse-global-prefix-key "\C-c\C-m"
- "Prefix key for Ebrowse commands.")
-
-(defvar-keymap ebrowse-global-submap-4
- :doc "Keymap used for `ebrowse-global-prefix' followed by `4'."
- "." #'ebrowse-tags-find-definition-other-window
- "f" #'ebrowse-tags-find-definition-other-window
- "v" #'ebrowse-tags-find-declaration-other-window
- "F" #'ebrowse-tags-view-definition-other-window
- "V" #'ebrowse-tags-view-declaration-other-window)
-
-(defvar-keymap ebrowse-global-submap-5
- :doc "Keymap used for `ebrowse-global-prefix' followed by `5'."
- "." #'ebrowse-tags-find-definition-other-frame
- "f" #'ebrowse-tags-find-definition-other-frame
- "v" #'ebrowse-tags-find-declaration-other-frame
- "F" #'ebrowse-tags-view-definition-other-frame
- "V" #'ebrowse-tags-view-declaration-other-frame)
-
-(unless ebrowse-global-map
- (setq ebrowse-global-map (make-sparse-keymap))
- (define-key ebrowse-global-map "a" 'ebrowse-tags-apropos)
- (define-key ebrowse-global-map "b" 'ebrowse-pop-to-browser-buffer)
- (define-key ebrowse-global-map "-" 'ebrowse-back-in-position-stack)
- (define-key ebrowse-global-map "+" 'ebrowse-forward-in-position-stack)
- (define-key ebrowse-global-map "l" 'ebrowse-tags-list-members-in-file)
- (define-key ebrowse-global-map "m" 'ebrowse-tags-display-member-buffer)
- (define-key ebrowse-global-map "n" 'ebrowse-tags-next-file)
- (define-key ebrowse-global-map "p" 'ebrowse-electric-position-menu)
- (define-key ebrowse-global-map "s" 'ebrowse-tags-search)
- (define-key ebrowse-global-map "u" 'ebrowse-tags-search-member-use)
- (define-key ebrowse-global-map "v" 'ebrowse-tags-view-definition)
- (define-key ebrowse-global-map "V" 'ebrowse-tags-view-declaration)
- (define-key ebrowse-global-map "%" 'ebrowse-tags-query-replace)
- (define-key ebrowse-global-map "." 'ebrowse-tags-find-definition)
- (define-key ebrowse-global-map "f" 'ebrowse-tags-find-definition)
- (define-key ebrowse-global-map "F" 'ebrowse-tags-find-declaration)
- (define-key ebrowse-global-map "," 'ebrowse-tags-loop-continue)
- (define-key ebrowse-global-map " " 'ebrowse-electric-buffer-list)
- (define-key ebrowse-global-map "\t" 'ebrowse-tags-complete-symbol)
- (define-key ebrowse-global-map "4" ebrowse-global-submap-4)
- (define-key ebrowse-global-map "5" ebrowse-global-submap-5)
- (define-key global-map ebrowse-global-prefix-key ebrowse-global-map))
-
-
-\f
-;;; Electric C++ browser buffer menu
-
-;; Electric buffer menu customization to display only some buffers
-;; (in this case Tree buffers). There is only one problem with this:
-;; If the very first character typed in the buffer menu is a space,
-;; this will select the buffer from which the buffer menu was
-;; invoked. But this buffer is not displayed in the buffer list if
-;; it isn't a tree buffer. I therefore let the buffer menu command
-;; loop read the command `p' via `unread-command-events'. This command
-;; has no effect since we are on the first line of the buffer.
-
-(defvar electric-buffer-menu-mode-hook nil)
-
-
-(defun ebrowse-hack-electric-buffer-menu ()
- "Hack the electric buffer menu to display browser buffers."
- (let (non-empty)
- (unwind-protect
- (save-excursion
- (setq buffer-read-only nil)
- (goto-char 1)
- (forward-line 2)
- (while (not (eobp))
- (let ((b (Buffer-menu-buffer nil)))
- (if (or (ebrowse-buffer-p b)
- (string= (buffer-name b) "*Apropos Members*"))
- (progn (forward-line 1)
- (setq non-empty t))
- (delete-region (point)
- (save-excursion (end-of-line)
- (min (point-max)
- (1+ (point)))))))))
- (unless non-empty
- (error "No tree buffers"))
- (setf unread-command-events
- (nconc (listify-key-sequence "p") unread-command-events))
- (shrink-window-if-larger-than-buffer (selected-window))
- (setq buffer-read-only t))))
-
-
-(defun ebrowse-select-1st-to-9nth ()
- "Select the nth entry in the list by the keys 1..9."
- (interactive)
- (let* ((maxlin (count-lines (point-min) (point-max)))
- (n (min maxlin (+ 2 (string-to-number (this-command-keys))))))
- (goto-char (point-min))
- (forward-line (1- n))
- (throw 'electric-buffer-menu-select (point))))
-
-
-(defun ebrowse-install-1-to-9-keys ()
- "Define keys 1..9 to select the 1st to 9nth entry in the list."
- (dotimes (i 9)
- (define-key (current-local-map) (char-to-string (+ i ?1))
- 'ebrowse-select-1st-to-9nth)))
-
-
-(defun ebrowse-electric-buffer-list ()
- "Display an electric list of Ebrowse buffers."
- (interactive)
- (unwind-protect
- (progn
- (add-hook 'electric-buffer-menu-mode-hook
- #'ebrowse-hack-electric-buffer-menu)
- (add-hook 'electric-buffer-menu-mode-hook
- #'ebrowse-install-1-to-9-keys)
- (call-interactively 'electric-buffer-list))
- (remove-hook 'electric-buffer-menu-mode-hook
- #'ebrowse-hack-electric-buffer-menu)))
-
-\f
-;;; Mouse support
-
-(defun ebrowse-mouse-find-member (event)
- "Find the member clicked on in another frame.
-EVENT is a mouse button event."
- (interactive "e")
- (mouse-set-point event)
- (let (start name)
- (save-excursion
- (skip-chars-backward "a-zA-Z0-9_")
- (setq start (point))
- (skip-chars-forward "a-zA-Z0-9_")
- (setq name (buffer-substring start (point))))
- (ebrowse-tags-view/find-member-decl/defn
- 5 :view nil :definition t :member-name name)))
-
-
-(defun ebrowse-popup-menu (menu event)
- "Pop up MENU and perform an action if something was selected.
-EVENT is the mouse event."
- (save-selected-window
- (select-window (posn-window (event-start event)))
- (let ((selection (x-popup-menu event menu)) binding)
- (while selection
- (setq binding (lookup-key (or binding menu) (vector (car selection)))
- selection (cdr selection)))
- (when binding
- (call-interactively binding)))))
-
-
-(easy-menu-define
- ebrowse-tree-buffer-class-object-menu ebrowse-tree-mode-map
- "Object menu for classes in the tree buffer."
- '("Class"
- ["Functions" ebrowse-tree-command:show-member-functions
- :help "Display a list of member functions"
- :active t]
- ["Variables" ebrowse-tree-command:show-member-variables
- :help "Display a list of member variables"
- :active t]
- ["Static Functions" ebrowse-tree-command:show-static-member-functions
- :help "Display a list of static member functions"
- :active t]
- ["Static Variables" ebrowse-tree-command:show-static-member-variables
- :help "Display a list of static member variables"
- :active t]
- ["Friends/ Defines" ebrowse-tree-command:show-friends
- :help "Display a list of friends of a class"
- :active t]
- ["Types" ebrowse-tree-command:show-types
- :help "Display a list of types defined in a class"
- :active t]
- "-----------------"
- ["View" ebrowse-view-class-declaration
- :help "View class declaration"
- :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
- ["Find" ebrowse-find-class-declaration
- :help "Find class declaration in file"
- :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
- "-----------------"
- ["Mark" ebrowse-toggle-mark-at-point
- :help "Mark class point is on"
- :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
- "-----------------"
- ["Collapse" ebrowse-collapse-branch
- :help "Collapse subtree under class point is on"
- :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
- ["Expand" ebrowse-expand-branch
- :help "Expand subtree under class point is on"
- :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]))
-
-
-(easy-menu-define
- ebrowse-tree-buffer-object-menu ebrowse-tree-mode-map
- "Object menu for tree buffers."
- '("Ebrowse"
- ["Filename Display" ebrowse-toggle-file-name-display
- :help "Toggle display of source files names"
- :style toggle
- :selected ebrowse--show-file-names-flag
- :active t]
- ["Tree Indentation" ebrowse-set-tree-indentation
- :help "Set the tree's indentation"
- :active t]
- ["Unmark All Classes" ebrowse-mark-all-classes
- :help "Unmark all classes in the class tree"
- :active t]
- ["Expand All" ebrowse-expand-all
- :help "Expand all subtrees in the class tree"
- :active t]
- ["Statistics" ebrowse-statistics
- :help "Show a buffer with class hierarchy statistics"
- :active t]
- ["Find Class" ebrowse-read-class-name-and-go
- :help "Find a class in the tree"
- :active t]
- ["Member Buffer" ebrowse-pop/switch-to-member-buffer-for-same-tree
- :help "Show a member buffer for this class tree"
- :active t]))
-
-
-(defun ebrowse-mouse-3-in-tree-buffer (event)
- "Perform mouse actions in tree buffers.
-EVENT is the mouse event."
- (interactive "e")
- (mouse-set-point event)
- (let* ((where (posn-point (event-start event)))
- (property (get-text-property where 'ebrowse-what)))
- (pcase (event-click-count event)
- (1
- (pcase property
- ('class-name
- (ebrowse-popup-menu ebrowse-tree-buffer-class-object-menu event))
- (_
- (ebrowse-popup-menu ebrowse-tree-buffer-object-menu event)))))))
-
-
-(defun ebrowse-mouse-2-in-tree-buffer (event)
- "Perform mouse actions in tree buffers.
-EVENT is the mouse event."
- (interactive "e")
- (mouse-set-point event)
- (let* ((where (posn-point (event-start event)))
- (property (get-text-property where 'ebrowse-what)))
- (pcase (event-click-count event)
- (1 (pcase property
- ('class-name
- (ebrowse-tree-command:show-member-functions)))))))
-
-
-(defun ebrowse-mouse-1-in-tree-buffer (event)
- "Perform mouse actions in tree buffers.
-EVENT is the mouse event."
- (interactive "e")
- (mouse-set-point event)
- (let* ((where (posn-point (event-start event)))
- (property (get-text-property where 'ebrowse-what)))
- (pcase (event-click-count event)
- (2 (pcase property
- ('class-name
- (let ((collapsed (ebrowse--hidden-p (line-end-position))))
- (ebrowse-collapse-fn (not collapsed))))
- ('mark
- (ebrowse-toggle-mark-at-point 1)))))))
-
-
-\f
-(provide 'ebrowse)
-;;; ebrowse.el ends here
install: all
if not exist bin\nul md bin
cd lib-src
- command.com /c >/dev/null for %p in (hexl etags ctags ebrowse) do\
+ command.com /c >/dev/null for %p in (hexl etags ctags) do\
if exist %p.exe mv -f %p.exe ../bin
cd ..
cd src
+ ctags.exe, etags.exe - Tools for generating tag files. See the
`Tags' node of the Emacs manual.
- + ebrowse.exe - A tool for generating C++ browse information. See the
- `Ebrowse' manual.
-
Several helper programs are installed in a version-specific
subdirectory of the libexec directory:
+ ctags.exe, etags.exe - Tools for generating tag files. See the
`Tags' node of the Emacs manual.
- + ebrowse.exe - A tool for generating C++ browse information. See the
- `Ebrowse' manual.
-
Several helper programs are in a version-specific subdirectory of
the libexec directory:
Vmovemail_program_name = build_pure_c_string ("libmovemail.so");
#endif
- DEFVAR_LISP ("ebrowse-program-name", Vebrowse_program_name,
- doc: /* Name of the `ebrowse' program distributed with Emacs.
-Use this instead of calling `ebrowse' directly, as `ebrowse'
-may have been renamed to comply with executable naming restrictions on
-the system. */);
-#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
- Vebrowse_program_name = build_pure_c_string ("ebrowse");
-#else
- Vebrowse_program_name = build_pure_c_string ("libebrowse.so");
-#endif
-
DEFVAR_LISP ("rcs2log-program-name", Vrcs2log_program_name,
doc: /* Name of the `rcs2log' program distributed with Emacs.
Use this instead of calling `rcs2log' directly, as `rcs2log'
(semantic-format-tag-prototype
(semantic-complete-read-tag-project "Symbol: "))))
-;;; From semanticdb-ebrowse
-
-(require 'semantic/db-ebrowse)
-
-(defun semanticdb-ebrowse-run-tests ()
- "Run some tests of the semanticdb-ebrowse system.
-All systems are different. Ask questions along the way."
- (interactive)
- (let ((doload nil))
- (when (y-or-n-p "Create a system database to test with?")
- (call-interactively 'semanticdb-create-ebrowse-database)
- (setq doload t))
- ;; Should we load in caches
- (when (if doload
- (y-or-n-p "New database created. Reload system databases? ")
- (y-or-n-p "Load in all system databases? "))
- (semanticdb-load-ebrowse-caches)))
- ;; Ok, databases were created. Let's try some searching.
- (when (not (or (eq major-mode 'c-mode)
- (eq major-mode 'c++-mode)))
- (error "Please make your default buffer be a C or C++ file, then
-run the test again")))
-
-(defun semanticdb-ebrowse-dump ()
- "Find the first loaded ebrowse table, and dump out the contents."
- (interactive)
- (let ((db semanticdb-database-list)
- ;; (ab nil)
- )
- (while db
- (when (semanticdb-project-database-ebrowse-p (car db))
- ;; (setq ab
- (data-debug-new-buffer "*EBROWSE Database*") ;;)
- (data-debug-insert-thing (car db) "*" "")
- (setq db nil)
- )
- (setq db (cdr db)))))
-
;;; From semanticdb-global:
(require 'semantic/db-global)