1/* ebrowse.c --- parsing files for the ebrowse C++ browser
2
3   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
4                 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
5
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
10   the Free Software Foundation; either version 2, or (at your option)
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
19   along with GNU Emacs; see the file COPYING.  If not, write to the
20   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21   Boston, MA 02110-1301, USA.  */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include <stdio.h>
28
29#ifdef HAVE_STDLIB_H
30#include <stdlib.h>
31#endif
32
33#ifdef HAVE_STRING_H
34#include <string.h>
35#endif
36
37#include <ctype.h>
38#include <assert.h>
39#include "getopt.h"
40
41/* The SunOS compiler doesn't have SEEK_END.  */
42#ifndef SEEK_END
43#define SEEK_END 2
44#endif
45
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
71#if defined(__MSDOS__)
72#define PATH_LIST_SEPARATOR ';'
73#define FILENAME_EQ(X,Y)    (strcasecmp(X,Y) == 0)
74#else
75#if defined(WINDOWSNT)
76#define PATH_LIST_SEPARATOR ';'
77#define FILENAME_EQ(X,Y)    (stricmp(X,Y) == 0)
78#else
79#define PATH_LIST_SEPARATOR ':'
80#define FILENAME_EQ(X,Y)    (streq(X,Y))
81#endif
82#endif
83/* The default output file name.  */
84
85#define DEFAULT_OUTFILE "BROWSE"
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.  */
286  struct sym *namesp;		/* Namespace in which defined.  */
287  struct link *aliasee;		/* List of aliased namespaces (A::B::C...).  */
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. .  */
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
407/* If current lookahead is CSTRING, the following points to the
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
428/* Hash table for namespace aliases */
429
430struct alias *namespace_alias_table[TABLE_SIZE];
431
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 *));
495void *xmalloc P_ ((int));
496void xfree P_ ((void *));
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 *));
503void register_namespace_alias P_ ((char *, struct link *));
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 *));
520struct sym *make_namespace P_ ((char *, struct sym *));
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));
528void declaration P_ ((int));
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));
535void yyerror P_ ((char *, char *));
536void usage P_ ((int)) NO_RETURN;
537void version P_ (()) NO_RETURN;
538
539
540
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
549yyerror (format, s)
550     char *format, *s;
551{
552  fprintf (stderr, "%s:%d: ", filename, yyline);
553  fprintf (stderr, format, s);
554  putc ('\n', stderr);
555}
556
557
558/* Like malloc but print an error and exit if not enough memory is
559   available.  */
560
561void *
562xmalloc (nbytes)
563     int nbytes;
564{
565  void *p = malloc (nbytes);
566  if (p == NULL)
567    {
568      yyerror ("out of memory", NULL);
569      exit (EXIT_FAILURE);
570    }
571  return p;
572}
573
574
575/* Like realloc but print an error and exit if out of memory.  */
576
577void *
578xrealloc (p, sz)
579     void *p;
580     int sz;
581{
582  p = realloc (p, sz);
583  if (p == NULL)
584    {
585      yyerror ("out of memory", NULL);
586      exit (EXIT_FAILURE);
587    }
588  return p;
589}
590
591
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
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)
611    s = strcpy (xmalloc (strlen (s) + 1), s);
612  return s;
613}
614
615
616
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)
653    if (streq (name, sym->name)
654	&& ((!sym->namesp && !scope)
655	    || (sym->namesp && scope
656		&& streq (sym->namesp->name, scope->name))))
657      break;
658
659  if (sym == NULL)
660    {
661      if (f_very_verbose)
662	{
663	  putchar ('\t');
664	  puts (name);
665	}
666
667      sym = (struct sym *) xmalloc (sizeof *sym + strlen (name));
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    {
696      lnk = (struct link *) xmalloc (sizeof *lnk);
697      lnk2 = (struct link *) xmalloc (sizeof *lnk2);
698
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;
740
741    case SC_TYPE:
742      list = &cls->types;
743      break;
744
745    case SC_STATIC:
746      list = var ? &cls->static_vars : &cls->static_fns;
747      break;
748
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.  */
795  if (!cls->filename || !FILENAME_EQ (cls->filename, filename))
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
866  if (!FILENAME_EQ (cls->sfilename, filename))
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
940void
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
965	  || !FILENAME_EQ (global_symbols->filename, filename))
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{
993  struct member *m = (struct member *) xmalloc (sizeof *m + strlen (name));
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;
1020
1021    case SC_TYPE:
1022      list = &cls->types;
1023      break;
1024
1025    case SC_STATIC:
1026      list = var ? &cls->static_vars : &cls->static_fns;
1027      break;
1028
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 *
1102make_namespace (name, context)
1103     char *name;
1104     struct sym *context;
1105{
1106  struct sym *s = (struct sym *) xmalloc (sizeof *s + strlen (name));
1107  bzero (s, sizeof *s);
1108  strcpy (s->name, name);
1109  s->next = all_namespaces;
1110  s->namesp = context;
1111  all_namespaces = s;
1112  return s;
1113}
1114
1115
1116/* Find the symbol for namespace NAME.  If not found, retrun NULL */
1117
1118struct sym *
1119check_namespace (name, context)
1120     char *name;
1121     struct sym *context;
1122{
1123  struct sym *p = NULL;
1124
1125  for (p = all_namespaces; p; p = p->next)
1126    {
1127      if (streq (p->name, name) && (p->namesp == context))
1128	    break;
1129	}
1130
1131  return p;
1132    }
1133
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
1144  if (p == NULL)
1145    p = make_namespace (name, context);
1146
1147  return p;
1148}
1149
1150
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.  */
1177
1178void
1179register_namespace_alias (new_name, old_name)
1180     char *new_name;
1181     struct link *old_name;
1182{
1183  unsigned h;
1184  char *s;
1185  struct alias *al;
1186
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))
1195      return;
1196
1197  al = (struct alias *) xmalloc (sizeof *al + strlen (new_name));
1198  strcpy (al->name, new_name);
1199  al->next = namespace_alias_table[h];
1200  al->namesp = current_namespace;
1201  al->aliasee = old_name;
1202  namespace_alias_table[h] = al;
1203}
1204
1205
1206/* Enter namespace with name NAME.  */
1207
1208void
1209enter_namespace (name)
1210     char *name;
1211{
1212  struct sym *p = find_namespace (name, current_namespace);
1213
1214  if (namespace_sp == namespace_stack_size)
1215    {
1216      int size = max (10, 2 * namespace_stack_size);
1217      namespace_stack
1218	= (struct sym **) xrealloc ((void *)namespace_stack,
1219				    size * sizeof *namespace_stack);
1220      namespace_stack_size = size;
1221    }
1222
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
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);
1279      scope_buffer = (char *) xrealloc (scope_buffer, new_size);
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;
1294
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;
1309
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    }
1316
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;
1331      scope_buffer = (char *) xmalloc (scope_buffer_size);
1332    }
1333
1334  *scope_buffer = '\0';
1335  scope_buffer_len = 0;
1336
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);
1389
1390  /* Print scope, if any.  */
1391  if (root->namesp)
1392    PUTSTR (sym_scope (root), fp);
1393  else
1394    PUTSTR (NULL, fp);
1395
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
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{
1537  int in_comment = 0, in_string = 0;
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    }
1575
1576  while (c && (c != '\n' || in_comment || in_string))
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	}
1590      else if (c == '"')
1591	in_string = !in_string;
1592
1593      if (c == '\n')
1594	INCREMENT_LINENO;
1595
1596      GET (c);
1597    }
1598
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 == '\'')
1648                        yyerror ("EOF in character constant", NULL);
1649                      else
1650                        yyerror ("EOF in string constant", NULL);
1651                      goto end_string;
1652                    }
1653                  else switch (c)
1654                    {
1655                    case '\n':
1656		      INCREMENT_LINENO;
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 == '\'')
1715                    yyerror ("newline in character constant", NULL);
1716                  else
1717                    yyerror ("newline in string constant", NULL);
1718                  INCREMENT_LINENO;
1719                  break;
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;
1751		    yytext = (char *) xrealloc (yytext, 2 * size);
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) != '.')
1871                yyerror ("invalid token '..' ('...' assumed)", NULL);
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
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
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;
2028
2029  if (!f_regexps)
2030    return NULL;
2031
2032  if (matching_regexp_buffer == NULL)
2033    {
2034      matching_regexp_buffer = (char *) xmalloc (max_regexp);
2035      matching_regexp_end_buf = &matching_regexp_buffer[max_regexp] - 1;
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.  */
2057  for (s = matching_regexp_end_buf - 1, t = in;
2058       s > matching_regexp_buffer && t > p;)
2059    {
2060      *--s = *--t;
2061
2062      if (*s == '"' || *s == '\\')
2063        *--s = '\\';
2064    }
2065
2066  *(matching_regexp_end_buf - 1) = '\0';
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";
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";
2174    case YYEOF:                 return "EOF";
2175
2176    default:
2177      if (t < 255)
2178	{
2179	  b[0] = t;
2180	  b[1] = '\0';
2181	  return b;
2182	}
2183      else
2184	return "???";
2185    }
2186}
2187
2188
2189/* Reinitialize the scanner for a new input file.  */
2190
2191void
2192re_init_scanner ()
2193{
2194  in = inbuffer;
2195  yyline = 1;
2196
2197  if (yytext == NULL)
2198    {
2199      int size = 256;
2200      yytext = (char *) xmalloc (size * sizeof *yytext);
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;
2216  struct kw *k = (struct kw *) xmalloc (sizeof *k);
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;
2239  inbuffer = in = (char *) xmalloc (inbuffer_size);
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
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
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;
2398
2399    case '(':
2400      close = ')';
2401      break;
2402
2403    case '<':
2404      close = '>';
2405      break;
2406
2407    case '[':
2408      close = ']';
2409      break;
2410
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
2431void
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}
2455
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
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        {
2519	  /* Skip over grouping parens or parameter lists in parameter
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            {
2539	      char *last_id;
2540	      unsigned ident_type_hash = 0;
2541
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		}
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:
2569        case ELLIPSIS:
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 ();
2589
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;
2674
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:
2713	  /* Remember IDENTS seen so far.  Among these will be the member
2714	     name.  */
2715	  id = (char *) xrealloc (id, strlen (yytext) + 2);
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:
2727	  {
2728	    char *s = operator_name (&sc);
2729	    id = (char *) xrealloc (id, strlen (s) + 1);
2730	    strcpy (id, s);
2731	  }
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);
2761
2762	  xfree (id);
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 ();
2809
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        }
2818
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    }
2840
2841  xfree (id);
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;
2915
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        }
2926
2927      if (!LOOKING_AT (DCOLON))
2928        break;
2929
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;
2949
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 ();
2960
2961      len = strlen (s) + 10;
2962      if (len > id_size)
2963	{
2964	  int new_size = max (len, 2 * id_size);
2965	  id = (char *) xrealloc (id, new_size);
2966	  id_size = new_size;
2967	}
2968      strcpy (id, s);
2969
2970      /* Vector new or delete?  */
2971      if (LOOKING_AT ('['))
2972	{
2973	  strcat (id, "[");
2974	  MATCH ();
2975
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);
2991	  id = (char *) xrealloc (id, new_size);
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);
3007	      id = (char *) xrealloc (id, new_size);
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.  */
3017	  if (!isalpha ((unsigned char) *s) && *s != '(' && *s != '[')
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
3029   `X::Y::z'.  This IDENT is returned in LAST_ID.  Value is the
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;
3037  char *id = NULL;
3038  size_t id_size = 0;
3039  int enter = 0;
3040
3041  while (LOOKING_AT (IDENT))
3042    {
3043      int len = strlen (yytext) + 1;
3044      if (len > id_size)
3045	{
3046	  id = (char *) xrealloc (id, len);
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	{
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
3077	  *last_id = NULL;
3078	  xfree (id);
3079	  id = NULL;
3080	  id_size = 0;
3081	  MATCH ();
3082	}
3083      else
3084	break;
3085    }
3086
3087  while (enter--)
3088    leave_namespace();
3089
3090  return cls;
3091}
3092
3093
3094/* This one consumes the last IDENT of a qualified member name like
3095   `X::Y::z'.  This IDENT is returned in LAST_ID.  Value is the
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;
3105
3106  while (LOOKING_AT (IDENT))
3107    {
3108      int len = strlen (yytext) + 1;
3109      if (len > id_size)
3110	{
3111	  id = (char *) xrealloc (id, len);
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{
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;
3156  else
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        {
3173          switch (LA1)
3174            {
3175            case VIRTUAL: case PUBLIC: case PROTECTED: case PRIVATE:
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
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
3258          if (*cls)
3259	    add_member_defn (*cls, *id, regexp, pos, 0, 1, SC_UNKNOWN, flags);
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}
3285
3286/* Parse a declaration.  */
3287
3288void
3289declaration (flags)
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;
3317
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)
3333	    {
3334	      xfree (id);
3335	      return;
3336	    }
3337
3338        case '=':
3339          /* Assumed to be the start of an initialization in this
3340	     context.  */
3341	  skip_initializer ();
3342          break;
3343
3344	case ',':
3345	  add_declarator (&cls, &id, flags, sc);
3346	  break;
3347
3348        case OPERATOR:
3349	  {
3350	    char *s = operator_name (&sc);
3351	    id = (char *) xrealloc (id, strlen (s) + 1);
3352	    strcpy (id, s);
3353	  }
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	    {
3365	      id = (char *) xrealloc (id, strlen (yytext) + 2);
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);
3427
3428	  xfree (id);
3429          id = NULL;
3430          break;
3431        }
3432    }
3433
3434  add_declarator (&cls, &id, flags, sc);
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;
3454
3455      switch (LA1)
3456        {
3457        case NAMESPACE:
3458          {
3459            MATCH ();
3460
3461            if (LOOKING_AT (IDENT))
3462              {
3463                char *namespace_name = xstrdup (yytext);
3464                MATCH ();
3465
3466                if (LOOKING_AT ('='))
3467                  {
3468		    struct link *qna = match_qualified_namespace_alias ();
3469		    if (qna)
3470                      register_namespace_alias (namespace_name, qna);
3471
3472                    if (skip_to (';') == ';')
3473                      MATCH ();
3474                  }
3475                else if (LOOKING_AT ('{'))
3476                  {
3477                    MATCH ();
3478                    enter_namespace (namespace_name);
3479                    globals (0);
3480                    leave_namespace ();
3481                    MATCH_IF ('}');
3482                  }
3483
3484		xfree (namespace_name);
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 ();
3496
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;
3507
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;
3547
3548        default:
3549          declaration (flags);
3550          flags = start_flags;
3551          break;
3552        }
3553
3554      if (prev_in == in)
3555        yyerror ("parse error", NULL);
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
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;
3586
3587      while (*path_list && *path_list != PATH_LIST_SEPARATOR)
3588        ++path_list;
3589
3590      p = (struct search_path *) xmalloc (sizeof *p);
3591      p->path = (char *) xmalloc (path_list - start + 1);
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;
3622  int flen = strlen (file) + 1;	/* +1 for the slash */
3623
3624  filename = xstrdup (file);
3625
3626  for (path = search_path; path && fp == NULL; path = path->next)
3627    {
3628      int len = strlen (path->path) + flen;
3629
3630      if (len + 1 >= buffer_size)
3631	{
3632	  buffer_size = max (len + 1, 2 * buffer_size);
3633	  buffer = (char *) xrealloc (buffer, buffer_size);
3634	}
3635
3636      strcpy (buffer, path->path);
3637      strcat (buffer, "/");
3638      strcat (buffer, file);
3639      fp = fopen (buffer, "r");
3640    }
3641
3642  /* Try the original file name.  */
3643  if (fp == NULL)
3644     fp = fopen (file, "r");
3645
3646  if (fp == NULL)
3647    yyerror ("cannot open", NULL);
3648
3649  return fp;
3650}
3651
3652
3653/* Display usage information and exit program.  */
3654
3655#define USAGE "\
3656Usage: ebrowse [options] {files}\n\
3657\n\
3658  -a, --append                  append output to existing file\n\
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);
3679  exit (error ? EXIT_FAILURE : EXIT_SUCCESS);
3680}
3681
3682
3683/* Display version and copyright info.  The VERSION macro is set
3684   from the Makefile and contains the Emacs version.  */
3685
3686#ifndef VERSION
3687# define VERSION "21"
3688#endif
3689
3690void
3691version ()
3692{
3693  printf ("ebrowse %s\n", VERSION);
3694  puts ("Copyright (C) 1992-2007 Free Software Foundation, Inc.");
3695  puts ("This program is distributed under the same terms as Emacs.");
3696  exit (EXIT_SUCCESS);
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;
3708
3709  fp = open_file (file);
3710  if (fp)
3711    {
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;
3732	      inbuffer = (char *) xrealloc (inbuffer, inbuffer_size);
3733	    }
3734
3735	  nbytes = fread (inbuffer + nread, 1, READ_CHUNK_SIZE, fp);
3736	  if (nbytes <= 0)
3737	    break;
3738	  nread += nbytes;
3739	}
3740      if (nread < 0)
3741	nread = 0;
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);
3772	  buffer = (char *) xrealloc (buffer, buffer_size);
3773	}
3774
3775      buffer[i++] = c;
3776    }
3777
3778  if (c == EOF && i == 0)
3779    return NULL;
3780
3781  if (i == buffer_size)
3782    {
3783      buffer_size = max (100, buffer_size * 2);
3784      buffer = (char *) xrealloc (buffer, buffer_size);
3785    }
3786
3787  buffer[i] = '\0';
3788  if (i > 0 && buffer[i - 1] == '\r')
3789    buffer[i - 1] = '\0';
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;
3820
3821        case 'n':
3822          f_nested_classes = 0;
3823          break;
3824
3825        case 'x':
3826          f_regexps = 0;
3827          break;
3828
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);
3834	      input_filenames = (char **) xrealloc ((void *)input_filenames,
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    {
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
3907	     produced by a previous run of ebrowse, but that's too
3908	     difficult to check.  */
3909	  FILE *fp;
3910	  int rc;
3911
3912	  fp = fopen (out_filename, "r");
3913	  if (fp == NULL)
3914	    {
3915	      yyerror ("file `%s' must exist for --append", out_filename);
3916	      exit (EXIT_FAILURE);
3917	    }
3918
3919	  rc = fseek (fp, 0, SEEK_END);
3920	  if (rc == -1)
3921	    {
3922	      yyerror ("error seeking in file `%s'", out_filename);
3923	      exit (EXIT_FAILURE);
3924	    }
3925
3926	  rc = ftell (fp);
3927	  if (rc == -1)
3928	    {
3929	      yyerror ("error getting size of file `%s'", out_filename);
3930	      exit (EXIT_FAILURE);
3931	    }
3932
3933	  else if (rc == 0)
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	    }
3939
3940	  fclose (fp);
3941	}
3942
3943      yyout = fopen (out_filename, f_append ? "a" : "w");
3944      if (yyout == NULL)
3945	{
3946	  yyerror ("cannot open output file `%s'", out_filename);
3947	  exit (EXIT_FAILURE);
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");
3972
3973          if (fp == NULL)
3974            yyerror ("cannot open input file `%s'", input_filenames[i]);
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
3992  return EXIT_SUCCESS;
3993}
3994
3995/* arch-tag: fc03b4bc-91a9-4c3d-b3b9-12a77fa86dd8
3996   (do not change this comment) */
3997
3998/* ebrowse.c ends here */
3999