(help-xref-on-pp): Check for constant symbols.
[bpt/emacs.git] / lib-src / ebrowse.c
CommitLineData
be0dbdab
GM
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));
8bef35f2 501void declaration P_ ((int));
be0dbdab
GM
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\f
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);
8bef35f2
GM
537 if (p == NULL)
538 {
539 yyerror ("out of memory");
540 exit (1);
541 }
542 return p;
be0dbdab
GM
543}
544
545
546/* Like realloc but print an error and exit if out of memory. */
547
548void *
549xrealloc (p, sz)
550 void *p;
551 int sz;
552{
553 p = realloc (p, sz);
8bef35f2
GM
554 if (p == NULL)
555 {
556 yyerror ("out of memory");
557 exit (1);
558 }
559 return p;
be0dbdab
GM
560}
561
562
563/* Like strdup, but print an error and exit if not enough memory is
564 available.. If S is null, return null. */
565
566char *
567xstrdup (s)
568 char *s;
569{
570 if (s)
571 s = strcpy (xmalloc (strlen (s) + 1), s);
572 return s;
573}
574
575
576\f
577/***********************************************************************
578 Symbols
579 ***********************************************************************/
580
581/* Initialize the symbol table. This currently only sets up the
582 special symbol for globals (`*Globals*'). */
583
584void
585init_sym ()
586{
587 global_symbols = add_sym (GLOBALS_NAME, NULL);
588}
589
590
591/* Add a symbol for class NAME to the symbol table. NESTED_IN_CLASS
592 is the class in which class NAME was found. If it is null,
593 this means the scope of NAME is the current namespace.
594
595 If a symbol for NAME already exists, return that. Otherwise
596 create a new symbol and set it to default values. */
597
598struct sym *
599add_sym (name, nested_in_class)
600 char *name;
601 struct sym *nested_in_class;
602{
603 struct sym *sym;
604 unsigned h;
605 char *s;
606 struct sym *scope = nested_in_class ? nested_in_class : current_namespace;
607
608 for (s = name, h = 0; *s; ++s)
609 h = (h << 1) ^ *s;
610 h %= TABLE_SIZE;
611
612 for (sym = class_table[h]; sym; sym = sym->next)
613 if (streq (name, sym->name) && sym->namesp == scope)
614 break;
615
616 if (sym == NULL)
617 {
618 if (f_very_verbose)
619 {
620 putchar ('\t');
621 puts (name);
622 }
623
624 sym = (struct sym *) xmalloc (sizeof *sym + strlen (name));
625 bzero (sym, sizeof *sym);
626 strcpy (sym->name, name);
627 sym->namesp = scope;
628 sym->next = class_table[h];
629 class_table[h] = sym;
630 }
631
632 return sym;
633}
634
635
636/* Add links between superclass SUPER and subclass SUB. */
637
638void
639add_link (super, sub)
640 struct sym *super, *sub;
641{
642 struct link *lnk, *lnk2, *p, *prev;
643
644 /* See if a link already exists. */
645 for (p = super->subs, prev = NULL;
646 p && strcmp (sub->name, p->sym->name) > 0;
647 prev = p, p = p->next)
648 ;
649
650 /* Avoid duplicates. */
651 if (p == NULL || p->sym != sub)
652 {
653 lnk = (struct link *) xmalloc (sizeof *lnk);
654 lnk2 = (struct link *) xmalloc (sizeof *lnk2);
655
656 lnk->sym = sub;
657 lnk->next = p;
658
659 if (prev)
660 prev->next = lnk;
661 else
662 super->subs = lnk;
663
664 lnk2->sym = super;
665 lnk2->next = sub->supers;
666 sub->supers = lnk2;
667 }
668}
669
670
671/* Find in class CLS member NAME.
672
673 VAR non-zero means look for a member variable; otherwise a function
674 is searched. SC specifies what kind of member is searched---a
675 static, or per-instance member etc. HASH is a hash code for the
676 parameter types of functions. Value is a pointer to the member
677 found or null if not found. */
678
679struct member *
680find_member (cls, name, var, sc, hash)
681 struct sym *cls;
682 char *name;
683 int var, sc;
684 unsigned hash;
685{
686 struct member **list;
687 struct member *p;
688 unsigned name_hash = 0;
689 char *s;
690 int i;
691
692 switch (sc)
693 {
694 case SC_FRIEND:
695 list = &cls->friends;
696 break;
697
698 case SC_TYPE:
699 list = &cls->types;
700 break;
701
702 case SC_STATIC:
703 list = var ? &cls->static_vars : &cls->static_fns;
704 break;
705
706 default:
707 list = var ? &cls->vars : &cls->fns;
708 break;
709 }
710
711 for (s = name; *s; ++s)
712 name_hash = (name_hash << 1) ^ *s;
713 i = name_hash % TABLE_SIZE;
714
715 for (p = member_table[i]; p; p = p->anext)
716 if (p->list == list && p->param_hash == hash && streq (name, p->name))
717 break;
718
719 return p;
720}
721
722
723/* Add to class CLS information for the declaration of member NAME.
724 REGEXP is a regexp matching the declaration, if non-null. POS is
725 the position in the source where the declaration is found. HASH is
726 a hash code for the parameter list of the member, if it's a
727 function. VAR non-zero means member is a variable or type. SC
728 specifies the type of member (instance member, static, ...). VIS
729 is the member's visibility (public, protected, private). FLAGS is
730 a bit set giving additional information about the member (see the
731 F_* defines). */
732
733void
734add_member_decl (cls, name, regexp, pos, hash, var, sc, vis, flags)
735 struct sym *cls;
736 char *name;
737 char *regexp;
738 int pos;
739 unsigned hash;
740 int var;
741 int sc;
742 int vis;
743 int flags;
744{
745 struct member *m;
746
747 m = find_member (cls, name, var, sc, hash);
748 if (m == NULL)
749 m = add_member (cls, name, var, sc, hash);
750
751 /* Have we seen a new filename? If so record that. */
752 if (!cls->filename || !streq (cls->filename, filename))
753 m->filename = filename;
754
755 m->regexp = regexp;
756 m->pos = pos;
757 m->flags = flags;
758
759 switch (vis)
760 {
761 case PRIVATE:
762 m->vis = V_PRIVATE;
763 break;
764
765 case PROTECTED:
766 m->vis = V_PROTECTED;
767 break;
768
769 case PUBLIC:
770 m->vis = V_PUBLIC;
771 break;
772 }
773
774 info_where = P_DECL;
775 info_cls = cls;
776 info_member = m;
777}
778
779
780/* Add to class CLS information for the definition of member NAME.
781 REGEXP is a regexp matching the declaration, if non-null. POS is
782 the position in the source where the declaration is found. HASH is
783 a hash code for the parameter list of the member, if it's a
784 function. VAR non-zero means member is a variable or type. SC
785 specifies the type of member (instance member, static, ...). VIS
786 is the member's visibility (public, protected, private). FLAGS is
787 a bit set giving additional information about the member (see the
788 F_* defines). */
789
790void
791add_member_defn (cls, name, regexp, pos, hash, var, sc, flags)
792 struct sym *cls;
793 char *name;
794 char *regexp;
795 int pos;
796 unsigned hash;
797 int var;
798 int sc;
799 int flags;
800{
801 struct member *m;
802
803 if (sc == SC_UNKNOWN)
804 {
805 m = find_member (cls, name, var, SC_MEMBER, hash);
806 if (m == NULL)
807 {
808 m = find_member (cls, name, var, SC_STATIC, hash);
809 if (m == NULL)
810 m = add_member (cls, name, var, sc, hash);
811 }
812 }
813 else
814 {
815 m = find_member (cls, name, var, sc, hash);
816 if (m == NULL)
817 m = add_member (cls, name, var, sc, hash);
818 }
819
820 if (!cls->sfilename)
821 cls->sfilename = filename;
822
823 if (!streq (cls->sfilename, filename))
824 m->def_filename = filename;
825
826 m->def_regexp = regexp;
827 m->def_pos = pos;
828 m->flags |= flags;
829
830 info_where = P_DEFN;
831 info_cls = cls;
832 info_member = m;
833}
834
835
836/* Add a symbol for a define named NAME to the symbol table.
837 REGEXP is a regular expression matching the define in the source,
838 if it is non-null. POS is the position in the file. */
839
840void
841add_define (name, regexp, pos)
842 char *name, *regexp;
843 int pos;
844{
845 add_global_defn (name, regexp, pos, 0, 1, SC_FRIEND, F_DEFINE);
846 add_global_decl (name, regexp, pos, 0, 1, SC_FRIEND, F_DEFINE);
847}
848
849
850/* Add information for the global definition of NAME.
851 REGEXP is a regexp matching the declaration, if non-null. POS is
852 the position in the source where the declaration is found. HASH is
853 a hash code for the parameter list of the member, if it's a
854 function. VAR non-zero means member is a variable or type. SC
855 specifies the type of member (instance member, static, ...). VIS
856 is the member's visibility (public, protected, private). FLAGS is
857 a bit set giving additional information about the member (see the
858 F_* defines). */
859
860void
861add_global_defn (name, regexp, pos, hash, var, sc, flags)
862 char *name, *regexp;
863 int pos;
864 unsigned hash;
865 int var;
866 int sc;
867 int flags;
868{
869 int i;
870 struct sym *sym;
871
872 /* Try to find out for which classes a function is a friend, and add
873 what we know about it to them. */
874 if (!var)
875 for (i = 0; i < TABLE_SIZE; ++i)
876 for (sym = class_table[i]; sym; sym = sym->next)
877 if (sym != global_symbols && sym->friends)
878 if (find_member (sym, name, 0, SC_FRIEND, hash))
879 add_member_defn (sym, name, regexp, pos, hash, 0,
880 SC_FRIEND, flags);
881
882 /* Add to global symbols. */
883 add_member_defn (global_symbols, name, regexp, pos, hash, var, sc, flags);
884}
885
886
887/* Add information for the global declaration of NAME.
888 REGEXP is a regexp matching the declaration, if non-null. POS is
889 the position in the source where the declaration is found. HASH is
890 a hash code for the parameter list of the member, if it's a
891 function. VAR non-zero means member is a variable or type. SC
892 specifies the type of member (instance member, static, ...). VIS
893 is the member's visibility (public, protected, private). FLAGS is
894 a bit set giving additional information about the member (see the
895 F_* defines). */
896
897void
898add_global_decl (name, regexp, pos, hash, var, sc, flags)
899 char *name, *regexp;
900 int pos;
901 unsigned hash;
902 int var;
903 int sc;
904 int flags;
905{
906 /* Add declaration only if not already declared. Header files must
907 be processed before source files for this to have the right effect.
908 I do not want to handle implicit declarations at the moment. */
909 struct member *m;
910 struct member *found;
911
912 m = found = find_member (global_symbols, name, var, sc, hash);
913 if (m == NULL)
914 m = add_member (global_symbols, name, var, sc, hash);
915
916 /* Definition already seen => probably last declaration implicit.
917 Override. This means that declarations must always be added to
918 the symbol table before definitions. */
919 if (!found)
920 {
921 if (!global_symbols->filename
922 || !streq (global_symbols->filename, filename))
923 m->filename = filename;
924
925 m->regexp = regexp;
926 m->pos = pos;
927 m->vis = V_PUBLIC;
928 m->flags = flags;
929
930 info_where = P_DECL;
931 info_cls = global_symbols;
932 info_member = m;
933 }
934}
935
936
937/* Add a symbol for member NAME to class CLS.
938 VAR non-zero means it's a variable. SC specifies the kind of
939 member. HASH is a hash code for the parameter types of a function.
940 Value is a pointer to the member's structure. */
941
942struct member *
943add_member (cls, name, var, sc, hash)
944 struct sym *cls;
945 char *name;
946 int var;
947 int sc;
948 unsigned hash;
949{
950 struct member *m = (struct member *) xmalloc (sizeof *m + strlen (name));
951 struct member **list;
952 struct member *p;
953 struct member *prev;
954 unsigned name_hash = 0;
955 int i;
956 char *s;
957
958 strcpy (m->name, name);
959 m->param_hash = hash;
960
961 m->vis = 0;
962 m->flags = 0;
963 m->regexp = NULL;
964 m->filename = NULL;
965 m->pos = 0;
966 m->def_regexp = NULL;
967 m->def_filename = NULL;
968 m->def_pos = 0;
969
970 assert (cls != NULL);
971
972 switch (sc)
973 {
974 case SC_FRIEND:
975 list = &cls->friends;
976 break;
977
978 case SC_TYPE:
979 list = &cls->types;
980 break;
981
982 case SC_STATIC:
983 list = var ? &cls->static_vars : &cls->static_fns;
984 break;
985
986 default:
987 list = var ? &cls->vars : &cls->fns;
988 break;
989 }
990
991 for (s = name; *s; ++s)
992 name_hash = (name_hash << 1) ^ *s;
993 i = name_hash % TABLE_SIZE;
994 m->anext = member_table[i];
995 member_table[i] = m;
996 m->list = list;
997
998 /* Keep the member list sorted. It's cheaper to do it here than to
999 sort them in Lisp. */
1000 for (prev = NULL, p = *list;
1001 p && strcmp (name, p->name) > 0;
1002 prev = p, p = p->next)
1003 ;
1004
1005 m->next = p;
1006 if (prev)
1007 prev->next = m;
1008 else
1009 *list = m;
1010 return m;
1011}
1012
1013
1014/* Given the root R of a class tree, step through all subclasses
1015 recursively, marking functions as virtual that are declared virtual
1016 in base classes. */
1017
1018void
1019mark_virtual (r)
1020 struct sym *r;
1021{
1022 struct link *p;
1023 struct member *m, *m2;
1024
1025 for (p = r->subs; p; p = p->next)
1026 {
1027 for (m = r->fns; m; m = m->next)
1028 if (HAS_FLAG (m->flags, F_VIRTUAL))
1029 {
1030 for (m2 = p->sym->fns; m2; m2 = m2->next)
1031 if (m->param_hash == m2->param_hash && streq (m->name, m2->name))
1032 SET_FLAG (m2->flags, F_VIRTUAL);
1033 }
1034
1035 mark_virtual (p->sym);
1036 }
1037}
1038
1039
1040/* For all roots of the class tree, mark functions as virtual that
1041 are virtual because of a virtual declaration in a base class. */
1042
1043void
1044mark_inherited_virtual ()
1045{
1046 struct sym *r;
1047 int i;
1048
1049 for (i = 0; i < TABLE_SIZE; ++i)
1050 for (r = class_table[i]; r; r = r->next)
1051 if (r->supers == NULL)
1052 mark_virtual (r);
1053}
1054
1055
1056/* Create and return a symbol for a namespace with name NAME. */
1057
1058struct sym *
1059make_namespace (name)
1060 char *name;
1061{
1062 struct sym *s = (struct sym *) xmalloc (sizeof *s + strlen (name));
1063 bzero (s, sizeof *s);
1064 strcpy (s->name, name);
1065 s->next = all_namespaces;
1066 s->namesp = current_namespace;
1067 all_namespaces = s;
1068 return s;
1069}
1070
1071
1072/* Find the symbol for namespace NAME. If not found, add a new symbol
1073 for NAME to all_namespaces. */
1074
1075struct sym *
1076find_namespace (name)
1077 char *name;
1078{
1079 struct sym *p;
1080
1081 for (p = all_namespaces; p; p = p->next)
1082 {
1083 if (streq (p->name, name))
1084 break;
1085 else
1086 {
1087 struct alias *p2;
1088 for (p2 = p->namesp_aliases; p2; p2 = p2->next)
1089 if (streq (p2->name, name))
1090 break;
1091 if (p2)
1092 break;
1093 }
1094 }
1095
1096 if (p == NULL)
1097 p = make_namespace (name);
1098
1099 return p;
1100}
1101
1102
1103/* Register the name NEW_NAME as an alias for namespace OLD_NAME. */
1104
1105void
1106register_namespace_alias (new_name, old_name)
1107 char *new_name, *old_name;
1108{
1109 struct sym *p = find_namespace (old_name);
1110 struct alias *al;
1111
1112 /* Is it already in the list of aliases? */
1113 for (al = p->namesp_aliases; al; al = al->next)
1114 if (streq (new_name, p->name))
1115 return;
1116
1117 al = (struct alias *) xmalloc (sizeof *al + strlen (new_name));
1118 strcpy (al->name, new_name);
1119 al->next = p->namesp_aliases;
1120 p->namesp_aliases = al;
1121}
1122
1123
1124/* Enter namespace with name NAME. */
1125
1126void
1127enter_namespace (name)
1128 char *name;
1129{
1130 struct sym *p = find_namespace (name);
1131
1132 if (namespace_sp == namespace_stack_size)
1133 {
1134 int size = max (10, 2 * namespace_stack_size);
1135 namespace_stack = (struct sym **) xrealloc (namespace_stack, size);
1136 namespace_stack_size = size;
1137 }
1138
1139 namespace_stack[namespace_sp++] = current_namespace;
1140 current_namespace = p;
1141}
1142
1143
1144/* Leave the current namespace. */
1145
1146void
1147leave_namespace ()
1148{
1149 assert (namespace_sp > 0);
1150 current_namespace = namespace_stack[--namespace_sp];
1151}
1152
1153
1154\f
1155/***********************************************************************
1156 Writing the Output File
1157 ***********************************************************************/
1158
1159/* Write string S to the output file FP in a Lisp-readable form.
1160 If S is null, write out `()'. */
1161
1162#define PUTSTR(s, fp) \
1163 do { \
1164 if (!s) \
1165 { \
1166 putc ('(', fp); \
1167 putc (')', fp); \
1168 putc (' ', fp); \
1169 } \
1170 else \
1171 { \
1172 putc ('"', fp); \
1173 fputs (s, fp); \
1174 putc ('"', fp); \
1175 putc (' ', fp); \
1176 } \
1177 } while (0)
1178
1179/* A dynamically allocated buffer for constructing a scope name. */
1180
1181char *scope_buffer;
1182int scope_buffer_size;
1183int scope_buffer_len;
1184
1185
1186/* Make sure scope_buffer has enough room to add LEN chars to it. */
1187
1188void
1189ensure_scope_buffer_room (len)
1190 int len;
1191{
1192 if (scope_buffer_len + len >= scope_buffer_size)
1193 {
1194 int new_size = max (2 * scope_buffer_size, scope_buffer_len + len);
1195 scope_buffer = (char *) xrealloc (new_size);
1196 scope_buffer_size = new_size;
1197 }
1198}
1199
1200
1201/* Recursively add the scope names of symbol P and the scopes of its
1202 namespaces to scope_buffer. Value is a pointer to the complete
1203 scope name constructed. */
1204
1205char *
1206sym_scope_1 (p)
1207 struct sym *p;
1208{
1209 int len;
1210
1211 if (p->namesp)
1212 sym_scope_1 (p->namesp);
1213
1214 if (*scope_buffer)
1215 {
1216 ensure_scope_buffer_room (3);
1217 strcat (scope_buffer, "::");
1218 scope_buffer_len += 2;
1219 }
1220
1221 len = strlen (p->name);
1222 ensure_scope_buffer_room (len + 1);
1223 strcat (scope_buffer, p->name);
1224 scope_buffer_len += len;
1225
1226 if (HAS_FLAG (p->flags, F_TEMPLATE))
1227 {
1228 ensure_scope_buffer_room (3);
1229 strcat (scope_buffer, "<>");
1230 scope_buffer_len += 2;
1231 }
1232
1233 return scope_buffer;
1234}
1235
1236
1237/* Return the scope of symbol P in printed representation, i.e.
1238 as it would appear in a C*+ source file. */
1239
1240char *
1241sym_scope (p)
1242 struct sym *p;
1243{
1244 if (!scope_buffer)
1245 {
1246 scope_buffer_size = 1024;
1247 scope_buffer = (char *) xmalloc (scope_buffer_size);
1248 }
1249
1250 *scope_buffer = '\0';
1251 scope_buffer_len = 0;
1252
1253 if (p->namesp)
1254 sym_scope_1 (p->namesp);
1255
1256 return scope_buffer;
1257}
1258
1259
1260/* Dump the list of members M to file FP. Value is the length of the
1261 list. */
1262
1263int
1264dump_members (fp, m)
1265 FILE *fp;
1266 struct member *m;
1267{
1268 int n;
1269
1270 putc ('(', fp);
1271
1272 for (n = 0; m; m = m->next, ++n)
1273 {
1274 fputs (MEMBER_STRUCT, fp);
1275 PUTSTR (m->name, fp);
1276 PUTSTR (NULL, fp); /* FIXME? scope for globals */
1277 fprintf (fp, "%u ", (unsigned) m->flags);
1278 PUTSTR (m->filename, fp);
1279 PUTSTR (m->regexp, fp);
1280 fprintf (fp, "%u ", (unsigned) m->pos);
1281 fprintf (fp, "%u ", (unsigned) m->vis);
1282 putc (' ', fp);
1283 PUTSTR (m->def_filename, fp);
1284 PUTSTR (m->def_regexp, fp);
1285 fprintf (fp, "%u", (unsigned) m->def_pos);
1286 putc (']', fp);
1287 putc ('\n', fp);
1288 }
1289
1290 putc (')', fp);
1291 putc ('\n', fp);
1292 return n;
1293}
1294
1295
1296/* Dump class ROOT to stream FP. */
1297
1298void
1299dump_sym (fp, root)
1300 FILE *fp;
1301 struct sym *root;
1302{
1303 fputs (CLASS_STRUCT, fp);
1304 PUTSTR (root->name, fp);
1305
1306 /* Print scope, if any. */
1307 if (root->namesp)
1308 PUTSTR (sym_scope (root), fp);
1309 else
1310 PUTSTR (NULL, fp);
1311
1312 /* Print flags. */
1313 fprintf (fp, "%u", root->flags);
1314 PUTSTR (root->filename, fp);
1315 PUTSTR (root->regexp, fp);
1316 fprintf (fp, "%u", (unsigned) root->pos);
1317 PUTSTR (root->sfilename, fp);
1318 putc (']', fp);
1319 putc ('\n', fp);
1320}
1321
1322
1323/* Dump class ROOT and its subclasses to file FP. Value is the
1324 number of classes written. */
1325
1326int
1327dump_tree (fp, root)
1328 FILE *fp;
1329 struct sym *root;
1330{
1331 struct link *lk;
1332 unsigned n = 0;
1333
1334 dump_sym (fp, root);
1335
1336 if (f_verbose)
1337 {
1338 putchar ('+');
1339 fflush (stdout);
1340 }
1341
1342 putc ('(', fp);
1343
1344 for (lk = root->subs; lk; lk = lk->next)
1345 {
1346 fputs (TREE_STRUCT, fp);
1347 n += dump_tree (fp, lk->sym);
1348 putc (']', fp);
1349 }
1350
1351 putc (')', fp);
1352
1353 dump_members (fp, root->vars);
1354 n += dump_members (fp, root->fns);
1355 dump_members (fp, root->static_vars);
1356 n += dump_members (fp, root->static_fns);
1357 n += dump_members (fp, root->friends);
1358 dump_members (fp, root->types);
1359
1360 /* Superclasses. */
1361 putc ('(', fp);
1362 putc (')', fp);
1363
1364 /* Mark slot. */
1365 putc ('(', fp);
1366 putc (')', fp);
1367
1368 putc ('\n', fp);
1369 return n;
1370}
1371
1372
1373/* Dump the entire class tree to file FP. */
1374
1375void
1376dump_roots (fp)
1377 FILE *fp;
1378{
1379 int i, n = 0;
1380 struct sym *r;
1381
1382 /* Output file header containing version string, command line
1383 options etc. */
1384 if (!f_append)
1385 {
1386 fputs (TREE_HEADER_STRUCT, fp);
1387 PUTSTR (EBROWSE_FILE_VERSION, fp);
1388
1389 putc ('\"', fp);
1390 if (!f_structs)
1391 fputs (" -s", fp);
1392 if (f_regexps)
1393 fputs (" -x", fp);
1394 putc ('\"', fp);
1395 fputs (" ()", fp);
1396 fputs (" ()", fp);
1397 putc (']', fp);
1398 }
1399
1400 /* Mark functions as virtual that are so because of functions
1401 declared virtual in base classes. */
1402 mark_inherited_virtual ();
1403
1404 /* Dump the roots of the graph. */
1405 for (i = 0; i < TABLE_SIZE; ++i)
1406 for (r = class_table[i]; r; r = r->next)
1407 if (!r->supers)
1408 {
1409 fputs (TREE_STRUCT, fp);
1410 n += dump_tree (fp, r);
1411 putc (']', fp);
1412 }
1413
1414 if (f_verbose)
1415 putchar ('\n');
1416}
1417
1418
1419\f
1420/***********************************************************************
1421 Scanner
1422 ***********************************************************************/
1423
1424#ifdef DEBUG
1425#define INCREMENT_LINENO \
1426do { \
1427 if (f_very_verbose) \
1428 { \
1429 ++yyline; \
1430 printf ("%d:\n", yyline); \
1431 } \
1432 else \
1433 ++yyline; \
1434} while (0)
1435#else
1436#define INCREMENT_LINENO ++yyline
1437#endif
1438
1439/* Define two macros for accessing the input buffer (current input
1440 file). GET(C) sets C to the next input character and advances the
1441 input pointer. UNGET retracts the input pointer. */
1442
1443#define GET(C) ((C) = *in++)
1444#define UNGET() (--in)
1445
1446
1447/* Process a preprocessor line. Value is the next character from the
1448 input buffer not consumed. */
1449
1450int
1451process_pp_line ()
1452{
1453 int in_comment = 0;
1454 int c;
1455 char *p = yytext;
1456
1457 /* Skip over white space. The `#' has been consumed already. */
1458 while (WHITEP (GET (c)))
1459 ;
1460
1461 /* Read the preprocessor command (if any). */
1462 while (IDENTP (c))
1463 {
1464 *p++ = c;
1465 GET (c);
1466 }
1467
1468 /* Is it a `define'? */
1469 *p = '\0';
1470
1471 if (*yytext && streq (yytext, "define"))
1472 {
1473 p = yytext;
1474 while (WHITEP (c))
1475 GET (c);
1476 while (IDENTP (c))
1477 {
1478 *p++ = c;
1479 GET (c);
1480 }
1481
1482 *p = '\0';
1483
1484 if (*yytext)
1485 {
1486 char *regexp = matching_regexp ();
1487 int pos = BUFFER_POS ();
1488 add_define (yytext, regexp, pos);
1489 }
1490 }
1491
1492 while (c && (c != '\n' || in_comment))
1493 {
1494 if (c == '\\')
1495 GET (c);
1496 else if (c == '/' && !in_comment)
1497 {
1498 if (GET (c) == '*')
1499 in_comment = 1;
1500 }
1501 else if (c == '*' && in_comment)
1502 {
1503 if (GET (c) == '/')
1504 in_comment = 0;
1505 }
1506
1507 if (c == '\n')
1508 INCREMENT_LINENO;
1509
1510 GET (c);
1511 }
1512
1513 return c;
1514}
1515
1516
1517/* Value is the next token from the input buffer. */
1518
1519int
1520yylex ()
1521{
1522 int c;
1523 char end_char;
1524 char *p;
1525
1526 for (;;)
1527 {
1528 while (WHITEP (GET (c)))
1529 ;
1530
1531 switch (c)
1532 {
1533 case '\n':
1534 INCREMENT_LINENO;
1535 break;
1536
1537 case '\r':
1538 break;
1539
1540 case 0:
1541 /* End of file. */
1542 return YYEOF;
1543
1544 case '\\':
1545 GET (c);
1546 break;
1547
1548 case '"':
1549 case '\'':
1550 /* String and character constants. */
1551 end_char = c;
1552 string_start = in;
1553 while (GET (c) && c != end_char)
1554 {
1555 switch (c)
1556 {
1557 case '\\':
1558 /* Escape sequences. */
1559 if (!GET (c))
1560 {
1561 if (end_char == '\'')
1562 yyerror ("EOF in character constant");
1563 else
1564 yyerror ("EOF in string constant");
1565 goto end_string;
1566 }
1567 else switch (c)
1568 {
1569 case '\n':
1570 case 'a':
1571 case 'b':
1572 case 'f':
1573 case 'n':
1574 case 'r':
1575 case 't':
1576 case 'v':
1577 break;
1578
1579 case 'x':
1580 {
1581 /* Hexadecimal escape sequence. */
1582 int i;
1583 for (i = 0; i < 2; ++i)
1584 {
1585 GET (c);
1586
1587 if (c >= '0' && c <= '7')
1588 ;
1589 else if (c >= 'a' && c <= 'f')
1590 ;
1591 else if (c >= 'A' && c <= 'F')
1592 ;
1593 else
1594 {
1595 UNGET ();
1596 break;
1597 }
1598 }
1599 }
1600 break;
1601
1602 case '0':
1603 {
1604 /* Octal escape sequence. */
1605 int i;
1606 for (i = 0; i < 3; ++i)
1607 {
1608 GET (c);
1609
1610 if (c >= '0' && c <= '7')
1611 ;
1612 else
1613 {
1614 UNGET ();
1615 break;
1616 }
1617 }
1618 }
1619 break;
1620
1621 default:
1622 break;
1623 }
1624 break;
1625
1626 case '\n':
1627 if (end_char == '\'')
1628 yyerror ("newline in character constant");
1629 else
1630 yyerror ("newline in string constant");
1631 INCREMENT_LINENO;
1632 goto end_string;
1633
1634 default:
1635 break;
1636 }
1637 }
1638
1639 end_string:
1640 return end_char == '\'' ? CCHAR : CSTRING;
1641
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':
1646 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
1647 case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
1648 case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
1649 case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_':
1650 {
1651 /* Identifier and keywords. */
1652 unsigned hash;
1653 struct kw *k;
1654
1655 p = yytext;
1656 *p++ = hash = c;
1657
1658 while (IDENTP (GET (*p)))
1659 {
1660 hash = (hash << 1) ^ *p++;
1661 if (p == yytext_end - 1)
1662 {
1663 int size = yytext_end - yytext;
1664 yytext = (char *) xrealloc (yytext, 2 * size);
1665 yytext_end = yytext + 2 * size;
1666 p = yytext + size - 1;
1667 }
1668 }
1669
1670 UNGET ();
1671 *p = 0;
1672
1673 for (k = keyword_table[hash % KEYWORD_TABLE_SIZE]; k; k = k->next)
1674 if (streq (k->name, yytext))
1675 return k->tk;
1676
1677 return IDENT;
1678 }
1679
1680 case '/':
1681 /* C and C++ comments, '/' and '/='. */
1682 switch (GET (c))
1683 {
1684 case '*':
1685 while (GET (c))
1686 {
1687 switch (c)
1688 {
1689 case '*':
1690 if (GET (c) == '/')
1691 goto comment_end;
1692 UNGET ();
1693 break;
1694 case '\\':
1695 GET (c);
1696 break;
1697 case '\n':
1698 INCREMENT_LINENO;
1699 break;
1700 }
1701 }
1702 comment_end:;
1703 break;
1704
1705 case '=':
1706 return DIVASGN;
1707
1708 case '/':
1709 while (GET (c) && c != '\n')
1710 ;
1711 INCREMENT_LINENO;
1712 break;
1713
1714 default:
1715 UNGET ();
1716 return '/';
1717 }
1718 break;
1719
1720 case '+':
1721 if (GET (c) == '+')
1722 return INC;
1723 else if (c == '=')
1724 return ADDASGN;
1725 UNGET ();
1726 return '+';
1727
1728 case '-':
1729 switch (GET (c))
1730 {
1731 case '-':
1732 return DEC;
1733 case '>':
1734 if (GET (c) == '*')
1735 return ARROWSTAR;
1736 UNGET ();
1737 return ARROW;
1738 case '=':
1739 return SUBASGN;
1740 }
1741 UNGET ();
1742 return '-';
1743
1744 case '*':
1745 if (GET (c) == '=')
1746 return MULASGN;
1747 UNGET ();
1748 return '*';
1749
1750 case '%':
1751 if (GET (c) == '=')
1752 return MODASGN;
1753 UNGET ();
1754 return '%';
1755
1756 case '|':
1757 if (GET (c) == '|')
1758 return LOR;
1759 else if (c == '=')
1760 return ORASGN;
1761 UNGET ();
1762 return '|';
1763
1764 case '&':
1765 if (GET (c) == '&')
1766 return LAND;
1767 else if (c == '=')
1768 return ANDASGN;
1769 UNGET ();
1770 return '&';
1771
1772 case '^':
1773 if (GET (c) == '=')
1774 return XORASGN;
1775 UNGET ();
1776 return '^';
1777
1778 case '.':
1779 if (GET (c) == '*')
1780 return POINTSTAR;
1781 else if (c == '.')
1782 {
1783 if (GET (c) != '.')
1784 yyerror ("invalid token '..' ('...' assumed)");
1785 UNGET ();
1786 return ELLIPSIS;
1787 }
1788 else if (!DIGITP (c))
1789 {
1790 UNGET ();
1791 return '.';
1792 }
1793 goto mantissa;
1794
1795 case ':':
1796 if (GET (c) == ':')
1797 return DCOLON;
1798 UNGET ();
1799 return ':';
1800
1801 case '=':
1802 if (GET (c) == '=')
1803 return EQ;
1804 UNGET ();
1805 return '=';
1806
1807 case '!':
1808 if (GET (c) == '=')
1809 return NE;
1810 UNGET ();
1811 return '!';
1812
1813 case '<':
1814 switch (GET (c))
1815 {
1816 case '=':
1817 return LE;
1818 case '<':
1819 if (GET (c) == '=')
1820 return LSHIFTASGN;
1821 UNGET ();
1822 return LSHIFT;
1823 }
1824 UNGET ();
1825 return '<';
1826
1827 case '>':
1828 switch (GET (c))
1829 {
1830 case '=':
1831 return GE;
1832 case '>':
1833 if (GET (c) == '=')
1834 return RSHIFTASGN;
1835 UNGET ();
1836 return RSHIFT;
1837 }
1838 UNGET ();
1839 return '>';
1840
1841 case '#':
1842 c = process_pp_line ();
1843 if (c == 0)
1844 return YYEOF;
1845 break;
1846
1847 case '(': case ')': case '[': case ']': case '{': case '}':
1848 case ';': case ',': case '?': case '~':
1849 return c;
1850
1851 case '0':
1852 yyival = 0;
1853
1854 if (GET (c) == 'x' || c == 'X')
1855 {
1856 while (GET (c))
1857 {
1858 if (DIGITP (c))
1859 yyival = yyival * 16 + c - '0';
1860 else if (c >= 'a' && c <= 'f')
1861 yyival = yyival * 16 + c - 'a' + 10;
1862 else if (c >= 'A' && c <= 'F')
1863 yyival = yyival * 16 + c - 'A' + 10;
1864 else
1865 break;
1866 }
1867
1868 goto int_suffixes;
1869 }
1870 else if (c == '.')
1871 goto mantissa;
1872
1873 while (c >= '0' && c <= '7')
1874 {
1875 yyival = (yyival << 3) + c - '0';
1876 GET (c);
1877 }
1878
1879 int_suffixes:
1880 /* Integer suffixes. */
1881 while (isalpha (c))
1882 GET (c);
1883 UNGET ();
1884 return CINT;
1885
1886 case '1': case '2': case '3': case '4': case '5': case '6':
1887 case '7': case '8': case '9':
1888 /* Integer or floating constant, part before '.'. */
1889 yyival = c - '0';
1890
1891 while (GET (c) && DIGITP (c))
1892 yyival = 10 * yyival + c - '0';
1893
1894 if (c != '.')
1895 goto int_suffixes;
1896
1897 mantissa:
1898 /* Digits following '.'. */
1899 while (DIGITP (c))
1900 GET (c);
1901
1902 /* Optional exponent. */
1903 if (c == 'E' || c == 'e')
1904 {
1905 if (GET (c) == '-' || c == '+')
1906 GET (c);
1907
1908 while (DIGITP (c))
1909 GET (c);
1910 }
1911
1912 /* Optional type suffixes. */
1913 while (isalpha (c))
1914 GET (c);
1915 UNGET ();
1916 return CFLOAT;
1917
1918 default:
1919 break;
1920 }
1921 }
1922}
1923
1924
1925/* Value is the string from the start of the line to the current
1926 position in the input buffer, or maybe a bit more if that string is
1927 shorter than min_regexp. */
1928
1929char *
1930matching_regexp ()
1931{
1932 char *p;
1933 char *s;
1934 char *t;
1935 static char *buffer, *end_buf;
1936
1937 if (!f_regexps)
1938 return NULL;
1939
1940 if (buffer == NULL)
1941 {
1942 buffer = (char *) xmalloc (max_regexp);
1943 end_buf = &buffer[max_regexp] - 1;
1944 }
1945
1946 /* Scan back to previous newline of buffer start. */
1947 for (p = in - 1; p > inbuffer && *p != '\n'; --p)
1948 ;
1949
1950 if (*p == '\n')
1951 {
1952 while (in - p < min_regexp && p > inbuffer)
1953 {
1954 /* Line probably not significant enough */
1955 for (--p; p >= inbuffer && *p != '\n'; --p)
1956 ;
1957 }
1958 if (*p == '\n')
1959 ++p;
1960 }
1961
1962 /* Copy from end to make sure significant portions are included.
1963 This implies that in the browser a regular expressing of the form
1964 `^.*{regexp}' has to be used. */
1965 for (s = end_buf - 1, t = in; s > buffer && t > p;)
1966 {
1967 *--s = *--t;
1968
1969 if (*s == '"')
1970 *--s = '\\';
1971 }
1972
1973 *(end_buf - 1) = '\0';
1974 return xstrdup (s);
1975}
1976
1977
1978/* Return a printable representation of token T. */
1979
1980char *
1981token_string (t)
1982 int t;
1983{
1984 static char b[3];
1985
1986 switch (t)
1987 {
1988 case CSTRING: return "string constant";
1989 case CCHAR: return "char constant";
1990 case CINT: return "int constant";
1991 case CFLOAT: return "floating constant";
1992 case ELLIPSIS: return "...";
1993 case LSHIFTASGN: return "<<=";
1994 case RSHIFTASGN: return ">>=";
1995 case ARROWSTAR: return "->*";
1996 case IDENT: return "identifier";
1997 case DIVASGN: return "/=";
1998 case INC: return "++";
1999 case ADDASGN: return "+=";
2000 case DEC: return "--";
2001 case ARROW: return "->";
2002 case SUBASGN: return "-=";
2003 case MULASGN: return "*=";
2004 case MODASGN: return "%=";
2005 case LOR: return "||";
2006 case ORASGN: return "|=";
2007 case LAND: return "&&";
2008 case ANDASGN: return "&=";
2009 case XORASGN: return "^=";
2010 case POINTSTAR: return ".*";
2011 case DCOLON: return "::";
2012 case EQ: return "==";
2013 case NE: return "!=";
2014 case LE: return "<=";
2015 case LSHIFT: return "<<";
2016 case GE: return ">=";
2017 case RSHIFT: return ">>";
2018 case ASM: return "asm";
2019 case AUTO: return "auto";
2020 case BREAK: return "break";
2021 case CASE: return "case";
2022 case CATCH: return "catch";
2023 case CHAR: return "char";
2024 case CLASS: return "class";
2025 case CONST: return "const";
2026 case CONTINUE: return "continue";
2027 case DEFAULT: return "default";
2028 case DELETE: return "delete";
2029 case DO: return "do";
2030 case DOUBLE: return "double";
2031 case ELSE: return "else";
2032 case ENUM: return "enum";
2033 case EXTERN: return "extern";
2034 case FLOAT: return "float";
2035 case FOR: return "for";
2036 case FRIEND: return "friend";
2037 case GOTO: return "goto";
2038 case IF: return "if";
2039 case T_INLINE: return "inline";
2040 case INT: return "int";
2041 case LONG: return "long";
2042 case NEW: return "new";
2043 case OPERATOR: return "operator";
2044 case PRIVATE: return "private";
2045 case PROTECTED: return "protected";
2046 case PUBLIC: return "public";
2047 case REGISTER: return "register";
2048 case RETURN: return "return";
2049 case SHORT: return "short";
2050 case SIGNED: return "signed";
2051 case SIZEOF: return "sizeof";
2052 case STATIC: return "static";
2053 case STRUCT: return "struct";
2054 case SWITCH: return "switch";
2055 case TEMPLATE: return "template";
2056 case THIS: return "this";
2057 case THROW: return "throw";
2058 case TRY: return "try";
2059 case TYPEDEF: return "typedef";
2060 case UNION: return "union";
2061 case UNSIGNED: return "unsigned";
2062 case VIRTUAL: return "virtual";
2063 case VOID: return "void";
2064 case VOLATILE: return "volatile";
2065 case WHILE: return "while";
2066 case YYEOF: return "EOF";
2067 }
2068
2069 assert (t < 255);
2070 b[0] = t;
2071 b[1] = '\0';
2072 return b;
2073}
2074
2075
2076/* Reinitialize the scanner for a new input file. */
2077
2078void
2079re_init_scanner ()
2080{
2081 in = inbuffer;
2082 yyline = 1;
2083
2084 if (yytext == NULL)
2085 {
2086 int size = 256;
2087 yytext = (char *) xmalloc (size * sizeof *yytext);
2088 yytext_end = yytext + size;
2089 }
2090}
2091
2092
2093/* Insert a keyword NAME with token value TK into the keyword hash
2094 table. */
2095
2096void
2097insert_keyword (name, tk)
2098 char *name;
2099 int tk;
2100{
2101 char *s;
2102 unsigned h = 0;
2103 struct kw *k = (struct kw *) xmalloc (sizeof *k);
2104
2105 for (s = name; *s; ++s)
2106 h = (h << 1) ^ *s;
2107
2108 h %= KEYWORD_TABLE_SIZE;
2109 k->name = name;
2110 k->tk = tk;
2111 k->next = keyword_table[h];
2112 keyword_table[h] = k;
2113}
2114
2115
2116/* Initialize the scanner for the first file. This sets up the
2117 character class vectors and fills the keyword hash table. */
2118
2119void
2120init_scanner ()
2121{
2122 int i;
2123
2124 /* Allocate the input buffer */
2125 inbuffer_size = READ_CHUNK_SIZE + 1;
2126 inbuffer = in = (char *) xmalloc (inbuffer_size);
2127 yyline = 1;
2128
2129 /* Set up character class vectors. */
2130 for (i = 0; i < sizeof is_ident; ++i)
2131 {
2132 if (i == '_' || isalnum (i))
2133 is_ident[i] = 1;
2134
2135 if (i >= '0' && i <= '9')
2136 is_digit[i] = 1;
2137
2138 if (i == ' ' || i == '\t' || i == '\f' || i == '\v')
2139 is_white[i] = 1;
2140 }
2141
2142 /* Fill keyword hash table. */
2143 insert_keyword ("and", LAND);
2144 insert_keyword ("and_eq", ANDASGN);
2145 insert_keyword ("asm", ASM);
2146 insert_keyword ("auto", AUTO);
2147 insert_keyword ("bitand", '&');
2148 insert_keyword ("bitor", '|');
2149 insert_keyword ("bool", BOOL);
2150 insert_keyword ("break", BREAK);
2151 insert_keyword ("case", CASE);
2152 insert_keyword ("catch", CATCH);
2153 insert_keyword ("char", CHAR);
2154 insert_keyword ("class", CLASS);
2155 insert_keyword ("compl", '~');
2156 insert_keyword ("const", CONST);
2157 insert_keyword ("const_cast", CONST_CAST);
2158 insert_keyword ("continue", CONTINUE);
2159 insert_keyword ("default", DEFAULT);
2160 insert_keyword ("delete", DELETE);
2161 insert_keyword ("do", DO);
2162 insert_keyword ("double", DOUBLE);
2163 insert_keyword ("dynamic_cast", DYNAMIC_CAST);
2164 insert_keyword ("else", ELSE);
2165 insert_keyword ("enum", ENUM);
2166 insert_keyword ("explicit", EXPLICIT);
2167 insert_keyword ("extern", EXTERN);
2168 insert_keyword ("false", FALSE);
2169 insert_keyword ("float", FLOAT);
2170 insert_keyword ("for", FOR);
2171 insert_keyword ("friend", FRIEND);
2172 insert_keyword ("goto", GOTO);
2173 insert_keyword ("if", IF);
2174 insert_keyword ("inline", T_INLINE);
2175 insert_keyword ("int", INT);
2176 insert_keyword ("long", LONG);
2177 insert_keyword ("mutable", MUTABLE);
2178 insert_keyword ("namespace", NAMESPACE);
2179 insert_keyword ("new", NEW);
2180 insert_keyword ("not", '!');
2181 insert_keyword ("not_eq", NE);
2182 insert_keyword ("operator", OPERATOR);
2183 insert_keyword ("or", LOR);
2184 insert_keyword ("or_eq", ORASGN);
2185 insert_keyword ("private", PRIVATE);
2186 insert_keyword ("protected", PROTECTED);
2187 insert_keyword ("public", PUBLIC);
2188 insert_keyword ("register", REGISTER);
2189 insert_keyword ("reinterpret_cast", REINTERPRET_CAST);
2190 insert_keyword ("return", RETURN);
2191 insert_keyword ("short", SHORT);
2192 insert_keyword ("signed", SIGNED);
2193 insert_keyword ("sizeof", SIZEOF);
2194 insert_keyword ("static", STATIC);
2195 insert_keyword ("static_cast", STATIC_CAST);
2196 insert_keyword ("struct", STRUCT);
2197 insert_keyword ("switch", SWITCH);
2198 insert_keyword ("template", TEMPLATE);
2199 insert_keyword ("this", THIS);
2200 insert_keyword ("throw", THROW);
2201 insert_keyword ("true", TRUE);
2202 insert_keyword ("try", TRY);
2203 insert_keyword ("typedef", TYPEDEF);
2204 insert_keyword ("typeid", TYPEID);
2205 insert_keyword ("typename", TYPENAME);
2206 insert_keyword ("union", UNION);
2207 insert_keyword ("unsigned", UNSIGNED);
2208 insert_keyword ("using", USING);
2209 insert_keyword ("virtual", VIRTUAL);
2210 insert_keyword ("void", VOID);
2211 insert_keyword ("volatile", VOLATILE);
2212 insert_keyword ("wchar_t", WCHAR);
2213 insert_keyword ("while", WHILE);
2214 insert_keyword ("xor", '^');
2215 insert_keyword ("xor_eq", XORASGN);
2216}
2217
2218
2219\f
2220/***********************************************************************
2221 Parser
2222 ***********************************************************************/
2223
2224/* Match the current lookahead token and set it to the next token. */
2225
2226#define MATCH() (tk = yylex ())
2227
2228/* Return the lookahead token. If current lookahead token is cleared,
2229 read a new token. */
2230
2231#define LA1 (tk == -1 ? (tk = yylex ()) : tk)
2232
2233/* Is the current lookahead equal to the token T? */
2234
2235#define LOOKING_AT(T) (tk == (T))
2236
2237/* Is the current lookahead one of T1 or T2? */
2238
2239#define LOOKING_AT2(T1, T2) (tk == (T1) || tk == (T2))
2240
2241/* Is the current lookahead one of T1, T2 or T3? */
2242
2243#define LOOKING_AT3(T1, T2, T3) (tk == (T1) || tk == (T2) || tk == (T3))
2244
2245/* Is the current lookahead one of T1...T4? */
2246
2247#define LOOKING_AT4(T1, T2, T3, T4) \
2248 (tk == (T1) || tk == (T2) || tk == (T3) || tk == (T4))
2249
2250/* Match token T if current lookahead is T. */
2251
2252#define MATCH_IF(T) if (LOOKING_AT (T)) MATCH (); else ((void) 0)
2253
2254/* Skip to matching token if current token is T. */
2255
2256#define SKIP_MATCHING_IF(T) \
2257 if (LOOKING_AT (T)) skip_matching (); else ((void) 0)
2258
2259
2260/* Skip forward until a given token TOKEN or YYEOF is seen and return
2261 the current lookahead token after skipping. */
2262
2263int
2264skip_to (token)
2265 int token;
2266{
2267 while (!LOOKING_AT2 (YYEOF, token))
2268 MATCH ();
2269 return tk;
2270}
2271
2272
2273/* Skip over pairs of tokens (parentheses, square brackets,
2274 angle brackets, curly brackets) matching the current lookahead. */
2275
2276void
2277skip_matching ()
2278{
2279 int open, close, n;
2280
2281 switch (open = LA1)
2282 {
2283 case '{':
2284 close = '}';
2285 break;
2286
2287 case '(':
2288 close = ')';
2289 break;
2290
2291 case '<':
2292 close = '>';
2293 break;
2294
2295 case '[':
2296 close = ']';
2297 break;
2298
2299 default:
2300 abort ();
2301 }
2302
2303 for (n = 0;;)
2304 {
2305 if (LOOKING_AT (open))
2306 ++n;
2307 else if (LOOKING_AT (close))
2308 --n;
2309 else if (LOOKING_AT (YYEOF))
2310 break;
2311
2312 MATCH ();
2313
2314 if (n == 0)
2315 break;
2316 }
2317}
2318
2319
2320/* Re-initialize the parser by resetting the lookahead token. */
2321
2322void
2323re_init_parser ()
2324{
2325 tk = -1;
2326}
2327
2328
2329/* Parse a parameter list, including the const-specifier,
2330 pure-specifier, and throw-list that may follow a parameter list.
2331 Return in FLAGS what was seen following the parameter list.
2332 Returns a hash code for the parameter types. This value is used to
2333 distinguish between overloaded functions. */
2334
2335unsigned
2336parm_list (flags)
2337 int *flags;
2338{
2339 unsigned hash = 0;
2340 int type_seen = 0;
2341
2342 while (!LOOKING_AT2 (YYEOF, ')'))
2343 {
2344 switch (LA1)
2345 {
2346 /* Skip over grouping parens or parameter lists in parameter
2347 declarations. */
2348 case '(':
2349 skip_matching ();
2350 break;
2351
2352 /* Next parameter. */
2353 case ',':
2354 MATCH ();
2355 type_seen = 0;
2356 break;
2357
2358 /* Ignore the scope part of types, if any. This is because
2359 some types need scopes when defined outside of a class body,
2360 and don't need them inside the class body. This means that
2361 we have to look for the last IDENT in a sequence of
2362 IDENT::IDENT::... */
2363 case IDENT:
2364 if (!type_seen)
2365 {
2366 char *s;
2367 unsigned ident_type_hash = 0;
2368
2369 parse_qualified_param_ident_or_type (&s);
2370 for (; *s; ++s)
2371 ident_type_hash = (ident_type_hash << 1) ^ *s;
2372 hash = (hash << 1) ^ ident_type_hash;
2373 type_seen = 1;
2374 }
2375 else
2376 MATCH ();
2377 break;
2378
2379 case VOID:
2380 /* This distinction is made to make `func (void)' equivalent
2381 to `func ()'. */
2382 type_seen = 1;
2383 MATCH ();
2384 if (!LOOKING_AT (')'))
2385 hash = (hash << 1) ^ VOID;
2386 break;
2387
2388 case BOOL: case CHAR: case CLASS: case CONST:
2389 case DOUBLE: case ENUM: case FLOAT: case INT:
2390 case LONG: case SHORT: case SIGNED: case STRUCT:
2391 case UNION: case UNSIGNED: case VOLATILE: case WCHAR:
2392 case ELLIPSIS:
2393 type_seen = 1;
2394 hash = (hash << 1) ^ LA1;
2395 MATCH ();
2396 break;
2397
2398 case '*': case '&': case '[': case ']':
2399 hash = (hash << 1) ^ LA1;
2400 MATCH ();
2401 break;
2402
2403 default:
2404 MATCH ();
2405 break;
2406 }
2407 }
2408
2409 if (LOOKING_AT (')'))
2410 {
2411 MATCH ();
2412
2413 if (LOOKING_AT (CONST))
2414 {
2415 /* We can overload the same function on `const' */
2416 hash = (hash << 1) ^ CONST;
2417 SET_FLAG (*flags, F_CONST);
2418 MATCH ();
2419 }
2420
2421 if (LOOKING_AT (THROW))
2422 {
2423 MATCH ();
2424 SKIP_MATCHING_IF ('(');
2425 SET_FLAG (*flags, F_THROW);
2426 }
2427
2428 if (LOOKING_AT ('='))
2429 {
2430 MATCH ();
2431 if (LOOKING_AT (CINT) && yyival == 0)
2432 {
2433 MATCH ();
2434 SET_FLAG (*flags, F_PURE);
2435 }
2436 }
2437 }
2438
2439 return hash;
2440}
2441
2442
2443/* Print position info to stdout. */
2444
2445void
2446print_info ()
2447{
2448 if (info_position >= 0 && BUFFER_POS () <= info_position)
2449 if (info_cls)
2450 printf ("(\"%s\" \"%s\" \"%s\" %d)\n",
2451 info_cls->name, sym_scope (info_cls),
2452 info_member->name, info_where);
2453}
2454
2455
2456/* Parse a member declaration within the class body of CLS. VIS is
2457 the access specifier for the member (private, protected,
2458 public). */
2459
2460void
2461member (cls, vis)
2462 struct sym *cls;
2463 int vis;
2464{
2465 char *id = NULL;
2466 int sc = SC_MEMBER;
2467 char *regexp = NULL;
2468 int pos;
2469 int is_constructor;
2470 int anonymous = 0;
2471 int flags = 0;
2472 int class_tag;
2473 int type_seen = 0;
2474 int paren_seen = 0;
2475 unsigned hash = 0;
2476 int tilde = 0;
2477
2478 while (!LOOKING_AT4 (';', '{', '}', YYEOF))
2479 {
2480 switch (LA1)
2481 {
2482 default:
2483 MATCH ();
2484 break;
2485
2486 /* A function or class may follow. */
2487 case TEMPLATE:
2488 MATCH();
2489 SET_FLAG (flags, F_TEMPLATE);
2490 /* Skip over template argument list */
2491 SKIP_MATCHING_IF ('<');
2492 break;
2493
2494 case EXPLICIT:
2495 SET_FLAG (flags, F_EXPLICIT);
2496 goto typeseen;
2497
2498 case MUTABLE:
2499 SET_FLAG (flags, F_MUTABLE);
2500 goto typeseen;
2501
2502 case T_INLINE:
2503 SET_FLAG (flags, F_INLINE);
2504 goto typeseen;
2505
2506 case VIRTUAL:
2507 SET_FLAG (flags, F_VIRTUAL);
2508 goto typeseen;
2509
2510 case '[':
2511 skip_matching ();
2512 break;
2513
2514 case ENUM:
2515 sc = SC_TYPE;
2516 goto typeseen;
2517
2518 case TYPEDEF:
2519 sc = SC_TYPE;
2520 goto typeseen;
2521
2522 case FRIEND:
2523 sc = SC_FRIEND;
2524 goto typeseen;
2525
2526 case STATIC:
2527 sc = SC_STATIC;
2528 goto typeseen;
2529
2530 case '~':
2531 tilde = 1;
2532 MATCH ();
2533 break;
2534
2535 case IDENT:
2536 /* Remember IDENTS seen so far. Among these will be the member
2537 name. */
2538 id = (char *) alloca (strlen (yytext) + 2);
2539 if (tilde)
2540 {
2541 *id = '~';
2542 strcpy (id + 1, yytext);
2543 }
2544 else
2545 strcpy (id, yytext);
2546 MATCH ();
2547 break;
2548
2549 case OPERATOR:
2550 id = operator_name (&sc);
2551 break;
2552
2553 case '(':
2554 /* Most probably the beginning of a parameter list. */
2555 MATCH ();
2556 paren_seen = 1;
2557
2558 if (id && cls)
2559 {
2560 if (!(is_constructor = streq (id, cls->name)))
2561 regexp = matching_regexp ();
2562 }
2563 else
2564 is_constructor = 0;
2565
2566 pos = BUFFER_POS ();
2567 hash = parm_list (&flags);
2568
2569 if (is_constructor)
2570 regexp = matching_regexp ();
2571
2572 if (id && cls != NULL)
2573 add_member_decl (cls, id, regexp, pos, hash, 0, sc, vis, flags);
2574
2575 while (!LOOKING_AT3 (';', '{', YYEOF))
2576 MATCH ();
2577
2578 if (LOOKING_AT ('{') && id && cls)
2579 add_member_defn (cls, id, regexp, pos, hash, 0, sc, flags);
2580
2581 id = NULL;
2582 sc = SC_MEMBER;
2583 break;
2584
2585 case STRUCT: case UNION: case CLASS:
2586 /* Nested class */
2587 class_tag = LA1;
2588 type_seen = 1;
2589 MATCH ();
2590 anonymous = 1;
2591
2592 /* More than one ident here to allow for MS-DOS specialties
2593 like `_export class' etc. The last IDENT seen counts
2594 as the class name. */
2595 while (!LOOKING_AT4 (YYEOF, ';', ':', '{'))
2596 {
2597 if (LOOKING_AT (IDENT))
2598 anonymous = 0;
2599 MATCH ();
2600 }
2601
2602 if (LOOKING_AT2 (':', '{'))
2603 class_definition (anonymous ? NULL : cls, class_tag, flags, 1);
2604 else
2605 skip_to (';');
2606 break;
2607
2608 case INT: case CHAR: case LONG: case UNSIGNED:
2609 case SIGNED: case CONST: case DOUBLE: case VOID:
2610 case SHORT: case VOLATILE: case BOOL: case WCHAR:
2611 case TYPENAME:
2612 typeseen:
2613 type_seen = 1;
2614 MATCH ();
2615 break;
2616 }
2617 }
2618
2619 if (LOOKING_AT (';'))
2620 {
2621 /* The end of a member variable, a friend declaration or an access
2622 declaration. We don't want to add friend classes as members. */
2623 if (id && sc != SC_FRIEND && cls)
2624 {
2625 regexp = matching_regexp ();
2626 pos = BUFFER_POS ();
2627
2628 if (cls != NULL)
2629 {
2630 if (type_seen || !paren_seen)
2631 add_member_decl (cls, id, regexp, pos, 0, 1, sc, vis, 0);
2632 else
2633 add_member_decl (cls, id, regexp, pos, hash, 0, sc, vis, 0);
2634 }
2635 }
2636
2637 MATCH ();
2638 print_info ();
2639 }
2640 else if (LOOKING_AT ('{'))
2641 {
2642 /* A named enum. */
2643 if (sc == SC_TYPE && id && cls)
2644 {
2645 regexp = matching_regexp ();
2646 pos = BUFFER_POS ();
2647
2648 if (cls != NULL)
2649 {
2650 add_member_decl (cls, id, regexp, pos, 0, 1, sc, vis, 0);
2651 add_member_defn (cls, id, regexp, pos, 0, 1, sc, 0);
2652 }
2653 }
2654
2655 skip_matching ();
2656 print_info ();
2657 }
2658}
2659
2660
2661/* Parse the body of class CLS. TAG is the tag of the class (struct,
2662 union, class). */
2663
2664void
2665class_body (cls, tag)
2666 struct sym *cls;
2667 int tag;
2668{
2669 int vis = tag == CLASS ? PRIVATE : PUBLIC;
2670 int temp;
2671
2672 while (!LOOKING_AT2 (YYEOF, '}'))
2673 {
2674 switch (LA1)
2675 {
2676 case PRIVATE: case PROTECTED: case PUBLIC:
2677 temp = LA1;
2678 MATCH ();
2679
2680 if (LOOKING_AT (':'))
2681 {
2682 vis = temp;
2683 MATCH ();
2684 }
2685 else
2686 {
2687 /* Probably conditional compilation for inheritance list.
2688 We don't known whether there comes more of this.
2689 This is only a crude fix that works most of the time. */
2690 do
2691 {
2692 MATCH ();
2693 }
2694 while (LOOKING_AT2 (IDENT, ',')
2695 || LOOKING_AT3 (PUBLIC, PROTECTED, PRIVATE));
2696 }
2697 break;
2698
2699 case TYPENAME:
2700 case USING:
2701 skip_to (';');
2702 break;
2703
2704 /* Try to synchronize */
2705 case CHAR: case CLASS: case CONST:
2706 case DOUBLE: case ENUM: case FLOAT: case INT:
2707 case LONG: case SHORT: case SIGNED: case STRUCT:
2708 case UNION: case UNSIGNED: case VOID: case VOLATILE:
2709 case TYPEDEF: case STATIC: case T_INLINE: case FRIEND:
2710 case VIRTUAL: case TEMPLATE: case IDENT: case '~':
2711 case BOOL: case WCHAR: case EXPLICIT: case MUTABLE:
2712 member (cls, vis);
2713 break;
2714
2715 default:
2716 MATCH ();
2717 break;
2718 }
2719 }
2720}
2721
2722
2723/* Parse a qualified identifier. Current lookahead is IDENT. A
2724 qualified ident has the form `X<..>::Y<...>::T<...>. Returns a
2725 symbol for that class. */
2726
2727struct sym *
2728parse_classname ()
2729{
2730 struct sym *last_class = NULL;
2731
2732 while (LOOKING_AT (IDENT))
2733 {
2734 last_class = add_sym (yytext, last_class);
2735 MATCH ();
2736
2737 if (LOOKING_AT ('<'))
2738 {
2739 skip_matching ();
2740 SET_FLAG (last_class->flags, F_TEMPLATE);
2741 }
2742
2743 if (!LOOKING_AT (DCOLON))
2744 break;
2745
2746 MATCH ();
2747 }
2748
2749 return last_class;
2750}
2751
2752
2753/* Parse an operator name. Add the `static' flag to *SC if an
2754 implicitly static operator has been parsed. Value is a pointer to
2755 a static buffer holding the constructed operator name string. */
2756
2757char *
2758operator_name (sc)
2759 int *sc;
2760{
2761 static int id_size = 0;
2762 static char *id = NULL;
2763 char *s;
2764 int len;
2765
2766 MATCH ();
2767
2768 if (LOOKING_AT2 (NEW, DELETE))
2769 {
2770 /* `new' and `delete' are implicitly static. */
2771 if (*sc != SC_FRIEND)
2772 *sc = SC_STATIC;
2773
2774 s = token_string (LA1);
2775 MATCH ();
2776
2777 len = strlen (s) + 10;
2778 if (len > id_size)
2779 {
2780 int new_size = max (len, 2 * id_size);
2781 id = (char *) xrealloc (id, new_size);
2782 id_size = new_size;
2783 }
2784 strcpy (id, s);
2785
2786 /* Vector new or delete? */
2787 if (LOOKING_AT ('['))
2788 {
2789 strcat (id, "[");
2790 MATCH ();
2791
2792 if (LOOKING_AT (']'))
2793 {
2794 strcat (id, "]");
2795 MATCH ();
2796 }
2797 }
2798 }
2799 else
2800 {
2801 int tokens_matched = 0;
2802
2803 len = 20;
2804 if (len > id_size)
2805 {
2806 int new_size = max (len, 2 * id_size);
2807 id = (char *) xrealloc (id, new_size);
2808 id_size = new_size;
2809 }
2810 strcpy (id, "operator");
2811
2812 /* Beware access declarations of the form "X::f;" Beware of
2813 `operator () ()'. Yet another difficulty is found in
2814 GCC 2.95's STL: `operator == __STL_NULL_TMPL_ARGS (...'. */
2815 while (!(LOOKING_AT ('(') && tokens_matched)
2816 && !LOOKING_AT2 (';', YYEOF))
2817 {
2818 s = token_string (LA1);
2819 len += strlen (s) + 2;
2820 if (len > id_size)
2821 {
2822 int new_size = max (len, 2 * id_size);
2823 id = (char *) xrealloc (id, new_size);
2824 id_size = new_size;
2825 }
2826
2827 if (*s != ')' && *s != ']')
2828 strcat (id, " ");
2829 strcat (id, s);
2830 MATCH ();
2831
2832 /* If this is a simple operator like `+', stop now. */
2833 if (!isalpha (*s) && *s != '(' && *s != '[')
2834 break;
2835
2836 ++tokens_matched;
2837 }
2838 }
2839
2840 return id;
2841}
2842
2843
2844/* This one consumes the last IDENT of a qualified member name like
2845 `X::Y::z'. This IDENT is returned in LAST_ID. Value if the
2846 symbol structure for the ident. */
2847
2848struct sym *
2849parse_qualified_ident_or_type (last_id)
2850 char **last_id;
2851{
2852 struct sym *cls = NULL;
2853 static char *id = NULL;
2854 static int id_size = 0;
2855
2856 while (LOOKING_AT (IDENT))
2857 {
2858 int len = strlen (yytext) + 1;
2859 if (len > id_size)
2860 {
2861 id = (char *) xrealloc (id, len);
2862 id_size = len;
2863 }
2864 strcpy (id, yytext);
2865 *last_id = id;
2866 MATCH ();
2867
2868 SKIP_MATCHING_IF ('<');
2869
2870 if (LOOKING_AT (DCOLON))
2871 {
2872 cls = add_sym (id, cls);
2873 *last_id = NULL;
2874 MATCH ();
2875 }
2876 else
2877 break;
2878 }
2879
2880 return cls;
2881}
2882
2883
2884/* This one consumes the last IDENT of a qualified member name like
2885 `X::Y::z'. This IDENT is returned in LAST_ID. Value if the
2886 symbol structure for the ident. */
2887
2888void
2889parse_qualified_param_ident_or_type (last_id)
2890 char **last_id;
2891{
2892 struct sym *cls = NULL;
2893 static char *id = NULL;
2894 static int id_size = 0;
2895
2896 while (LOOKING_AT (IDENT))
2897 {
2898 int len = strlen (yytext) + 1;
2899 if (len > id_size)
2900 {
2901 id = (char *) xrealloc (id, len);
2902 id_size = len;
2903 }
2904 strcpy (id, yytext);
2905 *last_id = id;
2906 MATCH ();
2907
2908 SKIP_MATCHING_IF ('<');
2909
2910 if (LOOKING_AT (DCOLON))
2911 {
2912 cls = add_sym (id, cls);
2913 *last_id = NULL;
2914 MATCH ();
2915 }
2916 else
2917 break;
2918 }
2919}
2920
2921
2922/* Parse a class definition.
2923
2924 CONTAINING is the class containing the class being parsed or null.
2925 This may also be null if NESTED != 0 if the containing class is
2926 anonymous. TAG is the tag of the class (struct, union, class).
2927 NESTED is non-zero if we are parsing a nested class.
2928
2929 Current lookahead is the class name. */
2930
2931void
2932class_definition (containing, tag, flags, nested)
2933 struct sym *containing;
2934 int tag;
2935 int flags;
2936 int nested;
2937{
be0dbdab
GM
2938 struct sym *current;
2939 struct sym *base_class;
2940
2941 /* Set CURRENT to null if no entry has to be made for the class
2942 parsed. This is the case for certain command line flag
2943 settings. */
2944 if ((tag != CLASS && !f_structs) || (nested && !f_nested_classes))
2945 current = NULL;
2946 else
2947 {
2948 current = add_sym (yytext, containing);
2949 current->pos = BUFFER_POS ();
2950 current->regexp = matching_regexp ();
2951 current->filename = filename;
2952 current->flags = flags;
2953 }
2954
2955 /* If at ':', base class list follows. */
2956 if (LOOKING_AT (':'))
2957 {
2958 int done = 0;
2959 MATCH ();
2960
2961 while (!done)
2962 {
8bef35f2 2963 switch (LA1)
be0dbdab
GM
2964 {
2965 case VIRTUAL: case PUBLIC: case PROTECTED: case PRIVATE:
2966 MATCH ();
2967 break;
2968
2969 case IDENT:
2970 base_class = parse_classname ();
2971 if (base_class && current && base_class != current)
2972 add_link (base_class, current);
2973 break;
2974
2975 /* The `,' between base classes or the end of the base
2976 class list. Add the previously found base class.
2977 It's done this way to skip over sequences of
2978 `A::B::C' until we reach the end.
2979
2980 FIXME: it is now possible to handle `class X : public B::X'
2981 because we have enough information. */
2982 case ',':
2983 MATCH ();
2984 break;
2985
2986 default:
2987 /* A syntax error, possibly due to preprocessor constructs
2988 like
2989
2990 #ifdef SOMETHING
2991 class A : public B
2992 #else
2993 class A : private B.
2994
2995 MATCH until we see something like `;' or `{'. */
2996 while (!LOOKING_AT3 (';', YYEOF, '{'))
2997 MATCH ();
2998 done = 1;
2999
3000 case '{':
3001 done = 1;
3002 break;
3003 }
3004 }
3005 }
3006
3007 /* Parse the class body if there is one. */
3008 if (LOOKING_AT ('{'))
3009 {
3010 if (tag != CLASS && !f_structs)
3011 skip_matching ();
3012 else
3013 {
3014 MATCH ();
3015 class_body (current, tag);
3016
3017 if (LOOKING_AT ('}'))
3018 {
3019 MATCH ();
3020 if (LOOKING_AT (';') && !nested)
3021 MATCH ();
3022 }
3023 }
3024 }
3025}
3026
3027
3028/* Parse a declaration. */
3029
3030void
8bef35f2 3031declaration (flags)
be0dbdab
GM
3032 int flags;
3033{
3034 char *id = NULL;
3035 struct sym *cls = NULL;
3036 char *regexp = NULL;
3037 int pos = 0;
3038 unsigned hash = 0;
3039 int is_constructor;
3040 int sc = 0;
3041
3042 while (!LOOKING_AT3 (';', '{', YYEOF))
3043 {
3044 switch (LA1)
3045 {
3046 default:
3047 MATCH ();
3048 break;
3049
3050 case '[':
3051 skip_matching ();
3052 break;
3053
3054 case ENUM:
3055 case TYPEDEF:
3056 sc = SC_TYPE;
3057 MATCH ();
3058 break;
3059
3060 case STATIC:
3061 sc = SC_STATIC;
3062 MATCH ();
3063 break;
3064
3065 case INT: case CHAR: case LONG: case UNSIGNED:
3066 case SIGNED: case CONST: case DOUBLE: case VOID:
3067 case SHORT: case VOLATILE: case BOOL: case WCHAR:
3068 MATCH ();
3069 break;
3070
3071 case CLASS: case STRUCT: case UNION:
3072 /* This is for the case `STARTWRAP class X : ...' or
3073 `declare (X, Y)\n class A : ...'. */
3074 if (id)
3075 return;
3076
3077 case '=':
3078 /* Assumed to be the start of an initialization in this context.
3079 Skip over everything up to ';'. */
3080 skip_to (';');
3081 break;
3082
3083 case OPERATOR:
3084 id = operator_name (&sc);
3085 break;
3086
3087 case T_INLINE:
3088 SET_FLAG (flags, F_INLINE);
3089 MATCH ();
3090 break;
3091
3092 case '~':
3093 MATCH ();
3094 if (LOOKING_AT (IDENT))
3095 {
3096 id = (char *) alloca (strlen (yytext) + 2);
3097 *id = '~';
3098 strcpy (id + 1, yytext);
3099 MATCH ();
3100 }
3101 break;
3102
3103 case IDENT:
3104 cls = parse_qualified_ident_or_type (&id);
3105 break;
3106
3107 case '(':
3108 /* Most probably the beginning of a parameter list. */
3109 if (cls)
3110 {
3111 MATCH ();
3112
3113 if (id && cls)
3114 {
3115 if (!(is_constructor = streq (id, cls->name)))
3116 regexp = matching_regexp ();
3117 }
3118 else
3119 is_constructor = 0;
3120
3121 pos = BUFFER_POS ();
3122 hash = parm_list (&flags);
3123
3124 if (is_constructor)
3125 regexp = matching_regexp ();
3126
3127 if (id && cls)
3128 add_member_defn (cls, id, regexp, pos, hash, 0,
3129 SC_UNKNOWN, flags);
3130 }
3131 else
3132 {
3133 /* This may be a C functions, but also a macro
3134 call of the form `declare (A, B)' --- such macros
3135 can be found in some class libraries. */
3136 MATCH ();
3137
3138 if (id)
3139 {
3140 regexp = matching_regexp ();
3141 pos = BUFFER_POS ();
3142 hash = parm_list (&flags);
3143 add_global_decl (id, regexp, pos, hash, 0, sc, flags);
3144 }
3145
3146 /* This is for the case that the function really is
3147 a macro with no `;' following it. If a CLASS directly
3148 follows, we would miss it otherwise. */
3149 if (LOOKING_AT3 (CLASS, STRUCT, UNION))
3150 return;
3151 }
3152
3153 while (!LOOKING_AT3 (';', '{', YYEOF))
3154 MATCH ();
3155
3156 if (!cls && id && LOOKING_AT ('{'))
3157 add_global_defn (id, regexp, pos, hash, 0, sc, flags);
3158 id = NULL;
3159 break;
3160 }
3161 }
3162
3163 if (LOOKING_AT (';'))
3164 {
3165 /* The end of a member variable or of an access declaration
3166 `X::f'. To distinguish between them we have to know whether
3167 type information has been seen. */
3168 if (id)
3169 {
3170 char *regexp = matching_regexp ();
3171 int pos = BUFFER_POS ();
3172
3173 if (cls)
3174 add_member_defn (cls, id, regexp, pos, 0, 1, SC_UNKNOWN, flags);
3175 else
3176 add_global_defn (id, regexp, pos, 0, 1, sc, flags);
3177 }
3178
3179 MATCH ();
3180 print_info ();
3181 }
3182 else if (LOOKING_AT ('{'))
3183 {
3184 if (sc == SC_TYPE && id)
3185 {
3186 /* A named enumeration. */
3187 regexp = matching_regexp ();
3188 pos = BUFFER_POS ();
3189 add_global_defn (id, regexp, pos, 0, 1, sc, flags);
3190 }
3191
3192 skip_matching ();
3193 print_info ();
3194 }
3195}
3196
3197
3198/* Parse a list of top-level declarations/definitions. START_FLAGS
3199 says in which context we are parsing. If it is F_EXTERNC, we are
3200 parsing in an `extern "C"' block. Value is 1 if EOF is reached, 0
3201 otherwise. */
3202
3203int
3204globals (start_flags)
3205 int start_flags;
3206{
3207 int anonymous;
3208 int class_tk;
3209 int flags = start_flags;
3210
3211 for (;;)
3212 {
3213 char *prev_in = in;
3214
3215 switch (LA1)
3216 {
3217 case NAMESPACE:
3218 {
3219 MATCH ();
3220
3221 if (LOOKING_AT (IDENT))
3222 {
3223 char *namespace_name
3224 = (char *) alloca (strlen (yytext) + 1);
3225 strcpy (namespace_name, yytext);
3226 MATCH ();
3227
3228 if (LOOKING_AT ('='))
3229 {
3230 if (skip_to (';') == ';')
3231 MATCH ();
3232 register_namespace_alias (namespace_name, yytext);
3233 }
3234 else if (LOOKING_AT ('{'))
3235 {
3236 MATCH ();
3237 enter_namespace (namespace_name);
3238 globals (0);
3239 leave_namespace ();
3240 MATCH_IF ('}');
3241 }
3242 }
3243 }
3244 break;
3245
3246 case EXTERN:
3247 MATCH ();
3248 if (LOOKING_AT (CSTRING) && *string_start == 'C'
3249 && *(string_start + 1) == '"')
3250 {
3251 /* This is `extern "C"'. */
3252 MATCH ();
3253
3254 if (LOOKING_AT ('{'))
3255 {
3256 MATCH ();
3257 globals (F_EXTERNC);
3258 MATCH_IF ('}');
3259 }
3260 else
3261 SET_FLAG (flags, F_EXTERNC);
3262 }
3263 break;
3264
3265 case TEMPLATE:
3266 MATCH ();
3267 SKIP_MATCHING_IF ('<');
3268 SET_FLAG (flags, F_TEMPLATE);
3269 break;
3270
3271 case CLASS: case STRUCT: case UNION:
3272 class_tk = LA1;
3273 MATCH ();
3274 anonymous = 1;
3275
3276 /* More than one ident here to allow for MS-DOS and OS/2
3277 specialties like `far', `_Export' etc. Some C++ libs
3278 have constructs like `_OS_DLLIMPORT(_OS_CLIENT)' in front
3279 of the class name. */
3280 while (!LOOKING_AT4 (YYEOF, ';', ':', '{'))
3281 {
3282 if (LOOKING_AT (IDENT))
3283 anonymous = 0;
3284 MATCH ();
3285 }
3286
3287 /* Don't add anonymous unions. */
3288 if (LOOKING_AT2 (':', '{') && !anonymous)
3289 class_definition (NULL, class_tk, flags, 0);
3290 else
3291 {
3292 if (skip_to (';') == ';')
3293 MATCH ();
3294 }
3295
3296 flags = start_flags;
3297 break;
3298
3299 case YYEOF:
3300 return 1;
3301
3302 case '}':
3303 return 0;
3304
3305 default:
8bef35f2 3306 declaration (flags);
be0dbdab
GM
3307 flags = start_flags;
3308 break;
3309 }
3310
3311 if (prev_in == in)
3312 yyerror ("parse error");
3313 }
3314}
3315
3316
3317/* Parse the current input file. */
3318
3319void
3320yyparse ()
3321{
3322 while (globals (0) == 0)
3323 MATCH_IF ('}');
3324}
3325
3326
3327\f
3328/***********************************************************************
3329 Main Program
3330 ***********************************************************************/
3331
3332/* Add the list of paths PATH_LIST to the current search path for
3333 input files. */
3334
3335void
3336add_search_path (path_list)
3337 char *path_list;
3338{
3339 while (*path_list)
3340 {
3341 char *start = path_list;
3342 struct search_path *p;
3343
3344 while (*path_list && *path_list != PATH_LIST_SEPARATOR)
3345 ++path_list;
3346
3347 p = (struct search_path *) xmalloc (sizeof *p);
3348 p->path = (char *) xmalloc (path_list - start + 1);
3349 memcpy (p->path, start, path_list - start);
3350 p->path[path_list - start] = '\0';
3351 p->next = NULL;
3352
3353 if (search_path_tail)
3354 {
3355 search_path_tail->next = p;
3356 search_path_tail = p;
3357 }
3358 else
3359 search_path = search_path_tail = p;
3360
3361 while (*path_list == PATH_LIST_SEPARATOR)
3362 ++path_list;
3363 }
3364}
3365
3366
3367/* Open FILE and return a file handle for it, or -1 if FILE cannot be
3368 opened. Try to find FILE in search_path first, then try the
3369 unchanged file name. */
3370
3371FILE *
3372open_file (file)
3373 char *file;
3374{
3375 FILE *fp = NULL;
3376 static char *buffer;
3377 static int buffer_size;
3378 struct search_path *path;
3379
3380 filename = xstrdup (file);
3381
3382 for (path = search_path; path && fp == NULL; path = path->next)
3383 {
3384 int len = strlen (path->path);
3385
3386 if (len + 1 >= buffer_size)
3387 {
3388 buffer_size = max (len + 1, 2 * buffer_size);
3389 buffer = (char *) xrealloc (buffer, buffer_size);
3390 }
3391
3392 strcpy (buffer, path->path);
3393 strcat (buffer, "/");
3394 strcat (buffer, file);
3395 fp = fopen (buffer, "r");
3396 }
3397
3398 /* Try the original file name. */
3399 if (fp == NULL)
3400 fp = fopen (file, "r");
3401
3402 if (fp == NULL)
3403 yyerror ("cannot open");
3404
3405 return fp;
3406}
3407
3408
3409/* Display usage information and exit program. */
3410
3411#define USAGE "\
3412Usage: ebrowse [options] {files}\n\
3413\n\
3414 -a, --append append output\n\
3415 -f, --files=FILES read input file names from FILE\n\
3416 -I, --search-path=LIST set search path for input files\n\
3417 -m, --min-regexp-length=N set minimum regexp length to N\n\
3418 -M, --max-regexp-length=N set maximum regexp length to N\n\
3419 -n, --no-nested-classes exclude nested classes\n\
3420 -o, --output-file=FILE set output file name to FILE\n\
3421 -p, --position-info print info about position in file\n\
3422 -s, --no-structs-or-unions don't record structs or unions\n\
3423 -v, --verbose be verbose\n\
3424 -V, --very-verbose be very verbose\n\
3425 -x, --no-regexps don't record regular expressions\n\
3426 --help display this help\n\
3427 --version display version info\n\
3428"
3429
3430void
3431usage (error)
3432 int error;
3433{
3434 puts (USAGE);
3435 exit (error ? 1 : 0);
3436}
3437
3438
3439/* Display version and copyright info. The VERSION macro is set
3440 from the Makefile and contains the Emacs version. */
3441
3442void
3443version ()
3444{
3445 printf ("ebrowse %s\n", VERSION);
3446 puts ("Copyright (C) 1992-1999, 2000 Free Software Foundation, Inc.");
3447 puts ("This program is distributed under the same terms as Emacs.");
3448 exit (0);
3449}
3450
3451
3452/* Parse one input file FILE, adding classes and members to the symbol
3453 table. */
3454
3455void
3456process_file (file)
3457 char *file;
3458{
3459 FILE *fp;
3460
3461 fp = open_file (file);
3462 if (fp)
3463 {
3464 int nread, nbytes;
3465
3466 /* Give a progress indication if needed. */
3467 if (f_very_verbose)
3468 {
3469 puts (filename);
3470 fflush (stdout);
3471 }
3472 else if (f_verbose)
3473 {
3474 putchar ('.');
3475 fflush (stdout);
3476 }
3477
3478 /* Read file to inbuffer. */
3479 for (nread = 0;;)
3480 {
3481 if (nread + READ_CHUNK_SIZE >= inbuffer_size)
3482 {
3483 inbuffer_size = nread + READ_CHUNK_SIZE + 1;
3484 inbuffer = (char *) xrealloc (inbuffer, inbuffer_size);
3485 }
3486
3487 nbytes = fread (inbuffer + nread, 1, READ_CHUNK_SIZE, fp);
3488 nread += nbytes;
3489 if (nbytes < READ_CHUNK_SIZE)
3490 break;
3491 }
3492 inbuffer[nread] = '\0';
3493
3494 /* Reinitialize scanner and parser for the new input file. */
3495 re_init_scanner ();
3496 re_init_parser ();
3497
3498 /* Parse it and close the file. */
3499 yyparse ();
3500 fclose (fp);
3501 }
3502}
3503
3504
3505/* Read a line from stream FP and return a pointer to a static buffer
3506 containing its contents without the terminating newline. Value
3507 is null when EOF is reached. */
3508
3509char *
3510read_line (fp)
3511 FILE *fp;
3512{
3513 static char *buffer;
3514 static int buffer_size;
3515 int i = 0, c;
3516
3517 while ((c = getc (fp)) != EOF && c != '\n')
3518 {
3519 if (i >= buffer_size)
3520 {
3521 buffer_size = max (100, buffer_size * 2);
3522 buffer = (char *) xrealloc (buffer, buffer_size);
3523 }
3524
3525 buffer[i++] = c;
3526 }
3527
3528 if (c == EOF && i == 0)
3529 return NULL;
3530
3531 if (i == buffer_size)
3532 {
3533 buffer_size = max (100, buffer_size * 2);
3534 buffer = (char *) xrealloc (buffer, buffer_size);
3535 }
3536
3537 buffer[i] = '\0';
3538 return buffer;
3539}
3540
3541
3542/* Main entry point. */
3543
3544int
3545main (argc, argv)
3546 int argc;
3547 char **argv;
3548{
3549 int i;
3550 int any_inputfiles = 0;
3551 static char *out_filename = DEFAULT_OUTFILE;
3552 static char **input_filenames = NULL;
3553 static int input_filenames_size = 0;
3554 static int n_input_files;
3555
3556 filename = "command line";
3557 yyout = stdout;
3558
3559 while ((i = getopt_long (argc, argv, "af:I:m:M:no:p:svVx",
3560 options, NULL)) != EOF)
3561 {
3562 switch (i)
3563 {
3564 /* Experimental. */
3565 case 'p':
3566 info_position = atoi (optarg);
3567 break;
3568
3569 case 'n':
3570 f_nested_classes = 0;
3571 break;
3572
3573 case 'x':
3574 f_regexps = 0;
3575 break;
3576
3577 /* Add the name of a file containing more input files. */
3578 case 'f':
3579 if (n_input_files == input_filenames_size)
3580 {
3581 input_filenames_size = max (10, 2 * input_filenames_size);
3582 input_filenames = (char **) xrealloc (input_filenames,
3583 input_filenames_size);
3584 }
3585 input_filenames[n_input_files++] = xstrdup (optarg);
3586 break;
3587
3588 /* Append new output to output file instead of truncating it. */
3589 case 'a':
3590 f_append = 1;
3591 break;
3592
3593 /* Include structs in the output */
3594 case 's':
3595 f_structs = 0;
3596 break;
3597
3598 /* Be verbose (give a progress indication). */
3599 case 'v':
3600 f_verbose = 1;
3601 break;
3602
3603 /* Be very verbose (print file names as they are processed). */
3604 case 'V':
3605 f_verbose = 1;
3606 f_very_verbose = 1;
3607 break;
3608
3609 /* Change the name of the output file. */
3610 case 'o':
3611 out_filename = optarg;
3612 break;
3613
3614 /* Set minimum length for regular expression strings
3615 when recorded in the output file. */
3616 case 'm':
3617 min_regexp = atoi (optarg);
3618 break;
3619
3620 /* Set maximum length for regular expression strings
3621 when recorded in the output file. */
3622 case 'M':
3623 max_regexp = atoi (optarg);
3624 break;
3625
3626 /* Add to search path. */
3627 case 'I':
3628 add_search_path (optarg);
3629 break;
3630
3631 /* Display help */
3632 case -2:
3633 usage (0);
3634 break;
3635
3636 case -3:
3637 version ();
3638 break;
3639 }
3640 }
3641
3642 /* Call init_scanner after command line flags have been processed to be
3643 able to add keywords depending on command line (not yet
3644 implemented). */
3645 init_scanner ();
3646 init_sym ();
3647
3648 /* Open output file */
3649 if (*out_filename)
3650 {
3651 yyout = fopen (out_filename, f_append ? "a" : "w");
3652 if (yyout == NULL)
3653 {
3654 yyerror ("cannot open output file `%s'", out_filename);
3655 exit (1);
3656 }
3657 }
3658
3659 /* Process input files specified on the command line. */
3660 while (optind < argc)
3661 {
3662 process_file (argv[optind++]);
3663 any_inputfiles = 1;
3664 }
3665
3666 /* Process files given on stdin if no files specified. */
3667 if (!any_inputfiles && n_input_files == 0)
3668 {
3669 char *file;
3670 while ((file = read_line (stdin)) != NULL)
3671 process_file (file);
3672 }
3673 else
3674 {
3675 /* Process files from `--files=FILE'. Every line in FILE names
3676 one input file to process. */
3677 for (i = 0; i < n_input_files; ++i)
3678 {
3679 FILE *fp = fopen (input_filenames[i], "r");
3680
3681 if (fp == NULL)
3682 yyerror ("cannot open input file `%s'", input_filenames[i]);
3683 else
3684 {
3685 char *file;
3686 while ((file = read_line (fp)) != NULL)
3687 process_file (file);
3688 fclose (fp);
3689 }
3690 }
3691 }
3692
3693 /* Write output file. */
3694 dump_roots (yyout);
3695
3696 /* Close output file. */
3697 if (yyout != stdout)
3698 fclose (yyout);
3699
3700 return 0;
3701}
3702
3703
3704/* ebrowse.c ends here. */