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

📄 c-common.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
     no work for us to do; prototype checking will catch the problem.  */  for (arg_num = 1; ; ++arg_num)    {      if (params == 0)	return;      if (arg_num == info->format_num)	break;      params = TREE_CHAIN (params);    }  format_tree = TREE_VALUE (params);  params = TREE_CHAIN (params);  if (format_tree == 0)    return;  /* We can only check the format if it's a string constant.  */  while (TREE_CODE (format_tree) == NOP_EXPR)    format_tree = TREE_OPERAND (format_tree, 0); /* strip coercion */  if (integer_zerop (format_tree))    {      warning ("null format string");      return;    }  if (TREE_CODE (format_tree) != ADDR_EXPR)    return;  format_tree = TREE_OPERAND (format_tree, 0);  if (TREE_CODE (format_tree) != STRING_CST)    return;  format_chars = TREE_STRING_POINTER (format_tree);  format_length = TREE_STRING_LENGTH (format_tree);  if (format_length <= 1)    warning ("zero-length format string");  if (format_chars[--format_length] != 0)    {      warning ("unterminated format string");      return;    }  /* Skip to first argument to check.  */  while (arg_num + 1 < info->first_arg_num)    {      if (params == 0)	return;      params = TREE_CHAIN (params);      ++arg_num;    }  first_fillin_param = params;  while (1)    {      int aflag;      if (*format_chars == 0)	{	  if (format_chars - TREE_STRING_POINTER (format_tree) != format_length)	    warning ("embedded `\\0' in format");	  if (info->first_arg_num != 0 && params != 0 && ! has_operand_number)	    warning ("too many arguments for format");	  return;	}      if (*format_chars++ != '%')	continue;      if (*format_chars == 0)	{	  warning ("spurious trailing `%%' in format");	  continue;	}      if (*format_chars == '%')	{	  ++format_chars;	  continue;	}      flag_chars[0] = 0;      suppressed = wide = precise = FALSE;      if (info->is_scan)	{	  suppressed = *format_chars == '*';	  if (suppressed)	    ++format_chars;	  while (isdigit (*format_chars))	    ++format_chars;	}      else	{	  /* See if we have a number followed by a dollar sign.  If we do,	     it is an operand number, so set PARAMS to that operand.  */	  if (*format_chars >= '0' && *format_chars <= '9')	    {	      char *p = format_chars;	      while (*p >= '0' && *p++ <= '9')		;	      if (*p == '$')		{		  int opnum = atoi (format_chars);		  params = first_fillin_param;		  format_chars = p + 1;		  has_operand_number = 1;		  for (i = 1; i < opnum && params != 0; i++)		    params = TREE_CHAIN (params);		  if (opnum == 0 || params == 0)		    {		      warning ("operand number out of range in format");		      return;		    }		}	    }	  while (*format_chars != 0 && index (" +#0-", *format_chars) != 0)	    {	      if (index (flag_chars, *format_chars) != 0)		{		  sprintf (message, "repeated `%c' flag in format",			   *format_chars);		  warning (message);		}	      i = strlen (flag_chars);	      flag_chars[i++] = *format_chars++;	      flag_chars[i] = 0;	    }	  /* "If the space and + flags both appear, 	     the space flag will be ignored."  */	  if (index (flag_chars, ' ') != 0	      && index (flag_chars, '+') != 0)	    warning ("use of both ` ' and `+' flags in format");	  /* "If the 0 and - flags both appear,	     the 0 flag will be ignored."  */	  if (index (flag_chars, '0') != 0	      && index (flag_chars, '-') != 0)	    warning ("use of both `0' and `-' flags in format");	  if (*format_chars == '*')	    {	      wide = TRUE;	      /* "...a field width...may be indicated by an asterisk.		 In this case, an int argument supplies the field width..."  */	      ++format_chars;	      if (params == 0)		{		  warning (tfaff);		  return;		}	      if (info->first_arg_num != 0)		{		  cur_param = TREE_VALUE (params);		  params = TREE_CHAIN (params);		  ++arg_num;		  /* size_t is generally not valid here.		     It will work on most machines, because size_t and int		     have the same mode.  But might as well warn anyway,		     since it will fail on other machines.  */		  if ((TYPE_MAIN_VARIANT (TREE_TYPE (cur_param))		       != integer_type_node)		      &&		      (TYPE_MAIN_VARIANT (TREE_TYPE (cur_param))		       != unsigned_type_node))		    {		      sprintf (message,			       "field width is not type int (arg %d)",			       arg_num);		      warning (message);		    }		}	    }	  else	    {	      while (isdigit (*format_chars))		{		  wide = TRUE;		  ++format_chars;		}	    }	  if (*format_chars == '.')	    {	      precise = TRUE;	      ++format_chars;	      if (*format_chars != '*' && !isdigit (*format_chars))		warning ("`.' not followed by `*' or digit in format");	      /* "...a...precision...may be indicated by an asterisk.		 In this case, an int argument supplies the...precision."  */	      if (*format_chars == '*')		{		  if (info->first_arg_num != 0)		    {		      ++format_chars;		      if (params == 0)		        {			  warning (tfaff);			  return;			}		      cur_param = TREE_VALUE (params);		      params = TREE_CHAIN (params);		      ++arg_num;		      if (TYPE_MAIN_VARIANT (TREE_TYPE (cur_param))			  != integer_type_node)		        {		          sprintf (message,				   "field width is not type int (arg %d)",				   arg_num);		          warning (message);		        }		    }		}	      else		{		  while (isdigit (*format_chars))		    ++format_chars;		}	    }	}      if (*format_chars == 'h' || *format_chars == 'l' || *format_chars == 'q' ||	  *format_chars == 'L')	length_char = *format_chars++;      else	length_char = 0;      if (length_char == 'l' && *format_chars == 'l')	length_char = 'q', format_chars++;      aflag = 0;      if (*format_chars == 'a')	{	  aflag = 1;	  format_chars++;	}      if (suppressed && length_char != 0)	{	  sprintf (message,		   "use of `*' and `%c' together in format",		   length_char);	  warning (message);	}      format_char = *format_chars;      if (format_char == 0)	{	  warning ("conversion lacks type at end of format");	  continue;	}      format_chars++;      fci = info->is_scan ? scan_char_table : print_char_table;      while (fci->format_chars != 0	     && index (fci->format_chars, format_char) == 0)	  ++fci;      if (fci->format_chars == 0)	{	  if (format_char >= 040 && format_char < 0177)	    sprintf (message,		     "unknown conversion type character `%c' in format",		     format_char);	  else	    sprintf (message,		     "unknown conversion type character 0x%x in format",		     format_char);	  warning (message);	  continue;	}      if (wide && index (fci->flag_chars, 'w') == 0)	{	  sprintf (message, "width used with `%c' format",		   format_char);	  warning (message);	}      if (precise && index (fci->flag_chars, 'p') == 0)	{	  sprintf (message, "precision used with `%c' format",		   format_char);	  warning (message);	}      if (aflag && index (fci->flag_chars, 'a') == 0)	{	  sprintf (message, "`a' flag used with `%c' format",		   format_char);	  warning (message);	}      if (info->is_scan && format_char == '[')	{	  /* Skip over scan set, in case it happens to have '%' in it.  */	  if (*format_chars == '^')	    ++format_chars;	  /* Find closing bracket; if one is hit immediately, then	     it's part of the scan set rather than a terminator.  */	  if (*format_chars == ']')	    ++format_chars;	  while (*format_chars && *format_chars != ']')	    ++format_chars;	  if (*format_chars != ']')	      /* The end of the format string was reached.  */	      warning ("no closing `]' for `%%[' format");	}      if (suppressed)	{	  if (index (fci->flag_chars, '*') == 0)	    {	      sprintf (message,		       "suppression of `%c' conversion in format",		       format_char);	      warning (message);	    }	  continue;	}      for (i = 0; flag_chars[i] != 0; ++i)	{	  if (index (fci->flag_chars, flag_chars[i]) == 0)	    {	      sprintf (message, "flag `%c' used with type `%c'",		       flag_chars[i], format_char);	      warning (message);	    }	}      if (precise && index (flag_chars, '0') != 0	  && (format_char == 'd' || format_char == 'i'	      || format_char == 'o' || format_char == 'u'	      || format_char == 'x' || format_char == 'x'))	{	  sprintf (message,		   "precision and `0' flag not both allowed with `%c' format",		   format_char);	  warning (message);	}      switch (length_char)	{	default: wanted_type = fci->nolen ? *(fci->nolen) : 0; break;	case 'h': wanted_type = fci->hlen ? *(fci->hlen) : 0; break;	case 'l': wanted_type = fci->llen ? *(fci->llen) : 0; break;	case 'q': wanted_type = fci->qlen ? *(fci->qlen) : 0; break;	case 'L': wanted_type = fci->bigllen ? *(fci->bigllen) : 0; break;	}      if (wanted_type == 0)	{	  sprintf (message,		   "use of `%c' length character with `%c' type character",		   length_char, format_char);	  warning (message);	}      /*       ** XXX -- should kvetch about stuff such as       **	{       **		const int	i;       **       **		scanf ("%d", &i);       **	}       */      /* Finally. . .check type of argument against desired type!  */      if (info->first_arg_num == 0)	continue;      if (fci->pointer_count == 0 && wanted_type == void_type_node)	/* This specifier takes no argument.  */	continue;      if (params == 0)	{	  warning (tfaff);	  return;	}      cur_param = TREE_VALUE (params);      params = TREE_CHAIN (params);      ++arg_num;      cur_type = TREE_TYPE (cur_param);      /* Check the types of any additional pointer arguments	 that precede the "real" argument.  */      for (i = 0; i < fci->pointer_count; ++i)	{	  if (TREE_CODE (cur_type) == POINTER_TYPE)	    {	      cur_type = TREE_TYPE (cur_type);	      continue;	    }	  if (TREE_CODE (cur_type) != ERROR_MARK)	    {	      sprintf (message,		       "format argument is not a %s (arg %d)",		       ((fci->pointer_count == 1) ? "pointer" : "pointer to a pointer"),		       arg_num);	      warning (message);	    }	  break;	}      /* Check the type of the "real" argument, if there's a type we want.  */      if (i == fci->pointer_count && wanted_type != 0	  && TREE_CODE (cur_type) != ERROR_MARK	  && wanted_type != TYPE_MAIN_VARIANT (cur_type)	  /* If we want `void *', allow any pointer type.	     (Anything else would already have got a warning.)  */	  && ! (wanted_type == void_type_node		&& fci->pointer_count > 0)	  /* Don't warn about differences merely in signedness.  */	  && !(TREE_CODE (wanted_type) == INTEGER_TYPE	       && TREE_CODE (TYPE_MAIN_VARIANT (cur_type)) == INTEGER_TYPE	       && (TREE_UNSIGNED (wanted_type)		   ? wanted_type == (cur_type = unsigned_type (cur_type))		   : wanted_type == (cur_type = signed_type (cur_type))))	  /* Likewise, "signed char", "unsigned char" and "char" are	     equivalent but the above test won't consider them equivalent.  */	  && ! (wanted_type == char_type_node		&& (TYPE_MAIN_VARIANT (cur_type) == signed_char_type_node		    || TYPE_MAIN_VARIANT (cur_type) == unsigned_char_type_node)))	{	  register char *this;	  register char *that;  	  this = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (wanted_type)));	  that = 0;	  if (TREE_CODE (cur_type) != ERROR_MARK	      && TYPE_NAME (cur_type) != 0	      && TREE_CODE (cur_type) != INTEGER_TYPE	      && !(TREE_CODE (cur_type) == POINTER_TYPE		   && TREE_CODE (TREE_TYPE (cur_type)) == INTEGER_TYPE))	    {	      if (TREE_CODE (TYPE_NAME (cur_type)) == TYPE_DECL		  && DECL_NAME (TYPE_NAME (cur_type)) != 0)		that = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (cur_type)));	      else		that = IDENTIFIER_POINTER (TYPE_NAME (cur_type));	    }	  /* A nameless type can't possibly match what the format wants.	     So there will be a warning for it.	     Make up a string to describe vaguely what it is.  */	  if (that == 0)	    {	      if (TREE_CODE (cur_type) == POINTER_TYPE)		that = "pointer";	      else		that = "different type";	    }	  /* Make the warning better in case of mismatch of int vs long.  */	  if (TREE_CODE (cur_type) == INTEGER_TYPE	      && TREE_CODE (wanted_type) == INTEGER_TYPE	      && TYPE_PRECISION (cur_type) == TYPE_PRECISION (wanted_type)

⌨️ 快捷键说明

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