aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerd Moellmann2000-04-09 11:15:57 +0000
committerGerd Moellmann2000-04-09 11:15:57 +0000
commitbe0dbdab007cf09a2cac30c89ad4d530b08abeae (patch)
tree67292bea88bc5bb6a5a997cd1b40461af29f75e4
parent25112054fe5d863c409dd9779cb5e7ed3530e9e7 (diff)
downloademacs-be0dbdab007cf09a2cac30c89ad4d530b08abeae.tar.gz
emacs-be0dbdab007cf09a2cac30c89ad4d530b08abeae.zip
*** empty log message ***
-rw-r--r--lib-src/ChangeLog7
-rw-r--r--lib-src/ebrowse.c3702
-rw-r--r--lisp/ChangeLog17
-rw-r--r--lisp/cus-load.el20
-rw-r--r--lisp/loaddefs.el180
-rw-r--r--lisp/progmodes/ebrowse.el4573
-rw-r--r--src/ChangeLog5
7 files changed, 8452 insertions, 52 deletions
diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog
index dc45c7cf8e6..bb0f635c598 100644
--- a/lib-src/ChangeLog
+++ b/lib-src/ChangeLog
@@ -1,3 +1,10 @@
12000-04-09 Gerd Moellmann <gerd@gnu.org>
2
3 * Makefile.in (INSTALLABLES): Add ebrowse.
4 (ebrowse): New target.
5
6 * ebrowse.c: New file.
7
12000-03-29 Andreas Schwab <schwab@suse.de> 82000-03-29 Andreas Schwab <schwab@suse.de>
2 9
3 * make-docfile.c (scan_lisp_file): Also look for `defsubst'. 10 * make-docfile.c (scan_lisp_file): Also look for `defsubst'.
diff --git a/lib-src/ebrowse.c b/lib-src/ebrowse.c
new file mode 100644
index 00000000000..5e70bcd1630
--- /dev/null
+++ b/lib-src/ebrowse.c
@@ -0,0 +1,3702 @@
1/* ebrowse.c --- parsing files for the ebrowse C++ browser
2
3 Copyright (C) 1992-1999, 2000 Free Software Foundation Inc.
4
5 Author: Gerd Moellmann <gerd@gnu.org>
6 Maintainer: FSF
7
8 This file is part of GNU Emacs.
9
10 GNU Emacs is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 GNU Emacs is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GNU Emacs; see the file COPYING. If not, write to
22 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <ctype.h>
28#include <assert.h>
29#include "getopt.h"
30
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35/* Conditionalize function prototypes. */
36
37#ifdef PROTOTYPES /* From config.h. */
38#define P_(x) x
39#else
40#define P_(x) ()
41#endif
42
43/* Value is non-zero if strings X and Y compare equal. */
44
45#define streq(X, Y) (*(X) == *(Y) && strcmp ((X) + 1, (Y) + 1) == 0)
46
47/* The ubiquitous `max' and `min' macros. */
48
49#ifndef max
50#define max(X, Y) ((X) > (Y) ? (X) : (Y))
51#define min(X, Y) ((X) < (Y) ? (X) : (Y))
52#endif
53
54/* Files are read in chunks of this number of bytes. */
55
56#define READ_CHUNK_SIZE (100 * 1024)
57
58/* The character used as a separator in path lists (like $PATH). */
59
60#define PATH_LIST_SEPARATOR ':'
61
62/* The default output file name. */
63
64#define DEFAULT_OUTFILE "EBROWSE"
65
66/* A version string written to the output file. Change this whenever
67 the structure of the output file changes. */
68
69#define EBROWSE_FILE_VERSION "ebrowse 5.0"
70
71/* The output file consists of a tree of Lisp objects, with major
72 nodes built out of Lisp structures. These are the heads of the
73 Lisp structs with symbols identifying their type. */
74
75#define TREE_HEADER_STRUCT "[ebrowse-hs "
76#define TREE_STRUCT "[ebrowse-ts "
77#define MEMBER_STRUCT "[ebrowse-ms "
78#define BROWSE_STRUCT "[ebrowse-bs "
79#define CLASS_STRUCT "[ebrowse-cs "
80
81/* The name of the symbol table entry for global functions, variables,
82 defines etc. This name also appears in the browser display. */
83
84#define GLOBALS_NAME "*Globals*"
85
86/* Token definitions. */
87
88enum token
89{
90 YYEOF = 0, /* end of file */
91 CSTRING = 256, /* string constant */
92 CCHAR, /* character constant */
93 CINT, /* integral constant */
94 CFLOAT, /* real constant */
95
96 ELLIPSIS, /* ... */
97 LSHIFTASGN, /* <<= */
98 RSHIFTASGN, /* >>= */
99 ARROWSTAR, /* ->* */
100 IDENT, /* identifier */
101 DIVASGN, /* /= */
102 INC, /* ++ */
103 ADDASGN, /* += */
104 DEC, /* -- */
105 ARROW, /* -> */
106 SUBASGN, /* -= */
107 MULASGN, /* *= */
108 MODASGN, /* %= */
109 LOR, /* || */
110 ORASGN, /* |= */
111 LAND, /* && */
112 ANDASGN, /* &= */
113 XORASGN, /* ^= */
114 POINTSTAR, /* .* */
115 DCOLON, /* :: */
116 EQ, /* == */
117 NE, /* != */
118 LE, /* <= */
119 LSHIFT, /* << */
120 GE, /* >= */
121 RSHIFT, /* >> */
122
123/* Keywords. The undef's are there because these
124 three symbols are very likely to be defined somewhere. */
125#undef BOOL
126#undef TRUE
127#undef FALSE
128
129 ASM, /* asm */
130 AUTO, /* auto */
131 BREAK, /* break */
132 CASE, /* case */
133 CATCH, /* catch */
134 CHAR, /* char */
135 CLASS, /* class */
136 CONST, /* const */
137 CONTINUE, /* continue */
138 DEFAULT, /* default */
139 DELETE, /* delete */
140 DO, /* do */
141 DOUBLE, /* double */
142 ELSE, /* else */
143 ENUM, /* enum */
144 EXTERN, /* extern */
145 FLOAT, /* float */
146 FOR, /* for */
147 FRIEND, /* friend */
148 GOTO, /* goto */
149 IF, /* if */
150 T_INLINE, /* inline */
151 INT, /* int */
152 LONG, /* long */
153 NEW, /* new */
154 OPERATOR, /* operator */
155 PRIVATE, /* private */
156 PROTECTED, /* protected */
157 PUBLIC, /* public */
158 REGISTER, /* register */
159 RETURN, /* return */
160 SHORT, /* short */
161 SIGNED, /* signed */
162 SIZEOF, /* sizeof */
163 STATIC, /* static */
164 STRUCT, /* struct */
165 SWITCH, /* switch */
166 TEMPLATE, /* template */
167 THIS, /* this */
168 THROW, /* throw */
169 TRY, /* try */
170 TYPEDEF, /* typedef */
171 UNION, /* union */
172 UNSIGNED, /* unsigned */
173 VIRTUAL, /* virtual */
174 VOID, /* void */
175 VOLATILE, /* volatile */
176 WHILE, /* while */
177 MUTABLE, /* mutable */
178 BOOL, /* bool */
179 TRUE, /* true */
180 FALSE, /* false */
181 SIGNATURE, /* signature (GNU extension) */
182 NAMESPACE, /* namespace */
183 EXPLICIT, /* explicit */
184 TYPENAME, /* typename */
185 CONST_CAST, /* const_cast */
186 DYNAMIC_CAST, /* dynamic_cast */
187 REINTERPRET_CAST, /* reinterpret_cast */
188 STATIC_CAST, /* static_cast */
189 TYPEID, /* typeid */
190 USING, /* using */
191 WCHAR /* wchar_t */
192};
193
194/* Storage classes, in a wider sense. */
195
196enum sc
197{
198 SC_UNKNOWN,
199 SC_MEMBER, /* Is an instance member. */
200 SC_STATIC, /* Is static member. */
201 SC_FRIEND, /* Is friend function. */
202 SC_TYPE /* Is a type definition. */
203};
204
205/* Member visibility. */
206
207enum visibility
208{
209 V_PUBLIC,
210 V_PROTECTED,
211 V_PRIVATE
212};
213
214/* Member flags. */
215
216#define F_VIRTUAL 1 /* Is virtual function. */
217#define F_INLINE 2 /* Is inline function. */
218#define F_CONST 4 /* Is const. */
219#define F_PURE 8 /* Is pure virtual function. */
220#define F_MUTABLE 16 /* Is mutable. */
221#define F_TEMPLATE 32 /* Is a template. */
222#define F_EXPLICIT 64 /* Is explicit constructor. */
223#define F_THROW 128 /* Has a throw specification. */
224#define F_EXTERNC 256 /* Is declared extern "C". */
225#define F_DEFINE 512 /* Is a #define. */
226
227/* Two macros to set and test a bit in an int. */
228
229#define SET_FLAG(F, FLAG) ((F) |= (FLAG))
230#define HAS_FLAG(F, FLAG) (((F) & (FLAG)) != 0)
231
232/* Structure describing a class member. */
233
234struct member
235{
236 struct member *next; /* Next in list of members. */
237 struct member *anext; /* Collision chain in member_table. */
238 struct member **list; /* Pointer to list in class. */
239 unsigned param_hash; /* Hash value for parameter types. */
240 int vis; /* Visibility (public, ...). */
241 int flags; /* See F_* above. */
242 char *regexp; /* Matching regular expression. */
243 char *filename; /* Don't free this shared string. */
244 int pos; /* Buffer position of occurrence. */
245 char *def_regexp; /* Regular expression matching definition. */
246 char *def_filename; /* File name of definition. */
247 int def_pos; /* Buffer position of definition. */
248 char name[1]; /* Member name. */
249};
250
251/* Structures of this type are used to connect class structures with
252 their super and subclasses. */
253
254struct link
255{
256 struct sym *sym; /* The super or subclass. */
257 struct link *next; /* Next in list or NULL. */
258};
259
260/* Structure used to record namespace aliases. */
261
262struct alias
263{
264 struct alias *next; /* Next in list. */
265 char name[1]; /* Alias name. */
266};
267
268/* The structure used to describe a class in the symbol table,
269 or a namespace in all_namespaces. */
270
271struct sym
272{
273 int flags; /* Is class a template class?. */
274 unsigned char visited; /* Used to find circles. */
275 struct sym *next; /* Hash collision list. */
276 struct link *subs; /* List of subclasses. */
277 struct link *supers; /* List of superclasses. */
278 struct member *vars; /* List of instance variables. */
279 struct member *fns; /* List of instance functions. */
280 struct member *static_vars; /* List of static variables. */
281 struct member *static_fns; /* List of static functions. */
282 struct member *friends; /* List of friend functions. */
283 struct member *types; /* List of local types. */
284 char *regexp; /* Matching regular expression. */
285 int pos; /* Buffer position. */
286 char *filename; /* File in which it can be found. */
287 char *sfilename; /* File in which members can be found. */
288 struct sym *namesp; /* Namespace in which defined. . */
289 struct alias *namesp_aliases; /* List of aliases for namespaces. */
290 char name[1]; /* Name of the class. */
291};
292
293/* Experimental: Print info for `--position-info'. We print
294 '(CLASS-NAME SCOPE MEMBER-NAME). */
295
296#define P_DEFN 1
297#define P_DECL 2
298
299int info_where;
300struct sym *info_cls = NULL;
301struct member *info_member = NULL;
302
303/* Experimental. For option `--position-info', the buffer position we
304 are interested in. When this position is reached, print out
305 information about what we know about that point. */
306
307int info_position = -1;
308
309/* Command line options structure for getopt_long. */
310
311struct option options[] =
312{
313 {"append", no_argument, NULL, 'a'},
314 {"files", required_argument, NULL, 'f'},
315 {"help", no_argument, NULL, -2},
316 {"min-regexp-length", required_argument, NULL, 'm'},
317 {"max-regexp-length", required_argument, NULL, 'M'},
318 {"no-nested-classes", no_argument, NULL, 'n'},
319 {"no-regexps", no_argument, NULL, 'x'},
320 {"no-structs-or-unions", no_argument, NULL, 's'},
321 {"output-file", required_argument, NULL, 'o'},
322 {"position-info", required_argument, NULL, 'p'},
323 {"search-path", required_argument, NULL, 'I'},
324 {"verbose", no_argument, NULL, 'v'},
325 {"version", no_argument, NULL, -3},
326 {"very-verbose", no_argument, NULL, 'V'},
327 {NULL, 0, NULL, 0}
328};
329
330/* Semantic values of tokens. Set by yylex.. */
331
332unsigned yyival; /* Set for token CINT. */
333char *yytext; /* Set for token IDENT. */
334char *yytext_end;
335
336/* Output file. */
337
338FILE *yyout;
339
340/* Current line number. */
341
342int yyline;
343
344/* The name of the current input file. */
345
346char *filename;
347
348/* Three character class vectors, and macros to test membership
349 of characters. */
350
351char is_ident[255];
352char is_digit[255];
353char is_white[255];
354
355#define IDENTP(C) is_ident[(unsigned char) (C)]
356#define DIGITP(C) is_digit[(unsigned char) (C)]
357#define WHITEP(C) is_white[(unsigned char) (C)]
358
359/* Command line flags. */
360
361int f_append;
362int f_verbose;
363int f_very_verbose;
364int f_structs = 1;
365int f_regexps = 1;
366int f_nested_classes = 1;
367
368/* Maximum and minimum lengths of regular expressions matching a
369 member, class etc., for writing them to the output file. These are
370 overridable from the command line. */
371
372int min_regexp = 5;
373int max_regexp = 50;
374
375/* Input buffer. */
376
377char *inbuffer;
378char *in;
379int inbuffer_size;
380
381/* Return the current buffer position in the input file. */
382
383#define BUFFER_POS() (in - inbuffer)
384
385/* If current lookahead is CSTRING, the following points to the
386 first character in the string constant. Used for recognizing
387 extern "C". */
388
389char *string_start;
390
391/* The size of the hash tables for classes.and members. Should be
392 prime. */
393
394#define TABLE_SIZE 1001
395
396/* The hash table for class symbols. */
397
398struct sym *class_table[TABLE_SIZE];
399
400/* Hash table containing all member structures. This is generally
401 faster for member lookup than traversing the member lists of a
402 `struct sym'. */
403
404struct member *member_table[TABLE_SIZE];
405
406/* The special class symbol used to hold global functions,
407 variables etc. */
408
409struct sym *global_symbols;
410
411/* The current namespace. */
412
413struct sym *current_namespace;
414
415/* The list of all known namespaces. */
416
417struct sym *all_namespaces;
418
419/* Stack of namespaces we're currently nested in, during the parse. */
420
421struct sym **namespace_stack;
422int namespace_stack_size;
423int namespace_sp;
424
425/* The current lookahead token. */
426
427int tk = -1;
428
429/* Structure describing a keyword. */
430
431struct kw
432{
433 char *name; /* Spelling. */
434 int tk; /* Token value. */
435 struct kw *next; /* Next in collision chain. */
436};
437
438/* Keywords are lookup up in a hash table of their own. */
439
440#define KEYWORD_TABLE_SIZE 1001
441struct kw *keyword_table[KEYWORD_TABLE_SIZE];
442
443/* Search path. */
444
445struct search_path
446{
447 char *path;
448 struct search_path *next;
449};
450
451struct search_path *search_path;
452struct search_path *search_path_tail;
453
454/* Function prototypes. */
455
456int yylex P_ ((void));
457void yyparse P_ ((void));
458void re_init_parser P_ ((void));
459char *token_string P_ ((int));
460char *matching_regexp P_ ((void));
461void init_sym P_ ((void));
462struct sym *add_sym P_ ((char *, struct sym *));
463void add_link P_ ((struct sym *, struct sym *));
464void add_member_defn P_ ((struct sym *, char *, char *,
465 int, unsigned, int, int, int));
466void add_member_decl P_ ((struct sym *, char *, char *, int,
467 unsigned, int, int, int, int));
468void dump_roots P_ ((FILE *));
469void *xmalloc P_ ((int));
470void add_global_defn P_ ((char *, char *, int, unsigned, int, int, int));
471void add_global_decl P_ ((char *, char *, int, unsigned, int, int, int));
472void add_define P_ ((char *, char *, int));
473void mark_inherited_virtual P_ ((void));
474void leave_namespace P_ ((void));
475void enter_namespace P_ ((char *));
476void register_namespace_alias P_ ((char *, char *));
477void insert_keyword P_ ((char *, int));
478void re_init_scanner P_ ((void));
479void init_scanner P_ ((void));
480void usage P_ ((int));
481void version P_ ((void));
482void process_file P_ ((char *));
483void add_search_path P_ ((char *));
484FILE *open_file P_ ((char *));
485int process_pp_line P_ ((void));
486int dump_members P_ ((FILE *, struct member *));
487void dump_sym P_ ((FILE *, struct sym *));
488int dump_tree P_ ((FILE *, struct sym *));
489struct member *find_member P_ ((struct sym *, char *, int, int, unsigned));
490struct member *add_member P_ ((struct sym *, char *, int, int, unsigned));
491void mark_virtual P_ ((struct sym *));
492void mark_virtual P_ ((struct sym *));
493struct sym *make_namespace P_ ((char *));
494char *sym_scope P_ ((struct sym *));
495char *sym_scope_1 P_ ((struct sym *));
496int skip_to P_ ((int));
497void skip_matching P_ ((void));
498void member P_ ((struct sym *, int));
499void class_body P_ ((struct sym *, int));
500void class_definition P_ ((struct sym *, int, int, int));
501void declaration P_ ((int, int));
502unsigned parm_list P_ ((int *));
503char *operator_name P_ ((int *));
504struct sym *parse_classname P_ ((void));
505struct sym *parse_qualified_ident_or_type P_ ((char **));
506void parse_qualified_param_ident_or_type P_ ((char **));
507int globals P_ ((int));
508
509
510
511/***********************************************************************
512 Utilities
513 ***********************************************************************/
514
515/* Print an error in a printf-like style with the current input file
516 name and line number. */
517
518void
519yyerror (format, a1, a2, a3, a4, a5)
520 char *format;
521 int a1, a2, a3, a4, a5;
522{
523 fprintf (stderr, "%s:%d: ", filename, yyline);
524 fprintf (stderr, format, a1, a2, a3, a4, a5);
525 putc ('\n', stderr);
526}
527
528
529/* Like malloc but print an error and exit if not enough memory is
530 available. */
531
532void *
533xmalloc (nbytes)
534 int nbytes;
535{
536 void *p = malloc (nbytes);
537 if (p)
538 return p;
539 yyerror ("out of memory");
540 exit (1);
541}
542
543
544/* Like realloc but print an error and exit if out of memory. */
545
546void *
547xrealloc (p, sz)
548 void *p;
549 int sz;
550{
551 p = realloc (p, sz);
552 if (p)
553 return p;
554 yyerror ("out of memory");
555 exit (1);
556}
557
558
559/* Like strdup, but print an error and exit if not enough memory is
560 available.. If S is null, return null. */
561
562char *
563xstrdup (s)
564 char *s;
565{
566 if (s)
567 s = strcpy (xmalloc (strlen (s) + 1), s);
568 return s;
569}
570
571
572
573/***********************************************************************
574 Symbols
575 ***********************************************************************/
576
577/* Initialize the symbol table. This currently only sets up the
578 special symbol for globals (`*Globals*'). */
579
580void
581init_sym ()
582{
583 global_symbols = add_sym (GLOBALS_NAME, NULL);
584}
585
586
587/* Add a symbol for class NAME to the symbol table. NESTED_IN_CLASS
588 is the class in which class NAME was found. If it is null,
589 this means the scope of NAME is the current namespace.
590
591 If a symbol for NAME already exists, return that. Otherwise
592 create a new symbol and set it to default values. */
593
594struct sym *
595add_sym (name, nested_in_class)
596 char *name;
597 struct sym *nested_in_class;
598{
599 struct sym *sym;
600 unsigned h;
601 char *s;
602 struct sym *scope = nested_in_class ? nested_in_class : current_namespace;
603
604 for (s = name, h = 0; *s; ++s)
605 h = (h << 1) ^ *s;
606 h %= TABLE_SIZE;
607
608 for (sym = class_table[h]; sym; sym = sym->next)
609 if (streq (name, sym->name) && sym->namesp == scope)
610 break;
611
612 if (sym == NULL)
613 {
614 if (f_very_verbose)
615 {
616 putchar ('\t');
617 puts (name);
618 }
619
620 sym = (struct sym *) xmalloc (sizeof *sym + strlen (name));
621 bzero (sym, sizeof *sym);
622 strcpy (sym->name, name);
623 sym->namesp = scope;
624 sym->next = class_table[h];
625 class_table[h] = sym;
626 }
627
628 return sym;
629}
630
631
632/* Add links between superclass SUPER and subclass SUB. */
633
634void
635add_link (super, sub)
636 struct sym *super, *sub;
637{
638 struct link *lnk, *lnk2, *p, *prev;
639
640 /* See if a link already exists. */
641 for (p = super->subs, prev = NULL;
642 p && strcmp (sub->name, p->sym->name) > 0;
643 prev = p, p = p->next)
644 ;
645
646 /* Avoid duplicates. */
647 if (p == NULL || p->sym != sub)
648 {
649 lnk = (struct link *) xmalloc (sizeof *lnk);
650 lnk2 = (struct link *) xmalloc (sizeof *lnk2);
651
652 lnk->sym = sub;
653 lnk->next = p;
654
655 if (prev)
656 prev->next = lnk;
657 else
658 super->subs = lnk;
659
660 lnk2->sym = super;
661 lnk2->next = sub->supers;
662 sub->supers = lnk2;
663 }
664}
665
666
667/* Find in class CLS member NAME.
668
669 VAR non-zero means look for a member variable; otherwise a function
670 is searched. SC specifies what kind of member is searched---a
671 static, or per-instance member etc. HASH is a hash code for the
672 parameter types of functions. Value is a pointer to the member
673 found or null if not found. */
674
675struct member *
676find_member (cls, name, var, sc, hash)
677 struct sym *cls;
678 char *name;
679 int var, sc;
680 unsigned hash;
681{
682 struct member **list;
683 struct member *p;
684 unsigned name_hash = 0;
685 char *s;
686 int i;
687
688 switch (sc)
689 {
690 case SC_FRIEND:
691 list = &cls->friends;
692 break;
693
694 case SC_TYPE:
695 list = &cls->types;
696 break;
697
698 case SC_STATIC:
699 list = var ? &cls->static_vars : &cls->static_fns;
700 break;
701
702 default:
703 list = var ? &cls->vars : &cls->fns;
704 break;
705 }
706
707 for (s = name; *s; ++s)
708 name_hash = (name_hash << 1) ^ *s;
709 i = name_hash % TABLE_SIZE;
710
711 for (p = member_table[i]; p; p = p->anext)
712 if (p->list == list && p->param_hash == hash && streq (name, p->name))
713 break;
714
715 return p;
716}
717
718
719/* Add to class CLS information for the declaration of member NAME.
720 REGEXP is a regexp matching the declaration, if non-null. POS is
721 the position in the source where the declaration is found. HASH is
722 a hash code for the parameter list of the member, if it's a
723 function. VAR non-zero means member is a variable or type. SC
724 specifies the type of member (instance member, static, ...). VIS
725 is the member's visibility (public, protected, private). FLAGS is
726 a bit set giving additional information about the member (see the
727 F_* defines). */
728
729void
730add_member_decl (cls, name, regexp, pos, hash, var, sc, vis, flags)
731 struct sym *cls;
732 char *name;
733 char *regexp;
734 int pos;
735 unsigned hash;
736 int var;
737 int sc;
738 int vis;
739 int flags;
740{
741 struct member *m;
742
743 m = find_member (cls, name, var, sc, hash);
744 if (m == NULL)
745 m = add_member (cls, name, var, sc, hash);
746
747 /* Have we seen a new filename? If so record that. */
748 if (!cls->filename || !streq (cls->filename, filename))
749 m->filename = filename;
750
751 m->regexp = regexp;
752 m->pos = pos;
753 m->flags = flags;
754
755 switch (vis)
756 {
757 case PRIVATE:
758 m->vis = V_PRIVATE;
759 break;
760
761 case PROTECTED:
762 m->vis = V_PROTECTED;
763 break;
764
765 case PUBLIC:
766 m->vis = V_PUBLIC;
767 break;
768 }
769
770 info_where = P_DECL;
771 info_cls = cls;
772 info_member = m;
773}
774
775
776/* Add to class CLS information for the definition of member NAME.
777 REGEXP is a regexp matching the declaration, if non-null. POS is
778 the position in the source where the declaration is found. HASH is
779 a hash code for the parameter list of the member, if it's a
780 function. VAR non-zero means member is a variable or type. SC
781 specifies the type of member (instance member, static, ...). VIS
782 is the member's visibility (public, protected, private). FLAGS is
783 a bit set giving additional information about the member (see the
784 F_* defines). */
785
786void
787add_member_defn (cls, name, regexp, pos, hash, var, sc, flags)
788 struct sym *cls;
789 char *name;
790 char *regexp;
791 int pos;
792 unsigned hash;
793 int var;
794 int sc;
795 int flags;
796{
797 struct member *m;
798
799 if (sc == SC_UNKNOWN)
800 {
801 m = find_member (cls, name, var, SC_MEMBER, hash);
802 if (m == NULL)
803 {
804 m = find_member (cls, name, var, SC_STATIC, hash);
805 if (m == NULL)
806 m = add_member (cls, name, var, sc, hash);
807 }
808 }
809 else
810 {
811 m = find_member (cls, name, var, sc, hash);
812 if (m == NULL)
813 m = add_member (cls, name, var, sc, hash);
814 }
815
816 if (!cls->sfilename)
817 cls->sfilename = filename;
818
819 if (!streq (cls->sfilename, filename))
820 m->def_filename = filename;
821
822 m->def_regexp = regexp;
823 m->def_pos = pos;
824 m->flags |= flags;
825
826 info_where = P_DEFN;
827 info_cls = cls;
828 info_member = m;
829}
830
831
832/* Add a symbol for a define named NAME to the symbol table.
833 REGEXP is a regular expression matching the define in the source,
834 if it is non-null. POS is the position in the file. */
835
836void
837add_define (name, regexp, pos)
838 char *name, *regexp;
839 int pos;
840{
841 add_global_defn (name, regexp, pos, 0, 1, SC_FRIEND, F_DEFINE);
842 add_global_decl (name, regexp, pos, 0, 1, SC_FRIEND, F_DEFINE);
843}
844
845
846/* Add information for the global definition of NAME.
847 REGEXP is a regexp matching the declaration, if non-null. POS is
848 the position in the source where the declaration is found. HASH is
849 a hash code for the parameter list of the member, if it's a
850 function. VAR non-zero means member is a variable or type. SC
851 specifies the type of member (instance member, static, ...). VIS
852 is the member's visibility (public, protected, private). FLAGS is
853 a bit set giving additional information about the member (see the
854 F_* defines). */
855
856void
857add_global_defn (name, regexp, pos, hash, var, sc, flags)
858 char *name, *regexp;
859 int pos;
860 unsigned hash;
861 int var;
862 int sc;
863 int flags;
864{
865 int i;
866 struct sym *sym;
867
868 /* Try to find out for which classes a function is a friend, and add
869 what we know about it to them. */
870 if (!var)
871 for (i = 0; i < TABLE_SIZE; ++i)
872 for (sym = class_table[i]; sym; sym = sym->next)
873 if (sym != global_symbols && sym->friends)
874 if (find_member (sym, name, 0, SC_FRIEND, hash))
875 add_member_defn (sym, name, regexp, pos, hash, 0,
876 SC_FRIEND, flags);
877
878 /* Add to global symbols. */
879 add_member_defn (global_symbols, name, regexp, pos, hash, var, sc, flags);
880}
881
882
883/* Add information for the global declaration of NAME.
884 REGEXP is a regexp matching the declaration, if non-null. POS is
885 the position in the source where the declaration is found. HASH is
886 a hash code for the parameter list of the member, if it's a
887 function. VAR non-zero means member is a variable or type. SC
888 specifies the type of member (instance member, static, ...). VIS
889 is the member's visibility (public, protected, private). FLAGS is
890 a bit set giving additional information about the member (see the
891 F_* defines). */
892
893void
894add_global_decl (name, regexp, pos, hash, var, sc, flags)
895 char *name, *regexp;
896 int pos;
897 unsigned hash;
898 int var;
899 int sc;
900 int flags;
901{
902 /* Add declaration only if not already declared. Header files must
903 be processed before source files for this to have the right effect.
904 I do not want to handle implicit declarations at the moment. */
905 struct member *m;
906 struct member *found;
907
908 m = found = find_member (global_symbols, name, var, sc, hash);
909 if (m == NULL)
910 m = add_member (global_symbols, name, var, sc, hash);
911
912 /* Definition already seen => probably last declaration implicit.
913 Override. This means that declarations must always be added to
914 the symbol table before definitions. */
915 if (!found)
916 {
917 if (!global_symbols->filename
918 || !streq (global_symbols->filename, filename))
919 m->filename = filename;
920
921 m->regexp = regexp;
922 m->pos = pos;
923 m->vis = V_PUBLIC;
924 m->flags = flags;
925
926 info_where = P_DECL;
927 info_cls = global_symbols;
928 info_member = m;
929 }
930}
931
932
933/* Add a symbol for member NAME to class CLS.
934 VAR non-zero means it's a variable. SC specifies the kind of
935 member. HASH is a hash code for the parameter types of a function.
936 Value is a pointer to the member's structure. */
937
938struct member *
939add_member (cls, name, var, sc, hash)
940 struct sym *cls;
941 char *name;
942 int var;
943 int sc;
944 unsigned hash;
945{
946 struct member *m = (struct member *) xmalloc (sizeof *m + strlen (name));
947 struct member **list;
948 struct member *p;
949 struct member *prev;
950 unsigned name_hash = 0;
951 int i;
952 char *s;
953
954 strcpy (m->name, name);
955 m->param_hash = hash;
956
957 m->vis = 0;
958 m->flags = 0;
959 m->regexp = NULL;
960 m->filename = NULL;
961 m->pos = 0;
962 m->def_regexp = NULL;
963 m->def_filename = NULL;
964 m->def_pos = 0;
965
966 assert (cls != NULL);
967
968 switch (sc)
969 {
970 case SC_FRIEND:
971 list = &cls->friends;
972 break;
973
974 case SC_TYPE:
975 list = &cls->types;
976 break;
977
978 case SC_STATIC:
979 list = var ? &cls->static_vars : &cls->static_fns;
980 break;
981
982 default:
983 list = var ? &cls->vars : &cls->fns;
984 break;
985 }
986
987 for (s = name; *s; ++s)
988 name_hash = (name_hash << 1) ^ *s;
989 i = name_hash % TABLE_SIZE;
990 m->anext = member_table[i];
991 member_table[i] = m;
992 m->list = list;
993
994 /* Keep the member list sorted. It's cheaper to do it here than to
995 sort them in Lisp. */
996 for (prev = NULL, p = *list;
997 p && strcmp (name, p->name) > 0;
998 prev = p, p = p->next)
999 ;
1000
1001 m->next = p;
1002 if (prev)
1003 prev->next = m;
1004 else
1005 *list = m;
1006 return m;
1007}
1008
1009
1010/* Given the root R of a class tree, step through all subclasses
1011 recursively, marking functions as virtual that are declared virtual
1012 in base classes. */
1013
1014void
1015mark_virtual (r)
1016 struct sym *r;
1017{
1018 struct link *p;
1019 struct member *m, *m2;
1020
1021 for (p = r->subs; p; p = p->next)
1022 {
1023 for (m = r->fns; m; m = m->next)
1024 if (HAS_FLAG (m->flags, F_VIRTUAL))
1025 {
1026 for (m2 = p->sym->fns; m2; m2 = m2->next)
1027 if (m->param_hash == m2->param_hash && streq (m->name, m2->name))
1028 SET_FLAG (m2->flags, F_VIRTUAL);
1029 }
1030
1031 mark_virtual (p->sym);
1032 }
1033}
1034
1035
1036/* For all roots of the class tree, mark functions as virtual that
1037 are virtual because of a virtual declaration in a base class. */
1038
1039void
1040mark_inherited_virtual ()
1041{
1042 struct sym *r;
1043 int i;
1044
1045 for (i = 0; i < TABLE_SIZE; ++i)
1046 for (r = class_table[i]; r; r = r->next)
1047 if (r->supers == NULL)
1048 mark_virtual (r);
1049}
1050
1051
1052/* Create and return a symbol for a namespace with name NAME. */
1053
1054struct sym *
1055make_namespace (name)
1056 char *name;
1057{
1058 struct sym *s = (struct sym *) xmalloc (sizeof *s + strlen (name));
1059 bzero (s, sizeof *s);
1060 strcpy (s->name, name);
1061 s->next = all_namespaces;
1062 s->namesp = current_namespace;
1063 all_namespaces = s;
1064 return s;
1065}
1066
1067
1068/* Find the symbol for namespace NAME. If not found, add a new symbol
1069 for NAME to all_namespaces. */
1070
1071struct sym *
1072find_namespace (name)
1073 char *name;
1074{
1075 struct sym *p;
1076
1077 for (p = all_namespaces; p; p = p->next)
1078 {
1079 if (streq (p->name, name))
1080 break;
1081 else
1082 {
1083 struct alias *p2;
1084 for (p2 = p->namesp_aliases; p2; p2 = p2->next)
1085 if (streq (p2->name, name))
1086 break;
1087 if (p2)
1088 break;
1089 }
1090 }
1091
1092 if (p == NULL)
1093 p = make_namespace (name);
1094
1095 return p;
1096}
1097
1098
1099/* Register the name NEW_NAME as an alias for namespace OLD_NAME. */
1100
1101void
1102register_namespace_alias (new_name, old_name)
1103 char *new_name, *old_name;
1104{
1105 struct sym *p = find_namespace (old_name);
1106 struct alias *al;
1107
1108 /* Is it already in the list of aliases? */
1109 for (al = p->namesp_aliases; al; al = al->next)
1110 if (streq (new_name, p->name))
1111 return;
1112
1113 al = (struct alias *) xmalloc (sizeof *al + strlen (new_name));
1114 strcpy (al->name, new_name);
1115 al->next = p->namesp_aliases;
1116 p->namesp_aliases = al;
1117}
1118
1119
1120/* Enter namespace with name NAME. */
1121
1122void
1123enter_namespace (name)
1124 char *name;
1125{
1126 struct sym *p = find_namespace (name);
1127
1128 if (namespace_sp == namespace_stack_size)
1129 {
1130 int size = max (10, 2 * namespace_stack_size);
1131 namespace_stack = (struct sym **) xrealloc (namespace_stack, size);
1132 namespace_stack_size = size;
1133 }
1134
1135 namespace_stack[namespace_sp++] = current_namespace;
1136 current_namespace = p;
1137}
1138
1139
1140/* Leave the current namespace. */
1141
1142void
1143leave_namespace ()
1144{
1145 assert (namespace_sp > 0);
1146 current_namespace = namespace_stack[--namespace_sp];
1147}
1148
1149
1150
1151/***********************************************************************
1152 Writing the Output File
1153 ***********************************************************************/
1154
1155/* Write string S to the output file FP in a Lisp-readable form.
1156 If S is null, write out `()'. */
1157
1158#define PUTSTR(s, fp) \
1159 do { \
1160 if (!s) \
1161 { \
1162 putc ('(', fp); \
1163 putc (')', fp); \
1164 putc (' ', fp); \
1165 } \
1166 else \
1167 { \
1168 putc ('"', fp); \
1169 fputs (s, fp); \
1170 putc ('"', fp); \
1171 putc (' ', fp); \
1172 } \
1173 } while (0)
1174
1175/* A dynamically allocated buffer for constructing a scope name. */
1176
1177char *scope_buffer;
1178int scope_buffer_size;
1179int scope_buffer_len;
1180
1181
1182/* Make sure scope_buffer has enough room to add LEN chars to it. */
1183
1184void
1185ensure_scope_buffer_room (len)
1186 int len;
1187{
1188 if (scope_buffer_len + len >= scope_buffer_size)
1189 {
1190 int new_size = max (2 * scope_buffer_size, scope_buffer_len + len);
1191 scope_buffer = (char *) xrealloc (new_size);
1192 scope_buffer_size = new_size;
1193 }
1194}
1195
1196
1197/* Recursively add the scope names of symbol P and the scopes of its
1198 namespaces to scope_buffer. Value is a pointer to the complete
1199 scope name constructed. */
1200
1201char *
1202sym_scope_1 (p)
1203 struct sym *p;
1204{
1205 int len;
1206
1207 if (p->namesp)
1208 sym_scope_1 (p->namesp);
1209
1210 if (*scope_buffer)
1211 {
1212 ensure_scope_buffer_room (3);
1213 strcat (scope_buffer, "::");
1214 scope_buffer_len += 2;
1215 }
1216
1217 len = strlen (p->name);
1218 ensure_scope_buffer_room (len + 1);
1219 strcat (scope_buffer, p->name);
1220 scope_buffer_len += len;
1221
1222 if (HAS_FLAG (p->flags, F_TEMPLATE))
1223 {
1224 ensure_scope_buffer_room (3);
1225 strcat (scope_buffer, "<>");
1226 scope_buffer_len += 2;
1227 }
1228
1229 return scope_buffer;
1230}
1231
1232
1233/* Return the scope of symbol P in printed representation, i.e.
1234 as it would appear in a C*+ source file. */
1235
1236char *
1237sym_scope (p)
1238 struct sym *p;
1239{
1240 if (!scope_buffer)
1241 {
1242 scope_buffer_size = 1024;
1243 scope_buffer = (char *) xmalloc (scope_buffer_size);
1244 }
1245
1246 *scope_buffer = '\0';
1247 scope_buffer_len = 0;
1248
1249 if (p->namesp)
1250 sym_scope_1 (p->namesp);
1251
1252 return scope_buffer;
1253}
1254
1255
1256/* Dump the list of members M to file FP. Value is the length of the
1257 list. */
1258
1259int
1260dump_members (fp, m)
1261 FILE *fp;
1262 struct member *m;
1263{
1264 int n;
1265
1266 putc ('(', fp);
1267
1268 for (n = 0; m; m = m->next, ++n)
1269 {
1270 fputs (MEMBER_STRUCT, fp);
1271 PUTSTR (m->name, fp);
1272 PUTSTR (NULL, fp); /* FIXME? scope for globals */
1273 fprintf (fp, "%u ", (unsigned) m->flags);
1274 PUTSTR (m->filename, fp);
1275 PUTSTR (m->regexp, fp);
1276 fprintf (fp, "%u ", (unsigned) m->pos);
1277 fprintf (fp, "%u ", (unsigned) m->vis);
1278 putc (' ', fp);
1279 PUTSTR (m->def_filename, fp);
1280 PUTSTR (m->def_regexp, fp);
1281 fprintf (fp, "%u", (unsigned) m->def_pos);
1282 putc (']', fp);
1283 putc ('\n', fp);
1284 }
1285
1286 putc (')', fp);
1287 putc ('\n', fp);
1288 return n;
1289}
1290
1291
1292/* Dump class ROOT to stream FP. */
1293
1294void
1295dump_sym (fp, root)
1296 FILE *fp;
1297 struct sym *root;
1298{
1299 fputs (CLASS_STRUCT, fp);
1300 PUTSTR (root->name, fp);
1301
1302 /* Print scope, if any. */
1303 if (root->namesp)
1304 PUTSTR (sym_scope (root), fp);
1305 else
1306 PUTSTR (NULL, fp);
1307
1308 /* Print flags. */
1309 fprintf (fp, "%u", root->flags);
1310 PUTSTR (root->filename, fp);
1311 PUTSTR (root->regexp, fp);
1312 fprintf (fp, "%u", (unsigned) root->pos);
1313 PUTSTR (root->sfilename, fp);
1314 putc (']', fp);
1315 putc ('\n', fp);
1316}
1317
1318
1319/* Dump class ROOT and its subclasses to file FP. Value is the
1320 number of classes written. */
1321
1322int
1323dump_tree (fp, root)
1324 FILE *fp;
1325 struct sym *root;
1326{
1327 struct link *lk;
1328 unsigned n = 0;
1329
1330 dump_sym (fp, root);
1331
1332 if (f_verbose)
1333 {
1334 putchar ('+');
1335 fflush (stdout);
1336 }
1337
1338 putc ('(', fp);
1339
1340 for (lk = root->subs; lk; lk = lk->next)
1341 {
1342 fputs (TREE_STRUCT, fp);
1343 n += dump_tree (fp, lk->sym);
1344 putc (']', fp);
1345 }
1346
1347 putc (')', fp);
1348
1349 dump_members (fp, root->vars);
1350 n += dump_members (fp, root->fns);
1351 dump_members (fp, root->static_vars);
1352 n += dump_members (fp, root->static_fns);
1353 n += dump_members (fp, root->friends);
1354 dump_members (fp, root->types);
1355
1356 /* Superclasses. */
1357 putc ('(', fp);
1358 putc (')', fp);
1359
1360 /* Mark slot. */
1361 putc ('(', fp);
1362 putc (')', fp);
1363
1364 putc ('\n', fp);
1365 return n;
1366}
1367
1368
1369/* Dump the entire class tree to file FP. */
1370
1371void
1372dump_roots (fp)
1373 FILE *fp;
1374{
1375 int i, n = 0;
1376 struct sym *r;
1377
1378 /* Output file header containing version string, command line
1379 options etc. */
1380 if (!f_append)
1381 {
1382 fputs (TREE_HEADER_STRUCT, fp);
1383 PUTSTR (EBROWSE_FILE_VERSION, fp);
1384
1385 putc ('\"', fp);
1386 if (!f_structs)
1387 fputs (" -s", fp);
1388 if (f_regexps)
1389 fputs (" -x", fp);
1390 putc ('\"', fp);
1391 fputs (" ()", fp);
1392 fputs (" ()", fp);
1393 putc (']', fp);
1394 }
1395
1396 /* Mark functions as virtual that are so because of functions
1397 declared virtual in base classes. */
1398 mark_inherited_virtual ();
1399
1400 /* Dump the roots of the graph. */
1401 for (i = 0; i < TABLE_SIZE; ++i)
1402 for (r = class_table[i]; r; r = r->next)
1403 if (!r->supers)
1404 {
1405 fputs (TREE_STRUCT, fp);
1406 n += dump_tree (fp, r);
1407 putc (']', fp);
1408 }
1409
1410 if (f_verbose)
1411 putchar ('\n');
1412}
1413
1414
1415
1416/***********************************************************************
1417 Scanner
1418 ***********************************************************************/
1419
1420#ifdef DEBUG
1421#define INCREMENT_LINENO \
1422do { \
1423 if (f_very_verbose) \
1424 { \
1425 ++yyline; \
1426 printf ("%d:\n", yyline); \
1427 } \
1428 else \
1429 ++yyline; \
1430} while (0)
1431#else
1432#define INCREMENT_LINENO ++yyline
1433#endif
1434
1435/* Define two macros for accessing the input buffer (current input
1436 file). GET(C) sets C to the next input character and advances the
1437 input pointer. UNGET retracts the input pointer. */
1438
1439#define GET(C) ((C) = *in++)
1440#define UNGET() (--in)
1441
1442
1443/* Process a preprocessor line. Value is the next character from the
1444 input buffer not consumed. */
1445
1446int
1447process_pp_line ()
1448{
1449 int in_comment = 0;
1450 int c;
1451 char *p = yytext;
1452
1453 /* Skip over white space. The `#' has been consumed already. */
1454 while (WHITEP (GET (c)))
1455 ;
1456
1457 /* Read the preprocessor command (if any). */
1458 while (IDENTP (c))
1459 {
1460 *p++ = c;
1461 GET (c);
1462 }
1463
1464 /* Is it a `define'? */
1465 *p = '\0';
1466
1467 if (*yytext && streq (yytext, "define"))
1468 {
1469 p = yytext;
1470 while (WHITEP (c))
1471 GET (c);
1472 while (IDENTP (c))
1473 {
1474 *p++ = c;
1475 GET (c);
1476 }
1477
1478 *p = '\0';
1479
1480 if (*yytext)
1481 {
1482 char *regexp = matching_regexp ();
1483 int pos = BUFFER_POS ();
1484 add_define (yytext, regexp, pos);
1485 }
1486 }
1487
1488 while (c && (c != '\n' || in_comment))
1489 {
1490 if (c == '\\')
1491 GET (c);
1492 else if (c == '/' && !in_comment)
1493 {
1494 if (GET (c) == '*')
1495 in_comment = 1;
1496 }
1497 else if (c == '*' && in_comment)
1498 {
1499 if (GET (c) == '/')
1500 in_comment = 0;
1501 }
1502
1503 if (c == '\n')
1504 INCREMENT_LINENO;
1505
1506 GET (c);
1507 }
1508
1509 return c;
1510}
1511
1512
1513/* Value is the next token from the input buffer. */
1514
1515int
1516yylex ()
1517{
1518 int c;
1519 char end_char;
1520 char *p;
1521
1522 for (;;)
1523 {
1524 while (WHITEP (GET (c)))
1525 ;
1526
1527 switch (c)
1528 {
1529 case '\n':
1530 INCREMENT_LINENO;
1531 break;
1532
1533 case '\r':
1534 break;
1535
1536 case 0:
1537 /* End of file. */
1538 return YYEOF;
1539
1540 case '\\':
1541 GET (c);
1542 break;
1543
1544 case '"':
1545 case '\'':
1546 /* String and character constants. */
1547 end_char = c;
1548 string_start = in;
1549 while (GET (c) && c != end_char)
1550 {
1551 switch (c)
1552 {
1553 case '\\':
1554 /* Escape sequences. */
1555 if (!GET (c))
1556 {
1557 if (end_char == '\'')
1558 yyerror ("EOF in character constant");
1559 else
1560 yyerror ("EOF in string constant");
1561 goto end_string;
1562 }
1563 else switch (c)
1564 {
1565 case '\n':
1566 case 'a':
1567 case 'b':
1568 case 'f':
1569 case 'n':
1570 case 'r':
1571 case 't':
1572 case 'v':
1573 break;
1574
1575 case 'x':
1576 {
1577 /* Hexadecimal escape sequence. */
1578 int i;
1579 for (i = 0; i < 2; ++i)
1580 {
1581 GET (c);
1582
1583 if (c >= '0' && c <= '7')
1584 ;
1585 else if (c >= 'a' && c <= 'f')
1586 ;
1587 else if (c >= 'A' && c <= 'F')
1588 ;
1589 else
1590 {
1591 UNGET ();
1592 break;
1593 }
1594 }
1595 }
1596 break;
1597
1598 case '0':
1599 {
1600 /* Octal escape sequence. */
1601 int i;
1602 for (i = 0; i < 3; ++i)
1603 {
1604 GET (c);
1605
1606 if (c >= '0' && c <= '7')
1607 ;
1608 else
1609 {
1610 UNGET ();
1611 break;
1612 }
1613 }
1614 }
1615 break;
1616
1617 default:
1618 break;
1619 }
1620 break;
1621
1622 case '\n':
1623 if (end_char == '\'')
1624 yyerror ("newline in character constant");
1625 else
1626 yyerror ("newline in string constant");
1627 INCREMENT_LINENO;
1628 goto end_string;
1629
1630 default:
1631 break;
1632 }
1633 }
1634
1635 end_string:
1636 return end_char == '\'' ? CCHAR : CSTRING;
1637
1638 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
1639 case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
1640 case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
1641 case 'v': case 'w': case 'x': case 'y': case 'z':
1642 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
1643 case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
1644 case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
1645 case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_':
1646 {
1647 /* Identifier and keywords. */
1648 unsigned hash;
1649 struct kw *k;
1650
1651 p = yytext;
1652 *p++ = hash = c;
1653
1654 while (IDENTP (GET (*p)))
1655 {
1656 hash = (hash << 1) ^ *p++;
1657 if (p == yytext_end - 1)
1658 {
1659 int size = yytext_end - yytext;
1660 yytext = (char *) xrealloc (yytext, 2 * size);
1661 yytext_end = yytext + 2 * size;
1662 p = yytext + size - 1;
1663 }
1664 }
1665
1666 UNGET ();
1667 *p = 0;
1668
1669 for (k = keyword_table[hash % KEYWORD_TABLE_SIZE]; k; k = k->next)
1670 if (streq (k->name, yytext))
1671 return k->tk;
1672
1673 return IDENT;
1674 }
1675
1676 case '/':
1677 /* C and C++ comments, '/' and '/='. */
1678 switch (GET (c))
1679 {
1680 case '*':
1681 while (GET (c))
1682 {
1683 switch (c)
1684 {
1685 case '*':
1686 if (GET (c) == '/')
1687 goto comment_end;
1688 UNGET ();
1689 break;
1690 case '\\':
1691 GET (c);
1692 break;
1693 case '\n':
1694 INCREMENT_LINENO;
1695 break;
1696 }
1697 }
1698 comment_end:;
1699 break;
1700
1701 case '=':
1702 return DIVASGN;
1703
1704 case '/':
1705 while (GET (c) && c != '\n')
1706 ;
1707 INCREMENT_LINENO;
1708 break;
1709
1710 default:
1711 UNGET ();
1712 return '/';
1713 }
1714 break;
1715
1716 case '+':
1717 if (GET (c) == '+')
1718 return INC;
1719 else if (c == '=')
1720 return ADDASGN;
1721 UNGET ();
1722 return '+';
1723
1724 case '-':
1725 switch (GET (c))
1726 {
1727 case '-':
1728 return DEC;
1729 case '>':
1730 if (GET (c) == '*')
1731 return ARROWSTAR;
1732 UNGET ();
1733 return ARROW;
1734 case '=':
1735 return SUBASGN;
1736 }
1737 UNGET ();
1738 return '-';
1739
1740 case '*':
1741 if (GET (c) == '=')
1742 return MULASGN;
1743 UNGET ();
1744 return '*';
1745
1746 case '%':
1747 if (GET (c) == '=')
1748 return MODASGN;
1749 UNGET ();
1750 return '%';
1751
1752 case '|':
1753 if (GET (c) == '|')
1754 return LOR;
1755 else if (c == '=')
1756 return ORASGN;
1757 UNGET ();
1758 return '|';
1759
1760 case '&':
1761 if (GET (c) == '&')
1762 return LAND;
1763 else if (c == '=')
1764 return ANDASGN;
1765 UNGET ();
1766 return '&';
1767
1768 case '^':
1769 if (GET (c) == '=')
1770 return XORASGN;
1771 UNGET ();
1772 return '^';
1773
1774 case '.':
1775 if (GET (c) == '*')
1776 return POINTSTAR;
1777 else if (c == '.')
1778 {
1779 if (GET (c) != '.')
1780 yyerror ("invalid token '..' ('...' assumed)");
1781 UNGET ();
1782 return ELLIPSIS;
1783 }
1784 else if (!DIGITP (c))
1785 {
1786 UNGET ();
1787 return '.';
1788 }
1789 goto mantissa;
1790
1791 case ':':
1792 if (GET (c) == ':')
1793 return DCOLON;
1794 UNGET ();
1795 return ':';
1796
1797 case '=':
1798 if (GET (c) == '=')
1799 return EQ;
1800 UNGET ();
1801 return '=';
1802
1803 case '!':
1804 if (GET (c) == '=')
1805 return NE;
1806 UNGET ();
1807 return '!';
1808
1809 case '<':
1810 switch (GET (c))
1811 {
1812 case '=':
1813 return LE;
1814 case '<':
1815 if (GET (c) == '=')
1816 return LSHIFTASGN;
1817 UNGET ();
1818 return LSHIFT;
1819 }
1820 UNGET ();
1821 return '<';
1822
1823 case '>':
1824 switch (GET (c))
1825 {
1826 case '=':
1827 return GE;
1828 case '>':
1829 if (GET (c) == '=')
1830 return RSHIFTASGN;
1831 UNGET ();
1832 return RSHIFT;
1833 }
1834 UNGET ();
1835 return '>';
1836
1837 case '#':
1838 c = process_pp_line ();
1839 if (c == 0)
1840 return YYEOF;
1841 break;
1842
1843 case '(': case ')': case '[': case ']': case '{': case '}':
1844 case ';': case ',': case '?': case '~':
1845 return c;
1846
1847 case '0':
1848 yyival = 0;
1849
1850 if (GET (c) == 'x' || c == 'X')
1851 {
1852 while (GET (c))
1853 {
1854 if (DIGITP (c))
1855 yyival = yyival * 16 + c - '0';
1856 else if (c >= 'a' && c <= 'f')
1857 yyival = yyival * 16 + c - 'a' + 10;
1858 else if (c >= 'A' && c <= 'F')
1859 yyival = yyival * 16 + c - 'A' + 10;
1860 else
1861 break;
1862 }
1863
1864 goto int_suffixes;
1865 }
1866 else if (c == '.')
1867 goto mantissa;
1868
1869 while (c >= '0' && c <= '7')
1870 {
1871 yyival = (yyival << 3) + c - '0';
1872 GET (c);
1873 }
1874
1875 int_suffixes:
1876 /* Integer suffixes. */
1877 while (isalpha (c))
1878 GET (c);
1879 UNGET ();
1880 return CINT;
1881
1882 case '1': case '2': case '3': case '4': case '5': case '6':
1883 case '7': case '8': case '9':
1884 /* Integer or floating constant, part before '.'. */
1885 yyival = c - '0';
1886
1887 while (GET (c) && DIGITP (c))
1888 yyival = 10 * yyival + c - '0';
1889
1890 if (c != '.')
1891 goto int_suffixes;
1892
1893 mantissa:
1894 /* Digits following '.'. */
1895 while (DIGITP (c))
1896 GET (c);
1897
1898 /* Optional exponent. */
1899 if (c == 'E' || c == 'e')
1900 {
1901 if (GET (c) == '-' || c == '+')
1902 GET (c);
1903
1904 while (DIGITP (c))
1905 GET (c);
1906 }
1907
1908 /* Optional type suffixes. */
1909 while (isalpha (c))
1910 GET (c);
1911 UNGET ();
1912 return CFLOAT;
1913
1914 default:
1915 break;
1916 }
1917 }
1918}
1919
1920
1921/* Value is the string from the start of the line to the current
1922 position in the input buffer, or maybe a bit more if that string is
1923 shorter than min_regexp. */
1924
1925char *
1926matching_regexp ()
1927{
1928 char *p;
1929 char *s;
1930 char *t;
1931 static char *buffer, *end_buf;
1932
1933 if (!f_regexps)
1934 return NULL;
1935
1936 if (buffer == NULL)
1937 {
1938 buffer = (char *) xmalloc (max_regexp);
1939 end_buf = &buffer[max_regexp] - 1;
1940 }
1941
1942 /* Scan back to previous newline of buffer start. */
1943 for (p = in - 1; p > inbuffer && *p != '\n'; --p)
1944 ;
1945
1946 if (*p == '\n')
1947 {
1948 while (in - p < min_regexp && p > inbuffer)
1949 {
1950 /* Line probably not significant enough */
1951 for (--p; p >= inbuffer && *p != '\n'; --p)
1952 ;
1953 }
1954 if (*p == '\n')
1955 ++p;
1956 }
1957
1958 /* Copy from end to make sure significant portions are included.
1959 This implies that in the browser a regular expressing of the form
1960 `^.*{regexp}' has to be used. */
1961 for (s = end_buf - 1, t = in; s > buffer && t > p;)
1962 {
1963 *--s = *--t;
1964
1965 if (*s == '"')
1966 *--s = '\\';
1967 }
1968
1969 *(end_buf - 1) = '\0';
1970 return xstrdup (s);
1971}
1972
1973
1974/* Return a printable representation of token T. */
1975
1976char *
1977token_string (t)
1978 int t;
1979{
1980 static char b[3];
1981
1982 switch (t)
1983 {
1984 case CSTRING: return "string constant";
1985 case CCHAR: return "char constant";
1986 case CINT: return "int constant";
1987 case CFLOAT: return "floating constant";
1988 case ELLIPSIS: return "...";
1989 case LSHIFTASGN: return "<<=";
1990 case RSHIFTASGN: return ">>=";
1991 case ARROWSTAR: return "->*";
1992 case IDENT: return "identifier";
1993 case DIVASGN: return "/=";
1994 case INC: return "++";
1995 case ADDASGN: return "+=";
1996 case DEC: return "--";
1997 case ARROW: return "->";
1998 case SUBASGN: return "-=";
1999 case MULASGN: return "*=";
2000 case MODASGN: return "%=";
2001 case LOR: return "||";
2002 case ORASGN: return "|=";
2003 case LAND: return "&&";
2004 case ANDASGN: return "&=";
2005 case XORASGN: return "^=";
2006 case POINTSTAR: return ".*";
2007 case DCOLON: return "::";
2008 case EQ: return "==";
2009 case NE: return "!=";
2010 case LE: return "<=";
2011 case LSHIFT: return "<<";
2012 case GE: return ">=";
2013 case RSHIFT: return ">>";
2014 case ASM: return "asm";
2015 case AUTO: return "auto";
2016 case BREAK: return "break";
2017 case CASE: return "case";
2018 case CATCH: return "catch";
2019 case CHAR: return "char";
2020 case CLASS: return "class";
2021 case CONST: return "const";
2022 case CONTINUE: return "continue";
2023 case DEFAULT: return "default";
2024 case DELETE: return "delete";
2025 case DO: return "do";
2026 case DOUBLE: return "double";
2027 case ELSE: return "else";
2028 case ENUM: return "enum";
2029 case EXTERN: return "extern";
2030 case FLOAT: return "float";
2031 case FOR: return "for";
2032 case FRIEND: return "friend";
2033 case GOTO: return "goto";
2034 case IF: return "if";
2035 case T_INLINE: return "inline";
2036 case INT: return "int";
2037 case LONG: return "long";
2038 case NEW: return "new";
2039 case OPERATOR: return "operator";
2040 case PRIVATE: return "private";
2041 case PROTECTED: return "protected";
2042 case PUBLIC: return "public";
2043 case REGISTER: return "register";
2044 case RETURN: return "return";
2045 case SHORT: return "short";
2046 case SIGNED: return "signed";
2047 case SIZEOF: return "sizeof";
2048 case STATIC: return "static";
2049 case STRUCT: return "struct";
2050 case SWITCH: return "switch";
2051 case TEMPLATE: return "template";
2052 case THIS: return "this";
2053 case THROW: return "throw";
2054 case TRY: return "try";
2055 case TYPEDEF: return "typedef";
2056 case UNION: return "union";
2057 case UNSIGNED: return "unsigned";
2058 case VIRTUAL: return "virtual";
2059 case VOID: return "void";
2060 case VOLATILE: return "volatile";
2061 case WHILE: return "while";
2062 case YYEOF: return "EOF";
2063 }
2064
2065 assert (t < 255);
2066 b[0] = t;
2067 b[1] = '\0';
2068 return b;
2069}
2070
2071
2072/* Reinitialize the scanner for a new input file. */
2073
2074void
2075re_init_scanner ()
2076{
2077 in = inbuffer;
2078 yyline = 1;
2079
2080 if (yytext == NULL)
2081 {
2082 int size = 256;
2083 yytext = (char *) xmalloc (size * sizeof *yytext);
2084 yytext_end = yytext + size;
2085 }
2086}
2087
2088
2089/* Insert a keyword NAME with token value TK into the keyword hash
2090 table. */
2091
2092void
2093insert_keyword (name, tk)
2094 char *name;
2095 int tk;
2096{
2097 char *s;
2098 unsigned h = 0;
2099 struct kw *k = (struct kw *) xmalloc (sizeof *k);
2100
2101 for (s = name; *s; ++s)
2102 h = (h << 1) ^ *s;
2103
2104 h %= KEYWORD_TABLE_SIZE;
2105 k->name = name;
2106 k->tk = tk;
2107 k->next = keyword_table[h];
2108 keyword_table[h] = k;
2109}
2110
2111
2112/* Initialize the scanner for the first file. This sets up the
2113 character class vectors and fills the keyword hash table. */
2114
2115void
2116init_scanner ()
2117{
2118 int i;
2119
2120 /* Allocate the input buffer */
2121 inbuffer_size = READ_CHUNK_SIZE + 1;
2122 inbuffer = in = (char *) xmalloc (inbuffer_size);
2123 yyline = 1;
2124
2125 /* Set up character class vectors. */
2126 for (i = 0; i < sizeof is_ident; ++i)
2127 {
2128 if (i == '_' || isalnum (i))
2129 is_ident[i] = 1;
2130
2131 if (i >= '0' && i <= '9')
2132 is_digit[i] = 1;
2133
2134 if (i == ' ' || i == '\t' || i == '\f' || i == '\v')
2135 is_white[i] = 1;
2136 }
2137
2138 /* Fill keyword hash table. */
2139 insert_keyword ("and", LAND);
2140 insert_keyword ("and_eq", ANDASGN);
2141 insert_keyword ("asm", ASM);
2142 insert_keyword ("auto", AUTO);
2143 insert_keyword ("bitand", '&');
2144 insert_keyword ("bitor", '|');
2145 insert_keyword ("bool", BOOL);
2146 insert_keyword ("break", BREAK);
2147 insert_keyword ("case", CASE);
2148 insert_keyword ("catch", CATCH);
2149 insert_keyword ("char", CHAR);
2150 insert_keyword ("class", CLASS);
2151 insert_keyword ("compl", '~');
2152 insert_keyword ("const", CONST);
2153 insert_keyword ("const_cast", CONST_CAST);
2154 insert_keyword ("continue", CONTINUE);
2155 insert_keyword ("default", DEFAULT);
2156 insert_keyword ("delete", DELETE);
2157 insert_keyword ("do", DO);
2158 insert_keyword ("double", DOUBLE);
2159 insert_keyword ("dynamic_cast", DYNAMIC_CAST);
2160 insert_keyword ("else", ELSE);
2161 insert_keyword ("enum", ENUM);
2162 insert_keyword ("explicit", EXPLICIT);
2163 insert_keyword ("extern", EXTERN);
2164 insert_keyword ("false", FALSE);
2165 insert_keyword ("float", FLOAT);
2166 insert_keyword ("for", FOR);
2167 insert_keyword ("friend", FRIEND);
2168 insert_keyword ("goto", GOTO);
2169 insert_keyword ("if", IF);
2170 insert_keyword ("inline", T_INLINE);
2171 insert_keyword ("int", INT);
2172 insert_keyword ("long", LONG);
2173 insert_keyword ("mutable", MUTABLE);
2174 insert_keyword ("namespace", NAMESPACE);
2175 insert_keyword ("new", NEW);
2176 insert_keyword ("not", '!');
2177 insert_keyword ("not_eq", NE);
2178 insert_keyword ("operator", OPERATOR);
2179 insert_keyword ("or", LOR);
2180 insert_keyword ("or_eq", ORASGN);
2181 insert_keyword ("private", PRIVATE);
2182 insert_keyword ("protected", PROTECTED);
2183 insert_keyword ("public", PUBLIC);
2184 insert_keyword ("register", REGISTER);
2185 insert_keyword ("reinterpret_cast", REINTERPRET_CAST);
2186 insert_keyword ("return", RETURN);
2187 insert_keyword ("short", SHORT);
2188 insert_keyword ("signed", SIGNED);
2189 insert_keyword ("sizeof", SIZEOF);
2190 insert_keyword ("static", STATIC);
2191 insert_keyword ("static_cast", STATIC_CAST);
2192 insert_keyword ("struct", STRUCT);
2193 insert_keyword ("switch", SWITCH);
2194 insert_keyword ("template", TEMPLATE);
2195 insert_keyword ("this", THIS);
2196 insert_keyword ("throw", THROW);
2197 insert_keyword ("true", TRUE);
2198 insert_keyword ("try", TRY);
2199 insert_keyword ("typedef", TYPEDEF);
2200 insert_keyword ("typeid", TYPEID);
2201 insert_keyword ("typename", TYPENAME);
2202 insert_keyword ("union", UNION);
2203 insert_keyword ("unsigned", UNSIGNED);
2204 insert_keyword ("using", USING);
2205 insert_keyword ("virtual", VIRTUAL);
2206 insert_keyword ("void", VOID);
2207 insert_keyword ("volatile", VOLATILE);
2208 insert_keyword ("wchar_t", WCHAR);
2209 insert_keyword ("while", WHILE);
2210 insert_keyword ("xor", '^');
2211 insert_keyword ("xor_eq", XORASGN);
2212}
2213
2214
2215
2216/***********************************************************************
2217 Parser
2218 ***********************************************************************/
2219
2220/* Match the current lookahead token and set it to the next token. */
2221
2222#define MATCH() (tk = yylex ())
2223
2224/* Return the lookahead token. If current lookahead token is cleared,
2225 read a new token. */
2226
2227#define LA1 (tk == -1 ? (tk = yylex ()) : tk)
2228
2229/* Is the current lookahead equal to the token T? */
2230
2231#define LOOKING_AT(T) (tk == (T))
2232
2233/* Is the current lookahead one of T1 or T2? */
2234
2235#define LOOKING_AT2(T1, T2) (tk == (T1) || tk == (T2))
2236
2237/* Is the current lookahead one of T1, T2 or T3? */
2238
2239#define LOOKING_AT3(T1, T2, T3) (tk == (T1) || tk == (T2) || tk == (T3))
2240
2241/* Is the current lookahead one of T1...T4? */
2242
2243#define LOOKING_AT4(T1, T2, T3, T4) \
2244 (tk == (T1) || tk == (T2) || tk == (T3) || tk == (T4))
2245
2246/* Match token T if current lookahead is T. */
2247
2248#define MATCH_IF(T) if (LOOKING_AT (T)) MATCH (); else ((void) 0)
2249
2250/* Skip to matching token if current token is T. */
2251
2252#define SKIP_MATCHING_IF(T) \
2253 if (LOOKING_AT (T)) skip_matching (); else ((void) 0)
2254
2255
2256/* Skip forward until a given token TOKEN or YYEOF is seen and return
2257 the current lookahead token after skipping. */
2258
2259int
2260skip_to (token)
2261 int token;
2262{
2263 while (!LOOKING_AT2 (YYEOF, token))
2264 MATCH ();
2265 return tk;
2266}
2267
2268
2269/* Skip over pairs of tokens (parentheses, square brackets,
2270 angle brackets, curly brackets) matching the current lookahead. */
2271
2272void
2273skip_matching ()
2274{
2275 int open, close, n;
2276
2277 switch (open = LA1)
2278 {
2279 case '{':
2280 close = '}';
2281 break;
2282
2283 case '(':
2284 close = ')';
2285 break;
2286
2287 case '<':
2288 close = '>';
2289 break;
2290
2291 case '[':
2292 close = ']';
2293 break;
2294
2295 default:
2296 abort ();
2297 }
2298
2299 for (n = 0;;)
2300 {
2301 if (LOOKING_AT (open))
2302 ++n;
2303 else if (LOOKING_AT (close))
2304 --n;
2305 else if (LOOKING_AT (YYEOF))
2306 break;
2307
2308 MATCH ();
2309
2310 if (n == 0)
2311 break;
2312 }
2313}
2314
2315
2316/* Re-initialize the parser by resetting the lookahead token. */
2317
2318void
2319re_init_parser ()
2320{
2321 tk = -1;
2322}
2323
2324
2325/* Parse a parameter list, including the const-specifier,
2326 pure-specifier, and throw-list that may follow a parameter list.
2327 Return in FLAGS what was seen following the parameter list.
2328 Returns a hash code for the parameter types. This value is used to
2329 distinguish between overloaded functions. */
2330
2331unsigned
2332parm_list (flags)
2333 int *flags;
2334{
2335 unsigned hash = 0;
2336 int type_seen = 0;
2337
2338 while (!LOOKING_AT2 (YYEOF, ')'))
2339 {
2340 switch (LA1)
2341 {
2342 /* Skip over grouping parens or parameter lists in parameter
2343 declarations. */
2344 case '(':
2345 skip_matching ();
2346 break;
2347
2348 /* Next parameter. */
2349 case ',':
2350 MATCH ();
2351 type_seen = 0;
2352 break;
2353
2354 /* Ignore the scope part of types, if any. This is because
2355 some types need scopes when defined outside of a class body,
2356 and don't need them inside the class body. This means that
2357 we have to look for the last IDENT in a sequence of
2358 IDENT::IDENT::... */
2359 case IDENT:
2360 if (!type_seen)
2361 {
2362 char *s;
2363 unsigned ident_type_hash = 0;
2364
2365 parse_qualified_param_ident_or_type (&s);
2366 for (; *s; ++s)
2367 ident_type_hash = (ident_type_hash << 1) ^ *s;
2368 hash = (hash << 1) ^ ident_type_hash;
2369 type_seen = 1;
2370 }
2371 else
2372 MATCH ();
2373 break;
2374
2375 case VOID:
2376 /* This distinction is made to make `func (void)' equivalent
2377 to `func ()'. */
2378 type_seen = 1;
2379 MATCH ();
2380 if (!LOOKING_AT (')'))
2381 hash = (hash << 1) ^ VOID;
2382 break;
2383
2384 case BOOL: case CHAR: case CLASS: case CONST:
2385 case DOUBLE: case ENUM: case FLOAT: case INT:
2386 case LONG: case SHORT: case SIGNED: case STRUCT:
2387 case UNION: case UNSIGNED: case VOLATILE: case WCHAR:
2388 case ELLIPSIS:
2389 type_seen = 1;
2390 hash = (hash << 1) ^ LA1;
2391 MATCH ();
2392 break;
2393
2394 case '*': case '&': case '[': case ']':
2395 hash = (hash << 1) ^ LA1;
2396 MATCH ();
2397 break;
2398
2399 default:
2400 MATCH ();
2401 break;
2402 }
2403 }
2404
2405 if (LOOKING_AT (')'))
2406 {
2407 MATCH ();
2408
2409 if (LOOKING_AT (CONST))
2410 {
2411 /* We can overload the same function on `const' */
2412 hash = (hash << 1) ^ CONST;
2413 SET_FLAG (*flags, F_CONST);
2414 MATCH ();
2415 }
2416
2417 if (LOOKING_AT (THROW))
2418 {
2419 MATCH ();
2420 SKIP_MATCHING_IF ('(');
2421 SET_FLAG (*flags, F_THROW);
2422 }
2423
2424 if (LOOKING_AT ('='))
2425 {
2426 MATCH ();
2427 if (LOOKING_AT (CINT) && yyival == 0)
2428 {
2429 MATCH ();
2430 SET_FLAG (*flags, F_PURE);
2431 }
2432 }
2433 }
2434
2435 return hash;
2436}
2437
2438
2439/* Print position info to stdout. */
2440
2441void
2442print_info ()
2443{
2444 if (info_position >= 0 && BUFFER_POS () <= info_position)
2445 if (info_cls)
2446 printf ("(\"%s\" \"%s\" \"%s\" %d)\n",
2447 info_cls->name, sym_scope (info_cls),
2448 info_member->name, info_where);
2449}
2450
2451
2452/* Parse a member declaration within the class body of CLS. VIS is
2453 the access specifier for the member (private, protected,
2454 public). */
2455
2456void
2457member (cls, vis)
2458 struct sym *cls;
2459 int vis;
2460{
2461 char *id = NULL;
2462 int sc = SC_MEMBER;
2463 char *regexp = NULL;
2464 int pos;
2465 int is_constructor;
2466 int anonymous = 0;
2467 int flags = 0;
2468 int class_tag;
2469 int type_seen = 0;
2470 int paren_seen = 0;
2471 unsigned hash = 0;
2472 int tilde = 0;
2473
2474 while (!LOOKING_AT4 (';', '{', '}', YYEOF))
2475 {
2476 switch (LA1)
2477 {
2478 default:
2479 MATCH ();
2480 break;
2481
2482 /* A function or class may follow. */
2483 case TEMPLATE:
2484 MATCH();
2485 SET_FLAG (flags, F_TEMPLATE);
2486 /* Skip over template argument list */
2487 SKIP_MATCHING_IF ('<');
2488 break;
2489
2490 case EXPLICIT:
2491 SET_FLAG (flags, F_EXPLICIT);
2492 goto typeseen;
2493
2494 case MUTABLE:
2495 SET_FLAG (flags, F_MUTABLE);
2496 goto typeseen;
2497
2498 case T_INLINE:
2499 SET_FLAG (flags, F_INLINE);
2500 goto typeseen;
2501
2502 case VIRTUAL:
2503 SET_FLAG (flags, F_VIRTUAL);
2504 goto typeseen;
2505
2506 case '[':
2507 skip_matching ();
2508 break;
2509
2510 case ENUM:
2511 sc = SC_TYPE;
2512 goto typeseen;
2513
2514 case TYPEDEF:
2515 sc = SC_TYPE;
2516 goto typeseen;
2517
2518 case FRIEND:
2519 sc = SC_FRIEND;
2520 goto typeseen;
2521
2522 case STATIC:
2523 sc = SC_STATIC;
2524 goto typeseen;
2525
2526 case '~':
2527 tilde = 1;
2528 MATCH ();
2529 break;
2530
2531 case IDENT:
2532 /* Remember IDENTS seen so far. Among these will be the member
2533 name. */
2534 id = (char *) alloca (strlen (yytext) + 2);
2535 if (tilde)
2536 {
2537 *id = '~';
2538 strcpy (id + 1, yytext);
2539 }
2540 else
2541 strcpy (id, yytext);
2542 MATCH ();
2543 break;
2544
2545 case OPERATOR:
2546 id = operator_name (&sc);
2547 break;
2548
2549 case '(':
2550 /* Most probably the beginning of a parameter list. */
2551 MATCH ();
2552 paren_seen = 1;
2553
2554 if (id && cls)
2555 {
2556 if (!(is_constructor = streq (id, cls->name)))
2557 regexp = matching_regexp ();
2558 }
2559 else
2560 is_constructor = 0;
2561
2562 pos = BUFFER_POS ();
2563 hash = parm_list (&flags);
2564
2565 if (is_constructor)
2566 regexp = matching_regexp ();
2567
2568 if (id && cls != NULL)
2569 add_member_decl (cls, id, regexp, pos, hash, 0, sc, vis, flags);
2570
2571 while (!LOOKING_AT3 (';', '{', YYEOF))
2572 MATCH ();
2573
2574 if (LOOKING_AT ('{') && id && cls)
2575 add_member_defn (cls, id, regexp, pos, hash, 0, sc, flags);
2576
2577 id = NULL;
2578 sc = SC_MEMBER;
2579 break;
2580
2581 case STRUCT: case UNION: case CLASS:
2582 /* Nested class */
2583 class_tag = LA1;
2584 type_seen = 1;
2585 MATCH ();
2586 anonymous = 1;
2587
2588 /* More than one ident here to allow for MS-DOS specialties
2589 like `_export class' etc. The last IDENT seen counts
2590 as the class name. */
2591 while (!LOOKING_AT4 (YYEOF, ';', ':', '{'))
2592 {
2593 if (LOOKING_AT (IDENT))
2594 anonymous = 0;
2595 MATCH ();
2596 }
2597
2598 if (LOOKING_AT2 (':', '{'))
2599 class_definition (anonymous ? NULL : cls, class_tag, flags, 1);
2600 else
2601 skip_to (';');
2602 break;
2603
2604 case INT: case CHAR: case LONG: case UNSIGNED:
2605 case SIGNED: case CONST: case DOUBLE: case VOID:
2606 case SHORT: case VOLATILE: case BOOL: case WCHAR:
2607 case TYPENAME:
2608 typeseen:
2609 type_seen = 1;
2610 MATCH ();
2611 break;
2612 }
2613 }
2614
2615 if (LOOKING_AT (';'))
2616 {
2617 /* The end of a member variable, a friend declaration or an access
2618 declaration. We don't want to add friend classes as members. */
2619 if (id && sc != SC_FRIEND && cls)
2620 {
2621 regexp = matching_regexp ();
2622 pos = BUFFER_POS ();
2623
2624 if (cls != NULL)
2625 {
2626 if (type_seen || !paren_seen)
2627 add_member_decl (cls, id, regexp, pos, 0, 1, sc, vis, 0);
2628 else
2629 add_member_decl (cls, id, regexp, pos, hash, 0, sc, vis, 0);
2630 }
2631 }
2632
2633 MATCH ();
2634 print_info ();
2635 }
2636 else if (LOOKING_AT ('{'))
2637 {
2638 /* A named enum. */
2639 if (sc == SC_TYPE && id && cls)
2640 {
2641 regexp = matching_regexp ();
2642 pos = BUFFER_POS ();
2643
2644 if (cls != NULL)
2645 {
2646 add_member_decl (cls, id, regexp, pos, 0, 1, sc, vis, 0);
2647 add_member_defn (cls, id, regexp, pos, 0, 1, sc, 0);
2648 }
2649 }
2650
2651 skip_matching ();
2652 print_info ();
2653 }
2654}
2655
2656
2657/* Parse the body of class CLS. TAG is the tag of the class (struct,
2658 union, class). */
2659
2660void
2661class_body (cls, tag)
2662 struct sym *cls;
2663 int tag;
2664{
2665 int vis = tag == CLASS ? PRIVATE : PUBLIC;
2666 int temp;
2667
2668 while (!LOOKING_AT2 (YYEOF, '}'))
2669 {
2670 switch (LA1)
2671 {
2672 case PRIVATE: case PROTECTED: case PUBLIC:
2673 temp = LA1;
2674 MATCH ();
2675
2676 if (LOOKING_AT (':'))
2677 {
2678 vis = temp;
2679 MATCH ();
2680 }
2681 else
2682 {
2683 /* Probably conditional compilation for inheritance list.
2684 We don't known whether there comes more of this.
2685 This is only a crude fix that works most of the time. */
2686 do
2687 {
2688 MATCH ();
2689 }
2690 while (LOOKING_AT2 (IDENT, ',')
2691 || LOOKING_AT3 (PUBLIC, PROTECTED, PRIVATE));
2692 }
2693 break;
2694
2695 case TYPENAME:
2696 case USING:
2697 skip_to (';');
2698 break;
2699
2700 /* Try to synchronize */
2701 case CHAR: case CLASS: case CONST:
2702 case DOUBLE: case ENUM: case FLOAT: case INT:
2703 case LONG: case SHORT: case SIGNED: case STRUCT:
2704 case UNION: case UNSIGNED: case VOID: case VOLATILE:
2705 case TYPEDEF: case STATIC: case T_INLINE: case FRIEND:
2706 case VIRTUAL: case TEMPLATE: case IDENT: case '~':
2707 case BOOL: case WCHAR: case EXPLICIT: case MUTABLE:
2708 member (cls, vis);
2709 break;
2710
2711 default:
2712 MATCH ();
2713 break;
2714 }
2715 }
2716}
2717
2718
2719/* Parse a qualified identifier. Current lookahead is IDENT. A
2720 qualified ident has the form `X<..>::Y<...>::T<...>. Returns a
2721 symbol for that class. */
2722
2723struct sym *
2724parse_classname ()
2725{
2726 struct sym *last_class = NULL;
2727
2728 while (LOOKING_AT (IDENT))
2729 {
2730 last_class = add_sym (yytext, last_class);
2731 MATCH ();
2732
2733 if (LOOKING_AT ('<'))
2734 {
2735 skip_matching ();
2736 SET_FLAG (last_class->flags, F_TEMPLATE);
2737 }
2738
2739 if (!LOOKING_AT (DCOLON))
2740 break;
2741
2742 MATCH ();
2743 }
2744
2745 return last_class;
2746}
2747
2748
2749/* Parse an operator name. Add the `static' flag to *SC if an
2750 implicitly static operator has been parsed. Value is a pointer to
2751 a static buffer holding the constructed operator name string. */
2752
2753char *
2754operator_name (sc)
2755 int *sc;
2756{
2757 static int id_size = 0;
2758 static char *id = NULL;
2759 char *s;
2760 int len;
2761
2762 MATCH ();
2763
2764 if (LOOKING_AT2 (NEW, DELETE))
2765 {
2766 /* `new' and `delete' are implicitly static. */
2767 if (*sc != SC_FRIEND)
2768 *sc = SC_STATIC;
2769
2770 s = token_string (LA1);
2771 MATCH ();
2772
2773 len = strlen (s) + 10;
2774 if (len > id_size)
2775 {
2776 int new_size = max (len, 2 * id_size);
2777 id = (char *) xrealloc (id, new_size);
2778 id_size = new_size;
2779 }
2780 strcpy (id, s);
2781
2782 /* Vector new or delete? */
2783 if (LOOKING_AT ('['))
2784 {
2785 strcat (id, "[");
2786 MATCH ();
2787
2788 if (LOOKING_AT (']'))
2789 {
2790 strcat (id, "]");
2791 MATCH ();
2792 }
2793 }
2794 }
2795 else
2796 {
2797 int tokens_matched = 0;
2798
2799 len = 20;
2800 if (len > id_size)
2801 {
2802 int new_size = max (len, 2 * id_size);
2803 id = (char *) xrealloc (id, new_size);
2804 id_size = new_size;
2805 }
2806 strcpy (id, "operator");
2807
2808 /* Beware access declarations of the form "X::f;" Beware of
2809 `operator () ()'. Yet another difficulty is found in
2810 GCC 2.95's STL: `operator == __STL_NULL_TMPL_ARGS (...'. */
2811 while (!(LOOKING_AT ('(') && tokens_matched)
2812 && !LOOKING_AT2 (';', YYEOF))
2813 {
2814 s = token_string (LA1);
2815 len += strlen (s) + 2;
2816 if (len > id_size)
2817 {
2818 int new_size = max (len, 2 * id_size);
2819 id = (char *) xrealloc (id, new_size);
2820 id_size = new_size;
2821 }
2822
2823 if (*s != ')' && *s != ']')
2824 strcat (id, " ");
2825 strcat (id, s);
2826 MATCH ();
2827
2828 /* If this is a simple operator like `+', stop now. */
2829 if (!isalpha (*s) && *s != '(' && *s != '[')
2830 break;
2831
2832 ++tokens_matched;
2833 }
2834 }
2835
2836 return id;
2837}
2838
2839
2840/* This one consumes the last IDENT of a qualified member name like
2841 `X::Y::z'. This IDENT is returned in LAST_ID. Value if the
2842 symbol structure for the ident. */
2843
2844struct sym *
2845parse_qualified_ident_or_type (last_id)
2846 char **last_id;
2847{
2848 struct sym *cls = NULL;
2849 static char *id = NULL;
2850 static int id_size = 0;
2851
2852 while (LOOKING_AT (IDENT))
2853 {
2854 int len = strlen (yytext) + 1;
2855 if (len > id_size)
2856 {
2857 id = (char *) xrealloc (id, len);
2858 id_size = len;
2859 }
2860 strcpy (id, yytext);
2861 *last_id = id;
2862 MATCH ();
2863
2864 SKIP_MATCHING_IF ('<');
2865
2866 if (LOOKING_AT (DCOLON))
2867 {
2868 cls = add_sym (id, cls);
2869 *last_id = NULL;
2870 MATCH ();
2871 }
2872 else
2873 break;
2874 }
2875
2876 return cls;
2877}
2878
2879
2880/* This one consumes the last IDENT of a qualified member name like
2881 `X::Y::z'. This IDENT is returned in LAST_ID. Value if the
2882 symbol structure for the ident. */
2883
2884void
2885parse_qualified_param_ident_or_type (last_id)
2886 char **last_id;
2887{
2888 struct sym *cls = NULL;
2889 static char *id = NULL;
2890 static int id_size = 0;
2891
2892 while (LOOKING_AT (IDENT))
2893 {
2894 int len = strlen (yytext) + 1;
2895 if (len > id_size)
2896 {
2897 id = (char *) xrealloc (id, len);
2898 id_size = len;
2899 }
2900 strcpy (id, yytext);
2901 *last_id = id;
2902 MATCH ();
2903
2904 SKIP_MATCHING_IF ('<');
2905
2906 if (LOOKING_AT (DCOLON))
2907 {
2908 cls = add_sym (id, cls);
2909 *last_id = NULL;
2910 MATCH ();
2911 }
2912 else
2913 break;
2914 }
2915}
2916
2917
2918/* Parse a class definition.
2919
2920 CONTAINING is the class containing the class being parsed or null.
2921 This may also be null if NESTED != 0 if the containing class is
2922 anonymous. TAG is the tag of the class (struct, union, class).
2923 NESTED is non-zero if we are parsing a nested class.
2924
2925 Current lookahead is the class name. */
2926
2927void
2928class_definition (containing, tag, flags, nested)
2929 struct sym *containing;
2930 int tag;
2931 int flags;
2932 int nested;
2933{
2934 register int token;
2935 struct sym *current;
2936 struct sym *base_class;
2937
2938 /* Set CURRENT to null if no entry has to be made for the class
2939 parsed. This is the case for certain command line flag
2940 settings. */
2941 if ((tag != CLASS && !f_structs) || (nested && !f_nested_classes))
2942 current = NULL;
2943 else
2944 {
2945 current = add_sym (yytext, containing);
2946 current->pos = BUFFER_POS ();
2947 current->regexp = matching_regexp ();
2948 current->filename = filename;
2949 current->flags = flags;
2950 }
2951
2952 /* If at ':', base class list follows. */
2953 if (LOOKING_AT (':'))
2954 {
2955 int done = 0;
2956 MATCH ();
2957
2958 while (!done)
2959 {
2960 switch (token = LA1)
2961 {
2962 case VIRTUAL: case PUBLIC: case PROTECTED: case PRIVATE:
2963 MATCH ();
2964 break;
2965
2966 case IDENT:
2967 base_class = parse_classname ();
2968 if (base_class && current && base_class != current)
2969 add_link (base_class, current);
2970 break;
2971
2972 /* The `,' between base classes or the end of the base
2973 class list. Add the previously found base class.
2974 It's done this way to skip over sequences of
2975 `A::B::C' until we reach the end.
2976
2977 FIXME: it is now possible to handle `class X : public B::X'
2978 because we have enough information. */
2979 case ',':
2980 MATCH ();
2981 break;
2982
2983 default:
2984 /* A syntax error, possibly due to preprocessor constructs
2985 like
2986
2987 #ifdef SOMETHING
2988 class A : public B
2989 #else
2990 class A : private B.
2991
2992 MATCH until we see something like `;' or `{'. */
2993 while (!LOOKING_AT3 (';', YYEOF, '{'))
2994 MATCH ();
2995 done = 1;
2996
2997 case '{':
2998 done = 1;
2999 break;
3000 }
3001 }
3002 }
3003
3004 /* Parse the class body if there is one. */
3005 if (LOOKING_AT ('{'))
3006 {
3007 if (tag != CLASS && !f_structs)
3008 skip_matching ();
3009 else
3010 {
3011 MATCH ();
3012 class_body (current, tag);
3013
3014 if (LOOKING_AT ('}'))
3015 {
3016 MATCH ();
3017 if (LOOKING_AT (';') && !nested)
3018 MATCH ();
3019 }
3020 }
3021 }
3022}
3023
3024
3025/* Parse a declaration. */
3026
3027void
3028declaration (is_extern, flags)
3029 int is_extern;
3030 int flags;
3031{
3032 char *id = NULL;
3033 struct sym *cls = NULL;
3034 char *regexp = NULL;
3035 int pos = 0;
3036 unsigned hash = 0;
3037 int is_constructor;
3038 int sc = 0;
3039
3040 while (!LOOKING_AT3 (';', '{', YYEOF))
3041 {
3042 switch (LA1)
3043 {
3044 default:
3045 MATCH ();
3046 break;
3047
3048 case '[':
3049 skip_matching ();
3050 break;
3051
3052 case ENUM:
3053 case TYPEDEF:
3054 sc = SC_TYPE;
3055 MATCH ();
3056 break;
3057
3058 case STATIC:
3059 sc = SC_STATIC;
3060 MATCH ();
3061 break;
3062
3063 case INT: case CHAR: case LONG: case UNSIGNED:
3064 case SIGNED: case CONST: case DOUBLE: case VOID:
3065 case SHORT: case VOLATILE: case BOOL: case WCHAR:
3066 MATCH ();
3067 break;
3068
3069 case CLASS: case STRUCT: case UNION:
3070 /* This is for the case `STARTWRAP class X : ...' or
3071 `declare (X, Y)\n class A : ...'. */
3072 if (id)
3073 return;
3074
3075 case '=':
3076 /* Assumed to be the start of an initialization in this context.
3077 Skip over everything up to ';'. */
3078 skip_to (';');
3079 break;
3080
3081 case OPERATOR:
3082 id = operator_name (&sc);
3083 break;
3084
3085 case T_INLINE:
3086 SET_FLAG (flags, F_INLINE);
3087 MATCH ();
3088 break;
3089
3090 case '~':
3091 MATCH ();
3092 if (LOOKING_AT (IDENT))
3093 {
3094 id = (char *) alloca (strlen (yytext) + 2);
3095 *id = '~';
3096 strcpy (id + 1, yytext);
3097 MATCH ();
3098 }
3099 break;
3100
3101 case IDENT:
3102 cls = parse_qualified_ident_or_type (&id);
3103 break;
3104
3105 case '(':
3106 /* Most probably the beginning of a parameter list. */
3107 if (cls)
3108 {
3109 MATCH ();
3110
3111 if (id && cls)
3112 {
3113 if (!(is_constructor = streq (id, cls->name)))
3114 regexp = matching_regexp ();
3115 }
3116 else
3117 is_constructor = 0;
3118
3119 pos = BUFFER_POS ();
3120 hash = parm_list (&flags);
3121
3122 if (is_constructor)
3123 regexp = matching_regexp ();
3124
3125 if (id && cls)
3126 add_member_defn (cls, id, regexp, pos, hash, 0,
3127 SC_UNKNOWN, flags);
3128 }
3129 else
3130 {
3131 /* This may be a C functions, but also a macro
3132 call of the form `declare (A, B)' --- such macros
3133 can be found in some class libraries. */
3134 MATCH ();
3135
3136 if (id)
3137 {
3138 regexp = matching_regexp ();
3139 pos = BUFFER_POS ();
3140 hash = parm_list (&flags);
3141 add_global_decl (id, regexp, pos, hash, 0, sc, flags);
3142 }
3143
3144 /* This is for the case that the function really is
3145 a macro with no `;' following it. If a CLASS directly
3146 follows, we would miss it otherwise. */
3147 if (LOOKING_AT3 (CLASS, STRUCT, UNION))
3148 return;
3149 }
3150
3151 while (!LOOKING_AT3 (';', '{', YYEOF))
3152 MATCH ();
3153
3154 if (!cls && id && LOOKING_AT ('{'))
3155 add_global_defn (id, regexp, pos, hash, 0, sc, flags);
3156 id = NULL;
3157 break;
3158 }
3159 }
3160
3161 if (LOOKING_AT (';'))
3162 {
3163 /* The end of a member variable or of an access declaration
3164 `X::f'. To distinguish between them we have to know whether
3165 type information has been seen. */
3166 if (id)
3167 {
3168 char *regexp = matching_regexp ();
3169 int pos = BUFFER_POS ();
3170
3171 if (cls)
3172 add_member_defn (cls, id, regexp, pos, 0, 1, SC_UNKNOWN, flags);
3173 else
3174 add_global_defn (id, regexp, pos, 0, 1, sc, flags);
3175 }
3176
3177 MATCH ();
3178 print_info ();
3179 }
3180 else if (LOOKING_AT ('{'))
3181 {
3182 if (sc == SC_TYPE && id)
3183 {
3184 /* A named enumeration. */
3185 regexp = matching_regexp ();
3186 pos = BUFFER_POS ();
3187 add_global_defn (id, regexp, pos, 0, 1, sc, flags);
3188 }
3189
3190 skip_matching ();
3191 print_info ();
3192 }
3193}
3194
3195
3196/* Parse a list of top-level declarations/definitions. START_FLAGS
3197 says in which context we are parsing. If it is F_EXTERNC, we are
3198 parsing in an `extern "C"' block. Value is 1 if EOF is reached, 0
3199 otherwise. */
3200
3201int
3202globals (start_flags)
3203 int start_flags;
3204{
3205 int anonymous;
3206 int class_tk;
3207 int flags = start_flags;
3208
3209 for (;;)
3210 {
3211 char *prev_in = in;
3212
3213 switch (LA1)
3214 {
3215 case NAMESPACE:
3216 {
3217 MATCH ();
3218
3219 if (LOOKING_AT (IDENT))
3220 {
3221 char *namespace_name
3222 = (char *) alloca (strlen (yytext) + 1);
3223 strcpy (namespace_name, yytext);
3224 MATCH ();
3225
3226 if (LOOKING_AT ('='))
3227 {
3228 if (skip_to (';') == ';')
3229 MATCH ();
3230 register_namespace_alias (namespace_name, yytext);
3231 }
3232 else if (LOOKING_AT ('{'))
3233 {
3234 MATCH ();
3235 enter_namespace (namespace_name);
3236 globals (0);
3237 leave_namespace ();
3238 MATCH_IF ('}');
3239 }
3240 }
3241 }
3242 break;
3243
3244 case EXTERN:
3245 MATCH ();
3246 if (LOOKING_AT (CSTRING) && *string_start == 'C'
3247 && *(string_start + 1) == '"')
3248 {
3249 /* This is `extern "C"'. */
3250 MATCH ();
3251
3252 if (LOOKING_AT ('{'))
3253 {
3254 MATCH ();
3255 globals (F_EXTERNC);
3256 MATCH_IF ('}');
3257 }
3258 else
3259 SET_FLAG (flags, F_EXTERNC);
3260 }
3261 break;
3262
3263 case TEMPLATE:
3264 MATCH ();
3265 SKIP_MATCHING_IF ('<');
3266 SET_FLAG (flags, F_TEMPLATE);
3267 break;
3268
3269 case CLASS: case STRUCT: case UNION:
3270 class_tk = LA1;
3271 MATCH ();
3272 anonymous = 1;
3273
3274 /* More than one ident here to allow for MS-DOS and OS/2
3275 specialties like `far', `_Export' etc. Some C++ libs
3276 have constructs like `_OS_DLLIMPORT(_OS_CLIENT)' in front
3277 of the class name. */
3278 while (!LOOKING_AT4 (YYEOF, ';', ':', '{'))
3279 {
3280 if (LOOKING_AT (IDENT))
3281 anonymous = 0;
3282 MATCH ();
3283 }
3284
3285 /* Don't add anonymous unions. */
3286 if (LOOKING_AT2 (':', '{') && !anonymous)
3287 class_definition (NULL, class_tk, flags, 0);
3288 else
3289 {
3290 if (skip_to (';') == ';')
3291 MATCH ();
3292 }
3293
3294 flags = start_flags;
3295 break;
3296
3297 case YYEOF:
3298 return 1;
3299
3300 case '}':
3301 return 0;
3302
3303 default:
3304 declaration (0, flags);
3305 flags = start_flags;
3306 break;
3307 }
3308
3309 if (prev_in == in)
3310 yyerror ("parse error");
3311 }
3312}
3313
3314
3315/* Parse the current input file. */
3316
3317void
3318yyparse ()
3319{
3320 while (globals (0) == 0)
3321 MATCH_IF ('}');
3322}
3323
3324
3325
3326/***********************************************************************
3327 Main Program
3328 ***********************************************************************/
3329
3330/* Add the list of paths PATH_LIST to the current search path for
3331 input files. */
3332
3333void
3334add_search_path (path_list)
3335 char *path_list;
3336{
3337 while (*path_list)
3338 {
3339 char *start = path_list;
3340 struct search_path *p;
3341
3342 while (*path_list && *path_list != PATH_LIST_SEPARATOR)
3343 ++path_list;
3344
3345 p = (struct search_path *) xmalloc (sizeof *p);
3346 p->path = (char *) xmalloc (path_list - start + 1);
3347 memcpy (p->path, start, path_list - start);
3348 p->path[path_list - start] = '\0';
3349 p->next = NULL;
3350
3351 if (search_path_tail)
3352 {
3353 search_path_tail->next = p;
3354 search_path_tail = p;
3355 }
3356 else
3357 search_path = search_path_tail = p;
3358
3359 while (*path_list == PATH_LIST_SEPARATOR)
3360 ++path_list;
3361 }
3362}
3363
3364
3365/* Open FILE and return a file handle for it, or -1 if FILE cannot be
3366 opened. Try to find FILE in search_path first, then try the
3367 unchanged file name. */
3368
3369FILE *
3370open_file (file)
3371 char *file;
3372{
3373 FILE *fp = NULL;
3374 static char *buffer;
3375 static int buffer_size;
3376 struct search_path *path;
3377
3378 filename = xstrdup (file);
3379
3380 for (path = search_path; path && fp == NULL; path = path->next)
3381 {
3382 int len = strlen (path->path);
3383
3384 if (len + 1 >= buffer_size)
3385 {
3386 buffer_size = max (len + 1, 2 * buffer_size);
3387 buffer = (char *) xrealloc (buffer, buffer_size);
3388 }
3389
3390 strcpy (buffer, path->path);
3391 strcat (buffer, "/");
3392 strcat (buffer, file);
3393 fp = fopen (buffer, "r");
3394 }
3395
3396 /* Try the original file name. */
3397 if (fp == NULL)
3398 fp = fopen (file, "r");
3399
3400 if (fp == NULL)
3401 yyerror ("cannot open");
3402
3403 return fp;
3404}
3405
3406
3407/* Display usage information and exit program. */
3408
3409#define USAGE "\
3410Usage: ebrowse [options] {files}\n\
3411\n\
3412 -a, --append append output\n\
3413 -f, --files=FILES read input file names from FILE\n\
3414 -I, --search-path=LIST set search path for input files\n\
3415 -m, --min-regexp-length=N set minimum regexp length to N\n\
3416 -M, --max-regexp-length=N set maximum regexp length to N\n\
3417 -n, --no-nested-classes exclude nested classes\n\
3418 -o, --output-file=FILE set output file name to FILE\n\
3419 -p, --position-info print info about position in file\n\
3420 -s, --no-structs-or-unions don't record structs or unions\n\
3421 -v, --verbose be verbose\n\
3422 -V, --very-verbose be very verbose\n\
3423 -x, --no-regexps don't record regular expressions\n\
3424 --help display this help\n\
3425 --version display version info\n\
3426"
3427
3428void
3429usage (error)
3430 int error;
3431{
3432 puts (USAGE);
3433 exit (error ? 1 : 0);
3434}
3435
3436
3437/* Display version and copyright info. The VERSION macro is set
3438 from the Makefile and contains the Emacs version. */
3439
3440void
3441version ()
3442{
3443 printf ("ebrowse %s\n", VERSION);
3444 puts ("Copyright (C) 1992-1999, 2000 Free Software Foundation, Inc.");
3445 puts ("This program is distributed under the same terms as Emacs.");
3446 exit (0);
3447}
3448
3449
3450/* Parse one input file FILE, adding classes and members to the symbol
3451 table. */
3452
3453void
3454process_file (file)
3455 char *file;
3456{
3457 FILE *fp;
3458
3459 fp = open_file (file);
3460 if (fp)
3461 {
3462 int nread, nbytes;
3463
3464 /* Give a progress indication if needed. */
3465 if (f_very_verbose)
3466 {
3467 puts (filename);
3468 fflush (stdout);
3469 }
3470 else if (f_verbose)
3471 {
3472 putchar ('.');
3473 fflush (stdout);
3474 }
3475
3476 /* Read file to inbuffer. */
3477 for (nread = 0;;)
3478 {
3479 if (nread + READ_CHUNK_SIZE >= inbuffer_size)
3480 {
3481 inbuffer_size = nread + READ_CHUNK_SIZE + 1;
3482 inbuffer = (char *) xrealloc (inbuffer, inbuffer_size);
3483 }
3484
3485 nbytes = fread (inbuffer + nread, 1, READ_CHUNK_SIZE, fp);
3486 nread += nbytes;
3487 if (nbytes < READ_CHUNK_SIZE)
3488 break;
3489 }
3490 inbuffer[nread] = '\0';
3491
3492 /* Reinitialize scanner and parser for the new input file. */
3493 re_init_scanner ();
3494 re_init_parser ();
3495
3496 /* Parse it and close the file. */
3497 yyparse ();
3498 fclose (fp);
3499 }
3500}
3501
3502
3503/* Read a line from stream FP and return a pointer to a static buffer
3504 containing its contents without the terminating newline. Value
3505 is null when EOF is reached. */
3506
3507char *
3508read_line (fp)
3509 FILE *fp;
3510{
3511 static char *buffer;
3512 static int buffer_size;
3513 int i = 0, c;
3514
3515 while ((c = getc (fp)) != EOF && c != '\n')
3516 {
3517 if (i >= buffer_size)
3518 {
3519 buffer_size = max (100, buffer_size * 2);
3520 buffer = (char *) xrealloc (buffer, buffer_size);
3521 }
3522
3523 buffer[i++] = c;
3524 }
3525
3526 if (c == EOF && i == 0)
3527 return NULL;
3528
3529 if (i == buffer_size)
3530 {
3531 buffer_size = max (100, buffer_size * 2);
3532 buffer = (char *) xrealloc (buffer, buffer_size);
3533 }
3534
3535 buffer[i] = '\0';
3536 return buffer;
3537}
3538
3539
3540/* Main entry point. */
3541
3542int
3543main (argc, argv)
3544 int argc;
3545 char **argv;
3546{
3547 int i;
3548 int any_inputfiles = 0;
3549 static char *out_filename = DEFAULT_OUTFILE;
3550 static char **input_filenames = NULL;
3551 static int input_filenames_size = 0;
3552 static int n_input_files;
3553
3554 filename = "command line";
3555 yyout = stdout;
3556
3557 while ((i = getopt_long (argc, argv, "af:I:m:M:no:p:svVx",
3558 options, NULL)) != EOF)
3559 {
3560 switch (i)
3561 {
3562 /* Experimental. */
3563 case 'p':
3564 info_position = atoi (optarg);
3565 break;
3566
3567 case 'n':
3568 f_nested_classes = 0;
3569 break;
3570
3571 case 'x':
3572 f_regexps = 0;
3573 break;
3574
3575 /* Add the name of a file containing more input files. */
3576 case 'f':
3577 if (n_input_files == input_filenames_size)
3578 {
3579 input_filenames_size = max (10, 2 * input_filenames_size);
3580 input_filenames = (char **) xrealloc (input_filenames,
3581 input_filenames_size);
3582 }
3583 input_filenames[n_input_files++] = xstrdup (optarg);
3584 break;
3585
3586 /* Append new output to output file instead of truncating it. */
3587 case 'a':
3588 f_append = 1;
3589 break;
3590
3591 /* Include structs in the output */
3592 case 's':
3593 f_structs = 0;
3594 break;
3595
3596 /* Be verbose (give a progress indication). */
3597 case 'v':
3598 f_verbose = 1;
3599 break;
3600
3601 /* Be very verbose (print file names as they are processed). */
3602 case 'V':
3603 f_verbose = 1;
3604 f_very_verbose = 1;
3605 break;
3606
3607 /* Change the name of the output file. */
3608 case 'o':
3609 out_filename = optarg;
3610 break;
3611
3612 /* Set minimum length for regular expression strings
3613 when recorded in the output file. */
3614 case 'm':
3615 min_regexp = atoi (optarg);
3616 break;
3617
3618 /* Set maximum length for regular expression strings
3619 when recorded in the output file. */
3620 case 'M':
3621 max_regexp = atoi (optarg);
3622 break;
3623
3624 /* Add to search path. */
3625 case 'I':
3626 add_search_path (optarg);
3627 break;
3628
3629 /* Display help */
3630 case -2:
3631 usage (0);
3632 break;
3633
3634 case -3:
3635 version ();
3636 break;
3637 }
3638 }
3639
3640 /* Call init_scanner after command line flags have been processed to be
3641 able to add keywords depending on command line (not yet
3642 implemented). */
3643 init_scanner ();
3644 init_sym ();
3645
3646 /* Open output file */
3647 if (*out_filename)
3648 {
3649 yyout = fopen (out_filename, f_append ? "a" : "w");
3650 if (yyout == NULL)
3651 {
3652 yyerror ("cannot open output file `%s'", out_filename);
3653 exit (1);
3654 }
3655 }
3656
3657 /* Process input files specified on the command line. */
3658 while (optind < argc)
3659 {
3660 process_file (argv[optind++]);
3661 any_inputfiles = 1;
3662 }
3663
3664 /* Process files given on stdin if no files specified. */
3665 if (!any_inputfiles && n_input_files == 0)
3666 {
3667 char *file;
3668 while ((file = read_line (stdin)) != NULL)
3669 process_file (file);
3670 }
3671 else
3672 {
3673 /* Process files from `--files=FILE'. Every line in FILE names
3674 one input file to process. */
3675 for (i = 0; i < n_input_files; ++i)
3676 {
3677 FILE *fp = fopen (input_filenames[i], "r");
3678
3679 if (fp == NULL)
3680 yyerror ("cannot open input file `%s'", input_filenames[i]);
3681 else
3682 {
3683 char *file;
3684 while ((file = read_line (fp)) != NULL)
3685 process_file (file);
3686 fclose (fp);
3687 }
3688 }
3689 }
3690
3691 /* Write output file. */
3692 dump_roots (yyout);
3693
3694 /* Close output file. */
3695 if (yyout != stdout)
3696 fclose (yyout);
3697
3698 return 0;
3699}
3700
3701
3702/* ebrowse.c ends here. */
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index a2fd5c2ead2..36aa9eefa6f 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,20 @@
12000-04-09 Gerd Moellmann <gerd@gnu.org>
2
3 * mail/rfc2368.el: Correct author's email address.
4
5 * progmodes/ebrowse.el: New file.
6
7 * emacs-lisp/easymenu.el (easy-menu-create-menu): Process menu
8 item help string.
9 (easy-menu-do-add-item): Ditto.
10 (easy-menu-define): Extend doc string.
11
12 * jit-lock.el (with-buffer-unmodified): Use
13 restore-buffer-modified-p.
14 (with-buffer-prepared-for-font-lock): Use with-buffer-unmodified.
15 (jit-lock-function, jit-lock-stealth-fontify): Don't use
16 with-buffer-unmodified.
17
12000-04-08 Dave Love <fx@gnu.org> 182000-04-08 Dave Love <fx@gnu.org>
2 19
3 * emacs-lisp/edebug.el: Fix specs for dolist, dotimes, push, pop, 20 * emacs-lisp/edebug.el: Fix specs for dolist, dotimes, push, pop,
diff --git a/lisp/cus-load.el b/lisp/cus-load.el
index cf0c724f6e6..df9b657c8a2 100644
--- a/lisp/cus-load.el
+++ b/lisp/cus-load.el
@@ -38,6 +38,7 @@
38(put 'nnmail-procmail 'custom-loads '("nnmail")) 38(put 'nnmail-procmail 'custom-loads '("nnmail"))
39(put 'desktop 'custom-loads '("desktop")) 39(put 'desktop 'custom-loads '("desktop"))
40(put 'cperl-help-system 'custom-loads '("cperl-mode")) 40(put 'cperl-help-system 'custom-loads '("cperl-mode"))
41(put 'ps-print-miscellany 'custom-loads '("ps-print"))
41(put 'comint-completion 'custom-loads '("comint")) 42(put 'comint-completion 'custom-loads '("comint"))
42(put 'gnus-score-kill 'custom-loads '("gnus-kill" "gnus")) 43(put 'gnus-score-kill 'custom-loads '("gnus-kill" "gnus"))
43(put 'ldap 'custom-loads '("ldap")) 44(put 'ldap 'custom-loads '("ldap"))
@@ -84,6 +85,7 @@
84(put 'gnus-various 'custom-loads '("gnus-sum" "gnus")) 85(put 'gnus-various 'custom-loads '("gnus-sum" "gnus"))
85(put 'elide-head 'custom-loads '("elide-head")) 86(put 'elide-head 'custom-loads '("elide-head"))
86(put 'vhdl-compile 'custom-loads '("vhdl-mode")) 87(put 'vhdl-compile 'custom-loads '("vhdl-mode"))
88(put 'ebrowse-tree 'custom-loads '("ebrowse"))
87(put 'font-lock-highlighting-faces 'custom-loads '("font-lock" "vhdl-mode")) 89(put 'font-lock-highlighting-faces 'custom-loads '("font-lock" "vhdl-mode"))
88(put 'flyspell 'custom-loads '("flyspell")) 90(put 'flyspell 'custom-loads '("flyspell"))
89(put 'ange-ftp 'custom-loads '("ange-ftp")) 91(put 'ange-ftp 'custom-loads '("ange-ftp"))
@@ -267,7 +269,7 @@
267(put 'ebnf-optimization 'custom-loads '("ebnf2ps")) 269(put 'ebnf-optimization 'custom-loads '("ebnf2ps"))
268(put 'apropos 'custom-loads '("apropos")) 270(put 'apropos 'custom-loads '("apropos"))
269(put 'gomoku 'custom-loads '("gomoku")) 271(put 'gomoku 'custom-loads '("gomoku"))
270(put 'tools 'custom-loads '("add-log" "calculator" "compare-w" "diff-mode" "diff" "ediff" "elide-head" "emerge" "gud" "pcvs-defs" "smerge-mode" "speedbar" "tempo" "tooltip" "vc" "which-func" "copyright" "compile" "etags" "glasses" "make-mode" "rcompile")) 272(put 'tools 'custom-loads '("add-log" "calculator" "compare-w" "diff-mode" "diff" "ediff" "elide-head" "emerge" "gud" "pcvs-defs" "smerge-mode" "speedbar" "tempo" "tooltip" "vc" "which-func" "copyright" "compile" "ebrowse" "etags" "glasses" "make-mode" "rcompile"))
271(put 'gnus-topic 'custom-loads '("gnus-topic")) 273(put 'gnus-topic 'custom-loads '("gnus-topic"))
272(put 'sgml 'custom-loads '("sgml-mode")) 274(put 'sgml 'custom-loads '("sgml-mode"))
273(put 'keyboard 'custom-loads '("simple" "chistory" "type-break")) 275(put 'keyboard 'custom-loads '("simple" "chistory" "type-break"))
@@ -278,6 +280,7 @@
278(put 'rmail-summary 'custom-loads '("rmail" "rmailsum")) 280(put 'rmail-summary 'custom-loads '("rmail" "rmailsum"))
279(put 'metamail 'custom-loads '("metamail")) 281(put 'metamail 'custom-loads '("metamail"))
280(put 'winner 'custom-loads '("winner")) 282(put 'winner 'custom-loads '("winner"))
283(put 'ebrowse-faces 'custom-loads '("ebrowse"))
281(put 'wp 'custom-loads '("cus-edit" "enriched" "lpr" "ps-print" "view" "ebnf2ps" "bib-mode" "nroff-mode" "refbib" "refer" "scribe" "tildify")) 284(put 'wp 'custom-loads '("cus-edit" "enriched" "lpr" "ps-print" "view" "ebnf2ps" "bib-mode" "nroff-mode" "refbib" "refer" "scribe" "tildify"))
282(put 'reftex-citation-support 'custom-loads '("reftex-vars")) 285(put 'reftex-citation-support 'custom-loads '("reftex-vars"))
283(put 'gnus-summary-choose 'custom-loads '("gnus-sum")) 286(put 'gnus-summary-choose 'custom-loads '("gnus-sum"))
@@ -385,6 +388,7 @@
385(put 'ebnf-repeat 'custom-loads '("ebnf2ps")) 388(put 'ebnf-repeat 'custom-loads '("ebnf2ps"))
386(put 'supercite 'custom-loads '("supercite")) 389(put 'supercite 'custom-loads '("supercite"))
387(put 'font-selection 'custom-loads '("faces")) 390(put 'font-selection 'custom-loads '("faces"))
391(put 'ps-print-headers 'custom-loads '("ps-print"))
388(put 'gnus-summary-marks 'custom-loads '("gnus-sum" "gnus")) 392(put 'gnus-summary-marks 'custom-loads '("gnus-sum" "gnus"))
389(put 'bibtex-autokey 'custom-loads '("bibtex")) 393(put 'bibtex-autokey 'custom-loads '("bibtex"))
390(put 'eudc 'custom-loads '("eudc-vars")) 394(put 'eudc 'custom-loads '("eudc-vars"))
@@ -409,6 +413,7 @@
409(put 'fill-comments 'custom-loads '("simple")) 413(put 'fill-comments 'custom-loads '("simple"))
410(put 'gnus-summary-various 'custom-loads '("gnus-sum")) 414(put 'gnus-summary-various 'custom-loads '("gnus-sum"))
411(put 'applications 'custom-loads '("calendar" "cus-edit" "uniquify" "spell")) 415(put 'applications 'custom-loads '("calendar" "cus-edit" "uniquify" "spell"))
416(put 'ebrowse-member 'custom-loads '("ebrowse"))
412(put 'terminal 'custom-loads '("terminal")) 417(put 'terminal 'custom-loads '("terminal"))
413(put 'shadow 'custom-loads '("shadowfile" "shadow")) 418(put 'shadow 'custom-loads '("shadowfile" "shadow"))
414(put 'hl-line 'custom-loads '("hl-line")) 419(put 'hl-line 'custom-loads '("hl-line"))
@@ -439,7 +444,7 @@
439(put 'hanoi 'custom-loads '("hanoi")) 444(put 'hanoi 'custom-loads '("hanoi"))
440(put 'reftex-index-support 'custom-loads '("reftex-vars")) 445(put 'reftex-index-support 'custom-loads '("reftex-vars"))
441(put 'pascal 'custom-loads '("pascal")) 446(put 'pascal 'custom-loads '("pascal"))
442(put 'rmail-retrieve 'custom-loads '("rmail")) 447(put 'rmail-retrieve 'custom-loads '("rmail" "rmailsum"))
443(put 'data 'custom-loads '("text-mode" "arc-mode" "forms" "hexl" "jka-compr" "saveplace" "sort" "tar-mode" "time-stamp" "snmp-mode")) 448(put 'data 'custom-loads '("text-mode" "arc-mode" "forms" "hexl" "jka-compr" "saveplace" "sort" "tar-mode" "time-stamp" "snmp-mode"))
444(put 'mail 'custom-loads '("simple" "startup" "time" "gnus" "message" "emacsbug" "feedmail" "mail-extr" "mail-hist" "mail-utils" "mailalias" "metamail" "mh-e" "mspools" "rmail" "sendmail" "smtpmail" "supercite" "uce" "fortune" "eudc-vars")) 449(put 'mail 'custom-loads '("simple" "startup" "time" "gnus" "message" "emacsbug" "feedmail" "mail-extr" "mail-hist" "mail-utils" "mailalias" "metamail" "mh-e" "mspools" "rmail" "sendmail" "smtpmail" "supercite" "uce" "fortune" "eudc-vars"))
445(put 'paren-blinking 'custom-loads '("simple")) 450(put 'paren-blinking 'custom-loads '("simple"))
@@ -451,9 +456,9 @@
451(put 'dired 'custom-loads '("files" "dired-aux" "dired-x" "dired" "find-dired")) 456(put 'dired 'custom-loads '("files" "dired-aux" "dired-x" "dired" "find-dired"))
452(put 'recentf 'custom-loads '("recentf")) 457(put 'recentf 'custom-loads '("recentf"))
453(put 'fill 'custom-loads '("simple" "fill" "align")) 458(put 'fill 'custom-loads '("simple" "fill" "align"))
454(put 'ps-print-header 'custom-loads '("ps-print"))
455(put 'outlines 'custom-loads '("allout" "outline")) 459(put 'outlines 'custom-loads '("allout" "outline"))
456(put 'paragraphs 'custom-loads '("paragraphs")) 460(put 'paragraphs 'custom-loads '("paragraphs"))
461(put 'ebrowse 'custom-loads '("ebrowse"))
457(put 'nnmail-split 'custom-loads '("nnmail")) 462(put 'nnmail-split 'custom-loads '("nnmail"))
458(put 'makefile 'custom-loads '("make-mode")) 463(put 'makefile 'custom-loads '("make-mode"))
459(put 'supercite-attr 'custom-loads '("supercite")) 464(put 'supercite-attr 'custom-loads '("supercite"))
@@ -502,12 +507,11 @@
502(put 'ps-print-zebra 'custom-loads '("ps-print")) 507(put 'ps-print-zebra 'custom-loads '("ps-print"))
503(put 'hideshow 'custom-loads '("hideshow")) 508(put 'hideshow 'custom-loads '("hideshow"))
504(put 'viper-search 'custom-loads '("viper-init")) 509(put 'viper-search 'custom-loads '("viper-init"))
505(put 'C 'custom-loads '("cpp"))
506(put 'mule 'custom-loads '("mule-cmds")) 510(put 'mule 'custom-loads '("mule-cmds"))
507(put 'glasses 'custom-loads '("glasses")) 511(put 'glasses 'custom-loads '("glasses"))
508(put 'vhdl-style 'custom-loads '("vhdl-mode")) 512(put 'vhdl-style 'custom-loads '("vhdl-mode"))
509(put 'tempo 'custom-loads '("tempo")) 513(put 'tempo 'custom-loads '("tempo"))
510(put 'c 'custom-loads '("tooltip" "cc-vars" "cmacexp" "hideif")) 514(put 'c 'custom-loads '("tooltip" "cc-vars" "cmacexp" "cpp" "hideif"))
511(put 'nnmail-prepare 'custom-loads '("nnmail")) 515(put 'nnmail-prepare 'custom-loads '("nnmail"))
512(put 'processes 'custom-loads '("comint" "cus-edit" "shell" "term" "metamail" "compile" "executable" "sql" "flyspell" "rcompile" "rlogin")) 516(put 'processes 'custom-loads '("comint" "cus-edit" "shell" "term" "metamail" "compile" "executable" "sql" "flyspell" "rcompile" "rlogin"))
513(put 'ebnf2ps 'custom-loads '("ebnf2ps")) 517(put 'ebnf2ps 'custom-loads '("ebnf2ps"))
@@ -693,6 +697,8 @@
693(custom-put-if-not 'border 'group-documentation nil) 697(custom-put-if-not 'border 'group-documentation nil)
694(custom-put-if-not 'hl-line 'custom-version "21.1") 698(custom-put-if-not 'hl-line 'custom-version "21.1")
695(custom-put-if-not 'hl-line 'group-documentation "Highliight the current line.") 699(custom-put-if-not 'hl-line 'group-documentation "Highliight the current line.")
700(custom-put-if-not 'find-file-wildcards 'custom-version "20.4")
701(custom-put-if-not 'find-file-wildcards 'standard-value t)
696(custom-put-if-not 'custom-comment-face 'custom-version "21.1") 702(custom-put-if-not 'custom-comment-face 'custom-version "21.1")
697(custom-put-if-not 'custom-comment-face 'group-documentation nil) 703(custom-put-if-not 'custom-comment-face 'group-documentation nil)
698(custom-put-if-not 'custom-raised-buttons 'custom-version "21.1") 704(custom-put-if-not 'custom-raised-buttons 'custom-version "21.1")
@@ -727,6 +733,8 @@
727(custom-put-if-not 'hscroll-global-mode 'standard-value t) 733(custom-put-if-not 'hscroll-global-mode 'standard-value t)
728(custom-put-if-not 'tags-apropos-verbose 'custom-version "21.1") 734(custom-put-if-not 'tags-apropos-verbose 'custom-version "21.1")
729(custom-put-if-not 'tags-apropos-verbose 'standard-value t) 735(custom-put-if-not 'tags-apropos-verbose 'standard-value t)
736(custom-put-if-not 'dabbrev-ignored-regexps 'custom-version "21.1")
737(custom-put-if-not 'dabbrev-ignored-regexps 'standard-value t)
730(custom-put-if-not 'find-variable-regexp 'custom-version "20.3") 738(custom-put-if-not 'find-variable-regexp 'custom-version "20.3")
731(custom-put-if-not 'find-variable-regexp 'standard-value t) 739(custom-put-if-not 'find-variable-regexp 'standard-value t)
732(custom-put-if-not 'header-line 'custom-version "21.1") 740(custom-put-if-not 'header-line 'custom-version "21.1")
@@ -744,7 +752,7 @@
744(custom-put-if-not 'eval-expression-print-level 'custom-version "21.1") 752(custom-put-if-not 'eval-expression-print-level 'custom-version "21.1")
745(custom-put-if-not 'eval-expression-print-level 'standard-value t) 753(custom-put-if-not 'eval-expression-print-level 'standard-value t)
746 754
747(defvar custom-versions-load-alist '(("20.3.3" "dos-vars") (21.1 "ange-ftp") ("20.4" "sh-script" "help" "compile") ("21.1" "debug" "paths" "sgml-mode" "fortran" "etags" "cus-edit" "add-log" "find-func" "simple") ("20.3" "desktop" "easymenu" "hscroll" "dabbrev" "ffap" "rmail" "paren" "mailabbrev" "frame" "uce" "mouse" "diary-lib" "sendmail" "debug" "hexl" "vcursor" "vc" "compile" "etags" "help" "browse-url" "add-log" "find-func" "vc-hooks" "cus-edit" "replace")) 755(defvar custom-versions-load-alist '(("20.3.3" "dos-vars") (21.1 "ange-ftp") ("20.4" "files" "sh-script" "help" "compile") ("21.1" "debug" "dabbrev" "paths" "sgml-mode" "fortran" "etags" "cus-edit" "add-log" "find-func" "simple") ("20.3" "desktop" "easymenu" "hscroll" "dabbrev" "ffap" "rmail" "paren" "mailabbrev" "frame" "uce" "mouse" "diary-lib" "sendmail" "debug" "hexl" "vcursor" "vc" "compile" "etags" "help" "browse-url" "add-log" "find-func" "vc-hooks" "cus-edit" "replace"))
748 "For internal use by custom.") 756 "For internal use by custom.")
749 757
750(provide 'cus-load) 758(provide 'cus-load)
diff --git a/lisp/loaddefs.el b/lisp/loaddefs.el
index 20127ec416c..a78d0906866 100644
--- a/lisp/loaddefs.el
+++ b/lisp/loaddefs.el
@@ -119,7 +119,7 @@ Insert a descriptive header at the top of the file." t nil)
119;;;### (autoloads (change-log-merge add-log-current-defun change-log-mode 119;;;### (autoloads (change-log-merge add-log-current-defun change-log-mode
120;;;;;; add-change-log-entry-other-window add-change-log-entry find-change-log 120;;;;;; add-change-log-entry-other-window add-change-log-entry find-change-log
121;;;;;; prompt-for-change-log-name add-log-mailing-address add-log-full-name) 121;;;;;; prompt-for-change-log-name add-log-mailing-address add-log-full-name)
122;;;;;; "add-log" "add-log.el" (14525 5303)) 122;;;;;; "add-log" "add-log.el" (14565 55609))
123;;; Generated autoloads from add-log.el 123;;; Generated autoloads from add-log.el
124 124
125(defvar add-log-full-name nil "\ 125(defvar add-log-full-name nil "\
@@ -192,11 +192,11 @@ Runs `change-log-mode-hook'." t nil)
192Return name of function definition point is in, or nil. 192Return name of function definition point is in, or nil.
193 193
194Understands C, Lisp, LaTeX (\"functions\" are chapters, sections, ...), 194Understands C, Lisp, LaTeX (\"functions\" are chapters, sections, ...),
195Texinfo (@node titles), Perl, and Fortran. 195Texinfo (@node titles) and Perl.
196 196
197Other modes are handled by a heuristic that looks in the 10K before 197Other modes are handled by a heuristic that looks in the 10K before
198point for uppercase headings starting in the first column or 198point for uppercase headings starting in the first column or
199identifiers followed by `:' or `=', see variables 199identifiers followed by `:' or `='. See variables
200`add-log-current-defun-header-regexp' and 200`add-log-current-defun-header-regexp' and
201`add-log-current-defun-function' 201`add-log-current-defun-function'
202 202
@@ -417,7 +417,7 @@ Used in `antlr-mode'. Also a useful function in `java-mode-hook'." nil nil)
417;;;### (autoloads (appt-make-list appt-delete appt-add appt-display-diary 417;;;### (autoloads (appt-make-list appt-delete appt-add appt-display-diary
418;;;;;; appt-display-duration appt-msg-window appt-display-mode-line 418;;;;;; appt-display-duration appt-msg-window appt-display-mode-line
419;;;;;; appt-visible appt-audible appt-message-warning-time appt-issue-message) 419;;;;;; appt-visible appt-audible appt-message-warning-time appt-issue-message)
420;;;;;; "appt" "calendar/appt.el" (14517 9487)) 420;;;;;; "appt" "calendar/appt.el" (14563 8413))
421;;; Generated autoloads from calendar/appt.el 421;;; Generated autoloads from calendar/appt.el
422 422
423(defvar appt-issue-message t "\ 423(defvar appt-issue-message t "\
@@ -448,13 +448,23 @@ as the first thing on a line.")
448This will occur at midnight when the appointment list is updated.") 448This will occur at midnight when the appointment list is updated.")
449 449
450(autoload (quote appt-add) "appt" "\ 450(autoload (quote appt-add) "appt" "\
451Add an appointment for the day at TIME and issue MESSAGE. 451Add an appointment for the day at NEW-APPT-TIME and issue message NEW-APPT-MSG.
452The time should be in either 24 hour format or am/pm format." t nil) 452The time should be in either 24 hour format or am/pm format." t nil)
453 453
454(autoload (quote appt-delete) "appt" "\ 454(autoload (quote appt-delete) "appt" "\
455Delete an appointment from the list of appointments." t nil) 455Delete an appointment from the list of appointments." t nil)
456 456
457(autoload (quote appt-make-list) "appt" nil nil nil) 457(autoload (quote appt-make-list) "appt" "\
458Create the appointments list from todays diary buffer.
459The time must be at the beginning of a line for it to be
460put in the appointments list.
461 02/23/89
462 12:00pm lunch
463 Wednesday
464 10:00am group meeting
465We assume that the variables DATE and NUMBER
466hold the arguments that `list-diary-entries' received.
467They specify the range of dates that the diary is being processed for." nil nil)
458 468
459;;;*** 469;;;***
460 470
@@ -665,7 +675,7 @@ insert a template for the file depending on the mode of the buffer." t nil)
665 675
666;;;### (autoloads (batch-update-autoloads update-autoloads-from-directories 676;;;### (autoloads (batch-update-autoloads update-autoloads-from-directories
667;;;;;; update-file-autoloads) "autoload" "emacs-lisp/autoload.el" 677;;;;;; update-file-autoloads) "autoload" "emacs-lisp/autoload.el"
668;;;;;; (14398 37513)) 678;;;;;; (14563 8438))
669;;; Generated autoloads from emacs-lisp/autoload.el 679;;; Generated autoloads from emacs-lisp/autoload.el
670 680
671(autoload (quote update-file-autoloads) "autoload" "\ 681(autoload (quote update-file-autoloads) "autoload" "\
@@ -1310,7 +1320,7 @@ corresponding bookmark function from Lisp (the one without the
1310;;;;;; browse-url-of-buffer browse-url-of-file browse-url-generic-program 1320;;;;;; browse-url-of-buffer browse-url-of-file browse-url-generic-program
1311;;;;;; browse-url-save-file browse-url-netscape-display browse-url-new-window-p 1321;;;;;; browse-url-save-file browse-url-netscape-display browse-url-new-window-p
1312;;;;;; browse-url-browser-function) "browse-url" "net/browse-url.el" 1322;;;;;; browse-url-browser-function) "browse-url" "net/browse-url.el"
1313;;;;;; (14554 2050)) 1323;;;;;; (14558 23455))
1314;;; Generated autoloads from net/browse-url.el 1324;;; Generated autoloads from net/browse-url.el
1315 1325
1316(defvar browse-url-browser-function (if (eq system-type (quote windows-nt)) (quote browse-url-default-windows-browser) (quote browse-url-netscape)) "\ 1326(defvar browse-url-browser-function (if (eq system-type (quote windows-nt)) (quote browse-url-default-windows-browser) (quote browse-url-netscape)) "\
@@ -1546,7 +1556,7 @@ name of buffer configuration." t nil)
1546;;;### (autoloads (batch-byte-recompile-directory batch-byte-compile 1556;;;### (autoloads (batch-byte-recompile-directory batch-byte-compile
1547;;;;;; display-call-tree byte-compile compile-defun byte-compile-file 1557;;;;;; display-call-tree byte-compile compile-defun byte-compile-file
1548;;;;;; byte-recompile-directory byte-force-recompile) "bytecomp" 1558;;;;;; byte-recompile-directory byte-force-recompile) "bytecomp"
1549;;;;;; "emacs-lisp/bytecomp.el" (14547 29523)) 1559;;;;;; "emacs-lisp/bytecomp.el" (14564 35790))
1550;;; Generated autoloads from emacs-lisp/bytecomp.el 1560;;; Generated autoloads from emacs-lisp/bytecomp.el
1551 1561
1552(autoload (quote byte-force-recompile) "bytecomp" "\ 1562(autoload (quote byte-force-recompile) "bytecomp" "\
@@ -2718,7 +2728,7 @@ If `compare-ignore-case' is non-nil, changes in case are also ignored." t nil)
2718;;;### (autoloads (next-error compilation-minor-mode compilation-shell-minor-mode 2728;;;### (autoloads (next-error compilation-minor-mode compilation-shell-minor-mode
2719;;;;;; compilation-mode grep-find grep compile compilation-search-path 2729;;;;;; compilation-mode grep-find grep compile compilation-search-path
2720;;;;;; compilation-ask-about-save compilation-window-height compilation-mode-hook) 2730;;;;;; compilation-ask-about-save compilation-window-height compilation-mode-hook)
2721;;;;;; "compile" "progmodes/compile.el" (14440 46010)) 2731;;;;;; "compile" "progmodes/compile.el" (14569 2479))
2722;;; Generated autoloads from progmodes/compile.el 2732;;; Generated autoloads from progmodes/compile.el
2723 2733
2724(defvar compilation-mode-hook nil "\ 2734(defvar compilation-mode-hook nil "\
@@ -3289,7 +3299,7 @@ or as help on variables `cperl-tips', `cperl-problems',
3289;;;*** 3299;;;***
3290 3300
3291;;;### (autoloads (cpp-parse-edit cpp-highlight-buffer) "cpp" "progmodes/cpp.el" 3301;;;### (autoloads (cpp-parse-edit cpp-highlight-buffer) "cpp" "progmodes/cpp.el"
3292;;;;;; (13826 9529)) 3302;;;;;; (14568 36509))
3293;;; Generated autoloads from progmodes/cpp.el 3303;;; Generated autoloads from progmodes/cpp.el
3294 3304
3295(autoload (quote cpp-highlight-buffer) "cpp" "\ 3305(autoload (quote cpp-highlight-buffer) "cpp" "\
@@ -3333,7 +3343,7 @@ With ARG, turn CRiSP mode on if ARG is positive, off otherwise." t nil)
3333;;;;;; customize-option-other-window customize-changed-options customize-option 3343;;;;;; customize-option-other-window customize-changed-options customize-option
3334;;;;;; customize-group-other-window customize-group customize customize-save-variable 3344;;;;;; customize-group-other-window customize-group customize customize-save-variable
3335;;;;;; customize-set-variable customize-set-value) "cus-edit" "cus-edit.el" 3345;;;;;; customize-set-variable customize-set-value) "cus-edit" "cus-edit.el"
3336;;;;;; (14552 48684)) 3346;;;;;; (14558 7062))
3337;;; Generated autoloads from cus-edit.el 3347;;; Generated autoloads from cus-edit.el
3338 (add-hook 'same-window-regexps "\\`\\*Customiz.*\\*\\'") 3348 (add-hook 'same-window-regexps "\\`\\*Customiz.*\\*\\'")
3339 3349
@@ -3582,7 +3592,7 @@ If the argument is nil, we return the display table to its standard state." t ni
3582;;;*** 3592;;;***
3583 3593
3584;;;### (autoloads (dabbrev-expand dabbrev-completion) "dabbrev" "dabbrev.el" 3594;;;### (autoloads (dabbrev-expand dabbrev-completion) "dabbrev" "dabbrev.el"
3585;;;;;; (14385 24830)) 3595;;;;;; (14568 46430))
3586;;; Generated autoloads from dabbrev.el 3596;;; Generated autoloads from dabbrev.el
3587 3597
3588(define-key esc-map "/" (quote dabbrev-expand)) 3598(define-key esc-map "/" (quote dabbrev-expand))
@@ -4066,7 +4076,7 @@ Minor mode for viewing/editing context diffs.
4066;;;;;; dired dired-copy-preserve-time dired-dwim-target dired-keep-marker-symlink 4076;;;;;; dired dired-copy-preserve-time dired-dwim-target dired-keep-marker-symlink
4067;;;;;; dired-keep-marker-hardlink dired-keep-marker-copy dired-keep-marker-rename 4077;;;;;; dired-keep-marker-hardlink dired-keep-marker-copy dired-keep-marker-rename
4068;;;;;; dired-trivial-filenames dired-ls-F-marks-symlinks dired-listing-switches) 4078;;;;;; dired-trivial-filenames dired-ls-F-marks-symlinks dired-listing-switches)
4069;;;;;; "dired" "dired.el" (14522 27392)) 4079;;;;;; "dired" "dired.el" (14563 8348))
4070;;; Generated autoloads from dired.el 4080;;; Generated autoloads from dired.el
4071 4081
4072(defvar dired-listing-switches "-al" "\ 4082(defvar dired-listing-switches "-al" "\
@@ -4625,8 +4635,8 @@ been generated automatically, with a reference to the keymap." nil (quote macro)
4625;;;*** 4635;;;***
4626 4636
4627;;;### (autoloads (easy-menu-change easy-menu-create-menu easy-menu-do-define 4637;;;### (autoloads (easy-menu-change easy-menu-create-menu easy-menu-do-define
4628;;;;;; easy-menu-define) "easymenu" "emacs-lisp/easymenu.el" (14385 4638;;;;;; easy-menu-define) "easymenu" "emacs-lisp/easymenu.el" (14574
4629;;;;;; 24854)) 4639;;;;;; 18612))
4630;;; Generated autoloads from emacs-lisp/easymenu.el 4640;;; Generated autoloads from emacs-lisp/easymenu.el
4631 4641
4632(autoload (quote easy-menu-define) "easymenu" "\ 4642(autoload (quote easy-menu-define) "easymenu" "\
@@ -4717,6 +4727,10 @@ anything else means an ordinary menu item.
4717SELECTED is an expression; the checkbox or radio button is selected 4727SELECTED is an expression; the checkbox or radio button is selected
4718whenever this expression's value is non-nil. 4728whenever this expression's value is non-nil.
4719 4729
4730 :help HELP
4731
4732HELP is a string, the help to display for the menu item.
4733
4720A menu item can be a string. Then that string appears in the menu as 4734A menu item can be a string. Then that string appears in the menu as
4721unselectable text. A string consisting solely of hyphens is displayed 4735unselectable text. A string consisting solely of hyphens is displayed
4722as a solid horizontal line. 4736as a solid horizontal line.
@@ -4860,6 +4874,43 @@ It returns the old style symbol." t nil)
4860 4874
4861;;;*** 4875;;;***
4862 4876
4877;;;### (autoloads (ebrowse-save-tree-as ebrowse-tags-query-replace
4878;;;;;; ebrowse-tags-loop-continue ebrowse-tags-complete-symbol ebrowse-electric-choose-tree
4879;;;;;; ebrowse-tree-mode) "ebrowse" "progmodes/ebrowse.el" (14575
4880;;;;;; 54558))
4881;;; Generated autoloads from progmodes/ebrowse.el
4882
4883(autoload (quote ebrowse-tree-mode) "ebrowse" "\
4884Major mode for Ebrowse class tree buffers.
4885Each line corresponds to a class in a class tree.
4886Letters do not insert themselves, they are commands.
4887File operations in the tree buffer work on class tree data structures.
4888E.g.\\[save-buffer] writes the tree to the file it was loaded from.
4889
4890Tree mode key bindings:
4891\\{ebrowse-tree-mode-map}" nil nil)
4892
4893(autoload (quote ebrowse-electric-choose-tree) "ebrowse" "\
4894Return a buffer containing a tree or nil if no tree found or canceled." t nil)
4895
4896(autoload (quote ebrowse-tags-complete-symbol) "ebrowse" "Perform completion on the C++ symbol preceding point.\nA second call of this function without changing point inserts the next match. \nA call with prefix PREFIX reads the symbol to insert from the minibuffer with\ncompletion." t nil)
4897
4898(autoload (quote ebrowse-tags-loop-continue) "ebrowse" "\
4899Repeat last operation on files in tree.
4900FIRST-TIME non-nil means this is not a repetition, but the first time.
4901TREE-BUFFER if indirectly specifies which files to loop over." t nil)
4902
4903(autoload (quote ebrowse-tags-query-replace) "ebrowse" "\
4904Query replace FROM with TO in all files of a class tree.
4905With prefix arg, process files of marked classes only." t nil)
4906
4907(autoload (quote ebrowse-save-tree-as) "ebrowse" "\
4908Write the current tree data structure to a file.
4909Read the file name from the minibuffer if interactive.
4910Otherwise, FILE-NAME specifies the file to save the tree in." t nil)
4911
4912;;;***
4913
4863;;;### (autoloads (electric-buffer-list) "ebuff-menu" "ebuff-menu.el" 4914;;;### (autoloads (electric-buffer-list) "ebuff-menu" "ebuff-menu.el"
4864;;;;;; (13778 5499)) 4915;;;;;; (13778 5499))
4865;;; Generated autoloads from ebuff-menu.el 4916;;; Generated autoloads from ebuff-menu.el
@@ -4894,7 +4945,7 @@ With prefix arg NOCONFIRM, execute current line as-is without editing." t nil)
4894;;;*** 4945;;;***
4895 4946
4896;;;### (autoloads (edebug-eval-top-level-form def-edebug-spec edebug-all-forms 4947;;;### (autoloads (edebug-eval-top-level-form def-edebug-spec edebug-all-forms
4897;;;;;; edebug-all-defs) "edebug" "emacs-lisp/edebug.el" (14482 54435)) 4948;;;;;; edebug-all-defs) "edebug" "emacs-lisp/edebug.el" (14576 25687))
4898;;; Generated autoloads from emacs-lisp/edebug.el 4949;;; Generated autoloads from emacs-lisp/edebug.el
4899 4950
4900(defvar edebug-all-defs nil "\ 4951(defvar edebug-all-defs nil "\
@@ -6957,7 +7008,7 @@ Some generic modes are defined in `generic-x.el'." t nil)
6957;;;*** 7008;;;***
6958 7009
6959;;;### (autoloads (glasses-mode) "glasses" "progmodes/glasses.el" 7010;;;### (autoloads (glasses-mode) "glasses" "progmodes/glasses.el"
6960;;;;;; (14480 59906)) 7011;;;;;; (14568 44804))
6961;;; Generated autoloads from progmodes/glasses.el 7012;;; Generated autoloads from progmodes/glasses.el
6962 7013
6963(autoload (quote glasses-mode) "glasses" "\ 7014(autoload (quote glasses-mode) "glasses" "\
@@ -8350,9 +8401,9 @@ and a negative argument disables it." t nil)
8350;;;*** 8401;;;***
8351 8402
8352;;;### (autoloads (iso-cvt-define-menu iso-cvt-write-only iso-cvt-read-only 8403;;;### (autoloads (iso-cvt-define-menu iso-cvt-write-only iso-cvt-read-only
8353;;;;;; iso-iso2duden iso-iso2gtex iso-gtex2iso iso-tex2iso iso-iso2tex 8404;;;;;; iso-sgml2iso iso-iso2sgml iso-iso2duden iso-iso2gtex iso-gtex2iso
8354;;;;;; iso-german iso-spanish) "iso-cvt" "international/iso-cvt.el" 8405;;;;;; iso-tex2iso iso-iso2tex iso-german iso-spanish) "iso-cvt"
8355;;;;;; (13768 42838)) 8406;;;;;; "international/iso-cvt.el" (14564 29908))
8356;;; Generated autoloads from international/iso-cvt.el 8407;;; Generated autoloads from international/iso-cvt.el
8357 8408
8358(autoload (quote iso-spanish) "iso-cvt" "\ 8409(autoload (quote iso-spanish) "iso-cvt" "\
@@ -8397,6 +8448,18 @@ The region between FROM and TO is translated using the table TRANS-TAB.
8397Optional arg BUFFER is ignored (so that the function can can be used in 8448Optional arg BUFFER is ignored (so that the function can can be used in
8398`format-alist')." t nil) 8449`format-alist')." t nil)
8399 8450
8451(autoload (quote iso-iso2sgml) "iso-cvt" "\
8452Translate ISO 8859-1 characters in the region to SGML entities.
8453The entities used are from \"ISO 8879:1986//ENTITIES Added Latin 1//EN\".
8454Optional arg BUFFER is ignored (so that the function can can be used in
8455`format-alist')." t nil)
8456
8457(autoload (quote iso-sgml2iso) "iso-cvt" "\
8458Translate SGML entities in the region to ISO 8859-1 characters.
8459The entities used are from \"ISO 8879:1986//ENTITIES Added Latin 1//EN\".
8460Optional arg BUFFER is ignored (so that the function can can be used in
8461`format-alist')." t nil)
8462
8400(autoload (quote iso-cvt-read-only) "iso-cvt" "\ 8463(autoload (quote iso-cvt-read-only) "iso-cvt" "\
8401Warn that format is read-only." t nil) 8464Warn that format is read-only." t nil)
8402 8465
@@ -8765,7 +8828,7 @@ If non-nil, second arg INITIAL-INPUT is a string to insert before reading." nil
8765;;;*** 8828;;;***
8766 8829
8767;;;### (autoloads (turn-on-jit-lock jit-lock-mode) "jit-lock" "jit-lock.el" 8830;;;### (autoloads (turn-on-jit-lock jit-lock-mode) "jit-lock" "jit-lock.el"
8768;;;;;; (14550 5866)) 8831;;;;;; (14571 7073))
8769;;; Generated autoloads from jit-lock.el 8832;;; Generated autoloads from jit-lock.el
8770 8833
8771(autoload (quote jit-lock-mode) "jit-lock" "\ 8834(autoload (quote jit-lock-mode) "jit-lock" "\
@@ -8806,7 +8869,7 @@ Unconditionally turn on Just-in-time Lock mode." nil nil)
8806;;;*** 8869;;;***
8807 8870
8808;;;### (autoloads (auto-compression-mode) "jka-compr" "jka-compr.el" 8871;;;### (autoloads (auto-compression-mode) "jka-compr" "jka-compr.el"
8809;;;;;; (14495 17985)) 8872;;;;;; (14568 39747))
8810;;; Generated autoloads from jka-compr.el 8873;;; Generated autoloads from jka-compr.el
8811 8874
8812(defvar auto-compression-mode nil "\ 8875(defvar auto-compression-mode nil "\
@@ -9057,7 +9120,7 @@ is nil, raise an error." t nil)
9057;;;*** 9120;;;***
9058 9121
9059;;;### (autoloads (locate-with-filter locate) "locate" "locate.el" 9122;;;### (autoloads (locate-with-filter locate) "locate" "locate.el"
9060;;;;;; (14396 4034)) 9123;;;;;; (14563 8348))
9061;;; Generated autoloads from locate.el 9124;;; Generated autoloads from locate.el
9062 9125
9063(autoload (quote locate) "locate" "\ 9126(autoload (quote locate) "locate" "\
@@ -9072,7 +9135,7 @@ shown; this is often useful to constrain a big search." t nil)
9072 9135
9073;;;*** 9136;;;***
9074 9137
9075;;;### (autoloads (log-edit) "log-edit" "log-edit.el" (14537 49316)) 9138;;;### (autoloads (log-edit) "log-edit" "log-edit.el" (14559 17354))
9076;;; Generated autoloads from log-edit.el 9139;;; Generated autoloads from log-edit.el
9077 9140
9078(autoload (quote log-edit) "log-edit" "\ 9141(autoload (quote log-edit) "log-edit" "\
@@ -9096,8 +9159,8 @@ Major mode for browsing CVS log output." t nil)
9096;;;*** 9159;;;***
9097 9160
9098;;;### (autoloads (print-region lpr-region print-buffer lpr-buffer 9161;;;### (autoloads (print-region lpr-region print-buffer lpr-buffer
9099;;;;;; lpr-command lpr-switches printer-name) "lpr" "lpr.el" (14440 9162;;;;;; lpr-command lpr-switches printer-name) "lpr" "lpr.el" (14563
9100;;;;;; 46009)) 9163;;;;;; 22518))
9101;;; Generated autoloads from lpr.el 9164;;; Generated autoloads from lpr.el
9102 9165
9103(defvar printer-name (if (memq system-type (quote (ms-dos windows-nt))) "PRN") "\ 9166(defvar printer-name (if (memq system-type (quote (ms-dos windows-nt))) "PRN") "\
@@ -9428,7 +9491,7 @@ current header, calls `mail-complete-function' and passes prefix arg if any." t
9428;;;*** 9491;;;***
9429 9492
9430;;;### (autoloads (makefile-mode) "make-mode" "progmodes/make-mode.el" 9493;;;### (autoloads (makefile-mode) "make-mode" "progmodes/make-mode.el"
9431;;;;;; (14554 2005)) 9494;;;;;; (14570 19448))
9432;;; Generated autoloads from progmodes/make-mode.el 9495;;; Generated autoloads from progmodes/make-mode.el
9433 9496
9434(autoload (quote makefile-mode) "make-mode" "\ 9497(autoload (quote makefile-mode) "make-mode" "\
@@ -9517,7 +9580,7 @@ Previous contents of that buffer are killed first." t nil)
9517 9580
9518;;;*** 9581;;;***
9519 9582
9520;;;### (autoloads (man-follow man) "man" "man.el" (14539 53667)) 9583;;;### (autoloads (man-follow man) "man" "man.el" (14570 21850))
9521;;; Generated autoloads from man.el 9584;;; Generated autoloads from man.el
9522 9585
9523(defalias (quote manual-entry) (quote man)) 9586(defalias (quote manual-entry) (quote man))
@@ -9955,7 +10018,7 @@ Multiplication puzzle with GNU Emacs." t nil)
9955 10018
9956;;;*** 10019;;;***
9957 10020
9958;;;### (autoloads (msb-mode msb-mode) "msb" "msb.el" (14263 63030)) 10021;;;### (autoloads (msb-mode msb-mode) "msb" "msb.el" (14555 52300))
9959;;; Generated autoloads from msb.el 10022;;; Generated autoloads from msb.el
9960 10023
9961(defvar msb-mode nil "\ 10024(defvar msb-mode nil "\
@@ -10111,16 +10174,18 @@ The file is saved in the directory `data-directory'." nil nil)
10111;;;;;; coding-system-post-read-conversion coding-system-eol-type-mnemonic 10174;;;;;; coding-system-post-read-conversion coding-system-eol-type-mnemonic
10112;;;;;; lookup-nested-alist set-nested-alist truncate-string-to-width 10175;;;;;; lookup-nested-alist set-nested-alist truncate-string-to-width
10113;;;;;; store-substring string-to-sequence) "mule-util" "international/mule-util.el" 10176;;;;;; store-substring string-to-sequence) "mule-util" "international/mule-util.el"
10114;;;;;; (14423 50997)) 10177;;;;;; (14568 36382))
10115;;; Generated autoloads from international/mule-util.el 10178;;; Generated autoloads from international/mule-util.el
10116 10179
10117(autoload (quote string-to-sequence) "mule-util" "\ 10180(autoload (quote string-to-sequence) "mule-util" "\
10118Convert STRING to a sequence of TYPE which contains characters in STRING. 10181Convert STRING to a sequence of TYPE which contains characters in STRING.
10119TYPE should be `list' or `vector'." nil nil) 10182TYPE should be `list' or `vector'." nil nil)
10120 10183
10121(defsubst string-to-list (string) "Return a list of characters in STRING." (string-to-sequence string (quote list))) 10184(defsubst string-to-list (string) "\
10185Return a list of characters in STRING." (string-to-sequence string (quote list)))
10122 10186
10123(defsubst string-to-vector (string) "Return a vector of characters in STRING." (string-to-sequence string (quote vector))) 10187(defsubst string-to-vector (string) "\
10188Return a vector of characters in STRING." (string-to-sequence string (quote vector)))
10124 10189
10125(autoload (quote store-substring) "mule-util" "\ 10190(autoload (quote store-substring) "mule-util" "\
10126Embed OBJ (string or character) at index IDX of STRING." nil nil) 10191Embed OBJ (string or character) at index IDX of STRING." nil nil)
@@ -10142,7 +10207,16 @@ the resulting string may be narrower than END-COLUMN." nil nil)
10142 10207
10143(defalias (quote truncate-string) (quote truncate-string-to-width)) 10208(defalias (quote truncate-string) (quote truncate-string-to-width))
10144 10209
10145(defsubst nested-alist-p (obj) "Return t if OBJ is a nested alist.\n\nNested alist is a list of the form (ENTRY . BRANCHES), where ENTRY is\nany Lisp object, and BRANCHES is a list of cons cells of the form\n(KEY-ELEMENT . NESTED-ALIST).\n\nYou can use a nested alist to store any Lisp object (ENTRY) for a key\nsequence KEYSEQ, where KEYSEQ is a sequence of KEY-ELEMENT. KEYSEQ\ncan be a string, a vector, or a list." (and obj (listp obj) (listp (cdr obj)))) 10210(defsubst nested-alist-p (obj) "\
10211Return t if OBJ is a nested alist.
10212
10213Nested alist is a list of the form (ENTRY . BRANCHES), where ENTRY is
10214any Lisp object, and BRANCHES is a list of cons cells of the form
10215\(KEY-ELEMENT . NESTED-ALIST).
10216
10217You can use a nested alist to store any Lisp object (ENTRY) for a key
10218sequence KEYSEQ, where KEYSEQ is a sequence of KEY-ELEMENT. KEYSEQ
10219can be a string, a vector, or a list." (and obj (listp obj) (listp (cdr obj))))
10146 10220
10147(autoload (quote set-nested-alist) "mule-util" "\ 10221(autoload (quote set-nested-alist) "mule-util" "\
10148Set ENTRY for KEYSEQ in a nested alist ALIST. 10222Set ENTRY for KEYSEQ in a nested alist ALIST.
@@ -10207,7 +10281,7 @@ Enable mouse wheel support." nil nil)
10207;;;### (autoloads (network-connection network-connection-to-service 10281;;;### (autoloads (network-connection network-connection-to-service
10208;;;;;; whois-reverse-lookup whois finger ftp dig nslookup nslookup-host 10282;;;;;; whois-reverse-lookup whois finger ftp dig nslookup nslookup-host
10209;;;;;; route arp netstat ipconfig ping traceroute) "net-utils" "net/net-utils.el" 10283;;;;;; route arp netstat ipconfig ping traceroute) "net-utils" "net/net-utils.el"
10210;;;;;; (14385 24830)) 10284;;;;;; (14564 29931))
10211;;; Generated autoloads from net/net-utils.el 10285;;; Generated autoloads from net/net-utils.el
10212 10286
10213(autoload (quote traceroute) "net-utils" "\ 10287(autoload (quote traceroute) "net-utils" "\
@@ -11097,7 +11171,7 @@ This checks if all multi-byte characters in the region are printable or not." ni
11097;;;;;; ps-spool-region ps-spool-buffer-with-faces ps-spool-buffer 11171;;;;;; ps-spool-region ps-spool-buffer-with-faces ps-spool-buffer
11098;;;;;; ps-print-region-with-faces ps-print-region ps-print-buffer-with-faces 11172;;;;;; ps-print-region-with-faces ps-print-region ps-print-buffer-with-faces
11099;;;;;; ps-print-buffer ps-print-customize ps-paper-type) "ps-print" 11173;;;;;; ps-print-buffer ps-print-customize ps-paper-type) "ps-print"
11100;;;;;; "ps-print.el" (14554 7425)) 11174;;;;;; "ps-print.el" (14563 18761))
11101;;; Generated autoloads from ps-print.el 11175;;; Generated autoloads from ps-print.el
11102 11176
11103(defvar ps-paper-type (quote letter) "\ 11177(defvar ps-paper-type (quote letter) "\
@@ -11679,7 +11753,7 @@ Here are all local bindings.
11679;;;*** 11753;;;***
11680 11754
11681;;;### (autoloads (regexp-opt-depth regexp-opt) "regexp-opt" "emacs-lisp/regexp-opt.el" 11755;;;### (autoloads (regexp-opt-depth regexp-opt) "regexp-opt" "emacs-lisp/regexp-opt.el"
11682;;;;;; (14535 45202)) 11756;;;;;; (14564 29908))
11683;;; Generated autoloads from emacs-lisp/regexp-opt.el 11757;;; Generated autoloads from emacs-lisp/regexp-opt.el
11684 11758
11685(autoload (quote regexp-opt) "regexp-opt" "\ 11759(autoload (quote regexp-opt) "regexp-opt" "\
@@ -12157,11 +12231,11 @@ KEYWORDS is a comma-separated list of labels." t nil)
12157 12231
12158;;;*** 12232;;;***
12159 12233
12160;;;### (autoloads (rmail-summary-line-decoder rmail-summary-by-senders 12234;;;### (autoloads (rmail-user-mail-address-regexp rmail-summary-line-decoder
12161;;;;;; rmail-summary-by-topic rmail-summary-by-regexp rmail-summary-by-recipients 12235;;;;;; rmail-summary-by-senders rmail-summary-by-topic rmail-summary-by-regexp
12162;;;;;; rmail-summary-by-labels rmail-summary rmail-summary-line-count-flag 12236;;;;;; rmail-summary-by-recipients rmail-summary-by-labels rmail-summary
12163;;;;;; rmail-summary-scroll-between-messages) "rmailsum" "mail/rmailsum.el" 12237;;;;;; rmail-summary-line-count-flag rmail-summary-scroll-between-messages)
12164;;;;;; (14547 28270)) 12238;;;;;; "rmailsum" "mail/rmailsum.el" (14568 47126))
12165;;; Generated autoloads from mail/rmailsum.el 12239;;; Generated autoloads from mail/rmailsum.el
12166 12240
12167(defvar rmail-summary-scroll-between-messages t "\ 12241(defvar rmail-summary-scroll-between-messages t "\
@@ -12206,6 +12280,20 @@ SENDERS is a string of names separated by commas." t nil)
12206 12280
12207By default, `identity' is set.") 12281By default, `identity' is set.")
12208 12282
12283(defvar rmail-user-mail-address-regexp nil "\
12284*Regexp matching user mail addresses.
12285If non-nil, this variable is used to identify the correspondent
12286when receiving new mail. If it matches the address of the sender,
12287the recipient is taken as correspondent of a mail.
12288If nil (default value), your `user-login-name' and `user-mail-address'
12289are used to exclude yourself as correspondent.
12290
12291Usually you don't have to set this variable, except if you collect mails
12292sent by you under different user names.
12293Then it should be a regexp matching your mail adresses.
12294
12295Setting this variable has an effect only before reading a mail.")
12296
12209;;;*** 12297;;;***
12210 12298
12211;;;### (autoloads (news-post-news) "rnewspost" "mail/rnewspost.el" 12299;;;### (autoloads (news-post-news) "rnewspost" "mail/rnewspost.el"
@@ -13450,7 +13538,7 @@ strokes with
13450;;;*** 13538;;;***
13451 13539
13452;;;### (autoloads (sc-cite-original) "supercite" "mail/supercite.el" 13540;;;### (autoloads (sc-cite-original) "supercite" "mail/supercite.el"
13453;;;;;; (14385 23097)) 13541;;;;;; (14565 55801))
13454;;; Generated autoloads from mail/supercite.el 13542;;; Generated autoloads from mail/supercite.el
13455 13543
13456(autoload (quote sc-cite-original) "supercite" "\ 13544(autoload (quote sc-cite-original) "supercite" "\
@@ -14160,7 +14248,7 @@ a symbol as a valid THING." nil nil)
14160;;;;;; tibetan-compose-buffer tibetan-decompose-buffer tibetan-composition-function 14248;;;;;; tibetan-compose-buffer tibetan-decompose-buffer tibetan-composition-function
14161;;;;;; tibetan-compose-region tibetan-compose-string tibetan-transcription-to-tibetan 14249;;;;;; tibetan-compose-region tibetan-compose-string tibetan-transcription-to-tibetan
14162;;;;;; tibetan-tibetan-to-transcription tibetan-char-p setup-tibetan-environment) 14250;;;;;; tibetan-tibetan-to-transcription tibetan-char-p setup-tibetan-environment)
14163;;;;;; "tibet-util" "language/tibet-util.el" (14423 51008)) 14251;;;;;; "tibet-util" "language/tibet-util.el" (14568 36412))
14164;;; Generated autoloads from language/tibet-util.el 14252;;; Generated autoloads from language/tibet-util.el
14165 14253
14166(autoload (quote setup-tibetan-environment) "tibet-util" nil t nil) 14254(autoload (quote setup-tibetan-environment) "tibet-util" nil t nil)
@@ -14747,8 +14835,8 @@ The buffer in question is current when this function is called." nil nil)
14747;;;;;; vc-create-snapshot vc-directory vc-resolve-conflicts vc-merge 14835;;;;;; vc-create-snapshot vc-directory vc-resolve-conflicts vc-merge
14748;;;;;; vc-insert-headers vc-version-other-window vc-diff vc-register 14836;;;;;; vc-insert-headers vc-version-other-window vc-diff vc-register
14749;;;;;; vc-next-action edit-vc-file with-vc-file vc-annotate-mode-hook 14837;;;;;; vc-next-action edit-vc-file with-vc-file vc-annotate-mode-hook
14750;;;;;; vc-before-checkin-hook vc-checkin-hook) "vc" "vc.el" (14478 14838;;;;;; vc-before-checkin-hook vc-checkin-hook) "vc" "vc.el" (14565
14751;;;;;; 52465)) 14839;;;;;; 59735))
14752;;; Generated autoloads from vc.el 14840;;; Generated autoloads from vc.el
14753 14841
14754(defvar vc-checkin-hook nil "\ 14842(defvar vc-checkin-hook nil "\
diff --git a/lisp/progmodes/ebrowse.el b/lisp/progmodes/ebrowse.el
new file mode 100644
index 00000000000..0bacb36da4a
--- /dev/null
+++ b/lisp/progmodes/ebrowse.el
@@ -0,0 +1,4573 @@
1;;; ebrowse.el --- Emacs C++ class browser & tags facility
2
3;; Copyright (C) 1992-1999, 2000 Free Software Foundation Inc.
4
5;; Author: Gerd Moellmann <gerd@gnu.org>
6;; Maintainer: FSF
7;; Keywords: C++ tags tools
8
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs; see the file COPYING. If not, write to
23;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24
25;;; Commentary:
26
27;; This package implements
28
29;; - A class browser for C++
30;; - A complete set of tags-like functions working on class trees
31;; - An electric buffer list showing class browser buffers only
32
33;; Documentation is found in a separate Info file.
34
35;;; Code:
36
37(require 'easymenu)
38(require 'view)
39(require 'ebuff-menu)
40
41(eval-when-compile
42 (require 'cl)
43 (require 'helper))
44
45
46;;; User-options
47
48(defgroup ebrowse nil
49 "Settings for the C++ class browser."
50 :group 'tools)
51
52
53(defcustom ebrowse-search-path nil
54 "*List of directories to search for source files in a class tree.
55Elements should be directory names; nil as an element means to try
56to find source files relative to the location of the EBROWSE file loaded."
57 :group 'ebrowse
58 :type '(repeat (choice (const :tag "Default" nil)
59 (string :tag "Directory"))))
60
61
62(defcustom ebrowse-view/find-hook nil
63 "*Hooks run after finding or viewing a member or class."
64 :group 'ebrowse
65 :type 'hook)
66
67
68(defcustom ebrowse-not-found-hook nil
69 "*Hooks run when finding or viewing a member or class was not successful."
70 :group 'ebrowse
71 :type 'hook)
72
73
74(defcustom ebrowse-electric-list-mode-hook nil
75 "*Hook called by `ebrowse-electric-position-mode'."
76 :group 'ebrowse
77 :type 'hook)
78
79
80(defcustom ebrowse-max-positions 50
81 "*Number of markers saved on electric position stack."
82 :group 'ebrowse
83 :type 'integer)
84
85
86
87(defgroup ebrowse-tree nil
88 "Settings for class tree buffers."
89 :group 'ebrowse)
90
91
92(defcustom ebrowse-tree-mode-hook nil
93 "*Hook run in each new tree buffer."
94 :group 'ebrowse-tree
95 :type 'hook)
96
97
98(defcustom ebrowse-tree-buffer-name "*Tree*"
99 "*The default name of class tree buffers."
100 :group 'ebrowse-tree
101 :type 'string)
102
103
104(defcustom ebrowse--indentation 4
105 "*The amount by which subclasses are indented in the tree."
106 :group 'ebrowse-tree
107 :type 'integer)
108
109
110(defcustom ebrowse-source-file-column 40
111 "*The column in which source file names are displayed in the tree."
112 :group 'ebrowse-tree
113 :type 'integer)
114
115
116(defcustom ebrowse-tree-left-margin 2
117 "*Amount of space left at the left side of the tree display.
118This space is used to display markers."
119 :group 'ebrowse-tree
120 :type 'integer)
121
122
123
124(defgroup ebrowse-member nil
125 "Settings for member buffers."
126 :group 'ebrowse)
127
128
129(defcustom ebrowse-default-declaration-column 25
130 "*The column in which member declarations are displayed in member buffers."
131 :group 'ebrowse-member
132 :type 'integer)
133
134
135(defcustom ebrowse-default-column-width 25
136 "*The width of the columns in member buffers (short display form)."
137 :group 'ebrowse-member
138 :type 'integer)
139
140
141(defcustom ebrowse-member-buffer-name "*Members*"
142 "*The name of the buffer for member display."
143 :group 'ebrowse-member
144 :type 'string)
145
146
147(defcustom ebrowse-member-mode-hook nil
148 "*Run in each new member buffer."
149 :group 'ebrowse-member
150 :type 'hook)
151
152
153
154(defgroup ebrowse-faces nil
155 "Faces used by Ebrowse."
156 :group 'ebrowse)
157
158
159(defface ebrowse-tree-mark-face
160 '((t (:foreground "red")))
161 "*The face used for the mark character in the tree."
162 :group 'ebrowse-faces)
163
164
165(defface ebrowse-root-class-face
166 '((t (:weight bold :foreground "blue")))
167 "*The face used for root classes in the tree."
168 :group 'ebrowse-faces)
169
170
171(defface ebrowse-file-name-face
172 '((t (:italic t)))
173 "*The face for filenames displayed in the tree."
174 :group 'ebrowse-faces)
175
176
177(defface ebrowse-default-face
178 '((t nil))
179 "*Face for everything else in the tree not having other faces."
180 :group 'ebrowse-faces)
181
182
183(defface ebrowse-member-attribute-face
184 '((t (:foreground "red")))
185 "*Face used to display member attributes."
186 :group 'ebrowse-faces)
187
188
189(defface ebrowse-member-class-face
190 '((t (:foreground "purple")))
191 "*Face used to display the class title in member buffers."
192 :group 'ebrowse-faces)
193
194
195(defface ebrowse-progress-face
196 '((t (:background "blue")))
197 "*Face for progress indicator."
198 :group 'ebrowse-faces)
199
200
201
202;;; Utilities.
203
204(defun ebrowse-some (predicate vector)
205 "Return true if PREDICATE is true of some element of VECTOR.
206If so, return the value returned by PREDICATE."
207 (let ((length (length vector))
208 (i 0)
209 result)
210 (while (and (< i length) (not result))
211 (setq result (funcall predicate (aref vector i))
212 i (1+ i)))
213 result))
214
215
216(defun ebrowse-every (predicate vector)
217 "Return true if PREDICATE is true of every element of VECTOR."
218 (let ((length (length vector))
219 (i 0)
220 (result t))
221 (while (and (< i length) result)
222 (setq result (funcall predicate (aref vector i))
223 i (1+ i)))
224 result))
225
226
227(defun ebrowse-position (item list &optional test)
228 "Return the position of ITEM in LIST or nil if not found.
229Compare items with `eq' or TEST if specified."
230 (let ((i 0) found)
231 (cond (test
232 (while list
233 (when (funcall test item (car list))
234 (setq found i list nil))
235 (setq list (cdr list) i (1+ i))))
236 (t
237 (while list
238 (when (eq item (car list))
239 (setq found i list nil))
240 (setq list (cdr list) i (1+ i)))))
241 found))
242
243
244(defun ebrowse-delete-if-not (predicate list)
245 "Remove elements not satisfying PREDICATE from LIST and return the result.
246This is a destructive operation."
247 (let (result)
248 (while list
249 (let ((next (cdr list)))
250 (when (funcall predicate (car list))
251 (setq result (nconc result list))
252 (setf (cdr list) nil))
253 (setq list next)))
254 result))
255
256
257(defun ebrowse-copy-list (list)
258 "Return a shallow copy of LIST."
259 (apply #'list list))
260
261
262(defmacro ebrowse-output (&rest body)
263 "Eval BODY with a writable current buffer.
264Preserve buffer's modified state."
265 (let ((modified (gensym "--ebrowse-output--")))
266 `(let (buffer-read-only (,modified (buffer-modified-p)))
267 (unwind-protect
268 (progn ,@body)
269 (set-buffer-modified-p ,modified)))))
270
271
272(defmacro ebrowse-ignoring-completion-case (&rest body)
273 "Eval BODY with `completion-ignore-case' bound to t."
274 `(let ((completion-ignore-case t))
275 ,@body))
276
277
278(defmacro ebrowse-save-selective (&rest body)
279 "Eval BODY with `selective-display' restored at the end."
280 (let ((var (make-symbol "var")))
281 `(let ((,var selective-display))
282 (unwind-protect
283 (progn ,@body)
284 (setq selective-display ,var)))))
285
286
287(defmacro ebrowse-for-all-trees (spec &rest body)
288 "For all trees in SPEC, eval BODY."
289 (let ((var (make-symbol "var"))
290 (spec-var (car spec))
291 (array (cadr spec)))
292 `(loop for ,var being the symbols of ,array
293 as ,spec-var = (get ,var 'ebrowse-root) do
294 (when (vectorp ,spec-var)
295 ,@body))))
296
297;;; Set indentation for macros above.
298
299(put 'ebrowse-output 'lisp-indent-hook 0)
300(put 'ebrowse-ignoring-completion-case 'lisp-indent-hook 0)
301(put 'ebrowse-save-selective 'lisp-indent-hook 0)
302(put 'ebrowse-for-all-trees 'lisp-indent-hook 1)
303
304
305(defsubst ebrowse-set-face (start end face)
306 "Set face of a region START END to FACE."
307 (overlay-put (make-overlay start end) 'face face))
308
309
310(defun ebrowse-completing-read-value (prompt table initial-input)
311 "Read a string in the minibuffer, with completion.
312Case is ignored in completions.
313
314PROMPT is a string to prompt with; normally it ends in a colon and a space.
315TABLE is an alist whose elements' cars are strings, or an obarray.
316TABLE can also be a function to do the completion itself.
317If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.
318If it is (STRING . POSITION), the initial input
319is STRING, but point is placed POSITION characters into the string."
320 (ebrowse-ignoring-completion-case
321 (completing-read prompt table nil t initial-input)))
322
323
324(defun ebrowse-value-in-buffer (sym buffer)
325 "Return the value of SYM in BUFFER."
326 (let ((old-buffer (current-buffer)))
327 (unwind-protect
328 (progn
329 (set-buffer buffer)
330 (symbol-value sym))
331 (set-buffer old-buffer))))
332
333
334(defun ebrowse-rename-buffer (new-name)
335 "Rename current buffer to NEW-NAME.
336If a buffer with name NEW-NAME already exists, delete it first."
337 (let ((old-buffer (get-buffer new-name)))
338 (unless (eq old-buffer (current-buffer))
339 (when old-buffer
340 (save-excursion (kill-buffer old-buffer)))
341 (rename-buffer new-name))))
342
343
344(defun ebrowse-trim-string (string)
345 "Return a copy of STRING with leading white space removed.
346Replace sequences of newlines with a single space."
347 (when (string-match "^[ \t\n\r]+" string)
348 (setq string (substring string (match-end 0))))
349 (loop while (string-match "[\n]+" string)
350 finally return string do
351 (setq string (replace-match " " nil t string))))
352
353
354(defun ebrowse-width-of-drawable-area ()
355 "Return the width of the display area for the current buffer.
356If buffer is displayed in a window, use that window's width,
357otherwise use the current frame's width."
358 (let ((window (get-buffer-window (current-buffer))))
359 (if window
360 (window-width window)
361 (frame-width))))
362
363
364;;; Structure definitions
365
366(defstruct (ebrowse-hs (:type vector) :named)
367 "Header structure found at the head of EBROWSE files."
368 ;; A version string that is compared against the version number of
369 ;; the Lisp package when the file is loaded. This is done to
370 ;; detect file format changes.
371 version
372 ;; Command line options used for producing the EBROWSE file.
373 command-line-options
374 ;; The following slot is currently not used. It's kept to keep
375 ;; the file format compatible.
376 unused
377 ;; A slot that is filled out after the tree is loaded. This slot is
378 ;; set to a hash table mapping members to lists of classes in which
379 ;; they are defined.
380 member-table)
381
382
383(defstruct (ebrowse-ts (:type vector) :named)
384 "Tree structure.
385Following the header structure, an EBROWSE file contains a number
386of `ebrowse-ts' structures, each one describing one root class of
387the class hierarchy with all its subclasses."
388 ;; A `ebrowse-cs' structure describing the root class.
389 class
390 ;; A list of `ebrowse-ts' structures for all subclasses.
391 subclasses
392 ;; Lists of `ebrowse-ms' structures for each member in a group of
393 ;; members.
394 member-variables member-functions static-variables static-functions
395 friends types
396 ;; List of `ebrowse-ts' structures for base classes. This slot is
397 ;; filled at load time.
398 base-classes
399 ;; A marker slot used in the tree buffer (can be saved back to disk.
400 mark)
401
402
403(defstruct (ebrowse-bs (:type vector) :named)
404 "Common sub-structure.
405A common structure defining an occurrence of some name in the
406source files."
407 ;; The class or member name as a string constant
408 name
409 ;; An optional string for the scope of nested classes or for
410 ;; namespaces.
411 scope
412 ;; Various flags describing properties of classes/members, e.g. is
413 ;; template, is const etc.
414 flags
415 ;; File in which the entity is found. If this is part of a
416 ;; `ebrowse-ms' member description structure, and FILE is nil, then
417 ;; search for the name in the SOURCE-FILE of the members class.
418 file
419 ;; Regular expression to search for. This slot can be a number in
420 ;; which case the number is the file position at which the regular
421 ;; expression is found in a separate regexp file (see the header
422 ;; structure). This slot can be nil in which case the regular
423 ;; expression will be generated from the class/member name.
424 pattern
425 ;; The buffer position at which the search for the class or member
426 ;; will start.
427 point)
428
429
430(defstruct (ebrowse-cs (:include ebrowse-bs) (:type vector) :named)
431 "Class structure.
432This is the structure stored in the CLASS slot of a `ebrowse-ts'
433structure. It describes the location of the class declaration."
434 source-file)
435
436
437(defstruct (ebrowse-ms (:include ebrowse-bs) (:type vector) :named)
438 "Member structure.
439This is the structure describing a single member. The `ebrowse-ts'
440structure contains various lists for the different types of
441members."
442 ;; Public, protected, private
443 visibility
444 ;; The file in which the member's definition can be found.
445 definition-file
446 ;; Same as PATTERN above, but for the member definition.
447 definition-pattern
448 ;; Same as POINT above but for member definition.
449 definition-point)
450
451
452
453;;; Some macros to access the FLAGS slot of a MEMBER.
454
455(defsubst ebrowse-member-bit-set-p (member bit)
456 "Value is non-nil if MEMBER's bit BIT is set."
457 (/= 0 (logand (ebrowse-bs-flags member) bit)))
458
459
460(defsubst ebrowse-virtual-p (member)
461 "Value is non-nil if MEMBER is virtual."
462 (ebrowse-member-bit-set-p member 1))
463
464
465(defsubst ebrowse-inline-p (member)
466 "Value is non-nil if MEMBER is inline."
467 (ebrowse-member-bit-set-p member 2))
468
469
470(defsubst ebrowse-const-p (member)
471 "Value is non-nil if MEMBER is const."
472 (ebrowse-member-bit-set-p member 4))
473
474
475(defsubst ebrowse-pure-virtual-p (member)
476 "Value is non-nil if MEMBER is a pure virtual function."
477 (ebrowse-member-bit-set-p member 8))
478
479
480(defsubst ebrowse-mutable-p (member)
481 "Value is non-nil if MEMBER is mutable."
482 (ebrowse-member-bit-set-p member 16))
483
484
485(defsubst ebrowse-template-p (member)
486 "Value is non-nil if MEMBER is a template."
487 (ebrowse-member-bit-set-p member 32))
488
489
490(defsubst ebrowse-explicit-p (member)
491 "Value is non-nil if MEMBER is explicit."
492 (ebrowse-member-bit-set-p member 64))
493
494
495(defsubst ebrowse-throw-list-p (member)
496 "Value is non-nil if MEMBER has a throw specification."
497 (ebrowse-member-bit-set-p member 128))
498
499
500(defsubst ebrowse-extern-c-p (member)
501 "Value is non-nil if MEMBER.is `extern \"C\"'."
502 (ebrowse-member-bit-set-p member 256))
503
504
505(defsubst ebrowse-define-p (member)
506 "Value is non-nil if MEMBER is a define."
507 (ebrowse-member-bit-set-p member 512))
508
509
510(defconst ebrowse-version-string "ebrowse 5.0"
511 "Version string expected in EBROWSE files.")
512
513
514(defconst ebrowse-globals-name "*Globals*"
515 "The name used for the surrogate class.containing global entities.
516This must be the same that `ebrowse' uses.")
517
518
519(defvar ebrowse--last-regexp nil
520 "Last regular expression searched for in tree and member buffers.
521Automatically buffer-local so that each tree and member buffer
522maintains its own search history.")
523(make-variable-buffer-local 'ebrowse--last-regexp)
524
525
526(defconst ebrowse-member-list-accessors
527 '(ebrowse-ts-member-variables
528 ebrowse-ts-member-functions
529 ebrowse-ts-static-variables
530 ebrowse-ts-static-functions
531 ebrowse-ts-friends
532 ebrowse-ts-types)
533 "List of accessors for member lists.
534Each element is the symbol of an accessor function.
535The nth element must be the accessor for the nth member list
536in an `ebrowse-ts' structure.")
537
538
539;;; FIXME: Add more doc strings for the buffer-local variables below.
540
541(defvar ebrowse--tree-obarray nil
542 "Obarray holding all `ebrowse-ts' structures of a class tree.
543Buffer-local in Ebrowse buffers.")
544
545
546(defvar ebrowse--tags-file-name nil
547 "File from which EBROWSE file was loaded.
548Buffer-local in Ebrowse buffers.")
549
550
551(defvar ebrowse--header nil
552 "Header structure of type `ebrowse-hs' of a class tree.
553Buffer-local in Ebrowse buffers.")
554
555
556(defvar ebrowse--frozen-flag nil
557 "Non-nil means an Ebrowse buffer won't be reused.
558Buffer-local in Ebrowse buffers.")
559
560
561(defvar ebrowse--show-file-names-flag nil
562 "Non-nil means show file names in a tree buffer.
563Buffer-local in Ebrowse tree buffers.")
564
565
566(defvar ebrowse--long-display-flag nil
567 "Non-nil means show members in long display form.
568Buffer-local in Ebrowse member buffers.")
569
570
571(defvar ebrowse--n-columns nil
572 "Number of columns to display for short member display form.
573Buffer-local in Ebrowse member buffers.")
574
575
576(defvar ebrowse--column-width nil
577 "Width of a columns to display for short member display form.
578Buffer-local in Ebrowse member buffers.")
579
580
581(defvar ebrowse--virtual-display-flag nil
582 "Non-nil means display virtual members in a member buffer.
583Buffer-local in Ebrowse member buffers.")
584
585
586(defvar ebrowse--inline-display-flag nil
587 "Non-nil means display inline members in a member buffer.
588Buffer-local in Ebrowse member buffers.")
589
590
591(defvar ebrowse--const-display-flag nil
592 "Non-nil means display const members in a member buffer.
593Buffer-local in Ebrowse member buffers.")
594
595
596(defvar ebrowse--pure-display-flag nil
597 "Non-nil means display pure virtual members in a member buffer.
598Buffer-local in Ebrowse member buffers.")
599
600
601(defvar ebrowse--filters nil
602 "Filter for display of public, protected, and private members.
603This is a vector of three elements. An element nil means the
604corresponding members are not shown.
605Buffer-local in Ebrowse member buffers.")
606
607
608(defvar ebrowse--show-inherited-flag nil
609 "Non-nil means display inherited members in a member buffer.
610Buffer-local in Ebrowse member buffers.")
611
612
613(defvar ebrowse--attributes-flag nil
614 "Non-nil means display member attributes in a member buffer.
615Buffer-local in Ebrowse member buffers.")
616
617
618(defvar ebrowse--source-regexp-flag nil
619 "Non-nil means display member regexps in a member buffer.
620Buffer-local in Ebrowse member buffers.")
621
622
623(defvar ebrowse--displayed-class nil
624 "Class displayed in a member buffer, a `ebrowse-ts' structure.
625Buffer-local in Ebrowse member buffers.")
626
627
628(defvar ebrowse--accessor nil
629 "Member list displayed in a member buffer.
630This is a symbol whose function definition is an accessor for the
631member list in `ebrowse-cs' structures.
632Buffer-local in Ebrowse member buffers.")
633
634
635(defvar ebrowse--member-list nil
636 "The list of `ebrowse-ms' structures displayed in a member buffer.
637Buffer-local in Ebrowse member buffers.")
638
639
640(defvar ebrowse--decl-column nil
641 "Column in which declarations are displayed in member buffers.
642Buffer-local in Ebrowse member buffers.")
643
644
645(defvar ebrowse--mode-strings nil
646 "Strings displayed in the mode line.
647Buffer-local in Ebrowse tree buffers.")
648
649
650(defvar ebrowse--frame-configuration nil
651 "Frame configuration saved when viewing a class/member in another frame.
652Buffer-local in Ebrowse buffers.")
653
654
655(defvar ebrowse--view-exit-action nil
656 "Action to perform after viewing a class/member.
657Either `kill-buffer' or nil.
658Buffer-local in Ebrowse buffers.")
659
660
661(defvar ebrowse--tree nil
662 "Class tree.
663Buffer-local in Ebrowse buffers.")
664
665
666(defvar ebrowse--mode-line-props nil
667 "Text properties of mode line strings in member buffers.
668Buffer-local in Ebrowse member buffers.")
669
670
671;;; Temporaries used to communicate with `ebrowse-find-pattern'.
672
673(defvar ebrowse-temp-position-to-view nil)
674(defvar ebrowse-temp-info-to-view nil)
675
676
677(defvar ebrowse-tree-mode-map ()
678 "The keymap used in tree mode buffers.")
679
680
681(defvar ebrowse--member-mode-strings nil
682 "Strings displayed in the mode line of member buffers.")
683
684
685(defvar ebrowse-member-mode-map ()
686 "The keymap used in the member buffers.")
687
688
689;;; Define mode line titles for each member list.
690
691(put 'ebrowse-ts-member-variables 'ebrowse-title "Member Variables")
692(put 'ebrowse-ts-member-functions 'ebrowse-title "Member Functions")
693(put 'ebrowse-ts-static-variables 'ebrowse-title "Static Variables")
694(put 'ebrowse-ts-static-functions 'ebrowse-title "Static Functions")
695(put 'ebrowse-ts-friends 'ebrowse-title "Friends")
696(put 'ebrowse-ts-types 'ebrowse-title "Types")
697
698(put 'ebrowse-ts-member-variables 'ebrowse-global-title "Global Variables")
699(put 'ebrowse-ts-member-functions 'ebrowse-global-title "Global Functions")
700(put 'ebrowse-ts-static-variables 'ebrowse-global-title "Static Variables")
701(put 'ebrowse-ts-static-functions 'ebrowse-global-title "Static Functions")
702(put 'ebrowse-ts-friends 'ebrowse-global-title "Defines")
703(put 'ebrowse-ts-types 'ebrowse-global-title "Types")
704
705
706
707;;; Operations on `ebrowse-ts' structures
708
709(defun ebrowse-files-table (&optional marked-only)
710 "Return an obarray containing all files mentioned in the current tree.
711The tree is expected in the buffer-local variable `ebrowse--tree-obarray'.
712MARKED-ONLY non-nil means include marked classes only."
713 (let ((files (make-hash-table :test 'equal))
714 (i -1))
715 (ebrowse-for-all-trees (tree ebrowse--tree-obarray)
716 (when (or (not marked-only) (ebrowse-ts-mark tree))
717 (let ((class (ebrowse-ts-class tree)))
718 (when (zerop (% (incf i) 20))
719 (ebrowse-show-progress "Preparing file list" (zerop i)))
720 ;; Add files mentioned in class description
721 (let ((source-file (ebrowse-cs-source-file class))
722 (file (ebrowse-cs-file class)))
723 (when source-file
724 (puthash source-file source-file files))
725 (when file
726 (puthash file file files))
727 ;; For all member lists in this class
728 (loop for accessor in ebrowse-member-list-accessors do
729 (loop for m in (funcall accessor tree)
730 for file = (ebrowse-ms-file m)
731 for def-file = (ebrowse-ms-definition-file m) do
732 (when file
733 (puthash file file files))
734 (when def-file
735 (puthash def-file def-file files))))))))
736 files))
737
738
739(defun ebrowse-files-list (&optional marked-only)
740 "Return a list containing all files mentioned in a tree.
741MARKED-ONLY non-nil means include marked classes only."
742 (let (list)
743 (maphash #'(lambda (file dummy) (setq list (cons file list)))
744 (ebrowse-files-table marked-only))
745 list))
746
747
748(defun* ebrowse-marked-classes-p ()
749 "Value is non-nil if any class in the current class tree is marked."
750 (ebrowse-for-all-trees (tree ebrowse--tree-obarray)
751 (when (ebrowse-ts-mark tree)
752 (return-from ebrowse-marked-classes-p tree))))
753
754
755(defsubst ebrowse-globals-tree-p (tree)
756 "Return t if TREE is the one for global entities."
757 (string= (ebrowse-bs-name (ebrowse-ts-class tree))
758 ebrowse-globals-name))
759
760
761(defsubst ebrowse-qualified-class-name (class)
762 "Return the name of CLASS with scope prepended, if any."
763 (if (ebrowse-cs-scope class)
764 (concat (ebrowse-cs-scope class) "::" (ebrowse-cs-name class))
765 (ebrowse-cs-name class)))
766
767
768(defun ebrowse-tree-obarray-as-alist (&optional qualified-names-p)
769 "Return an alist describing all classes in a tree.
770Each elements in the list has the form (CLASS-NAME . TREE).
771CLASS-NAME is the name of the class. TREE is the
772class tree whose root is QUALIFIED-CLASS-NAME.
773QUALIFIED-NAMES-P non-nil means return qualified names as CLASS-NAME.
774The class tree is found in the buffer-local variable `ebrowse--tree-obarray'."
775 (let (alist)
776 (if qualified-names-p
777 (ebrowse-for-all-trees (tree ebrowse--tree-obarray)
778 (setq alist
779 (acons (ebrowse-qualified-class-name (ebrowse-ts-class tree))
780 tree alist)))
781 (ebrowse-for-all-trees (tree ebrowse--tree-obarray)
782 (setq alist
783 (acons (ebrowse-cs-name (ebrowse-ts-class tree))
784 tree alist))))
785 alist))
786
787
788(defun ebrowse-sort-tree-list (list)
789 "Sort a LIST of `ebrowse-ts' structures by qualified class names."
790 (sort list
791 #'(lambda (a b)
792 (string< (ebrowse-qualified-class-name (ebrowse-ts-class a))
793 (ebrowse-qualified-class-name (ebrowse-ts-class b))))))
794
795
796(defun ebrowse-class-in-tree (class tree)
797 "Search for a class with name CLASS in TREE.
798Return the class found, if any. This function is used during the load
799phase where classes appended to a file replace older class
800information."
801 (let ((tclass (ebrowse-ts-class class))
802 found)
803 (while (and tree (not found))
804 (let ((root (car tree)))
805 (when (string= (ebrowse-qualified-class-name (ebrowse-ts-class root))
806 (ebrowse-qualified-class-name tclass))
807 (setq found root))
808 (setq tree (cdr tree))))
809 found))
810
811
812(defun ebrowse-base-classes (tree)
813 "Return list of base-classes of TREE by searching subclass lists.
814This function must be used instead of the struct slot
815`base-classes' to access the base-class list directly because it
816computes this information lazily."
817 (or (ebrowse-ts-base-classes tree)
818 (setf (ebrowse-ts-base-classes tree)
819 (loop with to-search = (list tree)
820 with result = nil
821 as search = (pop to-search)
822 while search finally return result
823 do (ebrowse-for-all-trees (ti ebrowse--tree-obarray)
824 (when (memq search (ebrowse-ts-subclasses ti))
825 (unless (memq ti result)
826 (setq result (nconc result (list ti))))
827 (push ti to-search)))))))
828
829
830(defun ebrowse-direct-base-classes (tree)
831 "Return the list of direct super classes of TREE."
832 (let (result)
833 (dolist (s (ebrowse-base-classes tree))
834 (when (memq tree (ebrowse-ts-subclasses s))
835 (setq result (cons s result))))
836 result))
837
838
839
840;;; Operations on MEMBER structures/lists
841
842(defun ebrowse-name/accessor-alist (tree accessor)
843 "Return an alist containing all members of TREE in group ACCESSOR.
844ACCESSOR is the accessor function for the member list.
845Elements of the result have the form (NAME . ACCESSOR), where NAME
846is the member name."
847 (loop for member in (funcall accessor tree)
848 collect (cons (ebrowse-ms-name member) accessor)))
849
850
851(defun ebrowse-name/accessor-alist-for-visible-members ()
852 "Return an alist describing all members visible in the current buffer.
853Each element of the list has the form (MEMBER-NAME . ACCESSOR),
854where MEMBER-NAME is the member's name, and ACCESSOR is the struct
855accessor with which the member's list can be accessed in an `ebrowse-ts'
856structure. The list includes inherited members if these are visible."
857 (let* ((list (ebrowse-name/accessor-alist ebrowse--displayed-class
858 ebrowse--accessor)))
859 (if ebrowse--show-inherited-flag
860 (nconc list
861 (loop for tree in (ebrowse-base-classes
862 ebrowse--displayed-class)
863 nconc (ebrowse-name/accessor-alist
864 tree ebrowse--accessor)))
865 list)))
866
867
868(defun ebrowse-name/accessor-alist-for-class-members ()
869 "Like `ebrowse-name/accessor-alist-for-visible-members'.
870This function includes members of base classes if base class members
871are visible in the buffer."
872 (let (list)
873 (dolist (func ebrowse-member-list-accessors list)
874 (setq list (nconc list (ebrowse-name/accessor-alist
875 ebrowse--displayed-class func)))
876 (when ebrowse--show-inherited-flag
877 (dolist (class (ebrowse-base-classes ebrowse--displayed-class))
878 (setq list
879 (nconc list (ebrowse-name/accessor-alist class func))))))))
880
881
882;;; Progress indication
883
884(defvar ebrowse-n-boxes 0)
885(defconst ebrowse-max-boxes 60)
886
887(defun ebrowse-show-progress (title &optional start)
888 "Display a progress indicator.
889TITLE is the title of the progress message. START non-nil means
890this is the first progress message displayed."
891 (let (message-log-max)
892 (when start (setq ebrowse-n-boxes 0))
893 (setq ebrowse-n-boxes (mod (1+ ebrowse-n-boxes) ebrowse-max-boxes))
894 (message (concat title ": "
895 (propertize (make-string ebrowse-n-boxes
896 (if (display-color-p) ?\ ?+))
897 'face 'ebrowse-progress-face)))))
898
899
900;;; Reading a tree from disk
901
902(defun ebrowse-find-file ()
903 "Function installed as `find-file hook'.
904This loads a tree when it sees a special signature at the beginning of
905the file loaded."
906 (when (looking-at "\\[ebrowse-hs")
907 (ebrowse-load buffer-file-name 'switch)))
908
909
910(defun ebrowse-read ()
911 "Read `ebrowse-hs' and `ebrowse-ts' structures in the current buffer.
912Return a list (HEADER TREE) where HEADER is the file header read
913and TREE is a list of `ebrowse-ts' structures forming the class tree."
914 (let ((header (condition-case nil
915 (read (current-buffer))
916 (error (error "No Ebrowse file header found"))))
917 tree)
918 ;; Check file format.
919 (unless (ebrowse-hs-p header)
920 (error "No Ebrowse file header found"))
921 (unless (string= (ebrowse-hs-version header) ebrowse-version-string)
922 (error "File has wrong version `%s' (`%s' expected)"
923 (ebrowse-hs-version header) ebrowse-version-string))
924 ;; Read Lisp objects. Temporarily increase `gc-cons-threshold' to
925 ;; prevent a GC that would not free any memory.
926 (let ((gc-cons-threshold 2000000))
927 (while (not (eobp))
928 (let* ((root (read (current-buffer)))
929 (old-root (ebrowse-class-in-tree root tree)))
930 (ebrowse-show-progress "Reading data" (null tree))
931 (if old-root
932 (setf (car old-root) root)
933 (push root tree)))))
934 (garbage-collect)
935 (list header tree)))
936
937
938(defun ebrowse-load (file &optional switch)
939 "Load an Ebrowse file FILE into memory and make a tree buffer.
940Optional SWITCH non-nil means switch to the tree buffer afterwards.
941This function is normally called from a `find-file-hook'.
942Value is the tree buffer created."
943 (let (tree
944 header
945 (buffer (get-file-buffer file))
946 tree-buffer)
947 (if buffer
948 (multiple-value-setq (header tree)
949 (ebrowse-read))
950 (save-excursion
951 ;; Since find-file hooks may be involved, we must visit the
952 ;; file in a way that these hooks are not called.
953 (set-buffer (create-file-buffer file))
954 (erase-buffer)
955 (insert-file file)
956 (set-buffer-modified-p nil)
957 (unwind-protect
958 (multiple-value-setq (header tree)
959 (ebrowse-read))
960 (kill-buffer (current-buffer)))))
961 (when tree
962 (message "Sorting. Please be patient...")
963 (setf tree (ebrowse-sort-tree-list tree))
964 ;; Create tree buffer
965 (setf tree-buffer
966 (ebrowse-create-tree-buffer tree file header
967 (ebrowse-build-tree-obarray tree)
968 switch buffer))
969 (message nil)
970 tree-buffer)))
971
972
973(defun ebrowse-revert-tree-buffer-from-file (ignore-auto-save noconfirm)
974 "Function installed as `revert-buffer-function' in tree buffers.
975See that variable's documentation for the meaning of IGNORE-AUTO-SAVE and
976NOCONFIRM."
977 (interactive)
978 (when (or noconfirm
979 (yes-or-no-p "Revert tree from disk? "))
980 (let ((ebrowse-file (or buffer-file-name ebrowse--tags-file-name)))
981 (loop for member-buffer in (ebrowse-same-tree-member-buffer-list)
982 do (kill-buffer member-buffer))
983 (kill-buffer (current-buffer))
984 (switch-to-buffer (ebrowse-load ebrowse-file)))))
985
986
987(defun ebrowse-create-tree-buffer (tree tags-file header obarray pop
988 &optional find-file-buffer)
989 "Create a new tree buffer for tree TREE.
990The tree was loaded from file TAGS-FILE.
991HEADER is the header structure of the file.
992OBARRAY is an obarray with a symbol for each class in the tree.
993POP non-nil means popup the buffer up at the end.
994FIND-FILE-BUFFER, if non-nil, is the buffer from which the Lisp data
995was read.
996Return the buffer created."
997 (let (name)
998 (cond (find-file-buffer
999 (set-buffer find-file-buffer)
1000 (erase-buffer)
1001 (setq name (ebrowse-frozen-tree-buffer-name tags-file))
1002 (ebrowse-rename-buffer name))
1003 (t
1004 (setq name ebrowse-tree-buffer-name)
1005 (set-buffer (get-buffer-create name))))
1006 ;; Switch to tree mode and initialize buffer local variables.
1007 (ebrowse-tree-mode)
1008 (setf ebrowse--tree tree
1009 ebrowse--tags-file-name tags-file
1010 ebrowse--tree-obarray obarray
1011 ebrowse--header header
1012 ebrowse--frozen-flag (not (null find-file-buffer)))
1013 ;; Switch or pop to the tree buffer; display the tree and return the
1014 ;; buffer.
1015 (case pop
1016 (switch (switch-to-buffer name))
1017 (pop (pop-to-buffer name)))
1018 (ebrowse-redraw-tree)
1019 (set-buffer-modified-p nil)
1020 (current-buffer)))
1021
1022
1023
1024;;; Operations for member obarrays
1025
1026(defun ebrowse-fill-member-table ()
1027 "Return an obarray holding all members of all classes in the current tree.
1028
1029For each member, a symbol is added to the obarray. Members are
1030extracted from the buffer-local tree `ebrowse--tree-obarray'.
1031
1032Each symbol has its property `ebrowse-info' set to a list (TREE MEMBER-LIST
1033MEMBER) where TREE is the tree in which the member is defined,
1034MEMBER-LIST is a symbol describing the member list in which the member
1035is found, and MEMBER is a MEMBER structure describing the member.
1036
1037The slot `member-table' of the buffer-local header structure of
1038type `ebrowse-hs' is set to the resulting obarray."
1039 (let ((members (make-hash-table :test 'equal))
1040 (i -1))
1041 (setf (ebrowse-hs-member-table ebrowse--header) nil)
1042 (garbage-collect)
1043 ;; For all classes...
1044 (ebrowse-for-all-trees (c ebrowse--tree-obarray)
1045 (when (zerop (% (incf i) 10))
1046 (ebrowse-show-progress "Preparing member lookup" (zerop i)))
1047 (loop for f in ebrowse-member-list-accessors do
1048 (loop for m in (funcall f c) do
1049 (let* ((member-name (ebrowse-ms-name m))
1050 (value (gethash member-name members)))
1051 (push (list c f m) value)
1052 (puthash member-name value members)))))
1053 (setf (ebrowse-hs-member-table ebrowse--header) members)))
1054
1055
1056(defun ebrowse-member-table (header)
1057 "Return the member obarray. Build it it hasn't been set up yet.
1058HEADER is the tree header structure of the class tree."
1059 (when (null (ebrowse-hs-member-table header))
1060 (loop for buffer in (ebrowse-browser-buffer-list)
1061 until (eq header (ebrowse-value-in-buffer 'ebrowse--header buffer))
1062 finally do
1063 (save-excursion
1064 (set-buffer buffer)
1065 (ebrowse-fill-member-table))))
1066 (ebrowse-hs-member-table header))
1067
1068
1069
1070;;; Operations on TREE obarrays
1071
1072(defun ebrowse-build-tree-obarray (tree)
1073 "Make sure every class in TREE is represented by a unique object.
1074Build obarray of all classes in TREE."
1075 (let ((classes (make-vector 127 0)))
1076 ;; Add root classes...
1077 (loop for root in tree
1078 as sym =
1079 (intern (ebrowse-qualified-class-name (ebrowse-ts-class root)) classes)
1080 do (unless (get sym 'ebrowse-root)
1081 (setf (get sym 'ebrowse-root) root)))
1082 ;; Process subclasses
1083 (ebrowse-insert-supers tree classes)
1084 classes))
1085
1086
1087(defun ebrowse-insert-supers (tree classes)
1088 "Build base class lists in class tree TREE.
1089CLASSES is an obarray used to collect classes.
1090
1091Helper function for `ebrowse-build-tree-obarray'. Base classes should
1092be ordered so that immediate base classes come first, then the base
1093class of the immediate base class and so on. This means that we must
1094construct the base-class list top down with adding each level at the
1095beginning of the base-class list.
1096
1097We have to be cautious here not to end up in an infinite recursion
1098if for some reason a circle is in the inheritance graph."
1099 (loop for class in tree
1100 as subclasses = (ebrowse-ts-subclasses class) do
1101 ;; Make sure every class is represented by a unique object
1102 (loop for subclass on subclasses
1103 as sym = (intern
1104 (ebrowse-qualified-class-name (ebrowse-ts-class (car subclass)))
1105 classes)
1106 as next = nil
1107 do
1108 ;; Replace the subclass tree with the one found in
1109 ;; CLASSES if there is already an entry for that class
1110 ;; in it. Otherwise make a new entry.
1111 ;;
1112 ;; CAVEAT: If by some means (e.g., use of the
1113 ;; preprocessor in class declarations, a name is marked
1114 ;; as a subclass of itself on some path, we would end up
1115 ;; in an endless loop. We have to omit subclasses from
1116 ;; the recursion that already have been processed.
1117 (if (get sym 'ebrowse-root)
1118 (setf (car subclass) (get sym 'ebrowse-root))
1119 (setf (get sym 'ebrowse-root) (car subclass))))
1120 ;; Process subclasses
1121 (ebrowse-insert-supers subclasses classes)))
1122
1123
1124;;; Tree buffers
1125
1126(unless ebrowse-tree-mode-map
1127 (let ((map (make-keymap)))
1128 (setf ebrowse-tree-mode-map map)
1129 (suppress-keymap map)
1130
1131 (when window-system
1132 (define-key map [down-mouse-3] 'ebrowse-mouse-3-in-tree-buffer)
1133 (define-key map [mouse-2] 'ebrowse-mouse-2-in-tree-buffer)
1134 (define-key map [down-mouse-1] 'ebrowse-mouse-1-in-tree-buffer))
1135
1136 (let ((map1 (make-sparse-keymap)))
1137 (suppress-keymap map1 t)
1138 (define-key map "L" map1)
1139 (define-key map1 "d" 'ebrowse-tree-command:show-friends)
1140 (define-key map1 "f" 'ebrowse-tree-command:show-member-functions)
1141 (define-key map1 "F" 'ebrowse-tree-command:show-static-member-functions)
1142 (define-key map1 "t" 'ebrowse-tree-command:show-types)
1143 (define-key map1 "v" 'ebrowse-tree-command:show-member-variables)
1144 (define-key map1 "V" 'ebrowse-tree-command:show-static-member-variables))
1145
1146 (let ((map1 (make-sparse-keymap)))
1147 (suppress-keymap map1 t)
1148 (define-key map "M" map1)
1149 (define-key map1 "a" 'ebrowse-mark-all-classes)
1150 (define-key map1 "t" 'ebrowse-toggle-mark-at-point))
1151
1152 (let ((map1 (make-sparse-keymap)))
1153 (suppress-keymap map1 t)
1154 (define-key map "T" map1)
1155 (define-key map1 "f" 'ebrowse-toggle-file-name-display)
1156 (define-key map1 "s" 'ebrowse-show-file-name-at-point)
1157 (define-key map1 "w" 'ebrowse-set-tree-indentation)
1158 (define-key map "x" 'ebrowse-statistics))
1159
1160 (define-key map "n" 'ebrowse-repeat-member-search)
1161 (define-key map "q" 'bury-buffer)
1162 (define-key map "*" 'ebrowse-expand-all)
1163 (define-key map "+" 'ebrowse-expand-branch)
1164 (define-key map "-" 'ebrowse-collapse-branch)
1165 (define-key map "/" 'ebrowse-read-class-name-and-go)
1166 (define-key map " " 'ebrowse-view-class-declaration)
1167 (define-key map "?" 'describe-mode)
1168 (define-key map "\C-i" 'ebrowse-pop/switch-to-member-buffer-for-same-tree)
1169 (define-key map "\C-k" 'ebrowse-remove-class-at-point)
1170 (define-key map "\C-l" 'ebrowse-redraw-tree)
1171 (define-key map "\C-m" 'ebrowse-find-class-declaration)))
1172
1173
1174
1175;;; Tree-mode - mode for tree buffers
1176
1177;;;###autoload
1178(defun ebrowse-tree-mode ()
1179 "Major mode for Ebrowse class tree buffers.
1180Each line corresponds to a class in a class tree.
1181Letters do not insert themselves, they are commands.
1182File operations in the tree buffer work on class tree data structures.
1183E.g.\\[save-buffer] writes the tree to the file it was loaded from.
1184
1185Tree mode key bindings:
1186\\{ebrowse-tree-mode-map}"
1187 (kill-all-local-variables)
1188 (mapcar 'make-local-variable
1189 '(ebrowse--tags-file-name
1190 ebrowse--indentation
1191 ebrowse--tree
1192 ebrowse--header
1193 ebrowse--show-file-names-flag
1194 ebrowse--frozen-flag
1195 ebrowse--tree-obarray
1196 ebrowse--mode-strings
1197 revert-buffer-function))
1198 (use-local-map ebrowse-tree-mode-map)
1199 (let* ((props (text-properties-at
1200 0
1201 (car (default-value 'mode-line-buffer-identification))))
1202 (ident (apply #'propertize "C++ Tree" props)))
1203 (setf ebrowse--show-file-names-flag nil
1204 ebrowse--tree-obarray (make-vector 127 0)
1205 ebrowse--frozen-flag nil
1206 major-mode 'ebrowse-tree-mode
1207 mode-name "Ebrowse-Tree"
1208 mode-line-buffer-identification (list ident)
1209 buffer-read-only t
1210 selective-display t
1211 selective-display-ellipses t
1212 revert-buffer-function 'ebrowse-revert-tree-buffer-from-file))
1213 (add-hook 'local-write-file-hooks 'ebrowse-write-file-hook-fn)
1214 (modify-syntax-entry ?_ (char-to-string (char-syntax ?a)))
1215 (run-hooks 'ebrowse-tree-mode-hook))
1216
1217
1218(defun ebrowse-update-tree-buffer-mode-line ()
1219 "Update the tree buffer mode line."
1220 (setf ebrowse--mode-strings
1221 (concat (if ebrowse--frozen-flag (or buffer-file-name
1222 ebrowse--tags-file-name))
1223 (if (buffer-modified-p) "-**")))
1224 (ebrowse-rename-buffer (if ebrowse--frozen-flag
1225 (ebrowse-frozen-tree-buffer-name
1226 ebrowse--tags-file-name)
1227 ebrowse-tree-buffer-name))
1228 (force-mode-line-update))
1229
1230
1231
1232;;; Removing classes from trees
1233
1234(defun ebrowse-remove-class-and-kill-member-buffers (tree class)
1235 "Remove from TREE class CLASS.
1236Kill all member buffers still containing a reference to the class."
1237 (let ((sym (intern-soft (ebrowse-cs-name (ebrowse-ts-class class))
1238 ebrowse--tree-obarray)))
1239 (setf tree (delq class tree)
1240 (get sym 'ebrowse-root) nil)
1241 (dolist (root tree)
1242 (setf (ebrowse-ts-subclasses root)
1243 (delq class (ebrowse-ts-subclasses root))
1244 (ebrowse-ts-base-classes root) nil)
1245 (ebrowse-remove-class-and-kill-member-buffers
1246 (ebrowse-ts-subclasses root) class))
1247 (ebrowse-kill-member-buffers-displaying class)
1248 tree))
1249
1250
1251(defun ebrowse-remove-class-at-point (forced)
1252 "Remove the class point is on from the class tree.
1253Do not ask for confirmation if FORCED is non-nil."
1254 (interactive "P")
1255 (let* ((class (ebrowse-tree-at-point))
1256 (class-name (ebrowse-cs-name (ebrowse-ts-class class)))
1257 (subclasses (ebrowse-ts-subclasses class)))
1258 (cond ((or forced
1259 (y-or-n-p (concat "Delete class " class-name "? ")))
1260 (setf ebrowse--tree (ebrowse-remove-class-and-kill-member-buffers
1261 ebrowse--tree class))
1262 (set-buffer-modified-p t)
1263 (message "%s %sdeleted." class-name
1264 (if subclasses "and derived classes " ""))
1265 (ebrowse-redraw-tree))
1266 (t (message "Aborted")))))
1267
1268
1269
1270;;; Marking classes in the tree buffer
1271
1272(defun ebrowse-toggle-mark-at-point (&optional n-times)
1273 "Toggle mark for class cursor is on.
1274If given a numeric N-TIMES argument, mark that many classes."
1275 (interactive "p")
1276 (let (to-change pnt)
1277 ;; Get the classes whose mark must be toggled. Note that
1278 ;; ebrowse-tree-at-point might issue an error.
1279 (condition-case error
1280 (loop repeat (or n-times 1)
1281 as tree = (ebrowse-tree-at-point)
1282 do (progn
1283 (setf (ebrowse-ts-mark tree) (not (ebrowse-ts-mark tree)))
1284 (forward-line 1)
1285 (push tree to-change)))
1286 (error nil))
1287 (save-excursion
1288 ;; For all these classes, reverse the mark char in the display
1289 ;; by a regexp replace over the whole buffer. The reason for this
1290 ;; is that classes might have multiple base classes. If this is
1291 ;; the case, they are displayed more than once in the tree.
1292 (ebrowse-output
1293 (loop for tree in to-change
1294 as regexp = (concat "^.*\\b"
1295 (regexp-quote
1296 (ebrowse-cs-name (ebrowse-ts-class tree)))
1297 "\\b")
1298 do
1299 (goto-char (point-min))
1300 (loop while (re-search-forward regexp nil t)
1301 do (progn
1302 (goto-char (match-beginning 0))
1303 (delete-char 1)
1304 (insert-char (if (ebrowse-ts-mark tree) ?> ? ) 1)
1305 (ebrowse-set-mark-props (1- (point)) (point) tree)
1306 (goto-char (match-end 0)))))))))
1307
1308
1309(defun ebrowse-mark-all-classes (prefix)
1310 "Unmark, with PREFIX mark, all classes in the tree."
1311 (interactive "P")
1312 (ebrowse-for-all-trees (tree ebrowse--tree-obarray)
1313 (setf (ebrowse-ts-mark tree) prefix))
1314 (ebrowse-redraw-marks (point-min) (point-max)))
1315
1316
1317(defun ebrowse-redraw-marks (start end)
1318 "Display class marker signs in the tree between START and END."
1319 (interactive)
1320 (save-excursion
1321 (ebrowse-output
1322 (catch 'end
1323 (goto-char (point-min))
1324 (dolist (root ebrowse--tree)
1325 (ebrowse-draw-marks-fn root start end))))
1326 (ebrowse-update-tree-buffer-mode-line)))
1327
1328
1329(defun ebrowse-draw-marks-fn (tree start end)
1330 "Display class marker signs in TREE between START and END."
1331 (when (>= (point) start)
1332 (delete-char 1)
1333 (insert (if (ebrowse-ts-mark tree) ?> ? ))
1334 (ebrowse-set-mark-props (1- (point)) (point) tree))
1335 (forward-line 1)
1336 (when (> (point) end)
1337 (throw 'end nil))
1338 (dolist (sub (ebrowse-ts-subclasses tree))
1339 (ebrowse-draw-marks-fn sub start end)))
1340
1341
1342
1343;;; File name display in tree buffers
1344
1345(defun ebrowse-show-file-name-at-point (prefix)
1346 "Show filename in the line point is in.
1347With PREFIX, insert that many filenames."
1348 (interactive "p")
1349 (unless ebrowse--show-file-names-flag
1350 (ebrowse-output
1351 (dotimes (i prefix)
1352 (let ((tree (ebrowse-tree-at-point))
1353 start
1354 file-name-existing)
1355 (unless tree return)
1356 (beginning-of-line)
1357 (skip-chars-forward " \t*a-zA-Z0-9_")
1358 (setq start (point)
1359 file-name-existing (looking-at "("))
1360 (delete-region start (save-excursion (end-of-line) (point)))
1361 (unless file-name-existing
1362 (indent-to ebrowse-source-file-column)
1363 (insert "(" (or (ebrowse-cs-file
1364 (ebrowse-ts-class tree))
1365 "unknown")
1366 ")"))
1367 (ebrowse-set-face start (point) 'ebrowse-file-name-face)
1368 (beginning-of-line)
1369 (forward-line 1))))))
1370
1371
1372(defun ebrowse-toggle-file-name-display ()
1373 "Toggle display of filenames in tree buffer."
1374 (interactive)
1375 (setf ebrowse--show-file-names-flag (not ebrowse--show-file-names-flag))
1376 (let ((old-line (count-lines (point-min) (point))))
1377 (ebrowse-redraw-tree)
1378 (goto-line old-line)))
1379
1380
1381
1382;;; General member and tree buffer functions
1383
1384(defun ebrowse-member-buffer-p (buffer)
1385 "Value is non-nil if BUFFER is a member buffer."
1386 (eq (cdr (assoc 'major-mode (buffer-local-variables buffer)))
1387 'ebrowse-member-mode))
1388
1389
1390(defun ebrowse-tree-buffer-p (buffer)
1391 "Value is non-nil if BUFFER is a class tree buffer."
1392 (eq (cdr (assoc 'major-mode (buffer-local-variables buffer)))
1393 'ebrowse-tree-mode))
1394
1395
1396(defun ebrowse-buffer-p (buffer)
1397 "Value is non-nil if BUFFER is a tree or member buffer."
1398 (memq (cdr (assoc 'major-mode (buffer-local-variables buffer)))
1399 '(ebrowse-tree-mode ebrowse-member-mode)))
1400
1401
1402(defun ebrowse-browser-buffer-list ()
1403 "Return a list of all tree or member buffers."
1404 (ebrowse-delete-if-not 'ebrowse-buffer-p (buffer-list)))
1405
1406
1407(defun ebrowse-member-buffer-list ()
1408 "Return a list of all member buffers."
1409 (ebrowse-delete-if-not 'ebrowse-member-buffer-p (buffer-list)))
1410
1411
1412(defun ebrowse-tree-buffer-list ()
1413 "Return a list of all tree buffers."
1414 (ebrowse-delete-if-not 'ebrowse-tree-buffer-p (buffer-list)))
1415
1416
1417(defun ebrowse-known-class-trees-buffer-list ()
1418 "Return a list of buffers containing class trees.
1419The list will contain, for each class tree loaded,
1420one buffer. Prefer tree buffers over member buffers."
1421 (let ((buffers (nconc (ebrowse-tree-buffer-list)
1422 (ebrowse-member-buffer-list)))
1423 (set (make-hash-table))
1424 result)
1425 (dolist (buffer buffers)
1426 (let ((tree (ebrowse-value-in-buffer 'ebrowse--tree buffer)))
1427 (unless (gethash tree set)
1428 (push buffer result))
1429 (puthash tree t set)))
1430 result))
1431
1432
1433(defun ebrowse-same-tree-member-buffer-list ()
1434 "Return a list of members buffers with same tree as current buffer."
1435 (ebrowse-delete-if-not
1436 #'(lambda (buffer)
1437 (eq (ebrowse-value-in-buffer 'ebrowse--tree buffer)
1438 ebrowse--tree))
1439 (ebrowse-member-buffer-list)))
1440
1441
1442
1443(defun ebrowse-pop/switch-to-member-buffer-for-same-tree (arg)
1444 "Pop to the buffer displaying members.
1445Switch to buffer if prefix ARG.
1446If no member buffer exists, make one."
1447 (interactive "P")
1448 (let ((buf (or (first (ebrowse-same-tree-member-buffer-list))
1449 (get-buffer ebrowse-member-buffer-name)
1450 (ebrowse-tree-command:show-member-functions))))
1451 (when buf
1452 (if arg
1453 (switch-to-buffer buf)
1454 (pop-to-buffer buf)))
1455 buf))
1456
1457
1458(defun ebrowse-switch-to-next-member-buffer ()
1459 "Switch to next member buffer."
1460 (interactive)
1461 (let* ((list (ebrowse-member-buffer-list))
1462 (next-list (cdr (memq (current-buffer) list)))
1463 (next-buffer (if next-list (car next-list) (car list))))
1464 (if (eq next-buffer (current-buffer))
1465 (error "No next buffer")
1466 (bury-buffer)
1467 (switch-to-buffer next-buffer))))
1468
1469
1470(defun ebrowse-kill-member-buffers-displaying (tree)
1471 "Kill all member buffers displaying TREE."
1472 (loop for buffer in (ebrowse-member-buffer-list)
1473 as class = (ebrowse-value-in-buffer 'ebrowse--displayed-class buffer)
1474 when (eq class tree) do (kill-buffer buffer)))
1475
1476
1477(defun ebrowse-frozen-tree-buffer-name (tags-file-name)
1478 "Return the buffer name of a tree which is associated TAGS-FILE-NAME."
1479 (concat ebrowse-tree-buffer-name " (" tags-file-name ")"))
1480
1481
1482(defun ebrowse-pop-to-browser-buffer (arg)
1483 "Pop to a browser buffer from any other buffer.
1484Pop to member buffer if no prefix ARG, to tree buffer otherwise."
1485 (interactive "P")
1486 (let ((buffer (get-buffer (if arg
1487 ebrowse-tree-buffer-name
1488 ebrowse-member-buffer-name))))
1489 (unless buffer
1490 (setq buffer
1491 (get-buffer (if arg
1492 ebrowse-member-buffer-name
1493 ebrowse-tree-buffer-name))))
1494 (unless buffer
1495 (error "No browser buffer found"))
1496 (pop-to-buffer buffer)))
1497
1498
1499
1500;;; Misc tree buffer commands
1501
1502(defun ebrowse-set-tree-indentation ()
1503 "Set the indentation width of the tree display."
1504 (interactive)
1505 (let ((width (string-to-int (read-from-minibuffer
1506 (concat "Indentation ("
1507 (int-to-string ebrowse--indentation)
1508 "): ")))))
1509 (when (plusp width)
1510 (setf ebrowse--indentation width)
1511 (ebrowse-redraw-tree))))
1512
1513
1514(defun ebrowse-read-class-name-and-go (&optional class)
1515 "Position cursor on CLASS.
1516Read a class name from the minibuffer if CLASS is nil."
1517 (interactive)
1518 (ebrowse-ignoring-completion-case
1519 ;; If no class specified, read the class name from mini-buffer
1520 (unless class
1521 (setf class
1522 (completing-read "Goto class: "
1523 (ebrowse-tree-obarray-as-alist) nil t)))
1524 (ebrowse-save-selective
1525 (goto-char (point-min))
1526 (widen)
1527 (setf selective-display nil)
1528 (setq ebrowse--last-regexp (concat "\\b" class "\\b"))
1529 (if (re-search-forward ebrowse--last-regexp nil t)
1530 (progn
1531 (goto-char (match-beginning 0))
1532 (ebrowse-unhide-base-classes))
1533 (error "Not found")))))
1534
1535
1536
1537;;; Showing various kinds of member buffers
1538
1539(defun ebrowse-tree-command:show-member-variables (arg)
1540 "Display member variables; with prefix ARG in frozen member buffer."
1541 (interactive "P")
1542 (ebrowse-display-member-buffer 'ebrowse-ts-member-variables arg))
1543
1544
1545(defun ebrowse-tree-command:show-member-functions (&optional arg)
1546 "Display member functions; with prefix ARG in frozen member buffer."
1547 (interactive "P")
1548 (ebrowse-display-member-buffer 'ebrowse-ts-member-functions arg))
1549
1550
1551(defun ebrowse-tree-command:show-static-member-variables (arg)
1552 "Display static member variables; with prefix ARG in frozen member buffer."
1553 (interactive "P")
1554 (ebrowse-display-member-buffer 'ebrowse-ts-static-variables arg))
1555
1556
1557(defun ebrowse-tree-command:show-static-member-functions (arg)
1558 "Display static member functions; with prefix ARG in frozen member buffer."
1559 (interactive "P")
1560 (ebrowse-display-member-buffer 'ebrowse-ts-static-functions arg))
1561
1562
1563(defun ebrowse-tree-command:show-friends (arg)
1564 "Display friend functions; with prefix ARG in frozen member buffer."
1565 (interactive "P")
1566 (ebrowse-display-member-buffer 'ebrowse-ts-friends arg))
1567
1568
1569(defun ebrowse-tree-command:show-types (arg)
1570 "Display types defined in a class; with prefix ARG in frozen member buffer."
1571 (interactive "P")
1572 (ebrowse-display-member-buffer 'ebrowse-ts-types arg))
1573
1574
1575
1576;;; Viewing or finding a class declaration
1577
1578(defun ebrowse-tree-at-point ()
1579 "Return the class structure for the class point is on."
1580 (or (get-text-property (point) 'ebrowse-tree)
1581 (error "Not on a class")))
1582
1583
1584(defun* ebrowse-view/find-class-declaration (&key view where)
1585 "View or find the declarator of the class point is on.
1586VIEW non-nil means view it. WHERE is additional position info."
1587 (let* ((class (ebrowse-ts-class (ebrowse-tree-at-point)))
1588 (file (ebrowse-cs-file class))
1589 (browse-struct (make-ebrowse-bs
1590 :name (ebrowse-cs-name class)
1591 :pattern (ebrowse-cs-pattern class)
1592 :flags (ebrowse-cs-flags class)
1593 :file (ebrowse-cs-file class)
1594 :point (ebrowse-cs-point class))))
1595 (ebrowse-view/find-file-and-search-pattern
1596 browse-struct
1597 (list ebrowse--header class nil)
1598 file
1599 ebrowse--tags-file-name
1600 view
1601 where)))
1602
1603
1604(defun ebrowse-find-class-declaration (prefix-arg)
1605 "Find a class declaration and position cursor on it.
1606PREFIX-ARG 4 means find it in another window.
1607PREFIX-ARG 5 means find it in another frame."
1608 (interactive "p")
1609 (ebrowse-view/find-class-declaration
1610 :view nil
1611 :where (cond ((= prefix-arg 4) 'other-window)
1612 ((= prefix-arg 5) 'other-frame)
1613 (t 'this-window))))
1614
1615
1616(defun ebrowse-view-class-declaration (prefix-arg)
1617 "View class declaration and position cursor on it.
1618PREFIX-ARG 4 means view it in another window.
1619PREFIX-ARG 5 means view it in another frame."
1620 (interactive "p")
1621 (ebrowse-view/find-class-declaration
1622 :view 'view
1623 :where (cond ((= prefix-arg 4) 'other-window)
1624 ((= prefix-arg 5) 'other-frame)
1625 (t 'this-window))))
1626
1627
1628
1629;;; The FIND engine
1630
1631(defun ebrowse-find-source-file (file tags-file-name)
1632 "Find source file FILE.
1633Source files are searched for (a) relative to TAGS-FILE-NAME
1634which is the path of the BROWSE file from which the class tree was loaded,
1635and (b) in the directories named in `ebrowse-search-path'."
1636 (let (file-name
1637 (try-file (expand-file-name file
1638 (file-name-directory tags-file-name))))
1639 (if (file-readable-p try-file)
1640 (setq file-name try-file)
1641 (let ((search-in ebrowse-search-path))
1642 (while (and search-in
1643 (null file-name))
1644 (let ((try-file (expand-file-name file (car search-in))))
1645 (if (file-readable-p try-file)
1646 (setq file-name try-file))
1647 (setq search-in (cdr search-in))))))
1648 (unless file-name
1649 (error "File `%s' not found" file))
1650 file-name))
1651
1652
1653(defun ebrowse-view-file-other-window (file)
1654 "View a file FILE in another window.
1655This is a replacement for `view-file-other-window' which does not
1656seem to work. It should be removed when `view.el' is fixed."
1657 (interactive)
1658 (let ((old-arrangement (current-window-configuration))
1659 (had-a-buf (get-file-buffer file))
1660 (buf-to-view (find-file-noselect file)))
1661 (switch-to-buffer-other-window buf-to-view)
1662 (view-mode-enter old-arrangement
1663 (and (not had-a-buf)
1664 (not (buffer-modified-p buf-to-view))
1665 'kill-buffer))))
1666
1667
1668(defun ebrowse-view-exit-fn (buffer)
1669 "Function called when exiting View mode in BUFFER.
1670Restore frame configuration active before viewing the file,
1671and possibly kill the viewed buffer."
1672 (let (exit-action original-frame-configuration)
1673 (save-excursion
1674 (set-buffer buffer)
1675 (setq original-frame-configuration ebrowse--frame-configuration
1676 exit-action ebrowse--view-exit-action))
1677 ;; Delete the frame in which we viewed.
1678 (mapcar 'delete-frame
1679 (loop for frame in (frame-list)
1680 when (not (assq frame original-frame-configuration))
1681 collect frame))
1682 (when exit-action
1683 (funcall exit-action buffer))))
1684
1685
1686(defun ebrowse-view-file-other-frame (file)
1687 "View a file FILE in another frame.
1688The new frame is deleted when it is no longer used."
1689 (interactive)
1690 (let ((old-frame-configuration (current-frame-configuration))
1691 (old-arrangement (current-window-configuration))
1692 (had-a-buf (get-file-buffer file))
1693 (buf-to-view (find-file-noselect file)))
1694 (switch-to-buffer-other-frame buf-to-view)
1695 (make-local-variable 'ebrowse--frame-configuration)
1696 (setq ebrowse--frame-configuration old-frame-configuration)
1697 (make-local-variable 'ebrowse--view-exit-action)
1698 (setq ebrowse--view-exit-action
1699 (and (not had-a-buf)
1700 (not (buffer-modified-p buf-to-view))
1701 'kill-buffer))
1702 (view-mode-enter old-arrangement 'ebrowse-view-exit-fn)))
1703
1704
1705(defun ebrowse-view/find-file-and-search-pattern
1706 (struc info file tags-file-name &optional view where)
1707 "Find or view a member or class.
1708STRUC is an `ebrowse-bs' structure (or a structure including that)
1709describing what to search.
1710INFO is a list (HEADER MEMBER-OR-CLASS ACCESSOR). HEADER is the
1711header structure of a class tree. MEMBER-OR-CLASS is either an
1712`ebrowse-ms' or `ebrowse-cs' structure depending on what is searched.
1713ACCESSOR is an accessor function for the member list of an member
1714if MEMBER-OR-CLASS is an `ebrowse-ms'.
1715FILE is the file to search the member in.
1716FILE is not taken out of STRUC here because the filename in STRUC
1717may be nil in which case the filename of the class description is used.
1718TAGS-FILE-NAME is the name of the EBROWSE file from which the
1719tree was loaded.
1720If VIEW is non-nil, view file else find the file.
1721WHERE is either `other-window', `other-frame' or `this-window' and
1722specifies where to find/view the result."
1723 (unless file
1724 (error "Sorry, no file information available for %s"
1725 (ebrowse-bs-name struc)))
1726 ;; Get the source file to view or find.
1727 (setf file (ebrowse-find-source-file file tags-file-name))
1728 ;; If current window is dedicated, use another frame.
1729 (when (window-dedicated-p (selected-window))
1730 (setf where 'other-frame))
1731 (cond (view
1732 (setf ebrowse-temp-position-to-view struc
1733 ebrowse-temp-info-to-view info)
1734 (unless (boundp 'view-mode-hook)
1735 (setq view-mode-hook nil))
1736 (push 'ebrowse-find-pattern view-mode-hook)
1737 (case where
1738 (other-window (ebrowse-view-file-other-window file))
1739 (other-frame (ebrowse-view-file-other-frame file))
1740 (t (view-file file))))
1741 (t
1742 (case where
1743 (other-window (find-file-other-window file))
1744 (other-frame (find-file-other-frame file))
1745 (t (find-file file)))
1746 (ebrowse-find-pattern struc info))))
1747
1748
1749(defun ebrowse-symbol-regexp (name)
1750 "Generate a suitable regular expression for a member or class NAME.
1751This is `regexp-quote' for most symbols, except for operator names
1752which may contain whitespace. For these symbols, replace white
1753space in the symbol name (generated by EBROWSE) with a regular
1754expression matching any number of whitespace characters."
1755 (loop with regexp = (regexp-quote name)
1756 with start = 0
1757 finally return regexp
1758 while (string-match "[ \t]+" regexp start)
1759 do (setf (substring regexp (match-beginning 0) (match-end 0))
1760 "[ \t]*"
1761 start (+ (match-beginning 0) 5))))
1762
1763
1764(defun ebrowse-class-declaration-regexp (name)
1765 "Construct a regexp for a declaration of class NAME."
1766 (concat "^[ \t]*\\(template[ \t\n]*<.*>\\)?"
1767 "[ \t\n]*\\(class\\|struct\\|union\\).*\\S_"
1768 (ebrowse-symbol-regexp name)
1769 "\\S_"))
1770
1771
1772(defun ebrowse-variable-declaration-regexp (name)
1773 "Construct a regexp for matching a variable NAME."
1774 (concat "\\S_" (ebrowse-symbol-regexp name) "\\S_"))
1775
1776
1777(defun ebrowse-function-declaration/definition-regexp (name)
1778 "Construct a regexp for matching a function NAME."
1779 (concat "^[a-zA-Z0-9_:*&<>, \t]*\\S_"
1780 (ebrowse-symbol-regexp name)
1781 "[ \t\n]*("))
1782
1783
1784(defun ebrowse-pp-define-regexp (name)
1785 "Construct a regexp matching a define of NAME."
1786 (concat "^[ \t]*#[ \t]*define[ \t]+" (regexp-quote name)))
1787
1788
1789(defun* ebrowse-find-pattern (&optional position info &aux viewing)
1790 "Find a pattern.
1791
1792This is a kluge: Ebrowse allows you to find or view a file containing
1793a pattern. To be able to do a search in a viewed buffer,
1794`view-mode-hook' is temporarily set to this function;
1795`ebrowse-temp-position-to-view' holds what to search for.
1796
1797INFO is a list (TREE-HEADER TREE-OR-MEMBER MEMBER-LIST)."
1798 (unless position
1799 (pop view-mode-hook)
1800 (setf viewing t
1801 position ebrowse-temp-position-to-view
1802 info ebrowse-temp-info-to-view))
1803 (widen)
1804 (let* ((pattern (ebrowse-bs-pattern position))
1805 (start (ebrowse-bs-point position))
1806 (offset 100)
1807 found)
1808 (destructuring-bind (header class-or-member member-list) info
1809 ;; If no pattern is specified, construct one from the member name.
1810 (when (stringp pattern)
1811 (setq pattern (concat "^.*" (regexp-quote pattern))))
1812 ;; Construct a regular expression if none given.
1813 (unless pattern
1814 (typecase class-or-member
1815 (ebrowse-ms
1816 (case member-list
1817 ((ebrowse-ts-member-variables
1818 ebrowse-ts-static-variables
1819 ebrowse-ts-types)
1820 (setf pattern (ebrowse-variable-declaration-regexp
1821 (ebrowse-bs-name position))))
1822 (otherwise
1823 (if (ebrowse-define-p class-or-member)
1824 (setf pattern (ebrowse-pp-define-regexp (ebrowse-bs-name position)))
1825 (setf pattern (ebrowse-function-declaration/definition-regexp
1826 (ebrowse-bs-name position)))))))
1827 (ebrowse-cs
1828 (setf pattern (ebrowse-class-declaration-regexp
1829 (ebrowse-bs-name position))))))
1830 ;; Begin searching some OFFSET from the original point where the
1831 ;; regular expression was found by the parse, and step forward.
1832 ;; When there is no regular expression in the database and a
1833 ;; member definition/declaration was not seen by the parser,
1834 ;; START will be 0.
1835 (when (and (boundp 'ebrowse-debug)
1836 (symbol-value 'ebrowse-debug))
1837 (y-or-n-p (format "start = %d" start))
1838 (y-or-n-p pattern))
1839 (setf found
1840 (loop do (goto-char (max (point-min) (- start offset)))
1841 when (re-search-forward pattern (+ start offset) t) return t
1842 never (bobp)
1843 do (incf offset offset)))
1844 (cond (found
1845 (beginning-of-line)
1846 (run-hooks 'ebrowse-view/find-hook))
1847 ((numberp (ebrowse-bs-pattern position))
1848 (goto-char start)
1849 (if ebrowse-not-found-hook
1850 (run-hooks 'ebrowse-not-found-hook)
1851 (message "Not found")
1852 (sit-for 2)))
1853 (t
1854 (if ebrowse-not-found-hook
1855 (run-hooks 'ebrowse-not-found-hook)
1856 (unless viewing
1857 (error "Not found"))
1858 (message "Not found")
1859 (sit-for 2)))))))
1860
1861
1862;;; Drawing the tree
1863
1864(defun ebrowse-redraw-tree (&optional quietly)
1865 "Redisplay the complete tree.
1866QUIETLY non-nil means don't display progress messages."
1867 (interactive)
1868 (or quietly (message "Displaying..."))
1869 (save-excursion
1870 (ebrowse-output
1871 (erase-buffer)
1872 (ebrowse-draw-tree-fn)))
1873 (ebrowse-update-tree-buffer-mode-line)
1874 (or quietly (message nil)))
1875
1876
1877(defun ebrowse-set-mark-props (start end tree)
1878 "Set text properties for class marker signs between START and END.
1879TREE denotes the class shown."
1880 (add-text-properties
1881 start end
1882 `(mouse-face highlight ebrowse-what mark ebrowse-tree ,tree
1883 help-echo "double-mouse-1: mark/unmark"))
1884 (ebrowse-set-face start end 'ebrowse-tree-mark-face))
1885
1886
1887(defun* ebrowse-draw-tree-fn (&aux stack1 stack2 start)
1888 "Display a single class and recursively it's subclasses.
1889This function may look weird, but this is faster than recursion."
1890 (setq stack1 (make-list (length ebrowse--tree) 0)
1891 stack2 (ebrowse-copy-list ebrowse--tree))
1892 (loop while stack2
1893 as level = (pop stack1)
1894 as tree = (pop stack2)
1895 as class = (ebrowse-ts-class tree) do
1896 (let ((start-of-line (point))
1897 start-of-class-name end-of-class-name)
1898 ;; Insert mark
1899 (insert (if (ebrowse-ts-mark tree) ">" " "))
1900
1901 ;; Indent and insert class name
1902 (indent-to (+ (* level ebrowse--indentation)
1903 ebrowse-tree-left-margin))
1904 (setq start (point))
1905 (insert (ebrowse-qualified-class-name class))
1906
1907 ;; If template class, add <>
1908 (when (ebrowse-template-p class)
1909 (insert "<>"))
1910 (ebrowse-set-face start (point) (if (zerop level)
1911 'ebrowse-root-class-face
1912 'ebrowse-default-face))
1913 (setf start-of-class-name start
1914 end-of-class-name (point))
1915 ;; If filenames are to be displayed...
1916 (when ebrowse--show-file-names-flag
1917 (indent-to ebrowse-source-file-column)
1918 (setq start (point))
1919 (insert "("
1920 (or (ebrowse-cs-file class)
1921 "unknown")
1922 ")")
1923 (ebrowse-set-face start (point) 'ebrowse-file-name-face))
1924 (ebrowse-set-mark-props start-of-line (1+ start-of-line) tree)
1925 (add-text-properties
1926 start-of-class-name end-of-class-name
1927 `(mouse-face highlight ebrowse-what class-name
1928 ebrowse-tree ,tree
1929 help-echo "double-mouse-1: (un)expand tree; mouse-2: member functions, mouse-3: menu"))
1930 (insert "\n"))
1931 ;; Push subclasses, if any.
1932 (when (ebrowse-ts-subclasses tree)
1933 (setq stack2
1934 (nconc (ebrowse-copy-list (ebrowse-ts-subclasses tree)) stack2)
1935 stack1
1936 (nconc (make-list (length (ebrowse-ts-subclasses tree))
1937 (1+ level)) stack1)))))
1938
1939
1940
1941;;; Expanding/ collapsing tree branches
1942
1943(defun ebrowse-expand-branch (arg)
1944 "Expand a sub-tree that has been previously collapsed.
1945With prefix ARG, expand all sub-trees."
1946 (interactive "P")
1947 (if arg
1948 (ebrowse-expand-all arg)
1949 (ebrowse-collapse-fn nil)))
1950
1951
1952(defun ebrowse-collapse-branch (arg)
1953 "Fold (do no longer display) the subclasses of the current class.
1954\(The class cursor is on.) With prefix ARG, fold all trees in the buffer."
1955 (interactive "P")
1956 (if arg
1957 (ebrowse-expand-all (not arg))
1958 (ebrowse-collapse-fn t)))
1959
1960
1961(defun ebrowse-expand-all (collapse)
1962 "Expand or fold all trees in the buffer.
1963COLLAPSE non-nil means fold them."
1964 (interactive "P")
1965 (let ((line-end (if collapse "^\n" "^\r"))
1966 (insertion (if collapse "\r" "\n")))
1967 (ebrowse-output
1968 (save-excursion
1969 (goto-char (point-min))
1970 (while (not (progn (skip-chars-forward line-end) (eobp)))
1971 (when (or (not collapse)
1972 (looking-at "\n "))
1973 (delete-char 1)
1974 (insert insertion))
1975 (when collapse
1976 (skip-chars-forward "\n ")))))))
1977
1978
1979(defun ebrowse-unhide-base-classes ()
1980 "Unhide the line the cursor is on and all base classes."
1981 (ebrowse-output
1982 (save-excursion
1983 (let (indent last-indent)
1984 (skip-chars-backward "^\r\n")
1985 (when (not (looking-at "[\r\n][^ \t]"))
1986 (skip-chars-forward "\r\n \t")
1987 (while (and (or (null last-indent) ;first time
1988 (> indent 1)) ;not root class
1989 (re-search-backward "[\r\n][ \t]*" nil t))
1990 (setf indent (- (match-end 0)
1991 (match-beginning 0)))
1992 (when (or (null last-indent)
1993 (< indent last-indent))
1994 (setf last-indent indent)
1995 (when (looking-at "\r")
1996 (delete-char 1)
1997 (insert 10)))
1998 (backward-char 1)))))))
1999
2000
2001(defun ebrowse-hide-line (collapse)
2002 "Hide/show a single line in the tree.
2003COLLAPSE non-nil means hide."
2004 (save-excursion
2005 (ebrowse-output
2006 (skip-chars-forward "^\r\n")
2007 (delete-char 1)
2008 (insert (if collapse 13 10)))))
2009
2010
2011(defun ebrowse-collapse-fn (collapse)
2012 "Collapse or expand a branch of the tree.
2013COLLAPSE non-nil means collapse the branch."
2014 (ebrowse-output
2015 (save-excursion
2016 (beginning-of-line)
2017 (skip-chars-forward "> \t")
2018 (let ((indentation (current-column)))
2019 (while (and (not (eobp))
2020 (save-excursion
2021 (skip-chars-forward "^\r\n")
2022 (goto-char (1+ (point)))
2023 (skip-chars-forward "> \t")
2024 (> (current-column) indentation)))
2025 (ebrowse-hide-line collapse)
2026 (skip-chars-forward "^\r\n")
2027 (goto-char (1+ (point))))))))
2028
2029
2030;;; Electric tree selection
2031
2032(defvar ebrowse-electric-list-mode-map ()
2033 "Keymap used in electric Ebrowse buffer list window.")
2034
2035
2036(unless ebrowse-electric-list-mode-map
2037 (let ((map (make-keymap))
2038 (submap (make-keymap)))
2039 (setq ebrowse-electric-list-mode-map map)
2040 (fillarray (car (cdr map)) 'ebrowse-electric-list-undefined)
2041 (fillarray (car (cdr submap)) 'ebrowse-electric-list-undefined)
2042 (define-key map "\e" submap)
2043 (define-key map "\C-z" 'suspend-emacs)
2044 (define-key map "\C-h" 'Helper-help)
2045 (define-key map "?" 'Helper-describe-bindings)
2046 (define-key map "\C-c" nil)
2047 (define-key map "\C-c\C-c" 'ebrowse-electric-list-quit)
2048 (define-key map "q" 'ebrowse-electric-list-quit)
2049 (define-key map " " 'ebrowse-electric-list-select)
2050 (define-key map "\C-l" 'recenter)
2051 (define-key map "\C-u" 'universal-argument)
2052 (define-key map "\C-p" 'previous-line)
2053 (define-key map "\C-n" 'next-line)
2054 (define-key map "p" 'previous-line)
2055 (define-key map "n" 'next-line)
2056 (define-key map "v" 'ebrowse-electric-view-buffer)
2057 (define-key map "\C-v" 'scroll-up)
2058 (define-key map "\ev" 'scroll-down)
2059 (define-key map "\e\C-v" 'scroll-other-window)
2060 (define-key map "\e>" 'end-of-buffer)
2061 (define-key map "\e<" 'beginning-of-buffer)
2062 (define-key map "\e>" 'end-of-buffer)))
2063
2064(put 'ebrowse-electric-list-mode 'mode-class 'special)
2065(put 'ebrowse-electric-list-undefined 'suppress-keymap t)
2066
2067
2068(defun ebrowse-electric-list-mode ()
2069 "Mode for electric tree list mode."
2070 (kill-all-local-variables)
2071 (use-local-map ebrowse-electric-list-mode-map)
2072 (setq mode-name "Electric Position Menu"
2073 mode-line-buffer-identification "Electric Tree Menu")
2074 (when (memq 'mode-name mode-line-format)
2075 (setq mode-line-format (copy-sequence mode-line-format))
2076 (setcar (memq 'mode-name mode-line-format) "Tree Buffers"))
2077 (make-local-variable 'Helper-return-blurb)
2078 (setq Helper-return-blurb "return to buffer editing"
2079 truncate-lines t
2080 buffer-read-only t
2081 major-mode 'ebrowse-electric-list-mode)
2082 (run-hooks 'ebrowse-electric-list-mode-hook))
2083
2084
2085(defun ebrowse-list-tree-buffers ()
2086 "Display a list of all tree buffers."
2087 (set-buffer (get-buffer-create "*Tree Buffers*"))
2088 (setq buffer-read-only nil)
2089 (erase-buffer)
2090 (insert "Tree\n" "----\n")
2091 (dolist (buffer (ebrowse-known-class-trees-buffer-list))
2092 (insert (buffer-name buffer) "\n"))
2093 (setq buffer-read-only t))
2094
2095
2096;;;###autoload
2097(defun ebrowse-electric-choose-tree ()
2098 "Return a buffer containing a tree or nil if no tree found or canceled."
2099 (interactive)
2100 (unless (car (ebrowse-known-class-trees-buffer-list))
2101 (error "No tree buffers"))
2102 (let (select buffer window)
2103 (save-window-excursion
2104 (save-window-excursion (ebrowse-list-tree-buffers))
2105 (setq window (Electric-pop-up-window "*Tree Buffers*")
2106 buffer (window-buffer window))
2107 (shrink-window-if-larger-than-buffer window)
2108 (unwind-protect
2109 (progn
2110 (set-buffer buffer)
2111 (ebrowse-electric-list-mode)
2112 (setq select
2113 (catch 'ebrowse-electric-list-select
2114 (message "<<< Press Space to bury the list >>>")
2115 (let ((first (progn (goto-char (point-min))
2116 (forward-line 2)
2117 (point)))
2118 (last (progn (goto-char (point-max))
2119 (forward-line -1)
2120 (point)))
2121 (goal-column 0))
2122 (goto-char first)
2123 (Electric-command-loop 'ebrowse-electric-list-select
2124 nil
2125 t
2126 'ebrowse-electric-list-looper
2127 (cons first last))))))
2128 (set-buffer buffer)
2129 (bury-buffer buffer)
2130 (message nil)))
2131 (when select
2132 (set-buffer buffer)
2133 (setq select (ebrowse-electric-get-buffer select)))
2134 (kill-buffer buffer)
2135 select))
2136
2137
2138(defun ebrowse-electric-list-looper (state condition)
2139 "Prevent cursor from moving beyond the buffer end.
2140Don't let it move into the title lines.
2141See 'Electric-command-loop' for a description of STATE and CONDITION."
2142 (cond ((and condition
2143 (not (memq (car condition)
2144 '(buffer-read-only end-of-buffer
2145 beginning-of-buffer))))
2146 (signal (car condition) (cdr condition)))
2147 ((< (point) (car state))
2148 (goto-char (point-min))
2149 (forward-line 2))
2150 ((> (point) (cdr state))
2151 (goto-char (point-max))
2152 (forward-line -1)
2153 (if (pos-visible-in-window-p (point-max))
2154 (recenter -1)))))
2155
2156
2157(defun ebrowse-electric-list-undefined ()
2158 "Function called for keys that are undefined."
2159 (interactive)
2160 (message "Type C-h for help, ? for commands, q to quit, Space to select.")
2161 (sit-for 4))
2162
2163
2164(defun ebrowse-electric-list-quit ()
2165 "Discard the buffer list."
2166 (interactive)
2167 (throw 'ebrowse-electric-list-select nil))
2168
2169
2170(defun ebrowse-electric-list-select ()
2171 "Select a buffer from the buffer list."
2172 (interactive)
2173 (throw 'ebrowse-electric-list-select (point)))
2174
2175
2176(defun ebrowse-electric-get-buffer (point)
2177 "Get a buffer corresponding to the line POINT is in."
2178 (let ((index (- (count-lines (point-min) point) 2)))
2179 (nth index (ebrowse-known-class-trees-buffer-list))))
2180
2181
2182;;; View a buffer for a tree.
2183
2184(defun ebrowse-electric-view-buffer ()
2185 "View buffer point is on."
2186 (interactive)
2187 (let ((buffer (ebrowse-electric-get-buffer (point))))
2188 (cond (buffer
2189 (view-buffer buffer))
2190 (t
2191 (error "Buffer no longer exists")))))
2192
2193
2194(defun ebrowse-choose-from-browser-buffers ()
2195 "Read a browser buffer name from the minibuffer and return that buffer."
2196 (let* ((buffers (ebrowse-known-class-trees-buffer-list)))
2197 (if buffers
2198 (if (not (second buffers))
2199 (first buffers)
2200 (or (ebrowse-electric-choose-tree) (error "No tree buffer")))
2201 (let* ((insert-default-directory t)
2202 (file (read-file-name "Find tree: " nil nil t)))
2203 (save-excursion
2204 (find-file file))
2205 (find-buffer-visiting file)))))
2206
2207
2208;;; Member buffers
2209
2210(unless ebrowse-member-mode-map
2211 (let ((map (make-keymap)))
2212 (setf ebrowse-member-mode-map map)
2213 (suppress-keymap map)
2214
2215 (when window-system
2216 (define-key map [down-mouse-3] 'ebrowse-member-mouse-3)
2217 (define-key map [mouse-2] 'ebrowse-member-mouse-2))
2218
2219 (let ((map1 (make-sparse-keymap)))
2220 (suppress-keymap map1 t)
2221 (define-key map "C" map1)
2222 (define-key map1 "b" 'ebrowse-switch-member-buffer-to-base-class)
2223 (define-key map1 "c" 'ebrowse-switch-member-buffer-to-any-class)
2224 (define-key map1 "d" 'ebrowse-switch-member-buffer-to-derived-class)
2225 (define-key map1 "n" 'ebrowse-switch-member-buffer-to-next-sibling-class)
2226 (define-key map1 "p" 'ebrowse-switch-member-buffer-to-previous-sibling-class))
2227
2228 (let ((map1 (make-sparse-keymap)))
2229 (suppress-keymap map1 t)
2230 (define-key map "D" map1)
2231 (define-key map1 "a" 'ebrowse-toggle-member-attributes-display)
2232 (define-key map1 "b" 'ebrowse-toggle-base-class-display)
2233 (define-key map1 "f" 'ebrowse-freeze-member-buffer)
2234 (define-key map1 "l" 'ebrowse-toggle-long-short-display)
2235 (define-key map1 "r" 'ebrowse-toggle-regexp-display)
2236 (define-key map1 "w" 'ebrowse-set-member-buffer-column-width))
2237
2238 (let ((map1 (make-sparse-keymap)))
2239 (suppress-keymap map1 t)
2240 (define-key map "F" map1)
2241 (let ((map2 (make-sparse-keymap)))
2242 (suppress-keymap map2 t)
2243 (define-key map1 "a" map2)
2244 (define-key map2 "i" 'ebrowse-toggle-private-member-filter)
2245 (define-key map2 "o" 'ebrowse-toggle-protected-member-filter)
2246 (define-key map2 "u" 'ebrowse-toggle-public-member-filter))
2247 (define-key map1 "c" 'ebrowse-toggle-const-member-filter)
2248 (define-key map1 "i" 'ebrowse-toggle-inline-member-filter)
2249 (define-key map1 "p" 'ebrowse-toggle-pure-member-filter)
2250 (define-key map1 "r" 'ebrowse-remove-all-member-filters)
2251 (define-key map1 "v" 'ebrowse-toggle-virtual-member-filter))
2252
2253 (let ((map1 (make-sparse-keymap)))
2254 (suppress-keymap map1 t)
2255 (define-key map "L" map1)
2256 (define-key map1 "d" 'ebrowse-display-friends-member-list)
2257 (define-key map1 "f" 'ebrowse-display-function-member-list)
2258 (define-key map1 "F" 'ebrowse-display-static-functions-member-list)
2259 (define-key map1 "n" 'ebrowse-display-next-member-list)
2260 (define-key map1 "p" 'ebrowse-display-previous-member-list)
2261 (define-key map1 "t" 'ebrowse-display-types-member-list)
2262 (define-key map1 "v" 'ebrowse-display-variables-member-list)
2263 (define-key map1 "V" 'ebrowse-display-static-variables-member-list))
2264
2265 (let ((map1 (make-sparse-keymap)))
2266 (suppress-keymap map1 t)
2267 (define-key map "G" map1)
2268 (define-key map1 "m" 'ebrowse-goto-visible-member/all-member-lists)
2269 (define-key map1 "n" 'ebrowse-repeat-member-search)
2270 (define-key map1 "v" 'ebrowse-goto-visible-member))
2271
2272 (define-key map "f" 'ebrowse-find-member-declaration)
2273 (define-key map "m" 'ebrowse-switch-to-next-member-buffer)
2274 (define-key map "q" 'bury-buffer)
2275 (define-key map "t" 'ebrowse-show-displayed-class-in-tree)
2276 (define-key map "v" 'ebrowse-view-member-declaration)
2277 (define-key map " " 'ebrowse-view-member-definition)
2278 (define-key map "?" 'describe-mode)
2279 (define-key map "\C-i" 'ebrowse-pop-from-member-to-tree-buffer)
2280 (define-key map "\C-l" 'ebrowse-redisplay-member-buffer)
2281 (define-key map "\C-m" 'ebrowse-find-member-definition)))
2282
2283
2284
2285;;; Member mode
2286
2287;;###autoload
2288(defun ebrowse-member-mode ()
2289 "Major mode for Ebrowse member buffers.
2290
2291\\{ebrowse-member-mode-map}"
2292 (kill-all-local-variables)
2293 (use-local-map ebrowse-member-mode-map)
2294 (setq major-mode 'ebrowse-member-mode)
2295 (mapcar 'make-local-variable
2296 '(ebrowse--decl-column ;display column
2297 ebrowse--n-columns ;number of short columns
2298 ebrowse--column-width ;width of columns above
2299 ebrowse--show-inherited-flag ;include inherited members?
2300 ebrowse--filters ;public, protected, private
2301 ebrowse--accessor ;vars, functions, friends
2302 ebrowse--displayed-class ;class displayed
2303 ebrowse--long-display-flag ;display with regexps?
2304 ebrowse--source-regexp-flag ;show source regexp?
2305 ebrowse--attributes-flag ;show `virtual' and `inline'
2306 ebrowse--member-list ;list of members displayed
2307 ebrowse--tree ;the class tree
2308 ebrowse--member-mode-strings ;part of mode line
2309 ebrowse--tags-file-name ;
2310 ebrowse--header
2311 ebrowse--tree-obarray
2312 ebrowse--virtual-display-flag
2313 ebrowse--inline-display-flag
2314 ebrowse--const-display-flag
2315 ebrowse--pure-display-flag
2316 ebrowse--mode-line-props
2317 ebrowse--frozen-flag)) ;buffer not automagically reused
2318 (setq ebrowse--mode-line-props (text-properties-at
2319 0 (car (default-value
2320 'mode-line-buffer-identification)))
2321 mode-name "Ebrowse-Members"
2322 mode-line-buffer-identification 'ebrowse--member-mode-strings
2323 buffer-read-only t
2324 ebrowse--long-display-flag nil
2325 ebrowse--attributes-flag t
2326 ebrowse--show-inherited-flag t
2327 ebrowse--source-regexp-flag nil
2328 ebrowse--filters [0 1 2]
2329 ebrowse--decl-column ebrowse-default-declaration-column
2330 ebrowse--column-width ebrowse-default-column-width
2331 ebrowse--virtual-display-flag nil
2332 ebrowse--inline-display-flag nil
2333 ebrowse--const-display-flag nil
2334 ebrowse--pure-display-flag nil)
2335 (modify-syntax-entry ?_ (char-to-string (char-syntax ?a)))
2336 (run-hooks 'ebrowse-member-mode-hook))
2337
2338
2339
2340;;; Member mode mode line
2341
2342(defsubst ebrowse-class-name-displayed-in-member-buffer ()
2343 "Return the name of the class displayed in the member buffer."
2344 (ebrowse-cs-name (ebrowse-ts-class ebrowse--displayed-class)))
2345
2346
2347(defsubst ebrowse-member-list-name ()
2348 "Return a string describing what is displayed in the member buffer."
2349 (get ebrowse--accessor (if (ebrowse-globals-tree-p ebrowse--displayed-class)
2350 'ebrowse-global-title
2351 'ebrowse-title)))
2352
2353
2354(defun ebrowse-update-member-buffer-mode-line ()
2355 "Update the mode line of member buffers."
2356 (let* ((name (when ebrowse--frozen-flag
2357 (concat (ebrowse-class-name-displayed-in-member-buffer)
2358 " ")))
2359 (ident (concat name (ebrowse-member-list-name))))
2360 (setq ebrowse--member-mode-strings
2361 (apply #'propertize ident ebrowse--mode-line-props))
2362 (ebrowse-rename-buffer (if name ident ebrowse-member-buffer-name))
2363 (force-mode-line-update)))
2364
2365
2366;;; Misc member buffer commands
2367
2368(defun ebrowse-freeze-member-buffer ()
2369 "Toggle frozen status of current buffer."
2370 (interactive)
2371 (setq ebrowse--frozen-flag (not ebrowse--frozen-flag))
2372 (ebrowse-redisplay-member-buffer))
2373
2374
2375(defun ebrowse-show-displayed-class-in-tree (arg)
2376 "Show the currently displayed class in the tree window.
2377With prefix ARG, switch to the tree buffer else pop to it."
2378 (interactive "P")
2379 (let ((class-name (ebrowse-class-name-displayed-in-member-buffer)))
2380 (when (ebrowse-pop-from-member-to-tree-buffer arg)
2381 (ebrowse-read-class-name-and-go class-name))))
2382
2383
2384(defun ebrowse-set-member-buffer-column-width ()
2385 "Set the column width of the member display.
2386The new width is read from the minibuffer."
2387 (interactive)
2388 (let ((width (string-to-int
2389 (read-from-minibuffer
2390 (concat "Column width ("
2391 (int-to-string (if ebrowse--long-display-flag
2392 ebrowse--decl-column
2393 ebrowse--column-width))
2394 "): ")))))
2395 (when (plusp width)
2396 (if ebrowse--long-display-flag
2397 (setq ebrowse--decl-column width)
2398 (setq ebrowse--column-width width))
2399 (ebrowse-redisplay-member-buffer))))
2400
2401
2402(defun ebrowse-pop-from-member-to-tree-buffer (arg)
2403 "Pop from a member buffer to the matching tree buffer.
2404Switch to the buffer if prefix ARG. If no tree buffer exists,
2405make one."
2406 (interactive "P")
2407 (let ((buf (or (get-buffer (ebrowse-frozen-tree-buffer-name
2408 ebrowse--tags-file-name))
2409 (get-buffer ebrowse-tree-buffer-name)
2410 (ebrowse-create-tree-buffer ebrowse--tree
2411 ebrowse--tags-file-name
2412 ebrowse--header
2413 ebrowse--tree-obarray
2414 'pop))))
2415 (and buf
2416 (funcall (if arg 'switch-to-buffer 'pop-to-buffer) buf))
2417 buf))
2418
2419
2420
2421;;; Switching between member lists
2422
2423(defun ebrowse-display-member-list-for-accessor (accessor)
2424 "Switch the member buffer to display the member list for ACCESSOR."
2425 (setf ebrowse--accessor accessor
2426 ebrowse--member-list (funcall accessor ebrowse--displayed-class))
2427 (ebrowse-redisplay-member-buffer))
2428
2429
2430(defun ebrowse-cyclic-display-next/previous-member-list (incr)
2431 "Switch buffer to INCR'th next/previous list of members."
2432 (let ((index (ebrowse-position ebrowse--accessor
2433 ebrowse-member-list-accessors)))
2434 (setf ebrowse--accessor
2435 (cond ((plusp incr)
2436 (or (nth (1+ index)
2437 ebrowse-member-list-accessors)
2438 (first ebrowse-member-list-accessors)))
2439 ((minusp incr)
2440 (or (and (>= (decf index) 0)
2441 (nth index
2442 ebrowse-member-list-accessors))
2443 (first (last ebrowse-member-list-accessors))))))
2444 (ebrowse-display-member-list-for-accessor ebrowse--accessor)))
2445
2446
2447(defun ebrowse-display-next-member-list ()
2448 "Switch buffer to next member list."
2449 (interactive)
2450 (ebrowse-cyclic-display-next/previous-member-list 1))
2451
2452
2453(defun ebrowse-display-previous-member-list ()
2454 "Switch buffer to previous member list."
2455 (interactive)
2456 (ebrowse-cyclic-display-next/previous-member-list -1))
2457
2458
2459(defun ebrowse-display-function-member-list ()
2460 "Display the list of member functions."
2461 (interactive)
2462 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-member-functions))
2463
2464
2465(defun ebrowse-display-variables-member-list ()
2466 "Display the list of member variables."
2467 (interactive)
2468 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-member-variables))
2469
2470
2471(defun ebrowse-display-static-variables-member-list ()
2472 "Display the list of static member variables."
2473 (interactive)
2474 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-static-variables))
2475
2476
2477(defun ebrowse-display-static-functions-member-list ()
2478 "Display the list of static member functions."
2479 (interactive)
2480 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-static-functions))
2481
2482
2483(defun ebrowse-display-friends-member-list ()
2484 "Display the list of friends."
2485 (interactive)
2486 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-friends))
2487
2488
2489(defun ebrowse-display-types-member-list ()
2490 "Display the list of types."
2491 (interactive)
2492 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-types))
2493
2494
2495
2496;;; Filters and other display attributes
2497
2498(defun ebrowse-toggle-member-attributes-display ()
2499 "Toggle display of `virtual', `inline', `const' etc."
2500 (interactive)
2501 (setq ebrowse--attributes-flag (not ebrowse--attributes-flag))
2502 (ebrowse-redisplay-member-buffer))
2503
2504
2505(defun ebrowse-toggle-base-class-display ()
2506 "Toggle the display of members inherited from base classes."
2507 (interactive)
2508 (setf ebrowse--show-inherited-flag (not ebrowse--show-inherited-flag))
2509 (ebrowse-redisplay-member-buffer))
2510
2511
2512(defun ebrowse-toggle-pure-member-filter ()
2513 "Toggle display of pure virtual members."
2514 (interactive)
2515 (setf ebrowse--pure-display-flag (not ebrowse--pure-display-flag))
2516 (ebrowse-redisplay-member-buffer))
2517
2518
2519(defun ebrowse-toggle-const-member-filter ()
2520 "Toggle display of const members."
2521 (interactive)
2522 (setf ebrowse--const-display-flag (not ebrowse--const-display-flag))
2523 (ebrowse-redisplay-member-buffer))
2524
2525
2526(defun ebrowse-toggle-inline-member-filter ()
2527 "Toggle display of inline members."
2528 (interactive)
2529 (setf ebrowse--inline-display-flag (not ebrowse--inline-display-flag))
2530 (ebrowse-redisplay-member-buffer))
2531
2532
2533(defun ebrowse-toggle-virtual-member-filter ()
2534 "Toggle display of virtual members."
2535 (interactive)
2536 (setf ebrowse--virtual-display-flag (not ebrowse--virtual-display-flag))
2537 (ebrowse-redisplay-member-buffer))
2538
2539
2540(defun ebrowse-remove-all-member-filters ()
2541 "Remove all filters."
2542 (interactive)
2543 (dotimes (i 3)
2544 (aset ebrowse--filters i i))
2545 (setq ebrowse--pure-display-flag nil
2546 ebrowse--const-display-flag nil
2547 ebrowse--virtual-display-flag nil
2548 ebrowse--inline-display-flag nil)
2549 (ebrowse-redisplay-member-buffer))
2550
2551
2552(defun ebrowse-toggle-public-member-filter ()
2553 "Toggle visibility of public members."
2554 (interactive)
2555 (ebrowse-set-member-access-visibility 0)
2556 (ebrowse-redisplay-member-buffer))
2557
2558
2559(defun ebrowse-toggle-protected-member-filter ()
2560 "Toggle visibility of protected members."
2561 (interactive)
2562 (ebrowse-set-member-access-visibility 1)
2563 (ebrowse-redisplay-member-buffer))
2564
2565
2566(defun ebrowse-toggle-private-member-filter ()
2567 "Toggle visibility of private members."
2568 (interactive)
2569 (ebrowse-set-member-access-visibility 2)
2570 (ebrowse-redisplay-member-buffer))
2571
2572
2573(defun ebrowse-set-member-access-visibility (vis)
2574 (setf (aref ebrowse--filters vis)
2575 (if (aref ebrowse--filters vis) nil vis)))
2576
2577
2578(defun ebrowse-toggle-long-short-display ()
2579 "Toggle between long and short display form of member buffers."
2580 (interactive)
2581 (setf ebrowse--long-display-flag (not ebrowse--long-display-flag))
2582 (ebrowse-redisplay-member-buffer))
2583
2584
2585(defun ebrowse-toggle-regexp-display ()
2586 "Toggle declaration/definition regular expression display.
2587Used in member buffers showing the long display form."
2588 (interactive)
2589 (setf ebrowse--source-regexp-flag (not ebrowse--source-regexp-flag))
2590 (ebrowse-redisplay-member-buffer))
2591
2592
2593
2594;;; Viewing/finding members
2595
2596(defun ebrowse-find-member-definition (&optional prefix)
2597 "Find the file containing a member definition.
2598With PREFIX 4. find file in another window, with prefix 5
2599find file in another frame."
2600 (interactive "p")
2601 (ebrowse-view/find-member-declaration/definition prefix nil t))
2602
2603
2604(defun ebrowse-view-member-definition (prefix)
2605 "View the file containing a member definition.
2606With PREFIX 4. find file in another window, with prefix 5
2607find file in another frame."
2608 (interactive "p")
2609 (ebrowse-view/find-member-declaration/definition prefix t t))
2610
2611
2612(defun ebrowse-find-member-declaration (prefix)
2613 "Find the file containing a member's declaration.
2614With PREFIX 4. find file in another window, with prefix 5
2615find file in another frame."
2616 (interactive "p")
2617 (ebrowse-view/find-member-declaration/definition prefix nil))
2618
2619
2620(defun ebrowse-view-member-declaration (prefix)
2621 "View the file containing a member's declaration.
2622With PREFIX 4. find file in another window, with prefix 5
2623find file in another frame."
2624 (interactive "p")
2625 (ebrowse-view/find-member-declaration/definition prefix t))
2626
2627
2628(defun* ebrowse-view/find-member-declaration/definition
2629 (prefix view &optional definition info header tags-file-name)
2630 "Find or view a member declaration or definition.
2631With PREFIX 4. find file in another window, with prefix 5
2632find file in another frame.
2633DEFINITION non-nil means find the definition, otherwise find the
2634declaration.
2635INFO is a list (TREE ACCESSOR MEMBER) describing the member to
2636search.
2637TAGS-FILE-NAME is the file name of the EBROWSE file."
2638 (unless header
2639 (setq header ebrowse--header))
2640 (unless tags-file-name
2641 (setq tags-file-name ebrowse--tags-file-name))
2642 (let (tree member accessor file on-class
2643 (where (if (= prefix 4) 'other-window
2644 (if (= prefix 5) 'other-frame 'this-window))))
2645 ;; If not given as parameters, get the necessary information
2646 ;; out of the member buffer.
2647 (if info
2648 (setq tree (first info)
2649 accessor (second info)
2650 member (third info))
2651 (multiple-value-setq (tree member on-class)
2652 (ebrowse-member-info-from-point))
2653 (setq accessor ebrowse--accessor))
2654 ;; View/find class if on a line containing a class name.
2655 (when on-class
2656 (return-from ebrowse-view/find-member-declaration/definition
2657 (ebrowse-view/find-file-and-search-pattern
2658 (ebrowse-ts-class tree)
2659 (list ebrowse--header (ebrowse-ts-class tree) nil)
2660 (ebrowse-cs-file (ebrowse-ts-class tree))
2661 tags-file-name view where)))
2662 ;; For some member lists, it doesn't make sense to search for
2663 ;; a definition. If this is requested, silently search for the
2664 ;; declaration.
2665 (when (and definition
2666 (eq accessor 'ebrowse-ts-member-variables))
2667 (setq definition nil))
2668 ;; Construct a suitable `browse' struct for definitions.
2669 (when definition
2670 (setf member (make-ebrowse-ms
2671 :name (ebrowse-ms-name member)
2672 :file (ebrowse-ms-definition-file member)
2673 :pattern (ebrowse-ms-definition-pattern
2674 member)
2675 :flags (ebrowse-ms-flags member)
2676 :point (ebrowse-ms-definition-point
2677 member))))
2678 ;; When no file information in member, use that of the class
2679 (setf file (or (ebrowse-ms-file member)
2680 (if definition
2681 (ebrowse-cs-source-file (ebrowse-ts-class tree))
2682 (ebrowse-cs-file (ebrowse-ts-class tree)))))
2683 ;; When we have no regular expressions in the database the only
2684 ;; indication that the parser hasn't seen a definition/declaration
2685 ;; is that the search start point will be zero.
2686 (if (or (null file) (zerop (ebrowse-ms-point member)))
2687 (if (y-or-n-p (concat "No information about "
2688 (if definition "definition" "declaration")
2689 ". Search for "
2690 (if definition "declaration" "definition")
2691 " of `"
2692 (ebrowse-ms-name member)
2693 "'? "))
2694 (progn
2695 (message nil)
2696 ;; Recurse with new info.
2697 (ebrowse-view/find-member-declaration/definition
2698 prefix view (not definition) info header tags-file-name))
2699 (error "Search canceled"))
2700 ;; Find that thing.
2701 (ebrowse-view/find-file-and-search-pattern
2702 (make-ebrowse-bs :name (ebrowse-ms-name member)
2703 :pattern (ebrowse-ms-pattern member)
2704 :file (ebrowse-ms-file member)
2705 :flags (ebrowse-ms-flags member)
2706 :point (ebrowse-ms-point member))
2707 (list header member accessor)
2708 file
2709 tags-file-name
2710 view
2711 where))))
2712
2713
2714
2715;;; Drawing the member buffer
2716
2717(defun ebrowse-redisplay-member-buffer ()
2718 "Force buffer redisplay."
2719 (interactive)
2720 (let ((display-fn (if ebrowse--long-display-flag
2721 'ebrowse-draw-member-long-fn
2722 'ebrowse-draw-member-short-fn)))
2723 (ebrowse-output
2724 (erase-buffer)
2725 ;; Show this class
2726 (ebrowse-draw-member-buffer-class-line)
2727 (funcall display-fn ebrowse--member-list ebrowse--displayed-class)
2728 ;; Show inherited members if corresponding switch is on
2729 (when ebrowse--show-inherited-flag
2730 (dolist (super (ebrowse-base-classes ebrowse--displayed-class))
2731 (goto-char (point-max))
2732 (insert (if (bolp) "\n\n" "\n"))
2733 (ebrowse-draw-member-buffer-class-line super)
2734 (funcall display-fn (funcall ebrowse--accessor super) super)))
2735 (ebrowse-update-member-buffer-mode-line))))
2736
2737
2738(defun ebrowse-draw-member-buffer-class-line (&optional class)
2739 "Display the title line for a class section in the member buffer.
2740CLASS non-nil means display that class' title. Otherwise use
2741the class cursor is on."
2742 (let ((start (point))
2743 (tree (or class ebrowse--displayed-class))
2744 class-name-start
2745 class-name-end)
2746 (insert "class ")
2747 (setq class-name-start (point))
2748 (insert (ebrowse-qualified-class-name (ebrowse-ts-class tree)))
2749 (when (ebrowse-template-p (ebrowse-ts-class tree))
2750 (insert "<>"))
2751 (setq class-name-end (point))
2752 (insert ":\n\n")
2753 (ebrowse-set-face start (point) 'ebrowse-member-class-face)
2754 (add-text-properties
2755 class-name-start class-name-end
2756 '(ebrowse-what class-name
2757 mouse-face highlight
2758 help-echo "mouse-3: menu"))
2759 (put-text-property start class-name-end 'ebrowse-tree tree)))
2760
2761
2762(defun ebrowse-display-member-buffer (list &optional stand-alone class)
2763 "Start point for member buffer creation.
2764LIST is the member list to display. STAND-ALONE non-nil
2765means the member buffer is standalone. CLASS is its class."
2766 (let* ((classes ebrowse--tree-obarray)
2767 (tree ebrowse--tree)
2768 (tags-file-name ebrowse--tags-file-name)
2769 (header ebrowse--header)
2770 temp-buffer-setup-hook
2771 (temp-buffer (get-buffer ebrowse-member-buffer-name)))
2772 ;; Get the class description from the name the cursor
2773 ;; is on if not specified as an argument.
2774 (unless class
2775 (setq class (ebrowse-tree-at-point)))
2776 (with-output-to-temp-buffer ebrowse-member-buffer-name
2777 (save-excursion
2778 (set-buffer standard-output)
2779 ;; If new buffer, set the mode and initial values of locals
2780 (unless temp-buffer
2781 (ebrowse-member-mode))
2782 ;; Set local variables
2783 (setq ebrowse--member-list (funcall list class)
2784 ebrowse--displayed-class class
2785 ebrowse--accessor list
2786 ebrowse--tree-obarray classes
2787 ebrowse--frozen-flag stand-alone
2788 ebrowse--tags-file-name tags-file-name
2789 ebrowse--header header
2790 ebrowse--tree tree
2791 buffer-read-only t)
2792 (ebrowse-redisplay-member-buffer)
2793 (current-buffer)))))
2794
2795
2796(defun ebrowse-member-display-p (member)
2797 "Return t if MEMBER must be displayed under the current filter settings."
2798 (if (and (aref ebrowse--filters (ebrowse-ms-visibility member))
2799 (or (null ebrowse--const-display-flag)
2800 (ebrowse-const-p member))
2801 (or (null ebrowse--inline-display-flag)
2802 (ebrowse-inline-p member))
2803 (or (null ebrowse--pure-display-flag)
2804 (ebrowse-bs-p member))
2805 (or (null ebrowse--virtual-display-flag)
2806 (ebrowse-virtual-p member)))
2807 member))
2808
2809
2810(defun ebrowse-draw-member-attributes (member)
2811 "Insert a string for the attributes of MEMBER."
2812 (insert (if (ebrowse-template-p member) "T" "-")
2813 (if (ebrowse-extern-c-p member) "C" "-")
2814 (if (ebrowse-virtual-p member) "v" "-")
2815 (if (ebrowse-inline-p member) "i" "-")
2816 (if (ebrowse-const-p member) "c" "-")
2817 (if (ebrowse-pure-virtual-p member) "0" "-")
2818 (if (ebrowse-mutable-p member) "m" "-")
2819 (if (ebrowse-explicit-p member) "e" "-")
2820 (if (ebrowse-throw-list-p member) "t" "-")))
2821
2822
2823(defun ebrowse-draw-member-regexp (member-struc)
2824 "Insert a string for the regular expression matching MEMBER-STRUC."
2825 (let ((pattern (if ebrowse--source-regexp-flag
2826 (ebrowse-ms-definition-pattern
2827 member-struc)
2828 (ebrowse-ms-pattern member-struc))))
2829 (cond ((stringp pattern)
2830 (insert (ebrowse-trim-string pattern) "...\n")
2831 (beginning-of-line 0)
2832 (move-to-column (+ 4 ebrowse--decl-column))
2833 (while (re-search-forward "[ \t]+" nil t)
2834 (delete-region (match-beginning 0) (match-end 0))
2835 (insert " "))
2836 (beginning-of-line 2))
2837 (t
2838 (insert "[not recorded or unknown]\n")))))
2839
2840
2841(defun ebrowse-draw-member-long-fn (member-list tree)
2842 "Display member buffer for MEMBER-LIST in long form.
2843TREE is the class tree of MEMBER-LIST."
2844 (dolist (member-struc (mapcar 'ebrowse-member-display-p member-list))
2845 (when member-struc
2846 (let ((name (ebrowse-ms-name member-struc))
2847 (start (point)))
2848 ;; Insert member name truncated to the right length
2849 (insert (substring name
2850 0
2851 (min (length name)
2852 (1- ebrowse--decl-column))))
2853 (add-text-properties
2854 start (point)
2855 `(mouse-face highlight ebrowse-what member-name
2856 ebrowse-member ,member-struc
2857 ebrowse-tree ,tree
2858 help-echo "mouse-2: view definition; mouse-3: menu"))
2859 ;; Display virtual, inline, and const status
2860 (setf start (point))
2861 (indent-to ebrowse--decl-column)
2862 (put-text-property start (point) 'mouse-face nil)
2863 (when ebrowse--attributes-flag
2864 (let ((start (point)))
2865 (insert "<")
2866 (ebrowse-draw-member-attributes member-struc)
2867 (insert ">")
2868 (ebrowse-set-face start (point)
2869 'ebrowse-member-attribute-face)))
2870 (insert " ")
2871 (ebrowse-draw-member-regexp member-struc))))
2872 (insert "\n")
2873 (goto-char (point-min)))
2874
2875
2876(defun ebrowse-draw-member-short-fn (member-list tree)
2877 "Display MEMBER-LIST in short form.
2878TREE is the class tree in which the members are found."
2879 (let ((i 0)
2880 (column-width (+ ebrowse--column-width
2881 (if ebrowse--attributes-flag 12 0))))
2882 ;; Get the number of columns to draw.
2883 (setq ebrowse--n-columns
2884 (max 1 (/ (ebrowse-width-of-drawable-area) column-width)))
2885 (dolist (member (mapcar #'ebrowse-member-display-p member-list))
2886 (when member
2887 (let ((name (ebrowse-ms-name member))
2888 start-of-entry
2889 (start-of-column (point))
2890 start-of-name)
2891 (indent-to (* i column-width))
2892 (put-text-property start-of-column (point) 'mouse-face nil)
2893 (setq start-of-entry (point))
2894 ;; Show various attributes
2895 (when ebrowse--attributes-flag
2896 (insert "<")
2897 (ebrowse-draw-member-attributes member)
2898 (insert "> ")
2899 (ebrowse-set-face start-of-entry (point)
2900 'ebrowse-member-attribute-face))
2901 ;; insert member name truncated to column width
2902 (setq start-of-name (point))
2903 (insert (substring name 0
2904 (min (length name)
2905 (1- ebrowse--column-width))))
2906 ;; set text properties
2907 (add-text-properties
2908 start-of-name (point)
2909 `(ebrowse-what member-name
2910 ebrowse-member ,member
2911 mouse-face highlight
2912 ebrowse-tree ,tree
2913 help-echo "mouse-2: view definition; mouse-3: menu"))
2914 (incf i)
2915 (when (>= i ebrowse--n-columns)
2916 (setf i 0)
2917 (insert "\n")))))
2918 (when (plusp i)
2919 (insert "\n"))
2920 (goto-char (point-min))))
2921
2922
2923
2924;;; Killing members from tree
2925
2926(defun ebrowse-member-info-from-point ()
2927 "Ger information about the member at point.
2928The result has the form (TREE MEMBER NULL-P). TREE is the tree
2929we're in, MEMBER is the member we're on. NULL-P is t if MEMBER
2930is nil."
2931 (let ((tree (or (get-text-property (point) 'ebrowse-tree)
2932 (error "No information at point")))
2933 (member (get-text-property (point) 'ebrowse-member)))
2934 (list tree member (null member))))
2935
2936
2937
2938;;; Switching member buffer to display a selected member
2939
2940(defun ebrowse-goto-visible-member/all-member-lists (prefix)
2941 "Position cursor on a member read from the minibuffer.
2942With PREFIX, search all members in the tree. Otherwise consider
2943only members visible in the buffer."
2944 (interactive "p")
2945 (ebrowse-ignoring-completion-case
2946 (let* ((completion-list (ebrowse-name/accessor-alist-for-class-members))
2947 (member (completing-read "Goto member: " completion-list nil t))
2948 (accessor (cdr (assoc member completion-list))))
2949 (unless accessor
2950 (error "`%s' not found" member))
2951 (unless (eq accessor ebrowse--accessor)
2952 (setf ebrowse--accessor accessor
2953 ebrowse--member-list (funcall accessor ebrowse--displayed-class))
2954 (ebrowse-redisplay-member-buffer))
2955 (ebrowse-move-point-to-member member))))
2956
2957
2958(defun ebrowse-goto-visible-member (repeat)
2959 "Position point on a member.
2960Read the member's name from the minibuffer. Consider only members
2961visible in the member buffer.
2962REPEAT non-nil means repeat the search that number of times."
2963 (interactive "p")
2964 (ebrowse-ignoring-completion-case
2965 ;; Read member name
2966 (let* ((completion-list (ebrowse-name/accessor-alist-for-visible-members))
2967 (member (completing-read "Goto member: " completion-list nil t)))
2968 (ebrowse-move-point-to-member member repeat))))
2969
2970
2971
2972;;; Searching a member in the member buffer
2973
2974(defun ebrowse-repeat-member-search (repeat)
2975 "Repeat the last regular expression search.
2976REPEAT, if specified, says repeat the search REPEAT times."
2977 (interactive "p")
2978 (unless ebrowse--last-regexp
2979 (error "No regular expression remembered"))
2980 ;; Skip over word the point is on
2981 (skip-chars-forward "^ \t\n")
2982 ;; Search for regexp from point
2983 (if (re-search-forward ebrowse--last-regexp nil t repeat)
2984 (progn
2985 (goto-char (match-beginning 0))
2986 (skip-chars-forward " \t\n"))
2987 ;; If not found above, repeat search from buffer start
2988 (goto-char (point-min))
2989 (if (re-search-forward ebrowse--last-regexp nil t)
2990 (progn
2991 (goto-char (match-beginning 0))
2992 (skip-chars-forward " \t\n"))
2993 (error "Not found"))))
2994
2995
2996(defun* ebrowse-move-point-to-member (name &optional count &aux member)
2997 "Set point on member NAME in the member buffer
2998COUNT, if specified, says search the COUNT'th member with the same name."
2999 (goto-char (point-min))
3000 (widen)
3001 (setq member
3002 (substring name 0 (min (length name) (1- ebrowse--column-width)))
3003 ebrowse--last-regexp
3004 (concat "[ \t\n]" (regexp-quote member) "[ \n\t]"))
3005 (if (re-search-forward ebrowse--last-regexp nil t count)
3006 (goto-char (1+ (match-beginning 0)))
3007 (error "Not found")))
3008
3009
3010
3011;;; Switching member buffer to another class.
3012
3013(defun ebrowse-switch-member-buffer-to-other-class (title compl-list)
3014 "Switch member buffer to a class read from the minibuffer.
3015Use TITLE as minibuffer prompt.
3016COMPL-LIST is a completion list to use."
3017 (let* ((initial (unless (second compl-list)
3018 (first (first compl-list))))
3019 (class (or (ebrowse-completing-read-value title compl-list initial)
3020 (error "Not found"))))
3021 (setf ebrowse--displayed-class class
3022 ebrowse--member-list (funcall ebrowse--accessor ebrowse--displayed-class))
3023 (ebrowse-redisplay-member-buffer)))
3024
3025
3026(defun ebrowse-switch-member-buffer-to-any-class ()
3027 "Switch member buffer to a class read from the minibuffer."
3028 (interactive)
3029 (ebrowse-switch-member-buffer-to-other-class
3030 "Goto class: " (ebrowse-tree-obarray-as-alist)))
3031
3032
3033(defun ebrowse-switch-member-buffer-to-base-class (arg)
3034 "Switch buffer to ARG'th base class."
3035 (interactive "P")
3036 (let ((supers (or (ebrowse-direct-base-classes ebrowse--displayed-class)
3037 (error "No base classes"))))
3038 (if (and arg (second supers))
3039 (let ((alist (loop for s in supers
3040 collect (cons (ebrowse-qualified-class-name
3041 (ebrowse-ts-class s))
3042 s))))
3043 (ebrowse-switch-member-buffer-to-other-class
3044 "Goto base class: " alist))
3045 (setq ebrowse--displayed-class (first supers)
3046 ebrowse--member-list
3047 (funcall ebrowse--accessor ebrowse--displayed-class))
3048 (ebrowse-redisplay-member-buffer))))
3049
3050(defun ebrowse-switch-member-buffer-to-next-sibling-class (arg)
3051 "Move to ARG'th next sibling."
3052 (interactive "p")
3053 (ebrowse-switch-member-buffer-to-sibling-class arg))
3054
3055
3056(defun ebrowse-switch-member-buffer-to-previous-sibling-class (arg)
3057 "Move to ARG'th previous sibling."
3058 (interactive "p")
3059 (ebrowse-switch-member-buffer-to-sibling-class (- arg)))
3060
3061
3062(defun ebrowse-switch-member-buffer-to-sibling-class (inc)
3063 "Switch member display to nth sibling class.
3064Prefix arg INC specifies which one."
3065 (interactive "p")
3066 (let ((containing-list ebrowse--tree)
3067 index cls
3068 (supers (ebrowse-direct-base-classes ebrowse--displayed-class)))
3069 (flet ((trees-alist (trees)
3070 (loop for tr in trees
3071 collect (cons (ebrowse-cs-name
3072 (ebrowse-ts-class tr)) tr))))
3073 (when supers
3074 (let ((tree (if (second supers)
3075 (ebrowse-completing-read-value
3076 "Relative to base class: "
3077 (trees-alist supers) nil)
3078 (first supers))))
3079 (unless tree (error "Not found"))
3080 (setq containing-list (ebrowse-ts-subclasses tree)))))
3081 (setq index (+ inc (ebrowse-position ebrowse--displayed-class
3082 containing-list)))
3083 (cond ((minusp index) (message "No previous class"))
3084 ((null (nth index containing-list)) (message "No next class")))
3085 (setq index (max 0 (min index (1- (length containing-list)))))
3086 (setq cls (nth index containing-list))
3087 (setf ebrowse--displayed-class cls
3088 ebrowse--member-list (funcall ebrowse--accessor cls))
3089 (ebrowse-redisplay-member-buffer)))
3090
3091
3092(defun ebrowse-switch-member-buffer-to-derived-class (arg)
3093 "Switch member display to nth derived class.
3094Prefix arg ARG says which class should be displayed. Default is
3095the first derived class."
3096 (interactive "P")
3097 (flet ((ebrowse-tree-obarray-as-alist ()
3098 (loop for s in (ebrowse-ts-subclasses
3099 ebrowse--displayed-class)
3100 collect (cons (ebrowse-cs-name
3101 (ebrowse-ts-class s)) s))))
3102 (let ((subs (or (ebrowse-ts-subclasses ebrowse--displayed-class)
3103 (error "No derived classes"))))
3104 (if (and arg (second subs))
3105 (ebrowse-switch-member-buffer-to-other-class
3106 "Goto derived class: " (ebrowse-tree-obarray-as-alist))
3107 (setq ebrowse--displayed-class (first subs)
3108 ebrowse--member-list
3109 (funcall ebrowse--accessor ebrowse--displayed-class))
3110 (ebrowse-redisplay-member-buffer)))))
3111
3112
3113
3114;;; Member buffer mouse functions
3115
3116(defun ebrowse-displaying-functions ()
3117 (eq ebrowse--accessor 'ebrowse-ts-member-functions))
3118(defun ebrowse-displaying-variables ()
3119 (eq ebrowse--accessor 'ebrowse-ts-member-variables))
3120(defun ebrowse-displaying-static-functions ()
3121 )
3122(defun ebrowse-displaying-static-variables ()
3123 )
3124(defun ebrowse-displaying-types ()
3125 (eq ebrowse--accessor 'ebrowse-ts-types))
3126(defun ebrowse-displaying-friends ()
3127 (eq ebrowse--accessor 'ebrowse-ts-friends))
3128
3129(easy-menu-define
3130 ebrowse-member-buffer-object-menu ebrowse-member-mode-map
3131 "Object menu for the member buffer itself."
3132 '("Members"
3133 ("Members List"
3134 ["Functions" ebrowse-display-function-member-list
3135 :help "Show the list of member functions"
3136 :style radio
3137 :selected (eq ebrowse--accessor 'ebrowse-ts-member-functions)
3138 :active t]
3139 ["Variables" ebrowse-display-variables-member-list
3140 :help "Show the list of member variables"
3141 :style radio
3142 :selected (eq ebrowse--accessor 'ebrowse-ts-member-variables)
3143 :active t]
3144 ["Static Functions" ebrowse-display-static-functions-member-list
3145 :help "Show the list of static member functions"
3146 :style radio
3147 :selected (eq ebrowse--accessor 'ebrowse-ts-static-functions)
3148 :active t]
3149 ["Static Variables" ebrowse-display-static-variables-member-list
3150 :help "Show the list of static member variables"
3151 :style radio
3152 :selected (eq ebrowse--accessor 'ebrowse-ts-static-variables)
3153 :active t]
3154 ["Types" ebrowse-display-types-member-list
3155 :help "Show the list of nested types"
3156 :style radio
3157 :selected (eq ebrowse--accessor 'ebrowse-ts-types)
3158 :active t]
3159 ["Friends/Defines" ebrowse-display-friends-member-list
3160 :help "Show the list of friends or defines"
3161 :style radio
3162 :selected (eq ebrowse--accessor 'ebrowse-ts-friends)
3163 :active t])
3164 ("Class"
3165 ["Up" ebrowse-switch-member-buffer-to-base-class
3166 :help "Show the base class of this class"
3167 :active t]
3168 ["Down" ebrowse-switch-member-buffer-to-derived-class
3169 :help "Show a derived class class of this class"
3170 :active t]
3171 ["Next Sibling" ebrowse-switch-member-buffer-to-next-sibling-class
3172 :help "Show the next sibling class"
3173 :active t]
3174 ["Previous Sibling" ebrowse-switch-member-buffer-to-previous-sibling-class
3175 :help "Show the previous sibling class"
3176 :active t])
3177 ("Member"
3178 ["Show in Tree" ebrowse-show-displayed-class-in-tree
3179 :help "Show this class in the class tree"
3180 :active t]
3181 ["Find in this Class" ebrowse-goto-visible-member
3182 :help "Search for a member of this class"
3183 :active t]
3184 ["Find in Tree" ebrowse-goto-visible-member/all-member-lists
3185 :help "Search for a member in any class"
3186 :active t])
3187 ("Display"
3188 ["Inherited" ebrowse-toggle-base-class-display
3189 :help "Toggle display of inherited members"
3190 :style toggle
3191 :selected ebrowse--show-inherited-flag
3192 :active t]
3193 ["Attributes" ebrowse-toggle-member-attributes-display
3194 :help "Show member attributes"
3195 :style toggle
3196 :selected ebrowse--attributes-flag
3197 :active t]
3198 ["Long Display" ebrowse-toggle-long-short-display
3199 :help "Toggle the member display format"
3200 :style toggle
3201 :selected ebrowse--long-display-flag
3202 :active t]
3203 ["Column Width" ebrowse-set-member-buffer-column-width
3204 :help "Set the display's column width"
3205 :active t])
3206 ("Filter"
3207 ["Public" ebrowse-toggle-public-member-filter
3208 :help "Toggle the visibility of public members"
3209 :style toggle
3210 :selected (not (aref ebrowse--filters 0))
3211 :active t]
3212 ["Protected" ebrowse-toggle-protected-member-filter
3213 :help "Toggle the visibility of protected members"
3214 :style toggle
3215 :selected (not (aref ebrowse--filters 1))
3216 :active t]
3217 ["Private" ebrowse-toggle-private-member-filter
3218 :help "Toggle the visibility of private members"
3219 :style toggle
3220 :selected (not (aref ebrowse--filters 2))
3221 :active t]
3222 ["Virtual" ebrowse-toggle-virtual-member-filter
3223 :help "Toggle the visibility of virtual members"
3224 :style toggle
3225 :selected ebrowse--virtual-display-flag
3226 :active t]
3227 ["Inline" ebrowse-toggle-inline-member-filter
3228 :help "Toggle the visibility of inline members"
3229 :style toggle
3230 :selected ebrowse--inline-display-flag
3231 :active t]
3232 ["Const" ebrowse-toggle-const-member-filter
3233 :help "Toggle the visibility of const members"
3234 :style toggle
3235 :selected ebrowse--const-display-flag
3236 :active t]
3237 ["Pure" ebrowse-toggle-pure-member-filter
3238 :help "Toggle the visibility of pure virtual members"
3239 :style toggle
3240 :selected ebrowse--pure-display-flag
3241 :active t]
3242 "-----------------"
3243 ["Show all" ebrowse-remove-all-member-filters
3244 :help "Remove any display filters"
3245 :active t])
3246 ("Buffer"
3247 ["Tree" ebrowse-pop-from-member-to-tree-buffer
3248 :help "Pop to the class tree buffer"
3249 :active t]
3250 ["Next Member Buffer" ebrowse-switch-to-next-member-buffer
3251 :help "Switch to the next member buffer of this class tree"
3252 :active t]
3253 ["Freeze" ebrowse-freeze-member-buffer
3254 :help "Freeze (do not reuse) this member buffer"
3255 :active t])))
3256
3257
3258(defun ebrowse-on-class-name ()
3259 "Value is non-nil if point is on a class name."
3260 (eq (get-text-property (point) 'ebrowse-what) 'class-name))
3261
3262
3263(defun ebrowse-on-member-name ()
3264 "Value is non-nil if point is on a member name."
3265 (eq (get-text-property (point) 'ebrowse-what) 'member-name))
3266
3267
3268(easy-menu-define
3269 ebrowse-member-class-name-object-menu ebrowse-member-mode-map
3270 "Object menu for class names in member buffer."
3271 '("Class"
3272 ["Find" ebrowse-find-member-definition
3273 :help "Find this class in the source files"
3274 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
3275 ["View" ebrowse-view-member-definition
3276 :help "View this class in the source files"
3277 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]))
3278
3279
3280(easy-menu-define
3281 ebrowse-member-name-object-menu ebrowse-member-mode-map
3282 "Object menu for member names"
3283 '("Ebrowse"
3284 ["Find Definition" ebrowse-find-member-definition
3285 :help "Find this member's definition in the source files"
3286 :active (ebrowse-on-member-name)]
3287 ["Find Declaration" ebrowse-find-member-declaration
3288 :help "Find this member's declaration in the source files"
3289 :active (ebrowse-on-member-name)]
3290 ["View Definition" ebrowse-view-member-definition
3291 :help "View this member's definition in the source files"
3292 :active (ebrowse-on-member-name)]
3293 ["View Declaration" ebrowse-view-member-declaration
3294 :help "View this member's declaration in the source files"
3295 :active (ebrowse-on-member-name)]))
3296
3297
3298(defun ebrowse-member-mouse-3 (event)
3299 "Handle `mouse-3' events in member buffers.
3300EVENT is the mouse event."
3301 (interactive "e")
3302 (mouse-set-point event)
3303 (case (event-click-count event)
3304 (2 (ebrowse-find-member-definition))
3305 (1 (case (get-text-property (posn-point (event-start event))
3306 'ebrowse-what)
3307 (member-name
3308 (ebrowse-popup-menu ebrowse-member-name-object-menu event))
3309 (class-name
3310 (ebrowse-popup-menu ebrowse-member-class-name-object-menu event))
3311 (t
3312 (ebrowse-popup-menu ebrowse-member-buffer-object-menu event))))))
3313
3314
3315(defun ebrowse-member-mouse-2 (event)
3316 "Handle `mouse-2' events in member buffers.
3317EVENT is the mouse event."
3318 (interactive "e")
3319 (mouse-set-point event)
3320 (case (event-click-count event)
3321 (2 (ebrowse-find-member-definition))
3322 (1 (case (get-text-property (posn-point (event-start event))
3323 'ebrowse-what)
3324 (member-name
3325 (ebrowse-view-member-definition 0))))))
3326
3327
3328
3329;;; Tags view/find
3330
3331(defun ebrowse-class-alist-for-member (tree-header name)
3332 "Return information about a member in a class tree.
3333TREE-HEADER is the header structure of the class tree.
3334NAME is the name of the member.
3335Value is an alist of elements (CLASS-NAME . (CLASS LIST NAME)),
3336where each element describes one occurrence of member NAME in the tree.
3337CLASS-NAME is the qualified name of the class in which the
3338member was found. The CDR of the acons is described in function
3339`ebrowse-class/index/member-for-member'."
3340 (let ((table (ebrowse-member-table tree-header))
3341 known-classes
3342 alist)
3343 (when name
3344 (dolist (info (gethash name table) alist)
3345 (unless (memq (first info) known-classes)
3346 (setf alist (acons (ebrowse-qualified-class-name
3347 (ebrowse-ts-class (first info)))
3348 info alist)
3349 known-classes (cons (first info) known-classes)))))))
3350
3351
3352(defun ebrowse-choose-tree ()
3353 "Choose a class tree to use.
3354If there's more than one class tree loaded, let the user choose
3355the one he wants. Value is (TREE HEADER BUFFER), with TREE being
3356the class tree, HEADER the header structure of the tree, and BUFFER
3357being the tree or member buffer containing the tree."
3358 (let* ((buffer (ebrowse-choose-from-browser-buffers)))
3359 (if buffer (list (ebrowse-value-in-buffer 'ebrowse--tree buffer)
3360 (ebrowse-value-in-buffer 'ebrowse--header buffer)
3361 buffer))))
3362
3363
3364(defun ebrowse-tags-read-name (header prompt)
3365 "Read a C++ identifier from the minibuffer.
3366HEADER is the `ebrowse-hs' structure of the class tree.
3367Prompt with PROMPT. Insert into the minibuffer a C++ identifier read
3368from point as default. Value is a list (CLASS-NAME MEMBER-NAME)."
3369 (save-excursion
3370 (let* (start member-info (members (ebrowse-member-table header)))
3371 (multiple-value-bind (class-name member-name)
3372 (ebrowse-tags-read-member+class-name)
3373 (unless member-name
3374 (error "No member name at point"))
3375 (if members
3376 (let* ((alist (ebrowse-hash-table-to-alist members))
3377 (name (ebrowse-ignoring-completion-case
3378 (completing-read prompt alist nil nil member-name)))
3379 (completion-result (try-completion name alist)))
3380 ;; Cannot rely on `try-completion' returning T for exact
3381 ;; matches! it returns the the name as a string.
3382 (unless (setq member-info (gethash name members))
3383 (if (y-or-n-p "No exact match found. Try substrings? ")
3384 (setq name
3385 (or (first (ebrowse-list-of-matching-members
3386 members (regexp-quote name) name))
3387 (error "Sorry, nothing found")))
3388 (error "Canceled")))
3389 (list class-name name))
3390 (list class-name (read-from-minibuffer prompt member-name)))))))
3391
3392
3393(defun ebrowse-tags-read-member+class-name ()
3394 "Read a C++ identifier from point.
3395Value is (CLASS-NAME MEMBER-NAME).
3396CLASS-NAME is the name of the class if the identifier was qualified.
3397It is nil otherwise.
3398MEMBER-NAME is the name of the member found."
3399 (save-excursion
3400 (skip-chars-backward "a-zA-Z0-9_")
3401 (let* ((start (point))
3402 (name (progn (skip-chars-forward "a-zA-Z0-9_")
3403 (buffer-substring start (point))))
3404 class)
3405 (list class name))))
3406
3407
3408(defun ebrowse-tags-choose-class (tree header name initial-class-name)
3409 "Read a class name for a member from the minibuffer.
3410TREE is the class tree we operate on.
3411HEADER is its header structure.
3412NAME is the name of the member.
3413INITIAL-CLASS-NAME is an initial class name to insert in the minibuffer.
3414Value is a list (TREE ACCESSOR MEMBER) for the member."
3415 (let ((alist (or (ebrowse-class-alist-for-member header name)
3416 (error "No classes with member `%s' found" name))))
3417 (ebrowse-ignoring-completion-case
3418 (if (null (second alist))
3419 (cdr (first alist))
3420 (push ?\? unread-command-events)
3421 (cdr (assoc (completing-read "In class: "
3422 alist nil t initial-class-name)
3423 alist))))))
3424
3425
3426(defun* ebrowse-tags-view/find-member-decl/defn
3427 (prefix &key view definition member-name)
3428 "If VIEW is t, view, else find an occurrence of MEMBER-NAME.
3429
3430If DEFINITION is t, find or view the member definition else its
3431declaration. This function reads the member's name from the
3432current buffer like FIND-TAG. It then prepares a completion list
3433of all classes containing a member with the given name and lets
3434the user choose the class to use. As a last step, a tags search
3435is performed that positions point on the member declaration or
3436definition."
3437 (multiple-value-bind
3438 (tree header tree-buffer) (ebrowse-choose-tree)
3439 (unless tree (error "No class tree"))
3440 (let* ((marker (point-marker))
3441 class-name
3442 (name member-name)
3443 info)
3444 (unless name
3445 (multiple-value-setq (class-name name)
3446 (ebrowse-tags-read-name
3447 header
3448 (concat (if view "View" "Find") " member "
3449 (if definition "definition" "declaration") ": "))))
3450 (setq info (ebrowse-tags-choose-class tree header name class-name))
3451 (ebrowse-push-position marker info)
3452 ;; Goto the occurrence of the member
3453 (ebrowse-view/find-member-declaration/definition
3454 prefix view definition info
3455 header
3456 (ebrowse-value-in-buffer 'ebrowse--tags-file-name tree-buffer))
3457 ;; Record position jumped to
3458 (ebrowse-push-position (point-marker) info t))))
3459
3460
3461;;###autoload
3462(defun ebrowse-tags-view-declaration ()
3463 "View declaration of member at point."
3464 (interactive)
3465 (ebrowse-tags-view/find-member-decl/defn 0 :view t :definition nil))
3466
3467
3468;;###autoload
3469(defun ebrowse-tags-find-declaration ()
3470 "Find declaration of member at point."
3471 (interactive)
3472 (ebrowse-tags-view/find-member-decl/defn 0 :view nil :definition nil))
3473
3474
3475;;###autoload
3476(defun ebrowse-tags-view-definition ()
3477 "View definition of member at point."
3478 (interactive)
3479 (ebrowse-tags-view/find-member-decl/defn 0 :view t :definition t))
3480
3481
3482;;###autoload
3483(defun ebrowse-tags-find-definition ()
3484 "Find definition of member at point."
3485 (interactive)
3486 (ebrowse-tags-view/find-member-decl/defn 0 :view nil :definition t))
3487
3488
3489(defun ebrowse-tags-view-declaration-other-window ()
3490 "View declaration of member at point in other window."
3491 (interactive)
3492 (ebrowse-tags-view/find-member-decl/defn 4 :view t :definition nil))
3493
3494
3495;;###autoload
3496(defun ebrowse-tags-find-declaration-other-window ()
3497 "Find declaration of member at point in other window."
3498 (interactive)
3499 (ebrowse-tags-view/find-member-decl/defn 4 :view nil :definition nil))
3500
3501
3502;;###autoload
3503(defun ebrowse-tags-view-definition-other-window ()
3504 "View definition of member at point in other window."
3505 (interactive)
3506 (ebrowse-tags-view/find-member-decl/defn 4 :view t :definition t))
3507
3508
3509;;###autoload
3510(defun ebrowse-tags-find-definition-other-window ()
3511 "Find definition of member at point in other window."
3512 (interactive)
3513 (ebrowse-tags-view/find-member-decl/defn 4 :view nil :definition t))
3514
3515
3516(defun ebrowse-tags-view-declaration-other-frame ()
3517 "View definition of member at point in other frame."
3518 (interactive)
3519 (ebrowse-tags-view/find-member-decl/defn 5 :view t :definition nil))
3520
3521
3522;;###autoload
3523(defun ebrowse-tags-find-declaration-other-frame ()
3524 "Find definition of member at point in other frame."
3525 (interactive)
3526 (ebrowse-tags-view/find-member-decl/defn 5 :view nil :definition nil))
3527
3528
3529;;###autoload
3530(defun ebrowse-tags-view-definition-other-frame ()
3531 "View definition of member at point in other frame."
3532 (interactive)
3533 (ebrowse-tags-view/find-member-decl/defn 5 :view t :definition t))
3534
3535
3536;;###autoload
3537(defun ebrowse-tags-find-definition-other-frame ()
3538 "Find definition of member at point in other frame."
3539 (interactive)
3540 (ebrowse-tags-view/find-member-decl/defn 5 :view nil :definition t))
3541
3542
3543(defun ebrowse-tags-select/create-member-buffer (tree-buffer info)
3544 "Select or create member buffer.
3545TREE-BUFFER specifies the tree to use. INFO describes the member.
3546It is a list (TREE ACCESSOR MEMBER)."
3547 (let ((buffer (get-buffer ebrowse-member-buffer-name)))
3548 (cond ((null buffer)
3549 (set-buffer tree-buffer)
3550 (switch-to-buffer (ebrowse-display-member-buffer
3551 (second info) nil (first info))))
3552 (t
3553 (switch-to-buffer buffer)
3554 (setq ebrowse--displayed-class (first info)
3555 ebrowse--accessor (second info)
3556 ebrowse--member-list (funcall ebrowse--accessor ebrowse--displayed-class))
3557 (ebrowse-redisplay-member-buffer)))
3558 (ebrowse-move-point-to-member (ebrowse-ms-name (third info)))))
3559
3560
3561(defun ebrowse-tags-display-member-buffer (&optional fix-name)
3562 "Display a member buffer for a member.
3563FIX-NAME non-nil means display the buffer for that member.
3564Otherwise read a member name from point."
3565 (interactive)
3566 (multiple-value-bind
3567 (tree header tree-buffer) (ebrowse-choose-tree)
3568 (unless tree (error "No class tree"))
3569 (let* ((marker (point-marker)) class-name (name fix-name) info)
3570 (unless name
3571 (multiple-value-setq (class-name name)
3572 (ebrowse-tags-read-name header
3573 (concat "Find member list of: "))))
3574 (setq info (ebrowse-tags-choose-class tree header name class-name))
3575 (ebrowse-push-position marker info)
3576 (ebrowse-tags-select/create-member-buffer tree-buffer info))))
3577
3578
3579(defun ebrowse-list-of-matching-members (members regexp &optional name)
3580 "Return a list of members in table MEMBERS matching REGEXP or NAME.
3581Both NAME and REGEXP may be nil in which case exact or regexp matches
3582are not performed."
3583 (let (list)
3584 (when (or name regexp)
3585 (maphash #'(lambda (member-name info)
3586 (when (or (and name (string= name member-name))
3587 (and regexp (string-match regexp member-name)))
3588 (setq list (cons member-name list))))
3589 members))
3590 list))
3591
3592
3593(defun ebrowse-tags-apropos ()
3594 "Display a list of members matching a regexp read from the minibuffer."
3595 (interactive)
3596 (let* ((buffer (or (ebrowse-choose-from-browser-buffers)
3597 (error "No tree buffer")))
3598 (header (ebrowse-value-in-buffer 'ebrowse--header buffer))
3599 (members (ebrowse-member-table header))
3600 temp-buffer-setup-hook
3601 (regexp (read-from-minibuffer "List members matching regexp: ")))
3602 (with-output-to-temp-buffer (concat "*Apropos Members*")
3603 (set-buffer standard-output)
3604 (erase-buffer)
3605 (insert "Members matching `" regexp "'\n\n")
3606 (loop for s in (ebrowse-list-of-matching-members members regexp) do
3607 (loop for info in (gethash s members) do
3608 (ebrowse-draw-file-member-info info))))))
3609
3610
3611(defun ebrowse-tags-list-members-in-file ()
3612 "Display a list of members found in a file.
3613The file name is read from the minibuffer."
3614 (interactive)
3615 (let* ((buffer (or (ebrowse-choose-from-browser-buffers)
3616 (error "No tree buffer")))
3617 (files (save-excursion (set-buffer buffer) (ebrowse-files-table)))
3618 (alist (ebrowse-hash-table-to-alist files))
3619 (file (completing-read "List members in file: " alist nil t))
3620 (header (ebrowse-value-in-buffer 'ebrowse--header buffer))
3621 temp-buffer-setup-hook
3622 (members (ebrowse-member-table header)))
3623 (with-output-to-temp-buffer (concat "*Members in file " file "*")
3624 (set-buffer standard-output)
3625 (maphash
3626 #'(lambda (member-name list)
3627 (loop for info in list
3628 as member = (third info)
3629 as class = (ebrowse-ts-class (first info))
3630 when (or (and (null (ebrowse-ms-file member))
3631 (string= (ebrowse-cs-file class) file))
3632 (string= file (ebrowse-ms-file member)))
3633 do (ebrowse-draw-file-member-info info "decl.")
3634 when (or (and (null (ebrowse-ms-definition-file member))
3635 (string= (ebrowse-cs-source-file class) file))
3636 (string= file (ebrowse-ms-definition-file member)))
3637 do (ebrowse-draw-file-member-info info "defn.")))
3638 members))))
3639
3640
3641(defun* ebrowse-draw-file-member-info (info &optional (kind ""))
3642 "Display a line in an the members per file info buffer.
3643INFO describes the member. It has the form (TREE ACCESSOR MEMBER).
3644TREE is the class of the member to display.
3645ACCESSOR is the accessor symbol of its member list.
3646MEMBER is the member structure.
3647KIND is a an additional string printed in the buffer."
3648 (let* ((tree (first info))
3649 (globals-p (ebrowse-globals-tree-p tree)))
3650 (unless globals-p
3651 (insert (ebrowse-cs-name (ebrowse-ts-class tree))))
3652 (insert "::" (ebrowse-ms-name (third info)))
3653 (indent-to 40)
3654 (insert kind)
3655 (indent-to 50)
3656 (insert (case (second info)
3657 ('ebrowse-ts-member-functions "member function")
3658 ('ebrowse-ts-member-variables "member variable")
3659 ('ebrowse-ts-static-functions "static function")
3660 ('ebrowse-ts-static-variables "static variable")
3661 ('ebrowse-ts-friends (if globals-p "define" "friend"))
3662 ('ebrowse-ts-types "type")
3663 (t "unknown"))
3664 "\n")))
3665
3666(defvar ebrowse-last-completion nil
3667 "Text inserted by the last completion operation.")
3668
3669
3670(defvar ebrowse-last-completion-start nil
3671 "String which was the basis for the last completion operation.")
3672
3673
3674(defvar ebrowse-last-completion-location nil
3675 "Buffer position at which the last completion operation was initiated.")
3676
3677
3678(defvar ebrowse-last-completion-obarray nil
3679 "Member used in last completion operation.")
3680
3681
3682(make-variable-buffer-local 'ebrowse-last-completion-obarray)
3683(make-variable-buffer-local 'ebrowse-last-completion-location)
3684(make-variable-buffer-local 'ebrowse-last-completion)
3685(make-variable-buffer-local 'ebrowse-last-completion-start)
3686
3687
3688
3689(defun ebrowse-some-member-table ()
3690 "Return a hash table containing all member of a tree.
3691If there's only one tree loaded, use that. Otherwise let the
3692use choose a tree."
3693 (let* ((buffers (ebrowse-known-class-trees-buffer-list))
3694 (buffer (cond ((and (first buffers) (not (second buffers)))
3695 (first buffers))
3696 (t (or (ebrowse-electric-choose-tree)
3697 (error "No tree buffer")))))
3698 (header (ebrowse-value-in-buffer 'ebrowse--header buffer)))
3699 (ebrowse-member-table header)))
3700
3701
3702(defun ebrowse-hash-table-to-alist (table)
3703 "Return an alist holding all key/value pairs of hash table TABLE."
3704 (let ((list))
3705 (maphash #'(lambda (key value)
3706 (setq list (cons (cons key value) list)))
3707 table)
3708 list))
3709
3710
3711(defun ebrowse-cyclic-successor-in-string-list (string list)
3712 "Return the item following STRING in LIST.
3713If STRING is the last element, return the first element as successor."
3714 (or (nth (1+ (ebrowse-position string list 'string=)) list)
3715 (first list)))
3716
3717
3718;;; Symbol completion
3719
3720;;;###autoload
3721(defun* ebrowse-tags-complete-symbol (prefix)
3722 "Perform completion on the C++ symbol preceding point.
3723A second call of this function without changing point inserts the next match.
3724A call with prefix PREFIX reads the symbol to insert from the minibuffer with
3725completion."
3726 (interactive "P")
3727 (let* ((end (point))
3728 (begin (save-excursion (skip-chars-backward "a-zA-Z_0-9") (point)))
3729 (pattern (buffer-substring begin end))
3730 list completion)
3731 (cond
3732 ;; With prefix, read name from minibuffer with completion.
3733 (prefix
3734 (let* ((members (ebrowse-some-member-table))
3735 (alist (ebrowse-hash-table-to-alist members))
3736 (completion (completing-read "Insert member: "
3737 alist nil t pattern)))
3738 (when completion
3739 (setf ebrowse-last-completion-location nil)
3740 (delete-region begin end)
3741 (insert completion))))
3742 ;; If this function is called at the same point the last
3743 ;; expansion ended, insert the next expansion.
3744 ((eq (point) ebrowse-last-completion-location)
3745 (setf list (all-completions ebrowse-last-completion-start
3746 ebrowse-last-completion-obarray)
3747 completion (ebrowse-cyclic-successor-in-string-list
3748 ebrowse-last-completion list))
3749 (cond ((null completion)
3750 (error "No completion"))
3751 ((string= completion pattern)
3752 (error "No further completion"))
3753 (t
3754 (delete-region begin end)
3755 (insert completion)
3756 (setf ebrowse-last-completion completion
3757 ebrowse-last-completion-location (point)))))
3758 ;; First time the function is called at some position in the
3759 ;; buffer: Start new completion.
3760 (t
3761 (let* ((members (ebrowse-some-member-table))
3762 (completion (first (all-completions pattern members nil))))
3763 (cond ((eq completion t))
3764 ((null completion)
3765 (error "Can't find completion for `%s'" pattern))
3766 (t
3767 (delete-region begin end)
3768 (insert completion)
3769
3770 (setf ebrowse-last-completion-location (point)
3771 ebrowse-last-completion-start pattern
3772 ebrowse-last-completion completion
3773 ebrowse-last-completion-obarray members))))))))
3774
3775
3776;;; Tags query replace & search
3777
3778(defvar ebrowse-tags-loop-form ()
3779 "Form for `ebrowse-loop-continue'.
3780Evaluated for each file in the tree. If it returns nil, proceed
3781with the next file.")
3782
3783(defvar ebrowse-tags-next-file-list ()
3784 "A list of files to be processed.")
3785
3786
3787(defvar ebrowse-tags-next-file-path nil
3788 "The path relative to which files have to be searched.")
3789
3790
3791(defvar ebrowse-tags-loop-last-file nil
3792 "The last file visited via `ebrowse-tags-loop'.")
3793
3794
3795(defun ebrowse-tags-next-file (&optional initialize tree-buffer)
3796 "Select next file among files in current tag table.
3797Non-nil argument INITIALIZE (prefix arg, if interactive) initializes
3798to the beginning of the list of files in the tag table.
3799TREE-BUFFER specifies the class tree we operate on."
3800 (interactive "P")
3801 ;; Call with INITIALIZE non-nil initializes the files list.
3802 ;; If more than one tree buffer is loaded, let the user choose
3803 ;; on which tree (s)he wants to operate.
3804 (when initialize
3805 (let ((buffer (or tree-buffer (ebrowse-choose-from-browser-buffers))))
3806 (save-excursion
3807 (set-buffer buffer)
3808 (setq ebrowse-tags-next-file-list
3809 (ebrowse-files-list (ebrowse-marked-classes-p))
3810 ebrowse-tags-loop-last-file
3811 nil
3812 ebrowse-tags-next-file-path
3813 (file-name-directory ebrowse--tags-file-name)))))
3814 ;; End of the loop if the stack of files is empty.
3815 (unless ebrowse-tags-next-file-list
3816 (error "All files processed"))
3817 ;; ebrowse-tags-loop-last-file is the last file that was visited due
3818 ;; to a call to BROWSE-LOOP (see below). If that file is still
3819 ;; in memory, and it wasn't modified, throw its buffer away to
3820 ;; prevent cluttering up the buffer list.
3821 (when ebrowse-tags-loop-last-file
3822 (let ((buffer (get-file-buffer ebrowse-tags-loop-last-file)))
3823 (when (and buffer
3824 (not (buffer-modified-p buffer)))
3825 (kill-buffer buffer))))
3826 ;; Remember this buffer file name for later deletion, if it
3827 ;; wasn't visited by other means.
3828 (let ((file (expand-file-name (car ebrowse-tags-next-file-list)
3829 ebrowse-tags-next-file-path)))
3830 (setq ebrowse-tags-loop-last-file (if (get-file-buffer file) nil file))
3831 ;; Find the file and pop the file list. Pop has to be done
3832 ;; before the file is loaded because FIND-FILE might encounter
3833 ;; an error, and we want to be able to proceed with the next
3834 ;; file in this case.
3835 (pop ebrowse-tags-next-file-list)
3836 (find-file file)))
3837
3838
3839;;;###autoload
3840(defun ebrowse-tags-loop-continue (&optional first-time tree-buffer)
3841 "Repeat last operation on files in tree.
3842FIRST-TIME non-nil means this is not a repetition, but the first time.
3843TREE-BUFFER if indirectly specifies which files to loop over."
3844 (interactive)
3845 (when first-time
3846 (ebrowse-tags-next-file first-time tree-buffer)
3847 (goto-char (point-min)))
3848 (while (not (eval ebrowse-tags-loop-form))
3849 (ebrowse-tags-next-file)
3850 (message "Scanning file `%s'..." buffer-file-name)
3851 (goto-char (point-min))))
3852
3853
3854;;###autoload
3855(defun ebrowse-tags-search (regexp)
3856 "Search for REGEXP in all files in a tree.
3857If marked classes exist, process marked classes, only.
3858If regular expression is nil, repeat last search."
3859 (interactive "sTree search (regexp): ")
3860 (if (and (string= regexp "")
3861 (eq (car ebrowse-tags-loop-form) 're-search-forward))
3862 (ebrowse-tags-loop-continue)
3863 (setq ebrowse-tags-loop-form (list 're-search-forward regexp nil t))
3864 (ebrowse-tags-loop-continue 'first-time)))
3865
3866
3867;;;###autoload
3868(defun ebrowse-tags-query-replace (from to)
3869 "Query replace FROM with TO in all files of a class tree.
3870With prefix arg, process files of marked classes only."
3871 (interactive
3872 "sTree query replace (regexp): \nsTree query replace %s by: ")
3873 (setq ebrowse-tags-loop-form
3874 (list 'and (list 'save-excursion
3875 (list 're-search-forward from nil t))
3876 (list 'not (list 'perform-replace from to t t nil))))
3877 (ebrowse-tags-loop-continue 'first-time))
3878
3879
3880;;; ###autoload
3881(defun ebrowse-tags-search-member-use (&optional fix-name)
3882 "Search for call sites of a member.
3883If FIX-NAME is specified, search uses of that member.
3884Otherwise, read a member name from the minibuffer.
3885Searches in all files mentioned in a class tree for something that
3886looks like a function call to the member."
3887 (interactive)
3888 ;; Choose the tree to use if there is more than one.
3889 (multiple-value-bind (tree header tree-buffer)
3890 (ebrowse-choose-tree)
3891 (unless tree
3892 (error "No class tree"))
3893 ;; Get the member name NAME (class-name is ignored).
3894 (let ((name fix-name) class-name regexp)
3895 (unless name
3896 (multiple-value-setq (class-name name)
3897 (ebrowse-tags-read-name header "Find calls of: ")))
3898 ;; Set tags loop form to search for member and begin loop.
3899 (setq regexp (concat "\\<" name "[ \t]*(")
3900 ebrowse-tags-loop-form (list 're-search-forward regexp nil t))
3901 (ebrowse-tags-loop-continue 'first-time tree-buffer))))
3902
3903
3904
3905;;; Tags position management
3906
3907;;; Structures of this kind are the elements of the position stack.
3908
3909(defstruct (ebrowse-position (:type vector) :named)
3910 file-name ; in which file
3911 point ; point in file
3912 target ; t if target of a jump
3913 info) ; (CLASS FUNC MEMBER) jumped to
3914
3915
3916(defvar ebrowse-position-stack ()
3917 "Stack of `ebrowse-position' structured.")
3918
3919
3920(defvar ebrowse-position-index 0
3921 "Current position in position stack.")
3922
3923
3924(defun ebrowse-position-name (position)
3925 "Return an identifying string for POSITION.
3926The string is printed in the electric position list buffer."
3927 (let ((info (ebrowse-position-info position)))
3928 (concat (if (ebrowse-position-target position) "at " "to ")
3929 (ebrowse-cs-name (ebrowse-ts-class (first info)))
3930 "::" (ebrowse-ms-name (third info)))))
3931
3932
3933(defun ebrowse-view/find-position (position &optional view)
3934 "Position point on POSITION.
3935If VIEW is non-nil, view the position, otherwise find it."
3936 (cond ((not view)
3937 (find-file (ebrowse-position-file-name position))
3938 (goto-char (ebrowse-position-point position)))
3939 (t
3940 (unwind-protect
3941 (progn
3942 (push (function
3943 (lambda ()
3944 (goto-char (ebrowse-position-point position))))
3945 view-mode-hook)
3946 (view-file (ebrowse-position-file-name position)))
3947 (pop view-mode-hook)))))
3948
3949
3950(defun ebrowse-push-position (marker info &optional target)
3951 "Push current position on position stack.
3952MARKER is the marker to remember as position.
3953INFO is a list (CLASS FUNC MEMBER) specifying what we jumped to.
3954TARGET non-nil means we performed a jump.
3955Positions in buffers that have no file names are not saved."
3956 (when (buffer-file-name (marker-buffer marker))
3957 (let ((too-much (- (length ebrowse-position-stack)
3958 ebrowse-max-positions)))
3959 ;; Do not let the stack grow to infinity.
3960 (when (plusp too-much)
3961 (setq ebrowse-position-stack
3962 (butlast ebrowse-position-stack too-much)))
3963 ;; Push the position.
3964 (push (make-ebrowse-position
3965 :file-name (buffer-file-name (marker-buffer marker))
3966 :point (marker-position marker)
3967 :target target
3968 :info info)
3969 ebrowse-position-stack))))
3970
3971
3972(defun ebrowse-move-in-position-stack (increment)
3973 "Move by INCREMENT in the position stack."
3974 (let ((length (length ebrowse-position-stack)))
3975 (when (zerop length)
3976 (error "No positions remembered"))
3977 (setq ebrowse-position-index
3978 (mod (+ increment ebrowse-position-index) length))
3979 (message "Position %d of %d " ebrowse-position-index length)
3980 (ebrowse-view/find-position (nth ebrowse-position-index
3981 ebrowse-position-stack))))
3982
3983
3984;;; ###autoload
3985(defun ebrowse-back-in-position-stack (arg)
3986 "Move backward in the position stack.
3987Prefix arg ARG says how much."
3988 (interactive "p")
3989 (ebrowse-move-in-position-stack (max 1 arg)))
3990
3991
3992;;; ###autoload
3993(defun ebrowse-forward-in-position-stack (arg)
3994 "Move forward in the position stack.
3995Prefix arg ARG says how much."
3996 (interactive "p")
3997 (ebrowse-move-in-position-stack (min -1 (- arg))))
3998
3999
4000
4001;;; Electric position list
4002
4003(defvar ebrowse-electric-position-mode-map ()
4004 "Keymap used in electric position stack window.")
4005
4006
4007(defvar ebrowse-electric-position-mode-hook nil
4008 "If non-nil, its value is called by ebrowse-electric-position-mode.")
4009
4010
4011(unless ebrowse-electric-position-mode-map
4012 (let ((map (make-keymap))
4013 (submap (make-keymap)))
4014 (setq ebrowse-electric-position-mode-map map)
4015 (fillarray (car (cdr map)) 'ebrowse-electric-position-undefined)
4016 (fillarray (car (cdr submap)) 'ebrowse-electric-position-undefined)
4017 (define-key map "\e" submap)
4018 (define-key map "\C-z" 'suspend-emacs)
4019 (define-key map "\C-h" 'Helper-help)
4020 (define-key map "?" 'Helper-describe-bindings)
4021 (define-key map "\C-c" nil)
4022 (define-key map "\C-c\C-c" 'ebrowse-electric-position-quit)
4023 (define-key map "q" 'ebrowse-electric-position-quit)
4024 (define-key map " " 'ebrowse-electric-select-position)
4025 (define-key map "\C-l" 'recenter)
4026 (define-key map "\C-u" 'universal-argument)
4027 (define-key map "\C-p" 'previous-line)
4028 (define-key map "\C-n" 'next-line)
4029 (define-key map "p" 'previous-line)
4030 (define-key map "n" 'next-line)
4031 (define-key map "v" 'ebrowse-electric-view-position)
4032 (define-key map "\C-v" 'scroll-up)
4033 (define-key map "\ev" 'scroll-down)
4034 (define-key map "\e\C-v" 'scroll-other-window)
4035 (define-key map "\e>" 'end-of-buffer)
4036 (define-key map "\e<" 'beginning-of-buffer)
4037 (define-key map "\e>" 'end-of-buffer)))
4038
4039(put 'ebrowse-electric-position-mode 'mode-class 'special)
4040(put 'ebrowse-electric-position-undefined 'suppress-keymap t)
4041
4042
4043(defun ebrowse-electric-position-mode ()
4044 "Mode for electric position buffers.
4045Runs the hook `ebrowse-electric-position-mode-hook'."
4046 (kill-all-local-variables)
4047 (use-local-map ebrowse-electric-position-mode-map)
4048 (setq mode-name "Electric Position Menu"
4049 mode-line-buffer-identification "Electric Position Menu")
4050 (when (memq 'mode-name mode-line-format)
4051 (setq mode-line-format (copy-sequence mode-line-format))
4052 (setcar (memq 'mode-name mode-line-format) "Positions"))
4053 (make-local-variable 'Helper-return-blurb)
4054 (setq Helper-return-blurb "return to buffer editing"
4055 truncate-lines t
4056 buffer-read-only t
4057 major-mode 'ebrowse-electric-position-mode)
4058 (run-hooks 'ebrowse-electric-position-mode-hook))
4059
4060
4061(defun ebrowse-draw-position-buffer ()
4062 "Display positions in buffer *Positions*."
4063 (set-buffer (get-buffer-create "*Positions*"))
4064 (setq buffer-read-only nil)
4065 (erase-buffer)
4066 (insert "File Point Description\n"
4067 "---- ----- -----------\n")
4068 (dolist (position ebrowse-position-stack)
4069 (insert (file-name-nondirectory (ebrowse-position-file-name position)))
4070 (indent-to 15)
4071 (insert (int-to-string (ebrowse-position-point position)))
4072 (indent-to 22)
4073 (insert (ebrowse-position-name position) "\n"))
4074 (setq buffer-read-only t))
4075
4076
4077;;; ###autoload
4078(defun ebrowse-electric-position-menu ()
4079 "List positions in the position stack in an electric buffer."
4080 (interactive)
4081 (unless ebrowse-position-stack
4082 (error "No positions remembered"))
4083 (let (select buffer window)
4084 (save-window-excursion
4085 (save-window-excursion (ebrowse-draw-position-buffer))
4086 (setq window (Electric-pop-up-window "*Positions*")
4087 buffer (window-buffer window))
4088 (shrink-window-if-larger-than-buffer window)
4089 (unwind-protect
4090 (progn
4091 (set-buffer buffer)
4092 (ebrowse-electric-position-mode)
4093 (setq select
4094 (catch 'ebrowse-electric-select-position
4095 (message "<<< Press Space to bury the list >>>")
4096 (let ((first (progn (goto-char (point-min))
4097 (forward-line 2)
4098 (point)))
4099 (last (progn (goto-char (point-max))
4100 (forward-line -1)
4101 (point)))
4102 (goal-column 0))
4103 (goto-char first)
4104 (Electric-command-loop 'ebrowse-electric-select-position
4105 nil t
4106 'ebrowse-electric-position-looper
4107 (cons first last))))))
4108 (set-buffer buffer)
4109 (bury-buffer buffer)
4110 (message nil)))
4111 (when select
4112 (set-buffer buffer)
4113 (ebrowse-electric-find-position select))
4114 (kill-buffer buffer)))
4115
4116
4117(defun ebrowse-electric-position-looper (state condition)
4118 "Prevent moving point on invalid lines.
4119Called from `Electric-command-loop'. See there for the meaning
4120of STATE and CONDITION."
4121 (cond ((and condition
4122 (not (memq (car condition) '(buffer-read-only
4123 end-of-buffer
4124 beginning-of-buffer))))
4125 (signal (car condition) (cdr condition)))
4126 ((< (point) (car state))
4127 (goto-char (point-min))
4128 (forward-line 2))
4129 ((> (point) (cdr state))
4130 (goto-char (point-max))
4131 (forward-line -1)
4132 (if (pos-visible-in-window-p (point-max))
4133 (recenter -1)))))
4134
4135
4136(defun ebrowse-electric-position-undefined ()
4137 "Function called for undefined keys."
4138 (interactive)
4139 (message "Type C-h for help, ? for commands, q to quit, Space to execute")
4140 (sit-for 4))
4141
4142
4143(defun ebrowse-electric-position-quit ()
4144 "Leave the electric position list."
4145 (interactive)
4146 (throw 'ebrowse-electric-select-position nil))
4147
4148
4149(defun ebrowse-electric-select-position ()
4150 "Select a position from the list."
4151 (interactive)
4152 (throw 'ebrowse-electric-select-position (point)))
4153
4154
4155(defun ebrowse-electric-find-position (point &optional view)
4156 "View/find what is described by the line at POINT.
4157If VIEW is non-nil, view else find source files."
4158 (let ((index (- (count-lines (point-min) point) 2)))
4159 (ebrowse-view/find-position (nth index
4160 ebrowse-position-stack) view)))
4161
4162
4163(defun ebrowse-electric-view-position ()
4164 "View the position described by the line point is in."
4165 (interactive)
4166 (ebrowse-electric-find-position (point) t))
4167
4168
4169
4170;;; Saving trees to disk
4171
4172(defun ebrowse-write-file-hook-fn ()
4173 "Write current buffer as a class tree.
4174Installed on `local-write-file-hooks'."
4175 (ebrowse-save-tree)
4176 t)
4177
4178
4179;;; ###autoload
4180(defun ebrowse-save-tree ()
4181 "Save current tree in same file it was loaded from."
4182 (interactive)
4183 (ebrowse-save-tree-as (or buffer-file-name ebrowse--tags-file-name)))
4184
4185
4186;;;###autoload
4187(defun ebrowse-save-tree-as (&optional file-name)
4188 "Write the current tree data structure to a file.
4189Read the file name from the minibuffer if interactive.
4190Otherwise, FILE-NAME specifies the file to save the tree in."
4191 (interactive "FSave tree as: ")
4192 (let ((temp-buffer (get-buffer-create "*Tree Output"))
4193 (old-standard-output standard-output)
4194 (header (copy-ebrowse-hs ebrowse--header))
4195 (tree ebrowse--tree))
4196 (unwind-protect
4197 (save-excursion
4198 (set-buffer (setq standard-output temp-buffer))
4199 (erase-buffer)
4200 (setf (ebrowse-hs-member-table header) nil)
4201 (insert (prin1-to-string header) " ")
4202 (mapcar 'ebrowse-save-class tree)
4203 (write-file file-name)
4204 (message "Tree written to file `%s'" file-name))
4205 (kill-buffer temp-buffer)
4206 (set-buffer-modified-p nil)
4207 (ebrowse-update-tree-buffer-mode-line)
4208 (setq standard-output old-standard-output))))
4209
4210
4211(defun ebrowse-save-class (class)
4212 "Write single class CLASS to current buffer."
4213 (message "%s..." (ebrowse-cs-name (ebrowse-ts-class class)))
4214 (insert "[ebrowse-ts ")
4215 (prin1 (ebrowse-ts-class class)) ;class name
4216 (insert "(") ;list of subclasses
4217 (mapcar 'ebrowse-save-class (ebrowse-ts-subclasses class))
4218 (insert ")")
4219 (dolist (func ebrowse-member-list-accessors)
4220 (prin1 (funcall func class))
4221 (insert "\n"))
4222 (insert "()") ;base-classes slot
4223 (prin1 (ebrowse-ts-mark class))
4224 (insert "]\n"))
4225
4226
4227
4228;;; Statistics
4229
4230;;; ###autoload
4231(defun ebrowse-statistics ()
4232 "Display statistics for a class tree."
4233 (interactive)
4234 (let ((tree-file (buffer-file-name))
4235 temp-buffer-setup-hook)
4236 (with-output-to-temp-buffer "*Tree Statistics*"
4237 (multiple-value-bind (classes member-functions member-variables
4238 static-functions static-variables)
4239 (ebrowse-gather-statistics)
4240 (set-buffer standard-output)
4241 (erase-buffer)
4242 (insert "STATISTICS FOR TREE " (or tree-file "unknown") ":\n\n")
4243 (ebrowse-print-statistics-line "Number of classes:" classes)
4244 (ebrowse-print-statistics-line "Number of member functions:"
4245 member-functions)
4246 (ebrowse-print-statistics-line "Number of member variables:"
4247 member-variables)
4248 (ebrowse-print-statistics-line "Number of static functions:"
4249 static-functions)
4250 (ebrowse-print-statistics-line "Number of static variables:"
4251 static-variables)))))
4252
4253
4254(defun ebrowse-print-statistics-line (title value)
4255 "Print a line in the statistics buffer.
4256TITLE is the title of the line, VALUE is number to be printed
4257after that."
4258 (insert title)
4259 (indent-to 40)
4260 (insert (format "%d\n" value)))
4261
4262
4263(defun ebrowse-gather-statistics ()
4264 "Return statistics for a class tree.
4265The result is a list (NUMBER-OF-CLASSES NUMBER-OF-MEMBER-FUNCTIONS
4266NUMBER-OF-INSTANCE-VARIABLES NUMBER-OF-STATIC-FUNCTIONS
4267NUMBER-OF-STATIC-VARIABLES:"
4268 (let ((classes 0) (member-functions 0) (member-variables 0)
4269 (static-functions 0) (static-variables 0))
4270 (ebrowse-for-all-trees (tree ebrowse--tree-obarray)
4271 (incf classes)
4272 (incf member-functions (length (ebrowse-ts-member-functions tree)))
4273 (incf member-variables (length (ebrowse-ts-member-variables tree)))
4274 (incf static-functions (length (ebrowse-ts-static-functions tree)))
4275 (incf static-variables (length (ebrowse-ts-static-variables tree))))
4276 (list classes member-functions member-variables
4277 static-functions static-variables)))
4278
4279
4280
4281;;; Global key bindings
4282
4283;;; The following can be used to bind key sequences starting with
4284;;; prefix `\C-cb' to browse commands.
4285
4286(defvar ebrowse-global-map nil
4287 "*Keymap for Ebrowse commands.")
4288
4289
4290(defvar ebrowse-global-prefix-key "\C-cb"
4291 "Prefix key for Ebrowse commands.")
4292
4293
4294(defvar ebrowse-global-submap-4 nil
4295 "Keymap used for `ebrowse-global-prefix' followed by `4'.")
4296
4297
4298(defvar ebrowse-global-submap-5 nil
4299 "Keymap used for `ebrowse-global-prefix' followed by `5'.")
4300
4301
4302(unless ebrowse-global-map
4303 (setq ebrowse-global-map (make-sparse-keymap))
4304 (setq ebrowse-global-submap-4 (make-sparse-keymap))
4305 (setq ebrowse-global-submap-5 (make-sparse-keymap))
4306 (define-key ebrowse-global-map "a" 'ebrowse-tags-apropos)
4307 (define-key ebrowse-global-map "b" 'ebrowse-pop-to-browser-buffer)
4308 (define-key ebrowse-global-map "-" 'ebrowse-back-in-position-stack)
4309 (define-key ebrowse-global-map "+" 'ebrowse-forward-in-position-stack)
4310 (define-key ebrowse-global-map "l" 'ebrowse-tags-list-members-in-file)
4311 (define-key ebrowse-global-map "m" 'ebrowse-tags-display-member-buffer)
4312 (define-key ebrowse-global-map "n" 'ebrowse-tags-next-file)
4313 (define-key ebrowse-global-map "p" 'ebrowse-electric-position-menu)
4314 (define-key ebrowse-global-map "s" 'ebrowse-tags-search)
4315 (define-key ebrowse-global-map "u" 'ebrowse-tags-search-member-use)
4316 (define-key ebrowse-global-map "v" 'ebrowse-tags-view-definition)
4317 (define-key ebrowse-global-map "V" 'ebrowse-tags-view-declaration)
4318 (define-key ebrowse-global-map "%" 'ebrowse-tags-query-replace)
4319 (define-key ebrowse-global-map "." 'ebrowse-tags-find-definition)
4320 (define-key ebrowse-global-map "f" 'ebrowse-tags-find-definition)
4321 (define-key ebrowse-global-map "F" 'ebrowse-tags-find-declaration)
4322 (define-key ebrowse-global-map "," 'ebrowse-tags-loop-continue)
4323 (define-key ebrowse-global-map " " 'ebrowse-electric-buffer-list)
4324 (define-key ebrowse-global-map "\t" 'ebrowse-tags-complete-symbol)
4325 (define-key ebrowse-global-map "4" ebrowse-global-submap-4)
4326 (define-key ebrowse-global-submap-4 "." 'ebrowse-tags-find-definition-other-window)
4327 (define-key ebrowse-global-submap-4 "f" 'ebrowse-tags-find-definition-other-window)
4328 (define-key ebrowse-global-submap-4 "v" 'ebrowse-tags-find-declaration-other-window)
4329 (define-key ebrowse-global-submap-4 "F" 'ebrowse-tags-view-definition-other-window)
4330 (define-key ebrowse-global-submap-4 "V" 'ebrowse-tags-view-declaration-other-window)
4331 (define-key ebrowse-global-map "5" ebrowse-global-submap-5)
4332 (define-key ebrowse-global-submap-5 "." 'ebrowse-tags-find-definition-other-frame)
4333 (define-key ebrowse-global-submap-5 "f" 'ebrowse-tags-find-definition-other-frame)
4334 (define-key ebrowse-global-submap-5 "v" 'ebrowse-tags-find-declaration-other-frame)
4335 (define-key ebrowse-global-submap-5 "F" 'ebrowse-tags-view-definition-other-frame)
4336 (define-key ebrowse-global-submap-5 "V" 'ebrowse-tags-view-declaration-other-frame)
4337 (define-key global-map ebrowse-global-prefix-key ebrowse-global-map))
4338
4339
4340
4341;;; Electric C++ browser buffer menu
4342
4343;;; Electric buffer menu customization to display only some buffers
4344;;; (in this case Tree buffers). There is only one problem with this:
4345;;; If the very first character typed in the buffer menu is a space,
4346;;; this will select the buffer from which the buffer menu was
4347;;; invoked. But this buffer is not displayed in the buffer list if
4348;;; it isn't a tree buffer. I therefore let the buffer menu command
4349;;; loop read the command `p' via `unread-command-char'. This command
4350;;; has no effect since we are on the first line of the buffer.
4351
4352(defvar electric-buffer-menu-mode-hook nil)
4353
4354
4355(defun ebrowse-hack-electric-buffer-menu ()
4356 "Hack the electric buffer menu to display browser buffers."
4357 (let (non-empty)
4358 (unwind-protect
4359 (save-excursion
4360 (setq buffer-read-only nil)
4361 (goto-char 1)
4362 (forward-line 2)
4363 (while (not (eobp))
4364 (let ((b (Buffer-menu-buffer nil)))
4365 (if (or (ebrowse-buffer-p b)
4366 (string= (buffer-name b) "*Apropos Members*"))
4367 (progn (forward-line 1)
4368 (setq non-empty t))
4369 (delete-region (point)
4370 (save-excursion (end-of-line)
4371 (min (point-max)
4372 (1+ (point)))))))))
4373 (unless non-empty
4374 (error "No tree buffers"))
4375 (setf unread-command-events (listify-key-sequence "p"))
4376 (shrink-window-if-larger-than-buffer (selected-window))
4377 (setq buffer-read-only t))))
4378
4379
4380(defun ebrowse-select-1st-to-9nth ()
4381 "Select the nth entry in the list by the keys 1..9."
4382 (interactive)
4383 (let* ((maxlin (count-lines (point-min) (point-max)))
4384 (n (min maxlin (+ 2 (string-to-int (this-command-keys))))))
4385 (goto-line n)
4386 (throw 'electric-buffer-menu-select (point))))
4387
4388
4389(defun ebrowse-install-1-to-9-keys ()
4390 "Define keys 1..9 to select the 1st to 0nth entry in the list."
4391 (dotimes (i 9)
4392 (define-key (current-local-map) (char-to-string (+ i ?1))
4393 'ebrowse-select-1st-to-9nth)))
4394
4395
4396(defun ebrowse-electric-buffer-list ()
4397 "Display an electric list of Ebrowse buffers."
4398 (interactive)
4399 (unwind-protect
4400 (progn
4401 (add-hook 'electric-buffer-menu-mode-hook
4402 'ebrowse-hack-electric-buffer-menu)
4403 (add-hook 'electric-buffer-menu-mode-hook
4404 'ebrowse-install-1-to-9-keys)
4405 (call-interactively 'electric-buffer-list))
4406 (remove-hook 'electric-buffer-menu-mode-hook
4407 'ebrowse-hack-electric-buffer-menu)))
4408
4409
4410;;; Mouse support
4411
4412(defun ebrowse-mouse-find-member (event)
4413 "Find the member clicked on in another frame.
4414EVENT is a mouse button event."
4415 (interactive "e")
4416 (mouse-set-point event)
4417 (let (start name)
4418 (save-excursion
4419 (skip-chars-backward "a-zA-Z0-9_")
4420 (setq start (point))
4421 (skip-chars-forward "a-zA-Z0-9_")
4422 (setq name (buffer-substring start (point))))
4423 (ebrowse-tags-view/find-member-decl/defn
4424 5 :view nil :definition t :member-name name)))
4425
4426
4427(defun ebrowse-popup-menu (menu event)
4428 "Pop up MENU and perform an action if something was selected.
4429EVENT is the mouse event."
4430 (save-selected-window
4431 (select-window (posn-window (event-start event)))
4432 (let ((selection (x-popup-menu event menu)) binding)
4433 (while selection
4434 (setq binding (lookup-key (or binding menu) (vector (car selection)))
4435 selection (cdr selection)))
4436 (when binding
4437 (call-interactively binding)))))
4438
4439
4440(easy-menu-define
4441 ebrowse-tree-buffer-class-object-menu ebrowse-tree-mode-map
4442 "Object menu for classes in the tree buffer"
4443 '("Class"
4444 ["Functions" ebrowse-tree-command:show-member-functions
4445 :help "Display a list of member functions"
4446 :active t]
4447 ["Variables" ebrowse-tree-command:show-member-variables
4448 :help "Display a list of member variables"
4449 :active t]
4450 ["Static Functions" ebrowse-tree-command:show-static-member-functions
4451 :help "Display a list of static member functions"
4452 :active t]
4453 ["Static Variables" ebrowse-tree-command:show-static-member-variables
4454 :help "Display a list of static member variables"
4455 :active t]
4456 ["Friends/ Defines" ebrowse-tree-command:show-friends
4457 :help "Display a list of friends of a class"
4458 :active t]
4459 ["Types" ebrowse-tree-command:show-types
4460 :help "Display a list of types defined in a class"
4461 :active t]
4462 "-----------------"
4463 ["View" ebrowse-view-class-declaration
4464 :help "View class declaration"
4465 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
4466 ["Find" ebrowse-find-class-declaration
4467 :help "Find class declaration in file"
4468 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
4469 "-----------------"
4470 ["Mark" ebrowse-toggle-mark-at-point
4471 :help "Mark class point is on"
4472 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
4473 "-----------------"
4474 ["Collapse" ebrowse-collapse-branch
4475 :help "Collapse subtree under class point is on"
4476 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
4477 ["Expand" ebrowse-expand-branch
4478 :help "Expand subtree under class point is on"
4479 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]))
4480
4481
4482(easy-menu-define
4483 ebrowse-tree-buffer-object-menu ebrowse-tree-mode-map
4484 "Object menu for tree buffers"
4485 '("Ebrowse"
4486 ["Filename Display" ebrowse-toggle-file-name-display
4487 :help "Toggle display of source files names"
4488 :style toggle
4489 :selected ebrowse--show-file-names-flag
4490 :active t]
4491 ["Tree Indentation" ebrowse-set-tree-indentation
4492 :help "Set the tree's indentation"
4493 :active t]
4494 ["Unmark All Classes" ebrowse-mark-all-classes
4495 :help "Unmark all classes in the class tree"
4496 :active t]
4497 ["Expand All" ebrowse-expand-all
4498 :help "Expand all subtrees in the class tree"
4499 :active t]
4500 ["Statistics" ebrowse-statistics
4501 :help "Show a buffer with class hierarchy statistics"
4502 :active t]
4503 ["Find Class" ebrowse-read-class-name-and-go
4504 :help "Find a class in the tree"
4505 :active t]
4506 ["Member Buffer" ebrowse-pop/switch-to-member-buffer-for-same-tree
4507 :help "Show a member buffer for this class tree"
4508 :active t]))
4509
4510
4511(defun ebrowse-mouse-3-in-tree-buffer (event)
4512 "Perform mouse actions in tree buffers.
4513EVENT is the mouse event."
4514 (interactive "e")
4515 (mouse-set-point event)
4516 (let* ((where (posn-point (event-start event)))
4517 (property (get-text-property where 'ebrowse-what)))
4518 (case (event-click-count event)
4519 (1
4520 (case property
4521 (class-name
4522 (ebrowse-popup-menu ebrowse-tree-buffer-class-object-menu event))
4523 (t
4524 (ebrowse-popup-menu ebrowse-tree-buffer-object-menu event)))))))
4525
4526
4527(defun ebrowse-mouse-2-in-tree-buffer (event)
4528 "Perform mouse actions in tree buffers.
4529EVENT is the mouse event."
4530 (interactive "e")
4531 (mouse-set-point event)
4532 (let* ((where (posn-point (event-start event)))
4533 (property (get-text-property where 'ebrowse-what)))
4534 (case (event-click-count event)
4535 (1 (case property
4536 (class-name
4537 (ebrowse-tree-command:show-member-functions)))))))
4538
4539
4540(defun ebrowse-mouse-1-in-tree-buffer (event)
4541 "Perform mouse actions in tree buffers.
4542EVENT is the mouse event."
4543 (interactive "e")
4544 (mouse-set-point event)
4545 (let* ((where (posn-point (event-start event)))
4546 (property (get-text-property where 'ebrowse-what)))
4547 (case (event-click-count event)
4548 (2 (case property
4549 (class-name
4550 (let ((collapsed (save-excursion (skip-chars-forward "^\r\n")
4551 (looking-at "\r"))))
4552 (ebrowse-collapse-fn (not collapsed))))
4553 (mark
4554 (ebrowse-toggle-mark-at-point 1)))))))
4555
4556
4557
4558;;; Hooks installed
4559
4560(add-hook 'find-file-hooks 'ebrowse-find-file)
4561
4562
4563(provide 'ebrowse)
4564
4565;;; Local variables:
4566;;; eval:(put 'ebrowse-output 'lisp-indent-hook 0)
4567;;; eval:(put 'ebrowse-ignoring-completion-case 'lisp-indent-hook 0)
4568;;; eval:(put 'ebrowse-save-selective 'lisp-indent-hook 0)
4569;;; eval:(put 'ebrowse-for-all-trees 'lisp-indent-hook 1)
4570;;; End:
4571
4572;;; ebrowse.el ends here.
4573
diff --git a/src/ChangeLog b/src/ChangeLog
index 2e2358e0679..6efbd878aee 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
12000-04-09 Gerd Moellmann <gerd@gnu.org>
2
3 * buffer.c (Frestore_buffer_modified_p): New function.
4 (syms_of_buffer): Defsubr it.
5
12000-04-08 Ken Raeburn <raeburn@gnu.org> 62000-04-08 Ken Raeburn <raeburn@gnu.org>
2 7
3 * charset.c (Fmake_char_internal): CHAR_COMPONENTS_VALID_P takes a 8 * charset.c (Fmake_char_internal): CHAR_COMPONENTS_VALID_P takes a