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