* ebrowse.c (parse_qualified_param_ident_or_type): Make it clear
[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
6c0668d9
PE
2955 assert (LOOKING_AT (IDENT));
2956
2957 do
be0dbdab
GM
2958 {
2959 int len = strlen (yytext) + 1;
2960 if (len > id_size)
2961 {
c43a1ff6 2962 id = (char *) xrealloc (id, len);
be0dbdab
GM
2963 id_size = len;
2964 }
2965 strcpy (id, yytext);
2966 *last_id = id;
2967 MATCH ();
2968
2969 SKIP_MATCHING_IF ('<');
2970
2971 if (LOOKING_AT (DCOLON))
2972 {
2973 cls = add_sym (id, cls);
2974 *last_id = NULL;
2975 MATCH ();
2976 }
2977 else
2978 break;
2979 }
6c0668d9 2980 while (LOOKING_AT (IDENT));
be0dbdab
GM
2981}
2982
2983
2984/* Parse a class definition.
2985
2986 CONTAINING is the class containing the class being parsed or null.
2987 This may also be null if NESTED != 0 if the containing class is
2988 anonymous. TAG is the tag of the class (struct, union, class).
2989 NESTED is non-zero if we are parsing a nested class.
2990
2991 Current lookahead is the class name. */
2992
b23b5a5b 2993static void
873fbd0b 2994class_definition (struct sym *containing, int tag, int flags, int nested)
be0dbdab 2995{
be0dbdab
GM
2996 struct sym *current;
2997 struct sym *base_class;
2998
2999 /* Set CURRENT to null if no entry has to be made for the class
3000 parsed. This is the case for certain command line flag
3001 settings. */
3002 if ((tag != CLASS && !f_structs) || (nested && !f_nested_classes))
3003 current = NULL;
177c0ea7 3004 else
be0dbdab
GM
3005 {
3006 current = add_sym (yytext, containing);
3007 current->pos = BUFFER_POS ();
3008 current->regexp = matching_regexp ();
3009 current->filename = filename;
3010 current->flags = flags;
3011 }
3012
3013 /* If at ':', base class list follows. */
3014 if (LOOKING_AT (':'))
3015 {
3016 int done = 0;
3017 MATCH ();
3018
3019 while (!done)
3020 {
8bef35f2 3021 switch (LA1)
be0dbdab 3022 {
177c0ea7 3023 case VIRTUAL: case PUBLIC: case PROTECTED: case PRIVATE:
be0dbdab
GM
3024 MATCH ();
3025 break;
3026
3027 case IDENT:
3028 base_class = parse_classname ();
3029 if (base_class && current && base_class != current)
3030 add_link (base_class, current);
3031 break;
3032
3033 /* The `,' between base classes or the end of the base
3034 class list. Add the previously found base class.
3035 It's done this way to skip over sequences of
3036 `A::B::C' until we reach the end.
3037
3038 FIXME: it is now possible to handle `class X : public B::X'
3039 because we have enough information. */
3040 case ',':
3041 MATCH ();
3042 break;
3043
3044 default:
3045 /* A syntax error, possibly due to preprocessor constructs
3046 like
3047
3048 #ifdef SOMETHING
3049 class A : public B
3050 #else
3051 class A : private B.
3052
3053 MATCH until we see something like `;' or `{'. */
3054 while (!LOOKING_AT3 (';', YYEOF, '{'))
3055 MATCH ();
3056 done = 1;
3057
3058 case '{':
3059 done = 1;
3060 break;
3061 }
3062 }
3063 }
3064
3065 /* Parse the class body if there is one. */
3066 if (LOOKING_AT ('{'))
3067 {
3068 if (tag != CLASS && !f_structs)
3069 skip_matching ();
3070 else
3071 {
3072 MATCH ();
3073 class_body (current, tag);
3074
3075 if (LOOKING_AT ('}'))
3076 {
3077 MATCH ();
3078 if (LOOKING_AT (';') && !nested)
3079 MATCH ();
3080 }
3081 }
3082 }
3083}
3084
fa8bc89d
GM
3085/* Add to class *CLS information for the declaration of variable or
3086 type *ID. If *CLS is null, this means a global declaration. SC is
3087 the storage class of *ID. FLAGS is a bit set giving additional
3088 information about the member (see the F_* defines). */
3089
b23b5a5b 3090static void
873fbd0b 3091add_declarator (struct sym **cls, char **id, int flags, int sc)
fa8bc89d
GM
3092{
3093 if (LOOKING_AT2 (';', ','))
3094 {
3095 /* The end of a member variable or of an access declaration
3096 `X::f'. To distinguish between them we have to know whether
3097 type information has been seen. */
3098 if (*id)
3099 {
3100 char *regexp = matching_regexp ();
3101 int pos = BUFFER_POS ();
3102
c901ceff 3103 if (*cls)
74974a34 3104 add_member_defn (*cls, *id, regexp, pos, 0, 1, SC_UNKNOWN, flags);
fa8bc89d
GM
3105 else
3106 add_global_defn (*id, regexp, pos, 0, 1, sc, flags);
3107 }
3108
3109 MATCH ();
3110 print_info ();
3111 }
3112 else if (LOOKING_AT ('{'))
3113 {
3114 if (sc == SC_TYPE && *id)
3115 {
3116 /* A named enumeration. */
3117 char *regexp = matching_regexp ();
3118 int pos = BUFFER_POS ();
3119 add_global_defn (*id, regexp, pos, 0, 1, sc, flags);
3120 }
3121
3122 skip_matching ();
3123 print_info ();
3124 }
3125
5c19cd0b 3126 free (*id);
fa8bc89d
GM
3127 *id = NULL;
3128 *cls = NULL;
3129}
be0dbdab
GM
3130
3131/* Parse a declaration. */
3132
b23b5a5b 3133static void
873fbd0b 3134declaration (int flags)
be0dbdab
GM
3135{
3136 char *id = NULL;
3137 struct sym *cls = NULL;
3138 char *regexp = NULL;
3139 int pos = 0;
3140 unsigned hash = 0;
3141 int is_constructor;
3142 int sc = 0;
3143
3144 while (!LOOKING_AT3 (';', '{', YYEOF))
3145 {
3146 switch (LA1)
3147 {
3148 default:
3149 MATCH ();
3150 break;
3151
3152 case '[':
3153 skip_matching ();
3154 break;
3155
3156 case ENUM:
3157 case TYPEDEF:
3158 sc = SC_TYPE;
3159 MATCH ();
3160 break;
69bfc389 3161
be0dbdab
GM
3162 case STATIC:
3163 sc = SC_STATIC;
3164 MATCH ();
3165 break;
3166
3167 case INT: case CHAR: case LONG: case UNSIGNED:
3168 case SIGNED: case CONST: case DOUBLE: case VOID:
3169 case SHORT: case VOLATILE: case BOOL: case WCHAR:
3170 MATCH ();
3171 break;
3172
3173 case CLASS: case STRUCT: case UNION:
3174 /* This is for the case `STARTWRAP class X : ...' or
3175 `declare (X, Y)\n class A : ...'. */
3176 if (id)
57b4c82e 3177 {
5c19cd0b 3178 free (id);
57b4c82e
GM
3179 return;
3180 }
be0dbdab
GM
3181
3182 case '=':
fa8bc89d
GM
3183 /* Assumed to be the start of an initialization in this
3184 context. */
3185 skip_initializer ();
be0dbdab
GM
3186 break;
3187
fa8bc89d
GM
3188 case ',':
3189 add_declarator (&cls, &id, flags, sc);
3190 break;
3191
be0dbdab 3192 case OPERATOR:
57b4c82e
GM
3193 {
3194 char *s = operator_name (&sc);
3195 id = (char *) xrealloc (id, strlen (s) + 1);
3196 strcpy (id, s);
3197 }
be0dbdab
GM
3198 break;
3199
3200 case T_INLINE:
3201 SET_FLAG (flags, F_INLINE);
3202 MATCH ();
3203 break;
3204
3205 case '~':
3206 MATCH ();
3207 if (LOOKING_AT (IDENT))
3208 {
57b4c82e 3209 id = (char *) xrealloc (id, strlen (yytext) + 2);
be0dbdab
GM
3210 *id = '~';
3211 strcpy (id + 1, yytext);
3212 MATCH ();
3213 }
3214 break;
3215
3216 case IDENT:
3217 cls = parse_qualified_ident_or_type (&id);
3218 break;
3219
3220 case '(':
3221 /* Most probably the beginning of a parameter list. */
3222 if (cls)
3223 {
3224 MATCH ();
3225
3226 if (id && cls)
3227 {
3228 if (!(is_constructor = streq (id, cls->name)))
3229 regexp = matching_regexp ();
3230 }
3231 else
3232 is_constructor = 0;
3233
3234 pos = BUFFER_POS ();
3235 hash = parm_list (&flags);
3236
3237 if (is_constructor)
3238 regexp = matching_regexp ();
3239
3240 if (id && cls)
3241 add_member_defn (cls, id, regexp, pos, hash, 0,
3242 SC_UNKNOWN, flags);
3243 }
3244 else
3245 {
3246 /* This may be a C functions, but also a macro
3247 call of the form `declare (A, B)' --- such macros
3248 can be found in some class libraries. */
3249 MATCH ();
3250
3251 if (id)
3252 {
3253 regexp = matching_regexp ();
3254 pos = BUFFER_POS ();
3255 hash = parm_list (&flags);
3256 add_global_decl (id, regexp, pos, hash, 0, sc, flags);
3257 }
3258
3259 /* This is for the case that the function really is
3260 a macro with no `;' following it. If a CLASS directly
3261 follows, we would miss it otherwise. */
3262 if (LOOKING_AT3 (CLASS, STRUCT, UNION))
3263 return;
3264 }
3265
3266 while (!LOOKING_AT3 (';', '{', YYEOF))
3267 MATCH ();
3268
3269 if (!cls && id && LOOKING_AT ('{'))
3270 add_global_defn (id, regexp, pos, hash, 0, sc, flags);
57b4c82e 3271
5c19cd0b 3272 free (id);
be0dbdab
GM
3273 id = NULL;
3274 break;
3275 }
3276 }
3277
fa8bc89d 3278 add_declarator (&cls, &id, flags, sc);
be0dbdab
GM
3279}
3280
3281
3282/* Parse a list of top-level declarations/definitions. START_FLAGS
3283 says in which context we are parsing. If it is F_EXTERNC, we are
3284 parsing in an `extern "C"' block. Value is 1 if EOF is reached, 0
3285 otherwise. */
3286
b23b5a5b 3287static int
873fbd0b 3288globals (int start_flags)
be0dbdab
GM
3289{
3290 int anonymous;
3291 int class_tk;
3292 int flags = start_flags;
3293
3294 for (;;)
3295 {
3296 char *prev_in = in;
69bfc389 3297
be0dbdab
GM
3298 switch (LA1)
3299 {
3300 case NAMESPACE:
3301 {
3302 MATCH ();
3303
3304 if (LOOKING_AT (IDENT))
3305 {
57b4c82e 3306 char *namespace_name = xstrdup (yytext);
be0dbdab 3307 MATCH ();
69bfc389 3308
be0dbdab
GM
3309 if (LOOKING_AT ('='))
3310 {
407094f4
GM
3311 struct link *qna = match_qualified_namespace_alias ();
3312 if (qna)
3313 register_namespace_alias (namespace_name, qna);
69bfc389 3314
be0dbdab
GM
3315 if (skip_to (';') == ';')
3316 MATCH ();
be0dbdab
GM
3317 }
3318 else if (LOOKING_AT ('{'))
3319 {
3320 MATCH ();
3321 enter_namespace (namespace_name);
3322 globals (0);
3323 leave_namespace ();
3324 MATCH_IF ('}');
3325 }
57b4c82e 3326
5c19cd0b 3327 free (namespace_name);
be0dbdab
GM
3328 }
3329 }
3330 break;
3331
3332 case EXTERN:
3333 MATCH ();
3334 if (LOOKING_AT (CSTRING) && *string_start == 'C'
3335 && *(string_start + 1) == '"')
3336 {
3337 /* This is `extern "C"'. */
3338 MATCH ();
69bfc389 3339
be0dbdab
GM
3340 if (LOOKING_AT ('{'))
3341 {
3342 MATCH ();
3343 globals (F_EXTERNC);
3344 MATCH_IF ('}');
3345 }
3346 else
3347 SET_FLAG (flags, F_EXTERNC);
3348 }
3349 break;
69bfc389 3350
be0dbdab
GM
3351 case TEMPLATE:
3352 MATCH ();
3353 SKIP_MATCHING_IF ('<');
3354 SET_FLAG (flags, F_TEMPLATE);
3355 break;
3356
3357 case CLASS: case STRUCT: case UNION:
3358 class_tk = LA1;
3359 MATCH ();
3360 anonymous = 1;
3361
3362 /* More than one ident here to allow for MS-DOS and OS/2
3363 specialties like `far', `_Export' etc. Some C++ libs
3364 have constructs like `_OS_DLLIMPORT(_OS_CLIENT)' in front
3365 of the class name. */
3366 while (!LOOKING_AT4 (YYEOF, ';', ':', '{'))
3367 {
3368 if (LOOKING_AT (IDENT))
3369 anonymous = 0;
3370 MATCH ();
3371 }
3372
3373 /* Don't add anonymous unions. */
3374 if (LOOKING_AT2 (':', '{') && !anonymous)
3375 class_definition (NULL, class_tk, flags, 0);
3376 else
3377 {
3378 if (skip_to (';') == ';')
3379 MATCH ();
3380 }
3381
3382 flags = start_flags;
3383 break;
3384
3385 case YYEOF:
3386 return 1;
3387
3388 case '}':
3389 return 0;
69bfc389 3390
be0dbdab 3391 default:
8bef35f2 3392 declaration (flags);
be0dbdab
GM
3393 flags = start_flags;
3394 break;
3395 }
3396
3397 if (prev_in == in)
e6a0814f 3398 yyerror ("parse error", NULL);
be0dbdab
GM
3399 }
3400}
3401
3402
3403/* Parse the current input file. */
3404
b23b5a5b 3405static void
873fbd0b 3406yyparse (void)
be0dbdab
GM
3407{
3408 while (globals (0) == 0)
3409 MATCH_IF ('}');
3410}
3411
3412
3413\f
3414/***********************************************************************
3415 Main Program
3416 ***********************************************************************/
3417
3418/* Add the list of paths PATH_LIST to the current search path for
3419 input files. */
3420
b23b5a5b 3421static void
873fbd0b 3422add_search_path (char *path_list)
be0dbdab
GM
3423{
3424 while (*path_list)
3425 {
3426 char *start = path_list;
3427 struct search_path *p;
69bfc389 3428
be0dbdab
GM
3429 while (*path_list && *path_list != PATH_LIST_SEPARATOR)
3430 ++path_list;
69bfc389 3431
c43a1ff6
GM
3432 p = (struct search_path *) xmalloc (sizeof *p);
3433 p->path = (char *) xmalloc (path_list - start + 1);
be0dbdab
GM
3434 memcpy (p->path, start, path_list - start);
3435 p->path[path_list - start] = '\0';
3436 p->next = NULL;
3437
3438 if (search_path_tail)
3439 {
3440 search_path_tail->next = p;
3441 search_path_tail = p;
3442 }
3443 else
3444 search_path = search_path_tail = p;
3445
3446 while (*path_list == PATH_LIST_SEPARATOR)
3447 ++path_list;
3448 }
3449}
3450
3451
3452/* Open FILE and return a file handle for it, or -1 if FILE cannot be
3453 opened. Try to find FILE in search_path first, then try the
3454 unchanged file name. */
3455
b23b5a5b 3456static FILE *
873fbd0b 3457open_file (char *file)
be0dbdab
GM
3458{
3459 FILE *fp = NULL;
3460 static char *buffer;
3461 static int buffer_size;
3462 struct search_path *path;
fd72561d 3463 int flen = strlen (file) + 1; /* +1 for the slash */
69bfc389 3464
be0dbdab
GM
3465 filename = xstrdup (file);
3466
3467 for (path = search_path; path && fp == NULL; path = path->next)
3468 {
fd72561d 3469 int len = strlen (path->path) + flen;
be0dbdab
GM
3470
3471 if (len + 1 >= buffer_size)
3472 {
3473 buffer_size = max (len + 1, 2 * buffer_size);
c43a1ff6 3474 buffer = (char *) xrealloc (buffer, buffer_size);
be0dbdab 3475 }
69bfc389 3476
be0dbdab
GM
3477 strcpy (buffer, path->path);
3478 strcat (buffer, "/");
3479 strcat (buffer, file);
3480 fp = fopen (buffer, "r");
3481 }
69bfc389 3482
be0dbdab
GM
3483 /* Try the original file name. */
3484 if (fp == NULL)
3485 fp = fopen (file, "r");
3486
3487 if (fp == NULL)
e6a0814f 3488 yyerror ("cannot open", NULL);
69bfc389 3489
be0dbdab
GM
3490 return fp;
3491}
3492
3493
3494/* Display usage information and exit program. */
3495
3496#define USAGE "\
3497Usage: ebrowse [options] {files}\n\
3498\n\
8e4b384e 3499 -a, --append append output to existing file\n\
be0dbdab
GM
3500 -f, --files=FILES read input file names from FILE\n\
3501 -I, --search-path=LIST set search path for input files\n\
3502 -m, --min-regexp-length=N set minimum regexp length to N\n\
3503 -M, --max-regexp-length=N set maximum regexp length to N\n\
3504 -n, --no-nested-classes exclude nested classes\n\
3505 -o, --output-file=FILE set output file name to FILE\n\
3506 -p, --position-info print info about position in file\n\
3507 -s, --no-structs-or-unions don't record structs or unions\n\
3508 -v, --verbose be verbose\n\
3509 -V, --very-verbose be very verbose\n\
3510 -x, --no-regexps don't record regular expressions\n\
3511 --help display this help\n\
3512 --version display version info\n\
3513"
3514
b23b5a5b 3515static void
873fbd0b 3516usage (int error)
be0dbdab
GM
3517{
3518 puts (USAGE);
65396510 3519 exit (error ? EXIT_FAILURE : EXIT_SUCCESS);
be0dbdab
GM
3520}
3521
3522
3523/* Display version and copyright info. The VERSION macro is set
16fab143 3524 from config.h and contains the Emacs version. */
be0dbdab 3525
2fe9a71c
AI
3526#ifndef VERSION
3527# define VERSION "21"
3528#endif
3529
b23b5a5b 3530static void
873fbd0b 3531version (void)
be0dbdab 3532{
969c3f66 3533 /* Makes it easier to update automatically. */
d7bfa7a1 3534 char emacs_copyright[] = "Copyright (C) 2011 Free Software Foundation, Inc.";
969c3f66 3535
be0dbdab 3536 printf ("ebrowse %s\n", VERSION);
969c3f66 3537 puts (emacs_copyright);
be0dbdab 3538 puts ("This program is distributed under the same terms as Emacs.");
65396510 3539 exit (EXIT_SUCCESS);
be0dbdab
GM
3540}
3541
3542
3543/* Parse one input file FILE, adding classes and members to the symbol
3544 table. */
3545
b23b5a5b 3546static void
873fbd0b 3547process_file (char *file)
be0dbdab
GM
3548{
3549 FILE *fp;
69bfc389 3550
be0dbdab
GM
3551 fp = open_file (file);
3552 if (fp)
69bfc389 3553 {
be0dbdab
GM
3554 int nread, nbytes;
3555
3556 /* Give a progress indication if needed. */
3557 if (f_very_verbose)
3558 {
3559 puts (filename);
3560 fflush (stdout);
3561 }
3562 else if (f_verbose)
3563 {
3564 putchar ('.');
3565 fflush (stdout);
3566 }
3567
3568 /* Read file to inbuffer. */
3569 for (nread = 0;;)
3570 {
3571 if (nread + READ_CHUNK_SIZE >= inbuffer_size)
3572 {
3573 inbuffer_size = nread + READ_CHUNK_SIZE + 1;
c43a1ff6 3574 inbuffer = (char *) xrealloc (inbuffer, inbuffer_size);
be0dbdab 3575 }
69bfc389 3576
be0dbdab 3577 nbytes = fread (inbuffer + nread, 1, READ_CHUNK_SIZE, fp);
fd72561d 3578 if (nbytes <= 0)
be0dbdab 3579 break;
fd72561d 3580 nread += nbytes;
be0dbdab 3581 }
fd72561d
EZ
3582 if (nread < 0)
3583 nread = 0;
be0dbdab
GM
3584 inbuffer[nread] = '\0';
3585
3586 /* Reinitialize scanner and parser for the new input file. */
3587 re_init_scanner ();
3588 re_init_parser ();
3589
3590 /* Parse it and close the file. */
3591 yyparse ();
3592 fclose (fp);
3593 }
3594}
3595
3596
3597/* Read a line from stream FP and return a pointer to a static buffer
3598 containing its contents without the terminating newline. Value
3599 is null when EOF is reached. */
3600
b23b5a5b 3601static char *
873fbd0b 3602read_line (FILE *fp)
be0dbdab
GM
3603{
3604 static char *buffer;
3605 static int buffer_size;
3606 int i = 0, c;
3607
3608 while ((c = getc (fp)) != EOF && c != '\n')
3609 {
3610 if (i >= buffer_size)
3611 {
3612 buffer_size = max (100, buffer_size * 2);
c43a1ff6 3613 buffer = (char *) xrealloc (buffer, buffer_size);
be0dbdab
GM
3614 }
3615
3616 buffer[i++] = c;
3617 }
69bfc389 3618
be0dbdab
GM
3619 if (c == EOF && i == 0)
3620 return NULL;
69bfc389 3621
be0dbdab
GM
3622 if (i == buffer_size)
3623 {
3624 buffer_size = max (100, buffer_size * 2);
c43a1ff6 3625 buffer = (char *) xrealloc (buffer, buffer_size);
be0dbdab
GM
3626 }
3627
3628 buffer[i] = '\0';
1727db8c
GM
3629 if (i > 0 && buffer[i - 1] == '\r')
3630 buffer[i - 1] = '\0';
be0dbdab
GM
3631 return buffer;
3632}
3633
3634
3635/* Main entry point. */
3636
3637int
873fbd0b 3638main (int argc, char **argv)
be0dbdab
GM
3639{
3640 int i;
3641 int any_inputfiles = 0;
988e88ab 3642 static const char *out_filename = DEFAULT_OUTFILE;
be0dbdab
GM
3643 static char **input_filenames = NULL;
3644 static int input_filenames_size = 0;
3645 static int n_input_files;
3646
3647 filename = "command line";
3648 yyout = stdout;
3649
3650 while ((i = getopt_long (argc, argv, "af:I:m:M:no:p:svVx",
3651 options, NULL)) != EOF)
3652 {
3653 switch (i)
3654 {
3655 /* Experimental. */
3656 case 'p':
3657 info_position = atoi (optarg);
3658 break;
69bfc389 3659
be0dbdab
GM
3660 case 'n':
3661 f_nested_classes = 0;
3662 break;
3663
3664 case 'x':
3665 f_regexps = 0;
3666 break;
69bfc389 3667
be0dbdab
GM
3668 /* Add the name of a file containing more input files. */
3669 case 'f':
3670 if (n_input_files == input_filenames_size)
3671 {
3672 input_filenames_size = max (10, 2 * input_filenames_size);
3a57e866 3673 input_filenames = (char **) xrealloc ((void *)input_filenames,
be0dbdab
GM
3674 input_filenames_size);
3675 }
3676 input_filenames[n_input_files++] = xstrdup (optarg);
3677 break;
3678
3679 /* Append new output to output file instead of truncating it. */
3680 case 'a':
3681 f_append = 1;
3682 break;
3683
3684 /* Include structs in the output */
3685 case 's':
3686 f_structs = 0;
3687 break;
3688
3689 /* Be verbose (give a progress indication). */
3690 case 'v':
3691 f_verbose = 1;
3692 break;
3693
3694 /* Be very verbose (print file names as they are processed). */
3695 case 'V':
3696 f_verbose = 1;
3697 f_very_verbose = 1;
3698 break;
3699
3700 /* Change the name of the output file. */
3701 case 'o':
3702 out_filename = optarg;
3703 break;
3704
3705 /* Set minimum length for regular expression strings
3706 when recorded in the output file. */
3707 case 'm':
3708 min_regexp = atoi (optarg);
3709 break;
3710
3711 /* Set maximum length for regular expression strings
3712 when recorded in the output file. */
3713 case 'M':
3714 max_regexp = atoi (optarg);
3715 break;
3716
3717 /* Add to search path. */
3718 case 'I':
3719 add_search_path (optarg);
3720 break;
3721
3722 /* Display help */
3723 case -2:
3724 usage (0);
3725 break;
3726
3727 case -3:
3728 version ();
3729 break;
3730 }
3731 }
3732
3733 /* Call init_scanner after command line flags have been processed to be
3734 able to add keywords depending on command line (not yet
3735 implemented). */
3736 init_scanner ();
3737 init_sym ();
3738
3739 /* Open output file */
3740 if (*out_filename)
3741 {
8e4b384e
GM
3742 if (f_append)
3743 {
3744 /* Check that the file to append to exists, and is not
3745 empty. More specifically, it should be a valid file
a10192f4 3746 produced by a previous run of ebrowse, but that's too
8e4b384e
GM
3747 difficult to check. */
3748 FILE *fp;
3749 int rc;
3750
3751 fp = fopen (out_filename, "r");
3752 if (fp == NULL)
0f29c66d
MY
3753 {
3754 yyerror ("file `%s' must exist for --append", out_filename);
3755 exit (EXIT_FAILURE);
3756 }
8e4b384e
GM
3757
3758 rc = fseek (fp, 0, SEEK_END);
3759 if (rc == -1)
0f29c66d
MY
3760 {
3761 yyerror ("error seeking in file `%s'", out_filename);
3762 exit (EXIT_FAILURE);
3763 }
8e4b384e
GM
3764
3765 rc = ftell (fp);
3766 if (rc == -1)
0f29c66d
MY
3767 {
3768 yyerror ("error getting size of file `%s'", out_filename);
3769 exit (EXIT_FAILURE);
3770 }
16fab143 3771
8e4b384e 3772 else if (rc == 0)
0f29c66d
MY
3773 {
3774 yyerror ("file `%s' is empty", out_filename);
3775 /* It may be ok to use an empty file for appending.
3776 exit (EXIT_FAILURE); */
3777 }
69bfc389 3778
8e4b384e
GM
3779 fclose (fp);
3780 }
69bfc389 3781
be0dbdab
GM
3782 yyout = fopen (out_filename, f_append ? "a" : "w");
3783 if (yyout == NULL)
3784 {
e6a0814f 3785 yyerror ("cannot open output file `%s'", out_filename);
65396510 3786 exit (EXIT_FAILURE);
be0dbdab
GM
3787 }
3788 }
3789
3790 /* Process input files specified on the command line. */
3791 while (optind < argc)
3792 {
3793 process_file (argv[optind++]);
3794 any_inputfiles = 1;
3795 }
3796
3797 /* Process files given on stdin if no files specified. */
3798 if (!any_inputfiles && n_input_files == 0)
3799 {
3800 char *file;
3801 while ((file = read_line (stdin)) != NULL)
3802 process_file (file);
3803 }
3804 else
3805 {
3806 /* Process files from `--files=FILE'. Every line in FILE names
3807 one input file to process. */
3808 for (i = 0; i < n_input_files; ++i)
3809 {
3810 FILE *fp = fopen (input_filenames[i], "r");
69bfc389 3811
be0dbdab 3812 if (fp == NULL)
e6a0814f 3813 yyerror ("cannot open input file `%s'", input_filenames[i]);
be0dbdab
GM
3814 else
3815 {
3816 char *file;
3817 while ((file = read_line (fp)) != NULL)
3818 process_file (file);
3819 fclose (fp);
3820 }
3821 }
3822 }
3823
3824 /* Write output file. */
3825 dump_roots (yyout);
3826
3827 /* Close output file. */
3828 if (yyout != stdout)
3829 fclose (yyout);
3830
65396510 3831 return EXIT_SUCCESS;
be0dbdab
GM
3832}
3833
65396510 3834/* ebrowse.c ends here */