📄 lex.c
字号:
/* Separate lexical analyzer for GNU C++. Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com)This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. *//* This file is the lexical analyzer for GNU C++. *//* Cause the `yydebug' variable to be defined. */#define YYDEBUG 1#include "config.h"#include "system.h"#include "input.h"#include "tree.h"#include "lex.h"#include "cp-tree.h"#include "parse.h"#include "flags.h"#include "obstack.h"#include "c-pragma.h"#include "toplev.h"#include "output.h"#ifdef MULTIBYTE_CHARS#include "mbchar.h"#include <locale.h>#endif#define obstack_chunk_alloc xmalloc#define obstack_chunk_free free#ifndef DIR_SEPARATOR#define DIR_SEPARATOR '/'#endifextern struct obstack permanent_obstack;extern struct obstack *current_obstack, *saveable_obstack;extern void yyprint PROTO((FILE *, int, YYSTYPE));static tree get_time_identifier PROTO((const char *));static int check_newline PROTO((void));static int skip_white_space PROTO((int));static void finish_defarg PROTO((void));static int my_get_run_time PROTO((void));static int get_last_nonwhite_on_line PROTO((void));static int interface_strcmp PROTO((const char *));static int readescape PROTO((int *));static char *extend_token_buffer PROTO((const char *));static void consume_string PROTO((struct obstack *, int));static int set_typedecl_interface_info PROTO((tree *, void *));static void feed_defarg PROTO((tree, tree));static int set_vardecl_interface_info PROTO((tree *, void *));static void store_pending_inline PROTO((tree, struct pending_inline *));static void reinit_parse_for_expr PROTO((struct obstack *));static int *init_cpp_parse PROTO((void));static int handle_cp_pragma PROTO((const char *));#ifdef HANDLE_GENERIC_PRAGMASstatic int handle_generic_pragma PROTO((int));#endif#ifdef GATHER_STATISTICS#ifdef REDUCE_LENGTHstatic int reduce_cmp PROTO((int *, int *));static int token_cmp PROTO((int *, int *));#endif#endifstatic void begin_definition_of_inclass_inline PROTO((struct pending_inline*));static void parse_float PROTO((PTR));static int is_global PROTO((tree));static void init_filename_times PROTO((void));/* Given a file name X, return the nondirectory portion. Keep in mind that X can be computed more than once. */char *file_name_nondirectory (x) const char *x;{ char *tmp = (char *) rindex (x, '/'); if (DIR_SEPARATOR != '/' && ! tmp) tmp = (char *) rindex (x, DIR_SEPARATOR); if (tmp) return (char *) (tmp + 1); else return (char *) x;}/* This obstack is needed to hold text. It is not safe to use TOKEN_BUFFER because `check_newline' calls `yylex'. */struct obstack inline_text_obstack;char *inline_text_firstobj;#if USE_CPPLIB#include "cpplib.h"extern cpp_reader parse_in;extern cpp_options parse_options;extern unsigned char *yy_cur, *yy_lim;#elseFILE *finput;#endifint end_of_file;/* Pending language change. Positive is push count, negative is pop count. */int pending_lang_change = 0;/* Wrap the current header file in extern "C". */static int c_header_level = 0;extern int first_token;extern struct obstack token_obstack;/* ??? Don't really know where this goes yet. */#if 1#include "input.c"#elseextern void put_back (/* int */);extern int input_redirected ();extern void feed_input (/* char *, int */);#endif/* Holds translations from TREE_CODEs to operator name strings, i.e., opname_tab[PLUS_EXPR] == "+". */char **opname_tab;char **assignop_tab;extern int yychar; /* the lookahead symbol */extern YYSTYPE yylval; /* the semantic value of the */ /* lookahead symbol */#if 0YYLTYPE yylloc; /* location data for the lookahead */ /* symbol */#endif/* the declaration found for the last IDENTIFIER token read in. yylex must look this up to detect typedefs, which get token type TYPENAME, so it is left around in case the identifier is not a typedef but is used in a context which makes it a reference to a variable. */tree lastiddecl;/* The elements of `ridpointers' are identifier nodes for the reserved type names and storage classes. It is indexed by a RID_... value. */tree ridpointers[(int) RID_MAX];/* We may keep statistics about how long which files took to compile. */static int header_time, body_time;static tree filename_times;static tree this_filename_time;/* Array for holding counts of the numbers of tokens seen. */extern int *token_count;/* Return something to represent absolute declarators containing a *. TARGET is the absolute declarator that the * contains. CV_QUALIFIERS is a list of modifiers such as const or volatile to apply to the pointer type, represented as identifiers. We return an INDIRECT_REF whose "contents" are TARGET and whose type is the modifier list. */treemake_pointer_declarator (cv_qualifiers, target) tree cv_qualifiers, target;{ if (target && TREE_CODE (target) == IDENTIFIER_NODE && ANON_AGGRNAME_P (target)) error ("type name expected before `*'"); target = build_parse_node (INDIRECT_REF, target); TREE_TYPE (target) = cv_qualifiers; return target;}/* Return something to represent absolute declarators containing a &. TARGET is the absolute declarator that the & contains. CV_QUALIFIERS is a list of modifiers such as const or volatile to apply to the reference type, represented as identifiers. We return an ADDR_EXPR whose "contents" are TARGET and whose type is the modifier list. */ treemake_reference_declarator (cv_qualifiers, target) tree cv_qualifiers, target;{ if (target) { if (TREE_CODE (target) == ADDR_EXPR) { error ("cannot declare references to references"); return target; } if (TREE_CODE (target) == INDIRECT_REF) { error ("cannot declare pointers to references"); return target; } if (TREE_CODE (target) == IDENTIFIER_NODE && ANON_AGGRNAME_P (target)) error ("type name expected before `&'"); } target = build_parse_node (ADDR_EXPR, target); TREE_TYPE (target) = cv_qualifiers; return target;}treemake_call_declarator (target, parms, cv_qualifiers, exception_specification) tree target, parms, cv_qualifiers, exception_specification;{ target = build_parse_node (CALL_EXPR, target, parms, cv_qualifiers); TREE_TYPE (target) = exception_specification; return target;}voidset_quals_and_spec (call_declarator, cv_qualifiers, exception_specification) tree call_declarator, cv_qualifiers, exception_specification;{ TREE_OPERAND (call_declarator, 2) = cv_qualifiers; TREE_TYPE (call_declarator) = exception_specification;}/* Build names and nodes for overloaded operators. */tree ansi_opname[LAST_CPLUS_TREE_CODE];tree ansi_assopname[LAST_CPLUS_TREE_CODE];char *operator_name_string (name) tree name;{ char *opname = IDENTIFIER_POINTER (name) + 2; tree *opname_table; int i, assign; /* Works for builtin and user defined types. */ if (IDENTIFIER_GLOBAL_VALUE (name) && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == TYPE_DECL) return IDENTIFIER_POINTER (name); if (opname[0] == 'a' && opname[2] != '\0' && opname[2] != '_') { opname += 1; assign = 1; opname_table = ansi_assopname; } else { assign = 0; opname_table = ansi_opname; } for (i = 0; i < (int) LAST_CPLUS_TREE_CODE; i++) { if (opname[0] == IDENTIFIER_POINTER (opname_table[i])[2+assign] && opname[1] == IDENTIFIER_POINTER (opname_table[i])[3+assign]) break; } if (i == LAST_CPLUS_TREE_CODE) return "<invalid operator>"; if (assign) return assignop_tab[i]; else return opname_tab[i];}int interface_only; /* whether or not current file is only for interface definitions. */int interface_unknown; /* whether or not we know this class to behave according to #pragma interface. *//* lexical analyzer */#ifndef WCHAR_TYPE_SIZE#ifdef INT_TYPE_SIZE#define WCHAR_TYPE_SIZE INT_TYPE_SIZE#else#define WCHAR_TYPE_SIZE BITS_PER_WORD#endif#endif/* Number of bytes in a wide character. */#define WCHAR_BYTES (WCHAR_TYPE_SIZE / BITS_PER_UNIT)static int maxtoken; /* Current nominal length of token buffer. */char *token_buffer; /* Pointer to token buffer. Actual allocated length is maxtoken + 2. */#include "hash.h"/* Nonzero tells yylex to ignore \ in string constants. */static int ignore_escape_flag = 0;static treeget_time_identifier (name) const char *name;{ tree time_identifier; int len = strlen (name); char *buf = (char *) alloca (len + 6); strcpy (buf, "file "); bcopy (name, buf+5, len); buf[len+5] = '\0'; time_identifier = get_identifier (buf); if (TIME_IDENTIFIER_TIME (time_identifier) == NULL_TREE) { push_obstacks_nochange (); end_temporary_allocation (); TIME_IDENTIFIER_TIME (time_identifier) = build_int_2 (0, 0); TIME_IDENTIFIER_FILEINFO (time_identifier) = build_int_2 (0, 1); SET_IDENTIFIER_GLOBAL_VALUE (time_identifier, filename_times); filename_times = time_identifier; pop_obstacks (); } return time_identifier;}#ifdef __GNUC____inline#endifstatic intmy_get_run_time (){ int old_quiet_flag = quiet_flag; int this_time; quiet_flag = 0; this_time = get_run_time (); quiet_flag = old_quiet_flag; return this_time;}/* Table indexed by tree code giving a string containing a character classifying the tree code. Possibilities are t, d, s, c, r, <, 1 and 2. See cp/cp-tree.def for details. */#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,char cplus_tree_code_type[] = { 'x',#include "cp-tree.def"};#undef DEFTREECODE/* Table indexed by tree code giving number of expression operands beyond the fixed part of the node structure. Not used for types or decls. */#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,int cplus_tree_code_length[] = { 0,#include "cp-tree.def"};#undef DEFTREECODE/* Names of tree components. Used for printing out the tree and error messages. */#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,const char *cplus_tree_code_name[] = { "@@dummy",#include "cp-tree.def"};#undef DEFTREECODE/* toplev.c needs to call these. */voidlang_init_options (){#if USE_CPPLIB cpp_reader_init (&parse_in); parse_in.opts = &parse_options; cpp_options_init (&parse_options);#endif /* Default exceptions on. */ flag_exceptions = 1;}voidlang_init (){ /* the beginning of the file is a new line; check for # */ /* With luck, we discover the real source file's name from that and put it in input_filename. */#if ! USE_CPPLIB put_back (check_newline ());#else check_newline (); yy_cur--;#endif if (flag_gnu_xref) GNU_xref_begin (input_filename); init_repo (input_filename);}voidlang_finish (){ extern int errorcount, sorrycount; if (flag_gnu_xref) GNU_xref_end (errorcount+sorrycount);}char *lang_identify (){ return "cplusplus";}static voidinit_filename_times (){ this_filename_time = get_time_identifier ("<top level>"); if (flag_detailed_statistics) { header_time = 0; body_time = my_get_run_time (); TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time)) = body_time; }}/* Change by Bryan Boreham, Kewill, Thu Jul 27 09:46:05 1989. Stuck this hack in to get the files open correctly; this is called in place of init_parse if we are an unexec'd binary. */#if 0voidreinit_lang_specific (){ init_filename_times (); reinit_search_statistics ();}#endifstatic int *init_cpp_parse (){#ifdef GATHER_STATISTICS#ifdef REDUCE_LENGTH reduce_count = (int *)malloc (sizeof (int) * (REDUCE_LENGTH + 1)); bzero (reduce_count, sizeof (int) * (REDUCE_LENGTH + 1)); reduce_count += 1; token_count = (int *)malloc (sizeof (int) * (TOKEN_LENGTH + 1)); bzero (token_count, sizeof (int) * (TOKEN_LENGTH + 1)); token_count += 1;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -