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