📄 lex.c
字号:
/* Lexical analyzer for GNU CHILL. -*- C -*- Copyright (C) 1992, 93, 1994, 1998 Free Software Foundation, Inc.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 the 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. */#include "config.h"#include "system.h"#include <setjmp.h>#include <sys/stat.h>#include "tree.h"#include "input.h"#include "lex.h"#include "ch-tree.h"#include "flags.h"#include "parse.h"#include "obstack.h"#include "toplev.h"#ifdef DWARF_DEBUGGING_INFO#include "dwarfout.h"#endif#ifdef MULTIBYTE_CHARS#include <locale.h>#endif/* include the keyword recognizers */#include "hash.h"FILE* finput;#if 0static int last_token = 0;/* Sun's C compiler warns about the safer sequence do { .. } while 0 when there's a 'return' inside the braces, so don't use it */#define RETURN_TOKEN(X) { last_token = X; return (X); }#endif/* This is set non-zero to force incoming tokens to lowercase. */extern int ignore_case;extern int module_number;extern int serious_errors;/* This is non-zero to recognize only uppercase special words. */extern int special_UC;extern struct obstack permanent_obstack;extern struct obstack temporary_obstack;/* forward declarations */static void close_input_file PROTO((char *));static tree convert_bitstring PROTO((char *));static tree convert_integer PROTO((char *));static void maybe_downcase PROTO((char *));static int maybe_number PROTO((char *));static tree equal_number PROTO((void));static void handle_use_seizefile_directive PROTO((int));static int handle_name PROTO((tree));static char *readstring PROTO((int, int *));static void read_directive PROTO((void));static tree read_identifier PROTO((int));static tree read_number PROTO((int));static void skip_c_comment PROTO((void));static void skip_line_comment PROTO((void));static int skip_whitespace PROTO((void));static tree string_or_char PROTO((int, char *));/* next variables are public, because ch-actions uses them *//* the default grantfile name, set by lang_init */tree default_grant_file = 0;/* These tasking-related variables are NULL at the start of each compiler pass, and are set to an expression tree if and when a compiler directive is parsed containing an expression. The NULL state is significant; it means 'no user-specified signal_code (or whatever) has been parsed'. *//* process type, set by <> PROCESS_TYPE = number <> */tree process_type = NULL_TREE;/* send buffer default priority, set by <> SEND_BUFFER_DEFAULT_PRIORITY = number <> */tree send_buffer_prio = NULL_TREE;/* send signal default priority, set by <> SEND_SIGNAL_DEFAULT_PRIORITY = number <> */tree send_signal_prio = NULL_TREE;/* signal code, set by <> SIGNAL_CODE = number <> */tree signal_code = NULL_TREE;/* flag for range checking */int range_checking = 1;/* flag for NULL pointer checking */int empty_checking = 1;/* flag to indicate making all procedure local variables to be STATIC */int all_static_flag = 0;/* flag to indicate -fruntime-checking command line option. Needed for initializing range_checking and empty_checking before pass 2 */int runtime_checking_flag = 1;/* 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];/* Nonzero tells yylex to ignore \ in string constants. */static int ignore_escape_flag = 0;static int maxtoken; /* Current nominal length of token buffer. */char *token_buffer; /* Pointer to token buffer. Actual allocated length is maxtoken + 2. This is not static because objc-parse.y uses it. *//* implement yylineno handling for flex */#define yylineno linenostatic int inside_c_comment = 0;static int saw_eol = 0; /* 1 if we've just seen a '\n' */static int saw_eof = 0; /* 1 if we've just seen an EOF */typedef struct string_list { struct string_list *next; char *str; } STRING_LIST;/* list of paths specified on the compiler command line by -L options. */static STRING_LIST *seize_path_list = (STRING_LIST *)0;/* List of seize file names. Each TREE_VALUE is an identifier (file name) from a <>USE_SEIZE_FILE<> directive. The TREE_PURPOSE is non-NULL if a USE_SEIZE_FILE directive has been written to the grant file. */static tree files_to_seize = NULL_TREE;/* Last node on files_to_seize list. */static tree last_file_to_seize = NULL_TREE;/* Pointer into files_to_seize list: Next unparsed file to read. */static tree next_file_to_seize = NULL_TREE;/* The most recent use_seize_file directive. */tree use_seizefile_name = NULL_TREE;/* If non-NULL, the name of the seizefile we're currently processing. */tree current_seizefile_name = NULL_TREE;/* called to reset for pass 2 */static voidch_lex_init (){ current_seizefile_name = NULL_TREE; lineno = 0; saw_eol = 0; saw_eof = 0; /* Initialize these compiler-directive variables. */ process_type = NULL_TREE; send_buffer_prio = NULL_TREE; send_signal_prio = NULL_TREE; signal_code = NULL_TREE; all_static_flag = 0; /* reinitialize rnage checking and empty checking */ range_checking = runtime_checking_flag; empty_checking = runtime_checking_flag;}char *init_parse (filename) char *filename;{ int lowercase_standard_names = ignore_case || ! special_UC; /* Open input file. */ if (filename == 0 || !strcmp (filename, "-")) { finput = stdin; filename = "stdin"; } else finput = fopen (filename, "r"); if (finput == 0) pfatal_with_name (filename);#ifdef IO_BUFFER_SIZE setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);#endif /* Make identifier nodes long enough for the language-specific slots. */ set_identifier_size (sizeof (struct lang_identifier)); /* Start it at 0, because check_newline is called at the very beginning and will increment it to 1. */ lineno = 0; /* Initialize these compiler-directive variables. */ process_type = NULL_TREE; send_buffer_prio = NULL_TREE; send_signal_prio = NULL_TREE; signal_code = NULL_TREE; maxtoken = 40; token_buffer = xmalloc ((unsigned)(maxtoken + 2)); init_chill_expand ();#define ENTER_STANDARD_NAME(RID, LOWER, UPPER) \ ridpointers[(int) RID] = \ get_identifier (lowercase_standard_names ? LOWER : UPPER) ENTER_STANDARD_NAME (RID_ALL, "all", "ALL"); ENTER_STANDARD_NAME (RID_ASSERTFAIL, "assertfail", "ASSERTFAIL"); ENTER_STANDARD_NAME (RID_ASSOCIATION, "association", "ASSOCIATION"); ENTER_STANDARD_NAME (RID_BIN, "bin", "BIN"); ENTER_STANDARD_NAME (RID_BOOL, "bool", "BOOL"); ENTER_STANDARD_NAME (RID_BOOLS, "bools", "BOOLS"); ENTER_STANDARD_NAME (RID_BYTE, "byte", "BYTE"); ENTER_STANDARD_NAME (RID_CHAR, "char", "CHAR"); ENTER_STANDARD_NAME (RID_DOUBLE, "double", "DOUBLE"); ENTER_STANDARD_NAME (RID_DURATION, "duration", "DURATION"); ENTER_STANDARD_NAME (RID_DYNAMIC, "dynamic", "DYNAMIC"); ENTER_STANDARD_NAME (RID_ELSE, "else", "ELSE"); ENTER_STANDARD_NAME (RID_EMPTY, "empty", "EMPTY"); ENTER_STANDARD_NAME (RID_FALSE, "false", "FALSE"); ENTER_STANDARD_NAME (RID_FLOAT, "float", "FLOAT"); ENTER_STANDARD_NAME (RID_GENERAL, "general", "GENERAL"); ENTER_STANDARD_NAME (RID_IN, "in", "IN"); ENTER_STANDARD_NAME (RID_INLINE, "inline", "INLINE"); ENTER_STANDARD_NAME (RID_INOUT, "inout", "INOUT"); ENTER_STANDARD_NAME (RID_INSTANCE, "instance", "INSTANCE"); ENTER_STANDARD_NAME (RID_INT, "int", "INT"); ENTER_STANDARD_NAME (RID_LOC, "loc", "LOC"); ENTER_STANDARD_NAME (RID_LONG, "long", "LONG"); ENTER_STANDARD_NAME (RID_LONG_REAL, "long_real", "LONG_REAL"); ENTER_STANDARD_NAME (RID_NULL, "null", "NULL"); ENTER_STANDARD_NAME (RID_OUT, "out", "OUT"); ENTER_STANDARD_NAME (RID_OVERFLOW, "overflow", "OVERFLOW"); ENTER_STANDARD_NAME (RID_PTR, "ptr", "PTR"); ENTER_STANDARD_NAME (RID_READ, "read", "READ"); ENTER_STANDARD_NAME (RID_REAL, "real", "REAL"); ENTER_STANDARD_NAME (RID_RANGE, "range", "RANGE"); ENTER_STANDARD_NAME (RID_RANGEFAIL, "rangefail", "RANGEFAIL"); ENTER_STANDARD_NAME (RID_RECURSIVE, "recursive", "RECURSIVE"); ENTER_STANDARD_NAME (RID_SHORT, "short", "SHORT"); ENTER_STANDARD_NAME (RID_SIMPLE, "simple", "SIMPLE"); ENTER_STANDARD_NAME (RID_TIME, "time", "TIME"); ENTER_STANDARD_NAME (RID_TRUE, "true", "TRUE"); ENTER_STANDARD_NAME (RID_UBYTE, "ubyte", "UBYTE"); ENTER_STANDARD_NAME (RID_UINT, "uint", "UINT"); ENTER_STANDARD_NAME (RID_ULONG, "ulong", "ULONG"); ENTER_STANDARD_NAME (RID_UNSIGNED, "unsigned", "UNSIGNED"); ENTER_STANDARD_NAME (RID_USHORT, "ushort", "USHORT"); ENTER_STANDARD_NAME (RID_VOID, "void", "VOID"); return filename;}voidfinish_parse (){ if (finput != NULL) fclose (finput);}static int yywrap ();#define YY_PUTBACK_SIZE 5#define YY_BUF_SIZE 1000static char yy_buffer[YY_PUTBACK_SIZE + YY_BUF_SIZE];static char *yy_cur = yy_buffer + YY_PUTBACK_SIZE;static char *yy_lim = yy_buffer + YY_PUTBACK_SIZE;int yy_refill (){ char *buf = yy_buffer + YY_PUTBACK_SIZE; int c, result; bcopy (yy_cur - YY_PUTBACK_SIZE, yy_buffer, YY_PUTBACK_SIZE); yy_cur = buf; retry: if (saw_eof) { if (yywrap ()) return EOF; saw_eof = 0; goto retry; } result = 0; while (saw_eol) { c = check_newline (); if (c == EOF) { saw_eof = 1; goto retry; } else if (c != '\n') { saw_eol = 0; buf[result++] = c; } } while (result < YY_BUF_SIZE) { c = getc(finput); if (c == EOF) { saw_eof = 1; break; } buf[result++] = c; /* Because we might switch input files on a compiler directive (that end with '>', don't read past a '>', just in case. */ if (c == '>') break; if (c == '\n') {#ifdef YYDEBUG extern int yydebug; if (yydebug) fprintf (stderr, "-------------------------- finished Line %d\n", yylineno);#endif saw_eol = 1; break; } } yy_lim = yy_cur + result; return yy_lim > yy_cur ? *yy_cur++ : EOF;}#define input() (yy_cur < yy_lim ? *yy_cur++ : yy_refill ())#define unput(c) (*--yy_cur = (c))int starting_pass_2 = 0;intyylex (){ int nextc; int len; char* tmp; int base; int ch; retry: ch = input (); if (starting_pass_2) { starting_pass_2 = 0; unput (ch); return END_PASS_1; } switch (ch) { case ' ': case '\t': case '\n': case '\f': case '\b': case '\v': case '\r': goto retry; case '[': return LPC; case ']': return RPC; case '{': return LC; case '}': return RC; case '(': nextc = input (); if (nextc == ':') return LPC; unput (nextc); return LPRN; case ')': return RPRN; case ':': nextc = input (); if (nextc == ')') return RPC; else if (nextc == '=') return ASGN; unput (nextc); return COLON; case ',': return COMMA; case ';': return SC; case '+': return PLUS; case '-': nextc = input (); if (nextc == '>') return ARROW; if (nextc == '-') { skip_line_comment (); goto retry; } unput (nextc); return SUB; case '*': return MUL; case '=': return EQL; case '/': nextc = input (); if (nextc == '/') return CONCAT; else if (nextc == '=') return NE; else if (nextc == '*') { skip_c_comment (); goto retry; } unput (nextc); return DIV; case '<': nextc = input (); if (nextc == '=') return LTE; if (nextc == '>') { read_directive (); goto retry; } unput (nextc); return LT; case '>': nextc = input (); if (nextc == '=') return GTE; unput (nextc); return GT; case 'D': case 'd': base = 10; goto maybe_digits; case 'B': case 'b': base = 2; goto maybe_digits; case 'H': case 'h': base = 16; goto maybe_digits; case 'O': case 'o': base = 8; goto maybe_digits; case 'C': case 'c': nextc = input (); if (nextc == '\'') { int byte_val = 0; char *start; int len = 0; /* Number of hex digits seen. */ for (;;) { ch = input (); if (ch == '\'') break; if (ch == '_') continue; if (!ISXDIGIT (ch)) /* error on non-hex digit */ { if (pass == 1) error ("invalid C'xx' "); break; } if (ch >= 'a') ch -= ' '; ch -= '0'; if (ch > 9) ch -= 7; byte_val *= 16; byte_val += (int)ch; if (len & 1) /* collected two digits, save byte */ obstack_1grow (&temporary_obstack, (char) byte_val); len++; } start = obstack_finish (&temporary_obstack); yylval.ttype = string_or_char (len >> 1, start); obstack_free (&temporary_obstack, start); return len == 2 ? SINGLECHAR : STRING; } unput (nextc); goto letter; maybe_digits: nextc = input (); if (nextc == '\'') { char *start; obstack_1grow (&temporary_obstack, ch); obstack_1grow (&temporary_obstack, nextc); for (;;) { ch = input (); if (ISALNUM (ch)) obstack_1grow (&temporary_obstack, ch); else if (ch != '_') break; } obstack_1grow (&temporary_obstack, '\0'); start = obstack_finish (&temporary_obstack); if (ch != '\'') { unput (ch); yylval.ttype = convert_integer (start); /* Pass base? */ return NUMBER; } else { yylval.ttype = convert_bitstring (start); return BITSTRING; } } unput (nextc); goto letter; case 'A': case 'E': case 'F': case 'G': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y':
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -