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