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