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