* ebrowse.c (insert_keyword): Rename parameter to avoid shadowing diagnostic.
[bpt/emacs.git] / lib-src / ebrowse.c
1 /* ebrowse.c --- parsing files for the ebrowse C++ browser
2
3 Copyright (C) 1992-2011 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19
20
21 #include <config.h>
22 #include <stdio.h>
23
24 #ifdef HAVE_STDLIB_H
25 #include <stdlib.h>
26 #endif
27
28 #include <string.h>
29 #include <ctype.h>
30 #include <assert.h>
31 #include <getopt.h>
32
33 /* The SunOS compiler doesn't have SEEK_END. */
34 #ifndef SEEK_END
35 #define SEEK_END 2
36 #endif
37
38 /* Conditionalize function prototypes. */
39
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
44 #include <min-max.h>
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
52 #if defined(__MSDOS__)
53 #define PATH_LIST_SEPARATOR ';'
54 #define FILENAME_EQ(X,Y) (strcasecmp(X,Y) == 0)
55 #else
56 #if defined(WINDOWSNT)
57 #define PATH_LIST_SEPARATOR ';'
58 #define FILENAME_EQ(X,Y) (stricmp(X,Y) == 0)
59 #else
60 #define PATH_LIST_SEPARATOR ':'
61 #define FILENAME_EQ(X,Y) (streq(X,Y))
62 #endif
63 #endif
64 /* The default output file name. */
65
66 #define DEFAULT_OUTFILE "BROWSE"
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
90 enum 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
198 enum 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
209 enum 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
236 struct 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. */
245 const char *filename; /* Don't free this shared string. */
246 int pos; /* Buffer position of occurrence. */
247 char *def_regexp; /* Regular expression matching definition. */
248 const char *def_filename; /* File name of definition. */
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
256 struct 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
264 struct alias
265 {
266 struct alias *next; /* Next in list. */
267 struct sym *namesp; /* Namespace in which defined. */
268 struct link *aliasee; /* List of aliased namespaces (A::B::C...). */
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
275 struct 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. */
290 const char *filename; /* File in which it can be found. */
291 const char *sfilename; /* File in which members can be found. */
292 struct sym *namesp; /* Namespace in which defined. . */
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
302 int info_where;
303 struct sym *info_cls = NULL;
304 struct 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
310 int info_position = -1;
311
312 /* Command line options structure for getopt_long. */
313
314 struct 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
335 unsigned yyival; /* Set for token CINT. */
336 char *yytext; /* Set for token IDENT. */
337 char *yytext_end;
338
339 /* Output file. */
340
341 FILE *yyout;
342
343 /* Current line number. */
344
345 int yyline;
346
347 /* The name of the current input file. */
348
349 const char *filename;
350
351 /* Three character class vectors, and macros to test membership
352 of characters. */
353
354 char is_ident[255];
355 char is_digit[255];
356 char 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
364 int f_append;
365 int f_verbose;
366 int f_very_verbose;
367 int f_structs = 1;
368 int f_regexps = 1;
369 int 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
375 int min_regexp = 5;
376 int max_regexp = 50;
377
378 /* Input buffer. */
379
380 char *inbuffer;
381 char *in;
382 int inbuffer_size;
383
384 /* Return the current buffer position in the input file. */
385
386 #define BUFFER_POS() (in - inbuffer)
387
388 /* If current lookahead is CSTRING, the following points to the
389 first character in the string constant. Used for recognizing
390 extern "C". */
391
392 char *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
401 struct 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
407 struct member *member_table[TABLE_SIZE];
408
409 /* Hash table for namespace aliases */
410
411 struct alias *namespace_alias_table[TABLE_SIZE];
412
413 /* The special class symbol used to hold global functions,
414 variables etc. */
415
416 struct sym *global_symbols;
417
418 /* The current namespace. */
419
420 struct sym *current_namespace;
421
422 /* The list of all known namespaces. */
423
424 struct sym *all_namespaces;
425
426 /* Stack of namespaces we're currently nested in, during the parse. */
427
428 struct sym **namespace_stack;
429 int namespace_stack_size;
430 int namespace_sp;
431
432 /* The current lookahead token. */
433
434 int tk = -1;
435
436 /* Structure describing a keyword. */
437
438 struct kw
439 {
440 const char *name; /* Spelling. */
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
448 struct kw *keyword_table[KEYWORD_TABLE_SIZE];
449
450 /* Search path. */
451
452 struct search_path
453 {
454 char *path;
455 struct search_path *next;
456 };
457
458 struct search_path *search_path;
459 struct search_path *search_path_tail;
460
461 /* Function prototypes. */
462
463 static char *matching_regexp (void);
464 static struct sym *add_sym (const char *, struct sym *);
465 static void add_global_defn (char *, char *, int, unsigned, int, int, int);
466 static void add_global_decl (char *, char *, int, unsigned, int, int, int);
467 static struct member *add_member (struct sym *, char *, int, int, unsigned);
468 static void class_definition (struct sym *, int, int, int);
469 static char *operator_name (int *);
470 static void parse_qualified_param_ident_or_type (char **);
471 static void usage (int) NO_RETURN;
472 static void version (void) NO_RETURN;
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
483 static void
484 yyerror (const char *format, const char *s)
485 {
486 fprintf (stderr, "%s:%d: ", filename, yyline);
487 fprintf (stderr, format, s);
488 putc ('\n', stderr);
489 }
490
491
492 /* Like malloc but print an error and exit if not enough memory is
493 available. */
494
495 static void *
496 xmalloc (int nbytes)
497 {
498 void *p = malloc (nbytes);
499 if (p == NULL)
500 {
501 yyerror ("out of memory", NULL);
502 exit (EXIT_FAILURE);
503 }
504 return p;
505 }
506
507
508 /* Like realloc but print an error and exit if out of memory. */
509
510 static void *
511 xrealloc (void *p, int sz)
512 {
513 p = realloc (p, sz);
514 if (p == NULL)
515 {
516 yyerror ("out of memory", NULL);
517 exit (EXIT_FAILURE);
518 }
519 return p;
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
526 static char *
527 xstrdup (char *s)
528 {
529 if (s)
530 s = strcpy (xmalloc (strlen (s) + 1), s);
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
543 static void
544 init_sym (void)
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
557 static struct sym *
558 add_sym (const char *name, struct sym *nested_in_class)
559 {
560 struct sym *sym;
561 unsigned h;
562 const char *s;
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)
570 if (streq (name, sym->name)
571 && ((!sym->namesp && !scope)
572 || (sym->namesp && scope
573 && streq (sym->namesp->name, scope->name))))
574 break;
575
576 if (sym == NULL)
577 {
578 if (f_very_verbose)
579 {
580 putchar ('\t');
581 puts (name);
582 }
583
584 sym = (struct sym *) xmalloc (sizeof *sym + strlen (name));
585 memset (sym, 0, sizeof *sym);
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
598 static void
599 add_link (struct sym *super, struct sym *sub)
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 {
612 lnk = (struct link *) xmalloc (sizeof *lnk);
613 lnk2 = (struct link *) xmalloc (sizeof *lnk2);
614
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
638 static struct member *
639 find_member (struct sym *cls, char *name, int var, int sc, unsigned int hash)
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;
652
653 case SC_TYPE:
654 list = &cls->types;
655 break;
656
657 case SC_STATIC:
658 list = var ? &cls->static_vars : &cls->static_fns;
659 break;
660
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
688 static void
689 add_member_decl (struct sym *cls, char *name, char *regexp, int pos, unsigned int hash, int var, int sc, int vis, int flags)
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. */
698 if (!cls->filename || !FILENAME_EQ (cls->filename, filename))
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
736 static void
737 add_member_defn (struct sym *cls, char *name, char *regexp, int pos, unsigned int hash, int var, int sc, int flags)
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
761 if (!FILENAME_EQ (cls->sfilename, filename))
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
778 static void
779 add_define (char *name, char *regexp, int pos)
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
796 static void
797 add_global_defn (char *name, char *regexp, int pos, unsigned int hash, int var, int sc, int flags)
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
827 static void
828 add_global_decl (char *name, char *regexp, int pos, unsigned int hash, int var, int sc, int flags)
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
846 || !FILENAME_EQ (global_symbols->filename, filename))
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
866 static struct member *
867 add_member (struct sym *cls, char *name, int var, int sc, unsigned int hash)
868 {
869 struct member *m = (struct member *) xmalloc (sizeof *m + strlen (name));
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;
896
897 case SC_TYPE:
898 list = &cls->types;
899 break;
900
901 case SC_STATIC:
902 list = var ? &cls->static_vars : &cls->static_fns;
903 break;
904
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
937 static void
938 mark_virtual (struct sym *r)
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
961 static void
962 mark_inherited_virtual (void)
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
976 static struct sym *
977 make_namespace (char *name, struct sym *context)
978 {
979 struct sym *s = (struct sym *) xmalloc (sizeof *s + strlen (name));
980 memset (s, 0, sizeof *s);
981 strcpy (s->name, name);
982 s->next = all_namespaces;
983 s->namesp = context;
984 all_namespaces = s;
985 return s;
986 }
987
988
989 /* Find the symbol for namespace NAME. If not found, retrun NULL */
990
991 static struct sym *
992 check_namespace (char *name, struct sym *context)
993 {
994 struct sym *p = NULL;
995
996 for (p = all_namespaces; p; p = p->next)
997 {
998 if (streq (p->name, name) && (p->namesp == context))
999 break;
1000 }
1001
1002 return p;
1003 }
1004
1005 /* Find the symbol for namespace NAME. If not found, add a new symbol
1006 for NAME to all_namespaces. */
1007
1008 static struct sym *
1009 find_namespace (char *name, struct sym *context)
1010 {
1011 struct sym *p = check_namespace (name, context);
1012
1013 if (p == NULL)
1014 p = make_namespace (name, context);
1015
1016 return p;
1017 }
1018
1019
1020 /* Find namespace alias with name NAME. If not found return NULL. */
1021
1022 static struct link *
1023 check_namespace_alias (char *name)
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. */
1045
1046 static void
1047 register_namespace_alias (char *new_name, struct link *old_name)
1048 {
1049 unsigned h;
1050 char *s;
1051 struct alias *al;
1052
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))
1061 return;
1062
1063 al = (struct alias *) xmalloc (sizeof *al + strlen (new_name));
1064 strcpy (al->name, new_name);
1065 al->next = namespace_alias_table[h];
1066 al->namesp = current_namespace;
1067 al->aliasee = old_name;
1068 namespace_alias_table[h] = al;
1069 }
1070
1071
1072 /* Enter namespace with name NAME. */
1073
1074 static void
1075 enter_namespace (char *name)
1076 {
1077 struct sym *p = find_namespace (name, current_namespace);
1078
1079 if (namespace_sp == namespace_stack_size)
1080 {
1081 int size = max (10, 2 * namespace_stack_size);
1082 namespace_stack
1083 = (struct sym **) xrealloc ((void *)namespace_stack,
1084 size * sizeof *namespace_stack);
1085 namespace_stack_size = size;
1086 }
1087
1088 namespace_stack[namespace_sp++] = current_namespace;
1089 current_namespace = p;
1090 }
1091
1092
1093 /* Leave the current namespace. */
1094
1095 static void
1096 leave_namespace (void)
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
1111 static inline void
1112 putstr (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 }
1128
1129 /* A dynamically allocated buffer for constructing a scope name. */
1130
1131 char *scope_buffer;
1132 int scope_buffer_size;
1133 int scope_buffer_len;
1134
1135
1136 /* Make sure scope_buffer has enough room to add LEN chars to it. */
1137
1138 static void
1139 ensure_scope_buffer_room (int len)
1140 {
1141 if (scope_buffer_len + len >= scope_buffer_size)
1142 {
1143 int new_size = max (2 * scope_buffer_size, scope_buffer_len + len);
1144 scope_buffer = (char *) xrealloc (scope_buffer, new_size);
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
1154 static char *
1155 sym_scope_1 (struct sym *p)
1156 {
1157 int len;
1158
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;
1173
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 }
1180
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
1188 static char *
1189 sym_scope (struct sym *p)
1190 {
1191 if (!scope_buffer)
1192 {
1193 scope_buffer_size = 1024;
1194 scope_buffer = (char *) xmalloc (scope_buffer_size);
1195 }
1196
1197 *scope_buffer = '\0';
1198 scope_buffer_len = 0;
1199
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
1210 static int
1211 dump_members (FILE *fp, struct member *m)
1212 {
1213 int n;
1214
1215 putc ('(', fp);
1216
1217 for (n = 0; m; m = m->next, ++n)
1218 {
1219 fputs (MEMBER_STRUCT, fp);
1220 putstr (m->name, fp);
1221 putstr (NULL, fp); /* FIXME? scope for globals */
1222 fprintf (fp, "%u ", (unsigned) m->flags);
1223 putstr (m->filename, fp);
1224 putstr (m->regexp, fp);
1225 fprintf (fp, "%u ", (unsigned) m->pos);
1226 fprintf (fp, "%u ", (unsigned) m->vis);
1227 putc (' ', fp);
1228 putstr (m->def_filename, fp);
1229 putstr (m->def_regexp, fp);
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
1243 static void
1244 dump_sym (FILE *fp, struct sym *root)
1245 {
1246 fputs (CLASS_STRUCT, fp);
1247 putstr (root->name, fp);
1248
1249 /* Print scope, if any. */
1250 if (root->namesp)
1251 putstr (sym_scope (root), fp);
1252 else
1253 putstr (NULL, fp);
1254
1255 /* Print flags. */
1256 fprintf (fp, "%u", root->flags);
1257 putstr (root->filename, fp);
1258 putstr (root->regexp, fp);
1259 fprintf (fp, "%u", (unsigned) root->pos);
1260 putstr (root->sfilename, fp);
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
1269 static int
1270 dump_tree (FILE *fp, struct sym *root)
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
1316 static void
1317 dump_roots (FILE *fp)
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);
1327 putstr (EBROWSE_FILE_VERSION, fp);
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 \
1366 do { \
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
1390 static int
1391 process_pp_line (void)
1392 {
1393 int in_comment = 0, in_string = 0;
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 }
1431
1432 while (c && (c != '\n' || in_comment || in_string))
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 }
1446 else if (c == '"')
1447 in_string = !in_string;
1448
1449 if (c == '\n')
1450 INCREMENT_LINENO;
1451
1452 GET (c);
1453 }
1454
1455 return c;
1456 }
1457
1458
1459 /* Value is the next token from the input buffer. */
1460
1461 static int
1462 yylex (void)
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 == '\'')
1504 yyerror ("EOF in character constant", NULL);
1505 else
1506 yyerror ("EOF in string constant", NULL);
1507 goto end_string;
1508 }
1509 else switch (c)
1510 {
1511 case '\n':
1512 INCREMENT_LINENO;
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 == '\'')
1571 yyerror ("newline in character constant", NULL);
1572 else
1573 yyerror ("newline in string constant", NULL);
1574 INCREMENT_LINENO;
1575 break;
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;
1607 yytext = (char *) xrealloc (yytext, 2 * size);
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 ;
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
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) != '.')
1732 yyerror ("invalid token '..' ('...' assumed)", NULL);
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
1873 /* Actually local to matching_regexp. These variables must be in
1874 global scope for the case that `static' get's defined away. */
1875
1876 static char *matching_regexp_buffer, *matching_regexp_end_buf;
1877
1878
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
1883 static char *
1884 matching_regexp (void)
1885 {
1886 char *p;
1887 char *s;
1888 char *t;
1889
1890 if (!f_regexps)
1891 return NULL;
1892
1893 if (matching_regexp_buffer == NULL)
1894 {
1895 matching_regexp_buffer = (char *) xmalloc (max_regexp);
1896 matching_regexp_end_buf = &matching_regexp_buffer[max_regexp] - 1;
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 */
1908 for (--p; p > inbuffer && *p != '\n'; --p)
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. */
1918 for (s = matching_regexp_end_buf - 1, t = in;
1919 s > matching_regexp_buffer && t > p;)
1920 {
1921 *--s = *--t;
1922
1923 if (*s == '"' || *s == '\\')
1924 *--s = '\\';
1925 }
1926
1927 *(matching_regexp_end_buf - 1) = '\0';
1928 return xstrdup (s);
1929 }
1930
1931
1932 /* Return a printable representation of token T. */
1933
1934 static const char *
1935 token_string (int t)
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";
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";
2034 case YYEOF: return "EOF";
2035
2036 default:
2037 if (t < 255)
2038 {
2039 b[0] = t;
2040 b[1] = '\0';
2041 return b;
2042 }
2043 else
2044 return "???";
2045 }
2046 }
2047
2048
2049 /* Reinitialize the scanner for a new input file. */
2050
2051 static void
2052 re_init_scanner (void)
2053 {
2054 in = inbuffer;
2055 yyline = 1;
2056
2057 if (yytext == NULL)
2058 {
2059 int size = 256;
2060 yytext = (char *) xmalloc (size * sizeof *yytext);
2061 yytext_end = yytext + size;
2062 }
2063 }
2064
2065
2066 /* Insert a keyword NAME with token value TKV into the keyword hash
2067 table. */
2068
2069 static void
2070 insert_keyword (const char *name, int tkv)
2071 {
2072 const char *s;
2073 unsigned h = 0;
2074 struct kw *k = (struct kw *) xmalloc (sizeof *k);
2075
2076 for (s = name; *s; ++s)
2077 h = (h << 1) ^ *s;
2078
2079 h %= KEYWORD_TABLE_SIZE;
2080 k->name = name;
2081 k->tk = tkv;
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
2090 static void
2091 init_scanner (void)
2092 {
2093 int i;
2094
2095 /* Allocate the input buffer */
2096 inbuffer_size = READ_CHUNK_SIZE + 1;
2097 inbuffer = in = (char *) xmalloc (inbuffer_size);
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
2234 static int
2235 skip_to (int token)
2236 {
2237 while (!LOOKING_AT2 (YYEOF, token))
2238 MATCH ();
2239 return tk;
2240 }
2241
2242 /* Skip over pairs of tokens (parentheses, square brackets,
2243 angle brackets, curly brackets) matching the current lookahead. */
2244
2245 static void
2246 skip_matching (void)
2247 {
2248 int open, close, n;
2249
2250 switch (open = LA1)
2251 {
2252 case '{':
2253 close = '}';
2254 break;
2255
2256 case '(':
2257 close = ')';
2258 break;
2259
2260 case '<':
2261 close = '>';
2262 break;
2263
2264 case '[':
2265 close = ']';
2266 break;
2267
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
2288 static void
2289 skip_initializer (void)
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 }
2312
2313 /* Build qualified namespace alias (A::B::c) and return it. */
2314
2315 static struct link *
2316 match_qualified_namespace_alias (void)
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);
2329 tmp->sym = find_namespace (yytext, cur ? cur->sym : NULL);
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
2350 /* Re-initialize the parser by resetting the lookahead token. */
2351
2352 static void
2353 re_init_parser (void)
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
2365 static unsigned
2366 parm_list (int *flags)
2367 {
2368 unsigned hash = 0;
2369 int type_seen = 0;
2370
2371 while (!LOOKING_AT2 (YYEOF, ')'))
2372 {
2373 switch (LA1)
2374 {
2375 /* Skip over grouping parens or parameter lists in parameter
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 {
2395 char *last_id;
2396 unsigned ident_type_hash = 0;
2397
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 }
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:
2425 case ELLIPSIS:
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 ();
2445
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
2478 static void
2479 print_info (void)
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
2493 static void
2494 member (struct sym *cls, int vis)
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;
2528
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:
2567 /* Remember IDENTS seen so far. Among these will be the member
2568 name. */
2569 id = (char *) xrealloc (id, strlen (yytext) + 2);
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:
2581 {
2582 char *s = operator_name (&sc);
2583 id = (char *) xrealloc (id, strlen (s) + 1);
2584 strcpy (id, s);
2585 }
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);
2615
2616 free (id);
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 ();
2663
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 }
2672
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 }
2694
2695 free (id);
2696 }
2697
2698
2699 /* Parse the body of class CLS. TAG is the tag of the class (struct,
2700 union, class). */
2701
2702 static void
2703 class_body (struct sym *cls, int tag)
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
2763 static struct sym *
2764 parse_classname (void)
2765 {
2766 struct sym *last_class = NULL;
2767
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 }
2778
2779 if (!LOOKING_AT (DCOLON))
2780 break;
2781
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
2793 static char *
2794 operator_name (int *sc)
2795 {
2796 static int id_size = 0;
2797 static char *id = NULL;
2798 const char *s;
2799 int len;
2800
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 ();
2811
2812 len = strlen (s) + 10;
2813 if (len > id_size)
2814 {
2815 int new_size = max (len, 2 * id_size);
2816 id = (char *) xrealloc (id, new_size);
2817 id_size = new_size;
2818 }
2819 strcpy (id, s);
2820
2821 /* Vector new or delete? */
2822 if (LOOKING_AT ('['))
2823 {
2824 strcat (id, "[");
2825 MATCH ();
2826
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);
2842 id = (char *) xrealloc (id, new_size);
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);
2858 id = (char *) xrealloc (id, new_size);
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. */
2868 if (!isalpha ((unsigned char) *s) && *s != '(' && *s != '[')
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
2880 `X::Y::z'. This IDENT is returned in LAST_ID. Value is the
2881 symbol structure for the ident. */
2882
2883 static struct sym *
2884 parse_qualified_ident_or_type (char **last_id)
2885 {
2886 struct sym *cls = NULL;
2887 char *id = NULL;
2888 size_t id_size = 0;
2889 int enter = 0;
2890
2891 while (LOOKING_AT (IDENT))
2892 {
2893 int len = strlen (yytext) + 1;
2894 if (len > id_size)
2895 {
2896 id = (char *) xrealloc (id, len);
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 {
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
2927 *last_id = NULL;
2928 free (id);
2929 id = NULL;
2930 id_size = 0;
2931 MATCH ();
2932 }
2933 else
2934 break;
2935 }
2936
2937 while (enter--)
2938 leave_namespace();
2939
2940 return cls;
2941 }
2942
2943
2944 /* This one consumes the last IDENT of a qualified member name like
2945 `X::Y::z'. This IDENT is returned in LAST_ID. Value is the
2946 symbol structure for the ident. */
2947
2948 static void
2949 parse_qualified_param_ident_or_type (char **last_id)
2950 {
2951 struct sym *cls = NULL;
2952 static char *id = NULL;
2953 static int id_size = 0;
2954
2955 while (LOOKING_AT (IDENT))
2956 {
2957 int len = strlen (yytext) + 1;
2958 if (len > id_size)
2959 {
2960 id = (char *) xrealloc (id, len);
2961 id_size = len;
2962 }
2963 strcpy (id, yytext);
2964 *last_id = id;
2965 MATCH ();
2966
2967 SKIP_MATCHING_IF ('<');
2968
2969 if (LOOKING_AT (DCOLON))
2970 {
2971 cls = add_sym (id, cls);
2972 *last_id = NULL;
2973 MATCH ();
2974 }
2975 else
2976 break;
2977 }
2978 }
2979
2980
2981 /* Parse a class definition.
2982
2983 CONTAINING is the class containing the class being parsed or null.
2984 This may also be null if NESTED != 0 if the containing class is
2985 anonymous. TAG is the tag of the class (struct, union, class).
2986 NESTED is non-zero if we are parsing a nested class.
2987
2988 Current lookahead is the class name. */
2989
2990 static void
2991 class_definition (struct sym *containing, int tag, int flags, int nested)
2992 {
2993 struct sym *current;
2994 struct sym *base_class;
2995
2996 /* Set CURRENT to null if no entry has to be made for the class
2997 parsed. This is the case for certain command line flag
2998 settings. */
2999 if ((tag != CLASS && !f_structs) || (nested && !f_nested_classes))
3000 current = NULL;
3001 else
3002 {
3003 current = add_sym (yytext, containing);
3004 current->pos = BUFFER_POS ();
3005 current->regexp = matching_regexp ();
3006 current->filename = filename;
3007 current->flags = flags;
3008 }
3009
3010 /* If at ':', base class list follows. */
3011 if (LOOKING_AT (':'))
3012 {
3013 int done = 0;
3014 MATCH ();
3015
3016 while (!done)
3017 {
3018 switch (LA1)
3019 {
3020 case VIRTUAL: case PUBLIC: case PROTECTED: case PRIVATE:
3021 MATCH ();
3022 break;
3023
3024 case IDENT:
3025 base_class = parse_classname ();
3026 if (base_class && current && base_class != current)
3027 add_link (base_class, current);
3028 break;
3029
3030 /* The `,' between base classes or the end of the base
3031 class list. Add the previously found base class.
3032 It's done this way to skip over sequences of
3033 `A::B::C' until we reach the end.
3034
3035 FIXME: it is now possible to handle `class X : public B::X'
3036 because we have enough information. */
3037 case ',':
3038 MATCH ();
3039 break;
3040
3041 default:
3042 /* A syntax error, possibly due to preprocessor constructs
3043 like
3044
3045 #ifdef SOMETHING
3046 class A : public B
3047 #else
3048 class A : private B.
3049
3050 MATCH until we see something like `;' or `{'. */
3051 while (!LOOKING_AT3 (';', YYEOF, '{'))
3052 MATCH ();
3053 done = 1;
3054
3055 case '{':
3056 done = 1;
3057 break;
3058 }
3059 }
3060 }
3061
3062 /* Parse the class body if there is one. */
3063 if (LOOKING_AT ('{'))
3064 {
3065 if (tag != CLASS && !f_structs)
3066 skip_matching ();
3067 else
3068 {
3069 MATCH ();
3070 class_body (current, tag);
3071
3072 if (LOOKING_AT ('}'))
3073 {
3074 MATCH ();
3075 if (LOOKING_AT (';') && !nested)
3076 MATCH ();
3077 }
3078 }
3079 }
3080 }
3081
3082 /* Add to class *CLS information for the declaration of variable or
3083 type *ID. If *CLS is null, this means a global declaration. SC is
3084 the storage class of *ID. FLAGS is a bit set giving additional
3085 information about the member (see the F_* defines). */
3086
3087 static void
3088 add_declarator (struct sym **cls, char **id, int flags, int sc)
3089 {
3090 if (LOOKING_AT2 (';', ','))
3091 {
3092 /* The end of a member variable or of an access declaration
3093 `X::f'. To distinguish between them we have to know whether
3094 type information has been seen. */
3095 if (*id)
3096 {
3097 char *regexp = matching_regexp ();
3098 int pos = BUFFER_POS ();
3099
3100 if (*cls)
3101 add_member_defn (*cls, *id, regexp, pos, 0, 1, SC_UNKNOWN, flags);
3102 else
3103 add_global_defn (*id, regexp, pos, 0, 1, sc, flags);
3104 }
3105
3106 MATCH ();
3107 print_info ();
3108 }
3109 else if (LOOKING_AT ('{'))
3110 {
3111 if (sc == SC_TYPE && *id)
3112 {
3113 /* A named enumeration. */
3114 char *regexp = matching_regexp ();
3115 int pos = BUFFER_POS ();
3116 add_global_defn (*id, regexp, pos, 0, 1, sc, flags);
3117 }
3118
3119 skip_matching ();
3120 print_info ();
3121 }
3122
3123 free (*id);
3124 *id = NULL;
3125 *cls = NULL;
3126 }
3127
3128 /* Parse a declaration. */
3129
3130 static void
3131 declaration (int flags)
3132 {
3133 char *id = NULL;
3134 struct sym *cls = NULL;
3135 char *regexp = NULL;
3136 int pos = 0;
3137 unsigned hash = 0;
3138 int is_constructor;
3139 int sc = 0;
3140
3141 while (!LOOKING_AT3 (';', '{', YYEOF))
3142 {
3143 switch (LA1)
3144 {
3145 default:
3146 MATCH ();
3147 break;
3148
3149 case '[':
3150 skip_matching ();
3151 break;
3152
3153 case ENUM:
3154 case TYPEDEF:
3155 sc = SC_TYPE;
3156 MATCH ();
3157 break;
3158
3159 case STATIC:
3160 sc = SC_STATIC;
3161 MATCH ();
3162 break;
3163
3164 case INT: case CHAR: case LONG: case UNSIGNED:
3165 case SIGNED: case CONST: case DOUBLE: case VOID:
3166 case SHORT: case VOLATILE: case BOOL: case WCHAR:
3167 MATCH ();
3168 break;
3169
3170 case CLASS: case STRUCT: case UNION:
3171 /* This is for the case `STARTWRAP class X : ...' or
3172 `declare (X, Y)\n class A : ...'. */
3173 if (id)
3174 {
3175 free (id);
3176 return;
3177 }
3178
3179 case '=':
3180 /* Assumed to be the start of an initialization in this
3181 context. */
3182 skip_initializer ();
3183 break;
3184
3185 case ',':
3186 add_declarator (&cls, &id, flags, sc);
3187 break;
3188
3189 case OPERATOR:
3190 {
3191 char *s = operator_name (&sc);
3192 id = (char *) xrealloc (id, strlen (s) + 1);
3193 strcpy (id, s);
3194 }
3195 break;
3196
3197 case T_INLINE:
3198 SET_FLAG (flags, F_INLINE);
3199 MATCH ();
3200 break;
3201
3202 case '~':
3203 MATCH ();
3204 if (LOOKING_AT (IDENT))
3205 {
3206 id = (char *) xrealloc (id, strlen (yytext) + 2);
3207 *id = '~';
3208 strcpy (id + 1, yytext);
3209 MATCH ();
3210 }
3211 break;
3212
3213 case IDENT:
3214 cls = parse_qualified_ident_or_type (&id);
3215 break;
3216
3217 case '(':
3218 /* Most probably the beginning of a parameter list. */
3219 if (cls)
3220 {
3221 MATCH ();
3222
3223 if (id && cls)
3224 {
3225 if (!(is_constructor = streq (id, cls->name)))
3226 regexp = matching_regexp ();
3227 }
3228 else
3229 is_constructor = 0;
3230
3231 pos = BUFFER_POS ();
3232 hash = parm_list (&flags);
3233
3234 if (is_constructor)
3235 regexp = matching_regexp ();
3236
3237 if (id && cls)
3238 add_member_defn (cls, id, regexp, pos, hash, 0,
3239 SC_UNKNOWN, flags);
3240 }
3241 else
3242 {
3243 /* This may be a C functions, but also a macro
3244 call of the form `declare (A, B)' --- such macros
3245 can be found in some class libraries. */
3246 MATCH ();
3247
3248 if (id)
3249 {
3250 regexp = matching_regexp ();
3251 pos = BUFFER_POS ();
3252 hash = parm_list (&flags);
3253 add_global_decl (id, regexp, pos, hash, 0, sc, flags);
3254 }
3255
3256 /* This is for the case that the function really is
3257 a macro with no `;' following it. If a CLASS directly
3258 follows, we would miss it otherwise. */
3259 if (LOOKING_AT3 (CLASS, STRUCT, UNION))
3260 return;
3261 }
3262
3263 while (!LOOKING_AT3 (';', '{', YYEOF))
3264 MATCH ();
3265
3266 if (!cls && id && LOOKING_AT ('{'))
3267 add_global_defn (id, regexp, pos, hash, 0, sc, flags);
3268
3269 free (id);
3270 id = NULL;
3271 break;
3272 }
3273 }
3274
3275 add_declarator (&cls, &id, flags, sc);
3276 }
3277
3278
3279 /* Parse a list of top-level declarations/definitions. START_FLAGS
3280 says in which context we are parsing. If it is F_EXTERNC, we are
3281 parsing in an `extern "C"' block. Value is 1 if EOF is reached, 0
3282 otherwise. */
3283
3284 static int
3285 globals (int start_flags)
3286 {
3287 int anonymous;
3288 int class_tk;
3289 int flags = start_flags;
3290
3291 for (;;)
3292 {
3293 char *prev_in = in;
3294
3295 switch (LA1)
3296 {
3297 case NAMESPACE:
3298 {
3299 MATCH ();
3300
3301 if (LOOKING_AT (IDENT))
3302 {
3303 char *namespace_name = xstrdup (yytext);
3304 MATCH ();
3305
3306 if (LOOKING_AT ('='))
3307 {
3308 struct link *qna = match_qualified_namespace_alias ();
3309 if (qna)
3310 register_namespace_alias (namespace_name, qna);
3311
3312 if (skip_to (';') == ';')
3313 MATCH ();
3314 }
3315 else if (LOOKING_AT ('{'))
3316 {
3317 MATCH ();
3318 enter_namespace (namespace_name);
3319 globals (0);
3320 leave_namespace ();
3321 MATCH_IF ('}');
3322 }
3323
3324 free (namespace_name);
3325 }
3326 }
3327 break;
3328
3329 case EXTERN:
3330 MATCH ();
3331 if (LOOKING_AT (CSTRING) && *string_start == 'C'
3332 && *(string_start + 1) == '"')
3333 {
3334 /* This is `extern "C"'. */
3335 MATCH ();
3336
3337 if (LOOKING_AT ('{'))
3338 {
3339 MATCH ();
3340 globals (F_EXTERNC);
3341 MATCH_IF ('}');
3342 }
3343 else
3344 SET_FLAG (flags, F_EXTERNC);
3345 }
3346 break;
3347
3348 case TEMPLATE:
3349 MATCH ();
3350 SKIP_MATCHING_IF ('<');
3351 SET_FLAG (flags, F_TEMPLATE);
3352 break;
3353
3354 case CLASS: case STRUCT: case UNION:
3355 class_tk = LA1;
3356 MATCH ();
3357 anonymous = 1;
3358
3359 /* More than one ident here to allow for MS-DOS and OS/2
3360 specialties like `far', `_Export' etc. Some C++ libs
3361 have constructs like `_OS_DLLIMPORT(_OS_CLIENT)' in front
3362 of the class name. */
3363 while (!LOOKING_AT4 (YYEOF, ';', ':', '{'))
3364 {
3365 if (LOOKING_AT (IDENT))
3366 anonymous = 0;
3367 MATCH ();
3368 }
3369
3370 /* Don't add anonymous unions. */
3371 if (LOOKING_AT2 (':', '{') && !anonymous)
3372 class_definition (NULL, class_tk, flags, 0);
3373 else
3374 {
3375 if (skip_to (';') == ';')
3376 MATCH ();
3377 }
3378
3379 flags = start_flags;
3380 break;
3381
3382 case YYEOF:
3383 return 1;
3384
3385 case '}':
3386 return 0;
3387
3388 default:
3389 declaration (flags);
3390 flags = start_flags;
3391 break;
3392 }
3393
3394 if (prev_in == in)
3395 yyerror ("parse error", NULL);
3396 }
3397 }
3398
3399
3400 /* Parse the current input file. */
3401
3402 static void
3403 yyparse (void)
3404 {
3405 while (globals (0) == 0)
3406 MATCH_IF ('}');
3407 }
3408
3409
3410 \f
3411 /***********************************************************************
3412 Main Program
3413 ***********************************************************************/
3414
3415 /* Add the list of paths PATH_LIST to the current search path for
3416 input files. */
3417
3418 static void
3419 add_search_path (char *path_list)
3420 {
3421 while (*path_list)
3422 {
3423 char *start = path_list;
3424 struct search_path *p;
3425
3426 while (*path_list && *path_list != PATH_LIST_SEPARATOR)
3427 ++path_list;
3428
3429 p = (struct search_path *) xmalloc (sizeof *p);
3430 p->path = (char *) xmalloc (path_list - start + 1);
3431 memcpy (p->path, start, path_list - start);
3432 p->path[path_list - start] = '\0';
3433 p->next = NULL;
3434
3435 if (search_path_tail)
3436 {
3437 search_path_tail->next = p;
3438 search_path_tail = p;
3439 }
3440 else
3441 search_path = search_path_tail = p;
3442
3443 while (*path_list == PATH_LIST_SEPARATOR)
3444 ++path_list;
3445 }
3446 }
3447
3448
3449 /* Open FILE and return a file handle for it, or -1 if FILE cannot be
3450 opened. Try to find FILE in search_path first, then try the
3451 unchanged file name. */
3452
3453 static FILE *
3454 open_file (char *file)
3455 {
3456 FILE *fp = NULL;
3457 static char *buffer;
3458 static int buffer_size;
3459 struct search_path *path;
3460 int flen = strlen (file) + 1; /* +1 for the slash */
3461
3462 filename = xstrdup (file);
3463
3464 for (path = search_path; path && fp == NULL; path = path->next)
3465 {
3466 int len = strlen (path->path) + flen;
3467
3468 if (len + 1 >= buffer_size)
3469 {
3470 buffer_size = max (len + 1, 2 * buffer_size);
3471 buffer = (char *) xrealloc (buffer, buffer_size);
3472 }
3473
3474 strcpy (buffer, path->path);
3475 strcat (buffer, "/");
3476 strcat (buffer, file);
3477 fp = fopen (buffer, "r");
3478 }
3479
3480 /* Try the original file name. */
3481 if (fp == NULL)
3482 fp = fopen (file, "r");
3483
3484 if (fp == NULL)
3485 yyerror ("cannot open", NULL);
3486
3487 return fp;
3488 }
3489
3490
3491 /* Display usage information and exit program. */
3492
3493 #define USAGE "\
3494 Usage: ebrowse [options] {files}\n\
3495 \n\
3496 -a, --append append output to existing file\n\
3497 -f, --files=FILES read input file names from FILE\n\
3498 -I, --search-path=LIST set search path for input files\n\
3499 -m, --min-regexp-length=N set minimum regexp length to N\n\
3500 -M, --max-regexp-length=N set maximum regexp length to N\n\
3501 -n, --no-nested-classes exclude nested classes\n\
3502 -o, --output-file=FILE set output file name to FILE\n\
3503 -p, --position-info print info about position in file\n\
3504 -s, --no-structs-or-unions don't record structs or unions\n\
3505 -v, --verbose be verbose\n\
3506 -V, --very-verbose be very verbose\n\
3507 -x, --no-regexps don't record regular expressions\n\
3508 --help display this help\n\
3509 --version display version info\n\
3510 "
3511
3512 static void
3513 usage (int error)
3514 {
3515 puts (USAGE);
3516 exit (error ? EXIT_FAILURE : EXIT_SUCCESS);
3517 }
3518
3519
3520 /* Display version and copyright info. The VERSION macro is set
3521 from config.h and contains the Emacs version. */
3522
3523 #ifndef VERSION
3524 # define VERSION "21"
3525 #endif
3526
3527 static void
3528 version (void)
3529 {
3530 /* Makes it easier to update automatically. */
3531 char emacs_copyright[] = "Copyright (C) 2011 Free Software Foundation, Inc.";
3532
3533 printf ("ebrowse %s\n", VERSION);
3534 puts (emacs_copyright);
3535 puts ("This program is distributed under the same terms as Emacs.");
3536 exit (EXIT_SUCCESS);
3537 }
3538
3539
3540 /* Parse one input file FILE, adding classes and members to the symbol
3541 table. */
3542
3543 static void
3544 process_file (char *file)
3545 {
3546 FILE *fp;
3547
3548 fp = open_file (file);
3549 if (fp)
3550 {
3551 int nread, nbytes;
3552
3553 /* Give a progress indication if needed. */
3554 if (f_very_verbose)
3555 {
3556 puts (filename);
3557 fflush (stdout);
3558 }
3559 else if (f_verbose)
3560 {
3561 putchar ('.');
3562 fflush (stdout);
3563 }
3564
3565 /* Read file to inbuffer. */
3566 for (nread = 0;;)
3567 {
3568 if (nread + READ_CHUNK_SIZE >= inbuffer_size)
3569 {
3570 inbuffer_size = nread + READ_CHUNK_SIZE + 1;
3571 inbuffer = (char *) xrealloc (inbuffer, inbuffer_size);
3572 }
3573
3574 nbytes = fread (inbuffer + nread, 1, READ_CHUNK_SIZE, fp);
3575 if (nbytes <= 0)
3576 break;
3577 nread += nbytes;
3578 }
3579 if (nread < 0)
3580 nread = 0;
3581 inbuffer[nread] = '\0';
3582
3583 /* Reinitialize scanner and parser for the new input file. */
3584 re_init_scanner ();
3585 re_init_parser ();
3586
3587 /* Parse it and close the file. */
3588 yyparse ();
3589 fclose (fp);
3590 }
3591 }
3592
3593
3594 /* Read a line from stream FP and return a pointer to a static buffer
3595 containing its contents without the terminating newline. Value
3596 is null when EOF is reached. */
3597
3598 static char *
3599 read_line (FILE *fp)
3600 {
3601 static char *buffer;
3602 static int buffer_size;
3603 int i = 0, c;
3604
3605 while ((c = getc (fp)) != EOF && c != '\n')
3606 {
3607 if (i >= buffer_size)
3608 {
3609 buffer_size = max (100, buffer_size * 2);
3610 buffer = (char *) xrealloc (buffer, buffer_size);
3611 }
3612
3613 buffer[i++] = c;
3614 }
3615
3616 if (c == EOF && i == 0)
3617 return NULL;
3618
3619 if (i == buffer_size)
3620 {
3621 buffer_size = max (100, buffer_size * 2);
3622 buffer = (char *) xrealloc (buffer, buffer_size);
3623 }
3624
3625 buffer[i] = '\0';
3626 if (i > 0 && buffer[i - 1] == '\r')
3627 buffer[i - 1] = '\0';
3628 return buffer;
3629 }
3630
3631
3632 /* Main entry point. */
3633
3634 int
3635 main (int argc, char **argv)
3636 {
3637 int i;
3638 int any_inputfiles = 0;
3639 static const char *out_filename = DEFAULT_OUTFILE;
3640 static char **input_filenames = NULL;
3641 static int input_filenames_size = 0;
3642 static int n_input_files;
3643
3644 filename = "command line";
3645 yyout = stdout;
3646
3647 while ((i = getopt_long (argc, argv, "af:I:m:M:no:p:svVx",
3648 options, NULL)) != EOF)
3649 {
3650 switch (i)
3651 {
3652 /* Experimental. */
3653 case 'p':
3654 info_position = atoi (optarg);
3655 break;
3656
3657 case 'n':
3658 f_nested_classes = 0;
3659 break;
3660
3661 case 'x':
3662 f_regexps = 0;
3663 break;
3664
3665 /* Add the name of a file containing more input files. */
3666 case 'f':
3667 if (n_input_files == input_filenames_size)
3668 {
3669 input_filenames_size = max (10, 2 * input_filenames_size);
3670 input_filenames = (char **) xrealloc ((void *)input_filenames,
3671 input_filenames_size);
3672 }
3673 input_filenames[n_input_files++] = xstrdup (optarg);
3674 break;
3675
3676 /* Append new output to output file instead of truncating it. */
3677 case 'a':
3678 f_append = 1;
3679 break;
3680
3681 /* Include structs in the output */
3682 case 's':
3683 f_structs = 0;
3684 break;
3685
3686 /* Be verbose (give a progress indication). */
3687 case 'v':
3688 f_verbose = 1;
3689 break;
3690
3691 /* Be very verbose (print file names as they are processed). */
3692 case 'V':
3693 f_verbose = 1;
3694 f_very_verbose = 1;
3695 break;
3696
3697 /* Change the name of the output file. */
3698 case 'o':
3699 out_filename = optarg;
3700 break;
3701
3702 /* Set minimum length for regular expression strings
3703 when recorded in the output file. */
3704 case 'm':
3705 min_regexp = atoi (optarg);
3706 break;
3707
3708 /* Set maximum length for regular expression strings
3709 when recorded in the output file. */
3710 case 'M':
3711 max_regexp = atoi (optarg);
3712 break;
3713
3714 /* Add to search path. */
3715 case 'I':
3716 add_search_path (optarg);
3717 break;
3718
3719 /* Display help */
3720 case -2:
3721 usage (0);
3722 break;
3723
3724 case -3:
3725 version ();
3726 break;
3727 }
3728 }
3729
3730 /* Call init_scanner after command line flags have been processed to be
3731 able to add keywords depending on command line (not yet
3732 implemented). */
3733 init_scanner ();
3734 init_sym ();
3735
3736 /* Open output file */
3737 if (*out_filename)
3738 {
3739 if (f_append)
3740 {
3741 /* Check that the file to append to exists, and is not
3742 empty. More specifically, it should be a valid file
3743 produced by a previous run of ebrowse, but that's too
3744 difficult to check. */
3745 FILE *fp;
3746 int rc;
3747
3748 fp = fopen (out_filename, "r");
3749 if (fp == NULL)
3750 {
3751 yyerror ("file `%s' must exist for --append", out_filename);
3752 exit (EXIT_FAILURE);
3753 }
3754
3755 rc = fseek (fp, 0, SEEK_END);
3756 if (rc == -1)
3757 {
3758 yyerror ("error seeking in file `%s'", out_filename);
3759 exit (EXIT_FAILURE);
3760 }
3761
3762 rc = ftell (fp);
3763 if (rc == -1)
3764 {
3765 yyerror ("error getting size of file `%s'", out_filename);
3766 exit (EXIT_FAILURE);
3767 }
3768
3769 else if (rc == 0)
3770 {
3771 yyerror ("file `%s' is empty", out_filename);
3772 /* It may be ok to use an empty file for appending.
3773 exit (EXIT_FAILURE); */
3774 }
3775
3776 fclose (fp);
3777 }
3778
3779 yyout = fopen (out_filename, f_append ? "a" : "w");
3780 if (yyout == NULL)
3781 {
3782 yyerror ("cannot open output file `%s'", out_filename);
3783 exit (EXIT_FAILURE);
3784 }
3785 }
3786
3787 /* Process input files specified on the command line. */
3788 while (optind < argc)
3789 {
3790 process_file (argv[optind++]);
3791 any_inputfiles = 1;
3792 }
3793
3794 /* Process files given on stdin if no files specified. */
3795 if (!any_inputfiles && n_input_files == 0)
3796 {
3797 char *file;
3798 while ((file = read_line (stdin)) != NULL)
3799 process_file (file);
3800 }
3801 else
3802 {
3803 /* Process files from `--files=FILE'. Every line in FILE names
3804 one input file to process. */
3805 for (i = 0; i < n_input_files; ++i)
3806 {
3807 FILE *fp = fopen (input_filenames[i], "r");
3808
3809 if (fp == NULL)
3810 yyerror ("cannot open input file `%s'", input_filenames[i]);
3811 else
3812 {
3813 char *file;
3814 while ((file = read_line (fp)) != NULL)
3815 process_file (file);
3816 fclose (fp);
3817 }
3818 }
3819 }
3820
3821 /* Write output file. */
3822 dump_roots (yyout);
3823
3824 /* Close output file. */
3825 if (yyout != stdout)
3826 fclose (yyout);
3827
3828 return EXIT_SUCCESS;
3829 }
3830
3831 /* ebrowse.c ends here */