📄 lex.c
字号:
my_friendly_abort (80); break; }}#if defined(GATHER_STATISTICS) && defined(REDUCE_LENGTH)static int *reduce_count;#endifint *token_count;#if 0#define REDUCE_LENGTH (sizeof (yyr2) / sizeof (yyr2[0]))#define TOKEN_LENGTH (256 + sizeof (yytname) / sizeof (yytname[0]))#endif#ifdef GATHER_STATISTICS#ifdef REDUCE_LENGTHvoidyyhook (yyn) int yyn;{ reduce_count[yyn] += 1;}static intreduce_cmp (p, q) int *p, *q;{ return reduce_count[*q] - reduce_count[*p];}static inttoken_cmp (p, q) int *p, *q;{ return token_count[*q] - token_count[*p];}#endif#endifvoidprint_parse_statistics (){#ifdef GATHER_STATISTICS#ifdef REDUCE_LENGTH#if YYDEBUG != 0 int i; int maxlen = REDUCE_LENGTH; unsigned *sorted; if (reduce_count[-1] == 0) return; if (TOKEN_LENGTH > REDUCE_LENGTH) maxlen = TOKEN_LENGTH; sorted = (unsigned *) alloca (sizeof (int) * maxlen); for (i = 0; i < TOKEN_LENGTH; i++) sorted[i] = i; qsort (sorted, TOKEN_LENGTH, sizeof (int), token_cmp); for (i = 0; i < TOKEN_LENGTH; i++) { int idx = sorted[i]; if (token_count[idx] == 0) break; if (token_count[idx] < token_count[-1]) break; fprintf (stderr, "token %d, `%s', count = %d\n", idx, yytname[YYTRANSLATE (idx)], token_count[idx]); } fprintf (stderr, "\n"); for (i = 0; i < REDUCE_LENGTH; i++) sorted[i] = i; qsort (sorted, REDUCE_LENGTH, sizeof (int), reduce_cmp); for (i = 0; i < REDUCE_LENGTH; i++) { int idx = sorted[i]; if (reduce_count[idx] == 0) break; if (reduce_count[idx] < reduce_count[-1]) break; fprintf (stderr, "rule %d, line %d, count = %d\n", idx, yyrline[idx], reduce_count[idx]); } fprintf (stderr, "\n");#endif#endif#endif}/* Sets the value of the 'yydebug' variable to VALUE. This is a function so we don't have to have YYDEBUG defined in order to build the compiler. */voidset_yydebug (value) int value;{#if YYDEBUG != 0 extern int yydebug; yydebug = value;#else warning ("YYDEBUG not defined.");#endif}/* Functions and data structures for #pragma interface. `#pragma implementation' means that the main file being compiled is considered to implement (provide) the classes that appear in its main body. I.e., if this is file "foo.cc", and class `bar' is defined in "foo.cc", then we say that "foo.cc implements bar". All main input files "implement" themselves automagically. `#pragma interface' means that unless this file (of the form "foo.h" is not presently being included by file "foo.cc", the CLASSTYPE_INTERFACE_ONLY bit gets set. The effect is that none of the vtables nor any of the inline functions defined in foo.h will ever be output. There are cases when we want to link files such as "defs.h" and "main.cc". In this case, we give "defs.h" a `#pragma interface', and "main.cc" has `#pragma implementation "defs.h"'. */struct impl_files{ char *filename; struct impl_files *next;};static struct impl_files *impl_file_chain;/* Helper function to load global variables with interface information. */voidextract_interface_info (){ tree fileinfo = 0; if (flag_alt_external_templates) { struct tinst_level *til = tinst_for_decl (); if (til) fileinfo = get_time_identifier (til->file); } if (!fileinfo) fileinfo = get_time_identifier (input_filename); fileinfo = TIME_IDENTIFIER_FILEINFO (fileinfo); interface_only = TREE_INT_CST_LOW (fileinfo); interface_unknown = TREE_INT_CST_HIGH (fileinfo);}/* Return nonzero if S is not considered part of an INTERFACE/IMPLEMENTATION pair. Otherwise, return 0. */static intinterface_strcmp (s) const char *s;{ /* Set the interface/implementation bits for this scope. */ struct impl_files *ifiles; const char *s1; for (ifiles = impl_file_chain; ifiles; ifiles = ifiles->next) { const char *t1 = ifiles->filename; s1 = s; if (*s1 != *t1 || *s1 == 0) continue; while (*s1 == *t1 && *s1 != 0) s1++, t1++; /* A match. */ if (*s1 == *t1) return 0; /* Don't get faked out by xxx.yyy.cc vs xxx.zzz.cc. */ if (index (s1, '.') || index (t1, '.')) continue; if (*s1 == '\0' || s1[-1] != '.' || t1[-1] != '.') continue; /* A match. */ return 0; } /* No matches. */ return 1;}static intset_typedecl_interface_info (t, data) tree *t; void *data ATTRIBUTE_UNUSED;{ tree id = get_time_identifier (DECL_SOURCE_FILE (*t)); tree fileinfo = TIME_IDENTIFIER_FILEINFO (id); tree type = TREE_TYPE (*t); CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo) = interface_strcmp (file_name_nondirectory (DECL_SOURCE_FILE (*t))); return 0;}static intset_vardecl_interface_info (t, data) tree *t; void *data ATTRIBUTE_UNUSED;{ tree type = DECL_CONTEXT (*t); if (CLASSTYPE_INTERFACE_KNOWN (type)) { if (CLASSTYPE_INTERFACE_ONLY (type)) set_typedecl_interface_info (&TYPE_MAIN_DECL (type), data); else CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1; DECL_EXTERNAL (*t) = CLASSTYPE_INTERFACE_ONLY (type); TREE_PUBLIC (*t) = 1; return 1; } return 0;}/* Set up the state required to correctly handle the definition of the inline function whose preparsed state has been saved in PI. */static voidbegin_definition_of_inclass_inline (pi) struct pending_inline* pi;{ tree context; if (!pi->fndecl) return; /* If this is an inline function in a local class, we must make sure that we save all pertinent information about the function surrounding the local class. */ context = hack_decl_function_context (pi->fndecl); if (context) push_cp_function_context (context); feed_input (pi->buf, pi->len); lineno = pi->lineno; input_filename = pi->filename; yychar = PRE_PARSED_FUNCTION_DECL; yylval.ttype = build_tree_list ((tree) pi, pi->fndecl); /* Pass back a handle to the rest of the inline functions, so that they can be processed later. */ DECL_PENDING_INLINE_INFO (pi->fndecl) = 0; interface_unknown = pi->interface == 1; interface_only = pi->interface == 0;}/* Called from the top level: if there are any pending inlines to do, set up to process them now. This function sets up the first function to be parsed; after it has been, the rule for fndef in parse.y will call process_next_inline to start working on the next one. */voiddo_pending_inlines (){ struct pending_inline *t; /* Oops, we're still dealing with the last batch. */ if (yychar == PRE_PARSED_FUNCTION_DECL) return; /* Reverse the pending inline functions, since they were cons'd instead of appended. */ { struct pending_inline *prev = 0, *tail; t = pending_inlines; pending_inlines = 0; for (; t; t = tail) { tail = t->next; t->next = prev; t->deja_vu = 1; prev = t; } t = prev; } if (t == 0) return; /* Now start processing the first inline function. */ begin_definition_of_inclass_inline (t);}static int nextchar = -1;/* Called from the fndecl rule in the parser when the function just parsed was declared using a PRE_PARSED_FUNCTION_DECL (i.e. came from do_pending_inlines). */voidprocess_next_inline (t) tree t;{ tree context; struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t); context = hack_decl_function_context (i->fndecl); if (context) pop_cp_function_context (context); i = i->next; if (yychar == YYEMPTY) yychar = yylex (); if (yychar != END_OF_SAVED_INPUT) { error ("parse error at end of saved function text"); /* restore_pending_input will abort unless yychar is either END_OF_SAVED_INPUT or YYEMPTY; since we already know we're hosed, feed back YYEMPTY. We also need to discard nextchar, since that may have gotten set as well. */ nextchar = -1; } yychar = YYEMPTY; end_input (); if (i) begin_definition_of_inclass_inline (i); else extract_interface_info ();}/* Since inline methods can refer to text which has not yet been seen, we store the text of the method in a structure which is placed in the DECL_PENDING_INLINE_INFO field of the FUNCTION_DECL. After parsing the body of the class definition, the FUNCTION_DECL's are scanned to see which ones have this field set. Those are then digested one at a time. This function's FUNCTION_DECL will have a bit set in its common so that we know to watch out for it. */static voidconsume_string (this_obstack, matching_char) register struct obstack *this_obstack; int matching_char;{ register int c; int starting_lineno = lineno; do { c = getch (); if (c == EOF) { int save_lineno = lineno; lineno = starting_lineno; if (matching_char == '"') error ("end of file encountered inside string constant"); else error ("end of file encountered inside character constant"); lineno = save_lineno; return; } if (c == '\\') { obstack_1grow (this_obstack, c); c = getch (); obstack_1grow (this_obstack, c); /* Make sure we continue the loop */ c = 0; continue; } if (c == '\n') { if (pedantic) pedwarn ("ANSI C++ forbids newline in string constant"); lineno++; } obstack_1grow (this_obstack, c); } while (c != matching_char);}static int nextyychar = YYEMPTY;static YYSTYPE nextyylval;struct pending_input { int nextchar, yychar, nextyychar, eof; YYSTYPE yylval, nextyylval; struct obstack token_obstack; int first_token;};struct pending_input *save_pending_input (){ struct pending_input *p; p = (struct pending_input *) xmalloc (sizeof (struct pending_input)); p->nextchar = nextchar; p->yychar = yychar; p->nextyychar = nextyychar; p->yylval = yylval; p->nextyylval = nextyylval; p->eof = end_of_file; yychar = nextyychar = YYEMPTY; nextchar = -1; p->first_token = first_token; p->token_obstack = token_obstack; first_token = 0; gcc_obstack_init (&token_obstack); end_of_file = 0; return p;}voidrestore_pending_input (p) struct pending_input *p;{ my_friendly_assert (nextchar == -1, 229); nextchar = p->nextchar; my_friendly_assert (yychar == YYEMPTY || yychar == END_OF_SAVED_INPUT, 230); yychar = p->yychar; my_friendly_assert (nextyychar == YYEMPTY, 231); nextyychar = p->nextyychar; yylval = p->yylval; nextyylval = p->nextyylval; first_token = p->first_token; obstack_free (&token_obstack, (char *) 0); token_obstack = p->token_obstack; end_of_file = p->eof; free (p);}/* Unget character CH from the input stream. If RESCAN is non-zero, then we want to `see' this character as the next input token. */voidyyungetc (ch, rescan) int ch; int rescan;{ /* Unget a character from the input stream. */ if (yychar == YYEMPTY || rescan == 0) { if (nextchar >= 0) put_back (nextchar); nextchar = ch; } else { my_friendly_assert (nextyychar == YYEMPTY, 232); nextyychar = yychar; nextyylval = yylval; yychar = ch; }}voidclear_inline_text_obstack (){ obstack_free (&inline_text_obstack, inline_text_firstobj);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -