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