📄 lex.c
字号:
/* Separate lexical analyzer for GNU C++. Copyright (C) 1987, 89, 92-96, 1997 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 <sys/types.h>#include <stdio.h>#include <errno.h>#include <setjmp.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"/* MULTIBYTE_CHARS support only works for native compilers. ??? Ideally what we want is to model widechar support after the current floating point support. */#ifdef CROSS_COMPILE#undef MULTIBYTE_CHARS#endif#ifdef MULTIBYTE_CHARS#include <stdlib.h>#include <locale.h>#endif#ifdef HAVE_STDLIB_H#ifndef MULTIBYTE_CHARS#include <stdlib.h>#endif#elseextern double atof ();#endif#ifdef HAVE_STRING_H#include <string.h>#elseextern char *index ();extern char *rindex ();#endif#ifndef errnoextern int errno; /* needed for VAX. */#endif#define obstack_chunk_alloc xmalloc#define obstack_chunk_free freeextern struct obstack permanent_obstack;extern struct obstack *current_obstack, *saveable_obstack;extern void yyprint PROTO((FILE *, int, YYSTYPE));extern void set_float_handler PROTO((jmp_buf));extern void compiler_error PROTO((char *, HOST_WIDE_INT, HOST_WIDE_INT));static tree get_time_identifier PROTO((char *));static int check_newline PROTO((void));static int skip_white_space PROTO((int));static int yynextch PROTO((void));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((char *));static int readescape PROTO((int *));static char *extend_token_buffer PROTO((char *));static void consume_string PROTO((struct obstack *, int));static void set_typedecl_interface_info PROTO((tree, tree));static void feed_defarg PROTO((tree, tree));static int set_vardecl_interface_info PROTO((tree, tree));static void store_pending_inline PROTO((tree, struct pending_inline *));static void reinit_parse_for_expr PROTO((struct obstack *));/* 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) char *x;{ char *tmp = (char *) rindex (x, '/'); if (tmp) return (char *) (tmp + 1); else return 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;int 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 *//* File used for outputting assembler code. */extern FILE *asm_out_file;#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) 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 (IDENTIFIER_LOCAL_VALUE (time_identifier) == NULL_TREE) { push_obstacks_nochange (); end_temporary_allocation (); IDENTIFIER_LOCAL_VALUE (time_identifier) = build_int_2 (0, 0); IDENTIFIER_CLASS_VALUE (time_identifier) = build_int_2 (0, 1); 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,char *cplus_tree_code_name[] = { "@@dummy",#include "cp-tree.def"};#undef DEFTREECODE/* toplev.c needs to call these. */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. */ put_back (check_newline ()); if (flag_gnu_xref) GNU_xref_begin (input_filename); init_repo (input_filename); /* See comments in toplev.c before the call to lang_init. */ if (flag_exceptions == 2) flag_exceptions = 1;}voidlang_finish (){ extern int errorcount, sorrycount; if (flag_gnu_xref) GNU_xref_end (errorcount+sorrycount);}char *lang_identify (){ return "cplusplus";}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 (IDENTIFIER_LOCAL_VALUE (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_lex if we are an unexec'd binary. */#if 0voidreinit_lang_specific (){ init_filename_times (); reinit_search_statistics ();}#endifvoidinit_lex (){ extern int flag_no_gnu_keywords;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -