⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c-parse.y

📁 这是完整的gcc源代码
💻 Y
📖 第 1 页 / 共 5 页
字号:
   last characters in the string, thus assuring the O(1) lookup time   (this keeps our constant down to an insignificant amount!).  Compiling   the following 2 functions as inline removes all overhead of the   function calls. */#ifdef __GNUC____inline#endifstatic inthash (str, len)     register char *str;     register int len;{/* This table is used to build the hash table index that recognizes   reserved words in 0(1) steps.  It is larger than strictly necessary,   but I'm trading off the space for the time-saving luxury of avoiding   subtraction of an offset.  All those ``91's'' (actually just a   short-hand for MAX_HASH_VALUE #defined above) are used to speed up   the search when the string found on the input stream doesn't have a   first or last character that is part of the set of alphabetic   characters that comprise the first or last characters in C   reserved words. */  static int hash_table[] =    {     91, 91, 91, 91, 91, 91, 91, 91, 91, 91,     91, 91, 91, 91, 91, 91, 91, 91, 91, 91,     91, 91, 91, 91, 91, 91, 91, 91, 91, 91,     91, 91, 91, 91, 91, 91, 91, 91, 91, 91,     91, 91, 91, 91, 91, 91, 91, 91, 91, 91,     91, 91, 91, 91, 91, 91, 91, 91, 91, 91,     91, 91, 91, 91, 91, 91, 91, 91, 91, 91,     91, 91, 91, 91, 91, 91, 91, 91, 91, 91,     91, 91, 91, 91, 91, 91, 91, 91, 91, 91,     91, 91, 91, 91, 91,  1, 91,  2,  1, 32,      7,  5, 18, 20,  1, 17, 91,  1, 18,  1,     28,  1, 23, 91, 12, 20,  1, 41,  7, 15,     91, 91, 10, 91, 91, 91, 91, 91,    };  register int hval = len ;  switch (hval)    {      default:      case 3:        hval += hash_table[str[2]];      case 2:      case 1:        return hval + hash_table[str[0]] + hash_table[str[len - 1]];    }}/* This routine attempts to match the string found in the reswords table   with the one from the input stream.  If all the relevant details   match then an actual strcmp comparison is performed and the address of   correct struct resword entry is returned.  Otherwise, a NULL   pointer is returned. */#ifdef __GNUC____inline#endifstruct resword *is_reserved_word (str, len)     register char *str;     register int len;{  /* This is the hash table of keywords.     The order of keywords has been chosen for perfect hashing.     Therefore, this table cannot be updated by hand.     Use the program ``gperf,'' available with the latest libg++     distribution, to generate an updated table.  A file called     c-parse.gperf, distributed with GNU C, contains the keyword file.  */  static struct resword reswords[] =    {      { "", }, { "", }, { "", }, { "", }, { "", }, { "", }, { "", },       {"asm",  ASM, NORID },      {"auto",  SCSPEC, RID_AUTO },      {"__asm",  ASM, NORID },      {"do",  DO, NORID },      {"__asm__",  ASM, NORID },      {"break",  BREAK, NORID },      {"__typeof__",  TYPEOF, NORID },      { "", },       {"__alignof__",  ALIGNOF, NORID },      { "", },       {"__attribute__",  ATTRIBUTE, NORID },      { "", },       {"__attribute",  ATTRIBUTE, NORID },      { "", },       {"__volatile__",  TYPE_QUAL, RID_VOLATILE },      {"int",  TYPESPEC, RID_INT },      {"__volatile",  TYPE_QUAL, RID_VOLATILE },      { "", },       {"float",  TYPESPEC, RID_FLOAT },      {"goto",  GOTO, NORID },      {"short",  TYPESPEC, RID_SHORT },      {"__typeof",  TYPEOF, NORID },      {"__inline__",  SCSPEC, RID_INLINE },      {"__alignof",  ALIGNOF, NORID },      {"__inline",  SCSPEC, RID_INLINE },      {"__signed__",  TYPESPEC, RID_SIGNED },      {"default",  DEFAULT, NORID },      {"else",  ELSE, NORID },      {"void",  TYPESPEC, RID_VOID },      {"__signed",  TYPESPEC, RID_SIGNED },      {"if",  IF, NORID },      {"volatile",  TYPE_QUAL, RID_VOLATILE },      {"struct",  STRUCT, NORID },      {"extern",  SCSPEC, RID_EXTERN },      {"__const",  TYPE_QUAL, RID_CONST },      {"while",  WHILE, NORID },      {"__const__",  TYPE_QUAL, RID_CONST },      {"switch",  SWITCH, NORID },      {"for",  FOR, NORID },      {"inline",  SCSPEC, RID_INLINE },      {"return",  RETURN, NORID },      {"typeof",  TYPEOF, NORID },      {"typedef",  SCSPEC, RID_TYPEDEF },      {"char",  TYPESPEC, RID_CHAR },      {"enum",  ENUM, NORID },      {"register",  SCSPEC, RID_REGISTER },      {"signed",  TYPESPEC, RID_SIGNED },      {"sizeof",  SIZEOF, NORID },      { "", }, { "", }, { "", }, { "", },       {"double",  TYPESPEC, RID_DOUBLE },      {"static",  SCSPEC, RID_STATIC },      {"case",  CASE, NORID },      { "", }, { "", }, { "", }, { "", },       {"const",  TYPE_QUAL, RID_CONST },      { "", }, { "", }, { "", },       {"long",  TYPESPEC, RID_LONG },      { "", }, { "", },       {"continue",  CONTINUE, NORID },      { "", }, { "", },       {"unsigned",  TYPESPEC, RID_UNSIGNED },      { "", }, { "", }, { "", }, { "", }, { "", }, { "", }, { "", }, { "", }, { "", },       { "", }, { "", }, { "", }, { "", }, { "", },       {"union",  UNION, NORID },    };  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)    {      register int key = hash (str, len);      if (key <= MAX_HASH_VALUE)        {          register char *s = reswords[key].name;          if (*s == *str && !strcmp (str + 1, s + 1))            return &reswords[key];        }    }  return 0;}/* 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];int check_newline ();voidinit_lex (){  /* Start it at 0, because check_newline is called at the very beginning     and will increment it to 1.  */  lineno = 0;  maxtoken = 40;  token_buffer = (char *) xmalloc (maxtoken + 2);  max_wide = 40;  wide_buffer = (int *) xmalloc ((max_wide + 1) * UNITS_PER_WORD);  ridpointers[(int) RID_INT] = get_identifier ("int");  ridpointers[(int) RID_CHAR] = get_identifier ("char");  ridpointers[(int) RID_VOID] = get_identifier ("void");  ridpointers[(int) RID_FLOAT] = get_identifier ("float");  ridpointers[(int) RID_DOUBLE] = get_identifier ("double");  ridpointers[(int) RID_SHORT] = get_identifier ("short");  ridpointers[(int) RID_LONG] = get_identifier ("long");  ridpointers[(int) RID_UNSIGNED] = get_identifier ("unsigned");  ridpointers[(int) RID_SIGNED] = get_identifier ("signed");  ridpointers[(int) RID_INLINE] = get_identifier ("inline");  ridpointers[(int) RID_CONST] = get_identifier ("const");  ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");  ridpointers[(int) RID_AUTO] = get_identifier ("auto");  ridpointers[(int) RID_STATIC] = get_identifier ("static");  ridpointers[(int) RID_EXTERN] = get_identifier ("extern");  ridpointers[(int) RID_TYPEDEF] = get_identifier ("typedef");  ridpointers[(int) RID_REGISTER] = get_identifier ("register");}static voidreinit_parse_for_function (){}/* If C is not whitespace, return C.   Otherwise skip whitespace and return first nonwhite char read.  */static intskip_white_space (c)     register int c;{#if 0  register int inside;#endif  for (;;)    {      switch (c)	{	  /* Don't recognize comments in cc1: all comments are removed by cpp,	     and cpp output can include / and * consecutively as operators.  */#if 0	case '/':	  c = getc (finput);	  if (c != '*')	    {	      ungetc (c, finput);	      return '/';	    }	  c = getc (finput);	  inside = 1;	  while (inside)	    {	      if (c == '*')		{		  while (c == '*')		    c = getc (finput);		  if (c == '/')		    {		      inside = 0;		      c = getc (finput);		    }		}	      else if (c == '\n')		{		  lineno++;		  c = getc (finput);		}	      else if (c == EOF)		{		  error ("unterminated comment");		  break;		}	      else		c = getc (finput);	    }	  break;#endif	case '\n':	  c = check_newline ();	  break;	case ' ':	case '\t':	case '\f':	case '\r':	case '\v':	case '\b':	  c = getc (finput);	  break;	case '\\':	  c = getc (finput);	  if (c == '\n')	    lineno++;	  else	    error ("stray '\\' in program");	  c = getc (finput);	  break;	default:	  return (c);	}    }}/* Make the token buffer longer, preserving the data in it.   P should point to just beyond the last valid character in the old buffer.   The value we return is a pointer to the new buffer   at a place corresponding to P.  */static char *extend_token_buffer (p)     char *p;{  int offset = p - token_buffer;  maxtoken = maxtoken * 2 + 10;  token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2);  return token_buffer + offset;}/* At the beginning of a line, increment the line number   and process any #-directive on this line.   If the line is a #-directive, read the entire line and return a newline.   Otherwise, return the line's first non-whitespace character.  */intcheck_newline (){  register int c;  register int token;  lineno++;  /* Read first nonwhite char on the line.  */  c = getc (finput);  while (c == ' ' || c == '\t')    c = getc (finput);  if (c != '#')    {      /* If not #, return it so caller will use it.  */      return c;    }  /* Read first nonwhite char after the `#'.  */  c = getc (finput);  while (c == ' ' || c == '\t')    c = getc (finput);  /* If a letter follows, then if the word here is `line', skip     it and ignore it; otherwise, ignore the line, with an error     if the word isn't `pragma'.  */  if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))    {      if (c == 'p')	{	  if (getc (finput) == 'r'	      && getc (finput) == 'a'	      && getc (finput) == 'g'	      && getc (finput) == 'm'	      && getc (finput) == 'a'	      && ((c = getc (finput)) == ' ' || c == '\t' || c == '\n'))	    goto skipline;	}      else if (c == 'l')	{	  if (getc (finput) == 'i'	      && getc (finput) == 'n'	      && getc (finput) == 'e'	      && ((c = getc (finput)) == ' ' || c == '\t'))	    goto linenum;	}      else if (c == 'i')	{	  if (getc (finput) == 'd'	      && getc (finput) == 'e'	      && getc (finput) == 'n'	      && getc (finput) == 't'	      && ((c = getc (finput)) == ' ' || c == '\t'))	    {	      extern FILE *asm_out_file;	      if (pedantic)		error ("ANSI C does not allow #ident");	      /* Here we have just seen `#ident '.		 A string constant should follow.  */	      while (c == ' ' || c == '\t')		c = getc (finput);	      /* If no argument, ignore the line.  */	      if (c == '\n')		return c;	      ungetc (c, finput);	      token = yylex ();	      if (nextchar >= 0)		ungetc (nextchar, finput), nextchar = -1;	      if (token != STRING		  || TREE_CODE (yylval.ttype) != STRING_CST)		{		  error ("invalid #ident");		  goto skipline;		}#ifdef ASM_OUTPUT_IDENT	      ASM_OUTPUT_IDENT (asm_out_file, TREE_STRING_POINTER (yylval.ttype));#endif	      /* Skip the rest of this line.  */	      goto skipline;	    }	}      error ("undefined or invalid # directive");      goto skipline;    }linenum:  /* Here we have either `#line' or `# <nonletter>'.     In either case, it should be a line number; a digit should follow.  */  while (c == ' ' || c == '\t')    c = getc (finput);  /* If the # is the only nonwhite char on the line,     just ignore it.  Check the new newline.  */  if (c == '\n')    return c;  /* Something follows the #; read a token.  */  ungetc (c, finput);  token = yylex ();  if (nextchar >= 0)    ungetc (nextchar, finput), nextchar = -1;  if (token == CONSTANT      && TREE_CODE (yylval.ttype) == INTEGER_CST)    {      int old_lineno = lineno;      /* subtract one, because it is the following line that	 gets the specified number */      int l = TREE_INT_CST_LOW (yylval.ttype) - 1;      /* Is this the last nonwhite stuff on the line?  */      c = getc (finput);      while (c == ' ' || c == '\t')	c = getc (finput);      if (c == '\n')	{	  /* No more: store the line number and check following line.  */	  lineno = l;	  return c;	}      ungetc (c, finput);      /* More follows: it must be a string constant (filename).  */      token = yylex ();      if (nextchar >= 0)	ungetc (nextchar, finput), nextchar = -1;      if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)	{	  error ("invalid #line");	  goto skipline;	}      input_filename	= (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);      strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));      lineno = l;      if (main_input_filename == 0)	main_input_filename = input_filename;      /* Is this the last nonwhite stuff on the line?  */      c = getc (finput);      while (c == ' ' || c == '\t')	c = getc (finput);      if (c == '\n')	return c;      ungetc (c, finput);      token = yylex ();      if (nextchar >= 0)	ungetc (nextchar, finput), nextchar = -1;      /* `1' after file name means entering new file.	 `2' after file name means just left a file.  */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -