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

📄 c-lex.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
		    spec_long = 1;		  }		else		  {		    if (isalnum (c))		      {			error ("garbage at end of number");			while (isalnum (c))			  {			    if (p >= token_buffer + maxtoken - 3)			      p = extend_token_buffer (p);			    *p++ = c;			    c = getc (finput);			  }		      }		    break;		  }		if (p >= token_buffer + maxtoken - 3)		  p = extend_token_buffer (p);		*p++ = c;		c = getc (finput);	      }	    ungetc (c, finput);	    /* If the constant is not long long and it won't fit in an	       unsigned long, or if the constant is long long and won't fit	       in an unsigned long long, then warn that the constant is out	       of range.  */	    /* ??? This assumes that long long and long integer types are	       a multiple of 8 bits.  This better than the original code	       though which assumed that long was exactly 32 bits and long	       long was exactly 64 bits.  */	    if (spec_long_long)	      bytes = TYPE_PRECISION (long_long_integer_type_node) / 8;	    else	      bytes = TYPE_PRECISION (long_integer_type_node) / 8;	    warn = overflow;	    for (i = bytes; i < TOTAL_PARTS; i++)	      if (parts[i])		warn = 1;	    if (warn)	      pedwarn ("integer constant out of range");	    /* This is simplified by the fact that our constant	       is always positive.  */	    high = low = 0;	    for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; i++)	      {		high |= ((HOST_WIDE_INT) parts[i + (HOST_BITS_PER_WIDE_INT						    / HOST_BITS_PER_CHAR)]			 << (i * HOST_BITS_PER_CHAR));		low |= (HOST_WIDE_INT) parts[i] << (i * HOST_BITS_PER_CHAR);	      }	    	    yylval.ttype = build_int_2 (low, high);	    TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node;	    /* If warn_traditional, calculate both the ANSI type and the	       traditional type, then see if they disagree.	       Otherwise, calculate only the type for the dialect in use.  */	    if (warn_traditional || flag_traditional)	      {		/* Calculate the traditional type.  */		/* Traditionally, any constant is signed;		   but if unsigned is specified explicitly, obey that.		   Use the smallest size with the right number of bits,		   except for one special case with decimal constants.  */		if (! spec_long && base != 10		    && int_fits_type_p (yylval.ttype, unsigned_type_node))		  traditional_type = (spec_unsigned ? unsigned_type_node				      : integer_type_node);		/* A decimal constant must be long		   if it does not fit in type int.		   I think this is independent of whether		   the constant is signed.  */		else if (! spec_long && base == 10			 && int_fits_type_p (yylval.ttype, integer_type_node))		  traditional_type = (spec_unsigned ? unsigned_type_node				      : integer_type_node);		else if (! spec_long_long)		  traditional_type = (spec_unsigned ? long_unsigned_type_node				      : long_integer_type_node);		else		  traditional_type = (spec_unsigned				      ? long_long_unsigned_type_node				      : long_long_integer_type_node);	      }	    if (warn_traditional || ! flag_traditional)	      {		/* Calculate the ANSI type.  */		if (! spec_long && ! spec_unsigned		    && int_fits_type_p (yylval.ttype, integer_type_node))		  ansi_type = integer_type_node;		else if (! spec_long && (base != 10 || spec_unsigned)			 && int_fits_type_p (yylval.ttype, unsigned_type_node))		  ansi_type = unsigned_type_node;		else if (! spec_unsigned && !spec_long_long			 && int_fits_type_p (yylval.ttype, long_integer_type_node))		  ansi_type = long_integer_type_node;		else if (! spec_long_long)		  ansi_type = long_unsigned_type_node;		else if (! spec_unsigned			 /* Verify value does not overflow into sign bit.  */			 && TREE_INT_CST_HIGH (yylval.ttype) >= 0			 && int_fits_type_p (yylval.ttype,					     long_long_integer_type_node))		  ansi_type = long_long_integer_type_node;		else		  ansi_type = long_long_unsigned_type_node;	      }	    type = flag_traditional ? traditional_type : ansi_type;	    if (warn_traditional && traditional_type != ansi_type)	      {		if (TYPE_PRECISION (traditional_type)		    != TYPE_PRECISION (ansi_type))		  warning ("width of integer constant changes with -traditional");		else if (TREE_UNSIGNED (traditional_type)			 != TREE_UNSIGNED (ansi_type))		  warning ("integer constant is unsigned in ANSI C, signed with -traditional");		else		  warning ("width of integer constant may change on other systems with -traditional");	      }	    if (!flag_traditional && !int_fits_type_p (yylval.ttype, type)		&& !warn)	      pedwarn ("integer constant out of range");	    if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))	      warning ("integer constant is so large that it is unsigned");	    if (flag_traditional && !int_fits_type_p (yylval.ttype, type))	      /* The traditional constant 0x80000000 is signed		 but doesn't fit in the range of int.		 This will change it to -0x80000000, which does fit.  */	      {		TREE_TYPE (yylval.ttype) = unsigned_type (type);		yylval.ttype = convert (type, yylval.ttype);	      }	    else	      TREE_TYPE (yylval.ttype) = type;	    *p = 0;	  }	value = CONSTANT; break;      }    case '\'':    char_constant:      {	register int result = 0;	register int num_chars = 0;	unsigned width = TYPE_PRECISION (char_type_node);	int max_chars;	if (wide_flag)	  {	    width = WCHAR_TYPE_SIZE;#ifdef MULTIBYTE_CHARS	    max_chars = MB_CUR_MAX;#else	    max_chars = 1;#endif	  }	else	  max_chars = TYPE_PRECISION (integer_type_node) / width;	while (1)	  {	  tryagain:	    c = getc (finput);	    if (c == '\'' || c == EOF)	      break;	    if (c == '\\')	      {		int ignore = 0;		c = readescape (&ignore);		if (ignore)		  goto tryagain;		if (width < HOST_BITS_PER_INT		    && (unsigned) c >= (1 << width))		  pedwarn ("escape sequence out of range for character");	      }	    else if (c == '\n')	      {		if (pedantic)		  pedwarn ("ANSI C forbids newline in character constant");		lineno++;	      }	    num_chars++;	    if (num_chars > maxtoken - 4)	      extend_token_buffer (token_buffer);	    token_buffer[num_chars] = c;	    /* Merge character into result; ignore excess chars.  */	    if (num_chars < max_chars + 1)	      {		if (width < HOST_BITS_PER_INT)		  result = (result << width) | (c & ((1 << width) - 1));		else		  result = c;	      }	  }	token_buffer[num_chars + 1] = '\'';	token_buffer[num_chars + 2] = 0;	if (c != '\'')	  error ("malformatted character constant");	else if (num_chars == 0)	  error ("empty character constant");	else if (num_chars > max_chars)	  {	    num_chars = max_chars;	    error ("character constant too long");	  }	else if (num_chars != 1 && ! flag_traditional)	  warning ("multi-character character constant");	/* If char type is signed, sign-extend the constant.  */	if (! wide_flag)	  {	    int num_bits = num_chars * width;	    if (TREE_UNSIGNED (char_type_node)		|| ((result >> (num_bits - 1)) & 1) == 0)	      yylval.ttype		= build_int_2 (result & ((unsigned HOST_WIDE_INT) ~0					 >> (HOST_BITS_PER_WIDE_INT - num_bits)),			       0);	    else	      yylval.ttype		= build_int_2 (result | ~((unsigned HOST_WIDE_INT) ~0					  >> (HOST_BITS_PER_WIDE_INT - num_bits)),			       -1);	  }	else	  {#ifdef MULTIBYTE_CHARS	    /* Set the initial shift state and convert the next sequence.  */	    result = 0;	    /* In all locales L'\0' is zero and mbtowc will return zero,	       so don't use it.  */	    if (num_chars > 1		|| (num_chars == 1 && token_buffer[1] != '\0'))	      {		wchar_t wc;		(void) mbtowc (NULL_PTR, NULL_PTR, 0);		if (mbtowc (& wc, token_buffer + 1, num_chars) == num_chars)		  result = wc;		else		  warning ("Ignoring invalid multibyte character");	      }#endif	    yylval.ttype = build_int_2 (result, 0);	  }	TREE_TYPE (yylval.ttype) = integer_type_node;	value = CONSTANT;	break;      }    case '"':    string_constant:      {	c = getc (finput);	p = token_buffer + 1;	while (c != '"' && c >= 0)	  {	    /* ignore_escape_flag is set for reading the filename in #line.  */	    if (!ignore_escape_flag && c == '\\')	      {		int ignore = 0;		c = readescape (&ignore);		if (ignore)		  goto skipnewline;		if (!wide_flag		    && TYPE_PRECISION (char_type_node) < HOST_BITS_PER_INT		    && c >= (1 << TYPE_PRECISION (char_type_node)))		  pedwarn ("escape sequence out of range for character");	      }	    else if (c == '\n')	      {		if (pedantic)		  pedwarn ("ANSI C forbids newline in string constant");		lineno++;	      }	    if (p == token_buffer + maxtoken)	      p = extend_token_buffer (p);	    *p++ = c;	  skipnewline:	    c = getc (finput);	  }	*p = 0;	/* We have read the entire constant.	   Construct a STRING_CST for the result.  */	if (wide_flag)	  {	    /* If this is a L"..." wide-string, convert the multibyte string	       to a wide character string.  */	    char *widep = (char *) alloca ((p - token_buffer) * WCHAR_BYTES);	    int len;#ifdef MULTIBYTE_CHARS	    len = mbstowcs ((wchar_t *) widep, token_buffer + 1, p - token_buffer);	    if ((unsigned) len >= (p - token_buffer))	      {		warning ("Ignoring invalid multibyte string");		len = 0;	      }	    bzero (widep + (len * WCHAR_BYTES), WCHAR_BYTES);#else	    {	      union { long l; char c[sizeof (long)]; } u;	      int big_endian;	      char *wp, *cp;	      /* Determine whether host is little or big endian.  */	      u.l = 1;	      big_endian = u.c[sizeof (long) - 1];	      wp = widep + (big_endian ? WCHAR_BYTES - 1 : 0);	      bzero (widep, (p - token_buffer) * WCHAR_BYTES);	      for (cp = token_buffer + 1; cp < p; cp++)		*wp = *cp, wp += WCHAR_BYTES;	      len = p - token_buffer - 1;	    }#endif	    yylval.ttype = build_string ((len + 1) * WCHAR_BYTES, widep);	    TREE_TYPE (yylval.ttype) = wchar_array_type_node;	  }	else	  {	    yylval.ttype = build_string (p - token_buffer, token_buffer + 1);	    TREE_TYPE (yylval.ttype) = char_array_type_node;	  }	*p++ = '"';	*p = 0;	value = STRING; break;      }    case '+':    case '-':    case '&':    case '|':    case '<':    case '>':    case '*':    case '/':    case '%':    case '^':    case '!':    case '=':      {	register int c1;      combine:	switch (c)	  {	  case '+':	    yylval.code = PLUS_EXPR; break;	  case '-':	    yylval.code = MINUS_EXPR; break;	  case '&':	    yylval.code = BIT_AND_EXPR; break;	  case '|':	    yylval.code = BIT_IOR_EXPR; break;	  case '*':	    yylval.code = MULT_EXPR; break;	  case '/':	    yylval.code = TRUNC_DIV_EXPR; break;	  case '%':	    yylval.code = TRUNC_MOD_EXPR; break;	  case '^':	    yylval.code = BIT_XOR_EXPR; break;	  case LSHIFT:	    yylval.code = LSHIFT_EXPR; break;	  case RSHIFT:	    yylval.code = RSHIFT_EXPR; break;	  case '<':	    yylval.code = LT_EXPR; break;	  case '>':	    yylval.code = GT_EXPR; break;	  }	token_buffer[1] = c1 = getc (finput);	token_buffer[2] = 0;	if (c1 == '=')	  {	    switch (c)	      {	      case '<':		value = ARITHCOMPARE; yylval.code = LE_EXPR; goto done;	      case '>':		value = ARITHCOMPARE; yylval.code = GE_EXPR; goto done;	      case '!':		value = EQCOMPARE; yylval.code = NE_EXPR; goto done;	      case '=':		value = EQCOMPARE; yylval.code = EQ_EXPR; goto done;	      }	    value = ASSIGN; goto done;	  }	else if (c == c1)	  switch (c)	    {	    case '+':	      value = PLUSPLUS; goto done;	    case '-':	      value = MINUSMINUS; goto done;	    case '&':	      value = ANDAND; goto done;	    case '|':	      value = OROR; goto done;	    case '<':	      c = LSHIFT;	      goto combine;	    case '>':	      c = RSHIFT;	      goto combine;	    }	else if ((c == '-') && (c1 == '>'))	  { value = POINTSAT; goto done; }	ungetc (c1, finput);	token_buffer[1] = 0;	if ((c == '<') || (c == '>'))	  value = ARITHCOMPARE;	else value = c;	goto done;      }    case 0:      /* Don't make yyparse think this is eof.  */      value = 1;      break;    default:      value = c;    }done:/*  yylloc.last_line = lineno; */  return value;}/* 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  yydebug = value;#else  warning ("YYDEBUG not defined.");#endif}

⌨️ 快捷键说明

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