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

📄 c-lex.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		    if (spec_long)		      {			if (spec_long_long)			  error ("three `l's in integer constant");			else if (pedantic)			  pedwarn ("ANSI C forbids long long integer constants");			spec_long_long = 1;		      }		    spec_long = 1;		  }		else if (c == 'i' || c == 'j' || c == 'I' || c == 'J')		  {		    if (spec_imag)		      error ("more than one `i' or `j' in numeric constant");		    else if (pedantic)		      pedwarn ("ANSI C forbids imaginary numeric constants");		    spec_imag = 1;		  }		else		  break;		if (p >= token_buffer + maxtoken - 3)		  p = extend_token_buffer (p);		*p++ = c;		c = GETC();	      }	    /* If the constant 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.  */	    bytes = TYPE_PRECISION (long_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			 && int_fits_type_p (yylval.ttype,					     long_unsigned_type_node))		  ansi_type = long_unsigned_type_node;		else if (! spec_unsigned			 && 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 (pedantic && !flag_traditional && !spec_long_long && !warn		&& (TYPE_PRECISION (long_integer_type_node)		    < TYPE_PRECISION (type)))	      pedwarn ("integer constant out of range");	    if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))	      warning ("decimal constant is so large that it is unsigned");	    if (spec_imag)	      {		if (TYPE_PRECISION (type)		    <= TYPE_PRECISION (integer_type_node))		  yylval.ttype		    = build_complex (NULL_TREE, integer_zero_node,				     convert (integer_type_node,					      yylval.ttype));		else		  error ("complex integer constant is too wide for `complex int'");	      }	    else 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);		TREE_OVERFLOW (yylval.ttype)		  = TREE_CONSTANT_OVERFLOW (yylval.ttype) = 0;	      }	    else	      TREE_TYPE (yylval.ttype) = type;	  }	UNGETC (c);	*p = 0;	if (isalnum (c) || c == '.' || c == '_' || c == '$'	    || (!flag_traditional && (c == '-' || c == '+')		&& (p[-1] == 'e' || p[-1] == 'E')))	  error ("missing white space after number `%s'", token_buffer);	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();	    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");#ifdef MAP_CHARACTER		if (isprint (c))		  c = MAP_CHARACTER (c);#endif	      }	    else if (c == '\n')	      {		if (pedantic)		  pedwarn ("ANSI C forbids newline in character constant");		lineno++;	      }#ifdef MAP_CHARACTER	    else	      c = MAP_CHARACTER (c);#endif	    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 (num_bits == 0)	      /* We already got an error; avoid invalid shift.  */	      yylval.ttype = build_int_2 (0, 0);	    else 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);	    TREE_TYPE (yylval.ttype) = integer_type_node;	  }	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) = wchar_type_node;	  }	value = CONSTANT;	break;      }    case '"':    string_constant:      {	c = GETC();	p = token_buffer + 1;	while (c != '"' && c >= 0)	  {	    if (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();	  }	*p = 0;	if (c < 0)	  error ("Unterminated string constant");	/* 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 (len < 0 || len >= (p - token_buffer))	      {		warning ("Ignoring invalid multibyte string");		len = 0;	      }	    bzero (widep + (len * WCHAR_BYTES), WCHAR_BYTES);#else	    {	      char *wp, *cp;	      wp = widep + (BYTES_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;	    value = STRING;	  }	else if (objc_flag)	  {	    extern tree build_objc_string();	    /* Return an Objective-C @"..." constant string object.  */	    yylval.ttype = build_objc_string (p - token_buffer,					      token_buffer + 1);	    TREE_TYPE (yylval.ttype) = char_array_type_node;	    value = OBJC_STRING;	  }	else	  {	    yylval.ttype = build_string (p - token_buffer, token_buffer + 1);	    TREE_TYPE (yylval.ttype) = char_array_type_node;	    value = STRING;	  }	*p++ = '"';	*p = 0;	break;      }    case '+':    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();	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	  switch (c)	    {	    case '-':	      if (c1 == '>')		{ value = POINTSAT; goto done; }	      break;	    case ':':	      if (c1 == '>')		{ value = ']'; goto done; }	      break;	    case '<':	      if (c1 == '%')		{ value = '{'; indent_level++; goto done; }	      if (c1 == ':')		{ value = '['; goto done; }	      break;	    case '%':	      if (c1 == '>')		{ value = '}'; indent_level--; goto done; }	      break;	    }	UNGETC (c1);	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;    case '{':      indent_level++;      value = c;      break;    case '}':      indent_level--;      value = c;      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 + -