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

📄 c-common.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
	      if (len > 4 && p[0] == '_' && p[1] == '_'		  && p[len - 1] == '_' && p[len - 2] == '_')		{		  char *newp = (char *) alloca (len - 1);		  strcpy (newp, &p[2]);		  newp[len - 4] = '\0';		  p = newp;		}	      /* Give this decl a type with the specified mode.		 First check for the special modes.  */	      if (! strcmp (p, "byte"))		mode = byte_mode;	      else if (!strcmp (p, "word"))		mode = word_mode;	      else if (! strcmp (p, "pointer"))		mode = ptr_mode;	      else		for (j = 0; j < NUM_MACHINE_MODES; j++)		  if (!strcmp (p, GET_MODE_NAME (j)))		    mode = (enum machine_mode) j;	      if (mode == VOIDmode)		error ("unknown machine mode `%s'", p);	      else if (0 == (typefm = type_for_mode (mode,						     TREE_UNSIGNED (type))))		error ("no data type for mode `%s'", p);	      else		{		  TREE_TYPE (decl) = type = typefm;		  DECL_SIZE (decl) = 0;		  layout_decl (decl, 0);		}	    }	  break;	case A_SECTION:#ifdef ASM_OUTPUT_SECTION_NAME	  if ((TREE_CODE (decl) == FUNCTION_DECL	       || TREE_CODE (decl) == VAR_DECL)	      && TREE_CODE (TREE_VALUE (args)) == STRING_CST)	    {	      if (TREE_CODE (decl) == VAR_DECL 		  && current_function_decl != NULL_TREE)		error_with_decl (decl,		  "section attribute cannot be specified for local variables");	      /* The decl may have already been given a section attribute from		 a previous declaration.  Ensure they match.  */	      else if (DECL_SECTION_NAME (decl) != NULL_TREE		       && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),				  TREE_STRING_POINTER (TREE_VALUE (args))) != 0)		error_with_decl (node,				 "section of `%s' conflicts with previous declaration");	      else		DECL_SECTION_NAME (decl) = TREE_VALUE (args);	    }	  else	    error_with_decl (node,			   "section attribute not allowed for `%s'");#else	  error_with_decl (node,		  "section attributes are not supported for this target");#endif	  break;	case A_ALIGNED:	  {	    tree align_expr	      = args ? TREE_VALUE (args) : size_int (BIGGEST_ALIGNMENT);	    int align;	    /* Strip any NOPs of any kind.  */	    while (TREE_CODE (align_expr) == NOP_EXPR		   || TREE_CODE (align_expr) == CONVERT_EXPR		   || TREE_CODE (align_expr) == NON_LVALUE_EXPR)	      align_expr = TREE_OPERAND (align_expr, 0);	  	    if (TREE_CODE (align_expr) != INTEGER_CST)	      {		error ("requested alignment is not a constant");		continue;	      }	    align = TREE_INT_CST_LOW (align_expr) * BITS_PER_UNIT;	    if (exact_log2 (align) == -1)	      error ("requested alignment is not a power of 2");	    else if (is_type)	      TYPE_ALIGN (type) = align;	    else if (TREE_CODE (decl) != VAR_DECL		     && TREE_CODE (decl) != FIELD_DECL)	      error_with_decl (decl,			       "alignment may not be specified for `%s'");	    else	      DECL_ALIGN (decl) = align;	  }	  break;	case A_FORMAT:	  {	    tree format_type = TREE_VALUE (args);	    tree format_num_expr = TREE_VALUE (TREE_CHAIN (args));	    tree first_arg_num_expr	      = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));	    int format_num;	    int first_arg_num;	    int is_scan;	    tree argument;	    int arg_num;		    if (TREE_CODE (decl) != FUNCTION_DECL)	      {		error_with_decl (decl,			 "argument format specified for non-function `%s'");		continue;	      }		    if (TREE_CODE (format_type) == IDENTIFIER_NODE		&& (!strcmp (IDENTIFIER_POINTER (format_type), "printf")		    || !strcmp (IDENTIFIER_POINTER (format_type),				"__printf__")))	      is_scan = 0;	    else if (TREE_CODE (format_type) == IDENTIFIER_NODE		     && (!strcmp (IDENTIFIER_POINTER (format_type), "scanf")			 || !strcmp (IDENTIFIER_POINTER (format_type),				     "__scanf__")))	      is_scan = 1;	    else	      {		error ("unrecognized format specifier for `%s'");		continue;	      }	    /* Strip any conversions from the string index and first arg number	       and verify they are constants.  */	    while (TREE_CODE (format_num_expr) == NOP_EXPR		   || TREE_CODE (format_num_expr) == CONVERT_EXPR		   || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR)	      format_num_expr = TREE_OPERAND (format_num_expr, 0);	    while (TREE_CODE (first_arg_num_expr) == NOP_EXPR		   || TREE_CODE (first_arg_num_expr) == CONVERT_EXPR		   || TREE_CODE (first_arg_num_expr) == NON_LVALUE_EXPR)	      first_arg_num_expr = TREE_OPERAND (first_arg_num_expr, 0);	    if (TREE_CODE (format_num_expr) != INTEGER_CST		|| TREE_CODE (first_arg_num_expr) != INTEGER_CST)	      {		error ("format string has non-constant operand number");		continue;	      }	    format_num = TREE_INT_CST_LOW (format_num_expr);	    first_arg_num = TREE_INT_CST_LOW (first_arg_num_expr);	    if (first_arg_num != 0 && first_arg_num <= format_num)	      {		error ("format string arg follows the args to be formatted");		continue;	      }	    /* If a parameter list is specified, verify that the format_num	       argument is actually a string, in case the format attribute	       is in error.  */	    argument = TYPE_ARG_TYPES (type);	    if (argument)	      {		for (arg_num = 1; ; ++arg_num)		  {		    if (argument == 0 || arg_num == format_num)		      break;		    argument = TREE_CHAIN (argument);		  }		if (! argument		    || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE		  || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument)))		      != char_type_node))		  {		    error ("format string arg not a string type");		    continue;		  }		if (first_arg_num != 0)		  {		    /* Verify that first_arg_num points to the last arg,		       the ... */		    while (argument)		      arg_num++, argument = TREE_CHAIN (argument);		  if (arg_num != first_arg_num)		    {		      error ("args to be formatted is not ...");		      continue;		    }		  }	      }	    record_function_format (DECL_NAME (decl),				    DECL_ASSEMBLER_NAME (decl),				    is_scan, format_num, first_arg_num);	    break;	  }	case A_WEAK:	  declare_weak (decl);	  break;	case A_ALIAS:	  if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))	      || TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl))	    error_with_decl (decl,			     "`%s' defined both normally and as an alias");	  else if (decl_function_context (decl) == 0)	    {	      tree id = get_identifier (TREE_STRING_POINTER					(TREE_VALUE (args)));	      if (TREE_CODE (decl) == FUNCTION_DECL)		DECL_INITIAL (decl) = error_mark_node;	      else		DECL_EXTERNAL (decl) = 0;	      assemble_alias (decl, id);	    }	  else	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	}    }}/* Check a printf/fprintf/sprintf/scanf/fscanf/sscanf format against   a parameter list.  */#define T_I	&integer_type_node#define T_L	&long_integer_type_node#define T_LL	&long_long_integer_type_node#define T_S	&short_integer_type_node#define T_UI	&unsigned_type_node#define T_UL	&long_unsigned_type_node#define T_ULL	&long_long_unsigned_type_node#define T_US	&short_unsigned_type_node#define T_F	&float_type_node#define T_D	&double_type_node#define T_LD	&long_double_type_node#define T_C	&char_type_node#define T_V	&void_type_node#define T_W	&wchar_type_node#define T_ST    &sizetypetypedef struct {  char *format_chars;  int pointer_count;  /* Type of argument if no length modifier is used.  */  tree *nolen;  /* Type of argument if length modifier for shortening is used.     If NULL, then this modifier is not allowed.  */  tree *hlen;  /* Type of argument if length modifier `l' is used.     If NULL, then this modifier is not allowed.  */  tree *llen;  /* Type of argument if length modifier `q' or `ll' is used.     If NULL, then this modifier is not allowed.  */  tree *qlen;  /* Type of argument if length modifier `L' is used.     If NULL, then this modifier is not allowed.  */  tree *bigllen;  /* List of other modifier characters allowed with these options.  */  char *flag_chars;} format_char_info;static format_char_info print_char_table[] = {  { "di",	0,	T_I,	T_I,	T_L,	T_LL,	T_LL,	"-wp0 +"	},  { "oxX",	0,	T_UI,	T_UI,	T_UL,	T_ULL,	T_ULL,	"-wp0#"		},  { "u",	0,	T_UI,	T_UI,	T_UL,	T_ULL,	T_ULL,	"-wp0"		},/* Two GNU extensions.  */  { "Z",	0,	T_ST,	NULL,	NULL,	NULL,	NULL,	"-wp0"		},  { "m",	0,	T_V,	NULL,	NULL,	NULL,	NULL,	"-wp"		},  { "feEgG",	0,	T_D,	NULL,	NULL,	NULL,	T_LD,	"-wp0 +#"	},  { "c",	0,	T_I,	NULL,	T_W,	NULL,	NULL,	"-w"		},  { "C",	0,	T_W,	NULL,	NULL,	NULL,	NULL,	"-w"		},  { "s",	1,	T_C,	NULL,	T_W,	NULL,	NULL,	"-wp"		},  { "S",	1,	T_W,	NULL,	NULL,	NULL,	NULL,	"-wp"		},  { "p",	1,	T_V,	NULL,	NULL,	NULL,	NULL,	"-w"		},  { "n",	1,	T_I,	T_S,	T_L,	T_LL,	NULL,	""		},  { NULL }};static format_char_info scan_char_table[] = {  { "di",	1,	T_I,	T_S,	T_L,	T_LL,	T_LL,	"*"	},  { "ouxX",	1,	T_UI,	T_US,	T_UL,	T_ULL,	T_ULL,	"*"	},	  { "efgEG",	1,	T_F,	NULL,	T_D,	NULL,	T_LD,	"*"	},  { "sc",	1,	T_C,	NULL,	T_W,	NULL,	NULL,	"*a"	},  { "[",	1,	T_C,	NULL,	NULL,	NULL,	NULL,	"*a"	},  { "C",	1,	T_W,	NULL,	NULL,	NULL,	NULL,	"*"	},  { "S",	1,	T_W,	NULL,	NULL,	NULL,	NULL,	"*"	},  { "p",	2,	T_V,	NULL,	NULL,	NULL,	NULL,	"*"	},  { "n",	1,	T_I,	T_S,	T_L,	T_LL,	NULL,	""	},  { NULL }};typedef struct function_format_info {  struct function_format_info *next;  /* next structure on the list */  tree name;			/* identifier such as "printf" */  tree assembler_name;		/* optional mangled identifier (for C++) */  int is_scan;			/* TRUE if *scanf */  int format_num;		/* number of format argument */  int first_arg_num;		/* number of first arg (zero for varargs) */} function_format_info;static function_format_info *function_format_list = NULL;static void check_format_info PROTO((function_format_info *, tree));/* Initialize the table of functions to perform format checking on.   The ANSI functions are always checked (whether <stdio.h> is   included or not), since it is common to call printf without   including <stdio.h>.  There shouldn't be a problem with this,   since ANSI reserves these function names whether you include the   header file or not.  In any case, the checking is harmless.  */voidinit_function_format_info (){  record_function_format (get_identifier ("printf"), NULL_TREE, 0, 1, 2);  record_function_format (get_identifier ("fprintf"), NULL_TREE, 0, 2, 3);  record_function_format (get_identifier ("sprintf"), NULL_TREE, 0, 2, 3);  record_function_format (get_identifier ("scanf"), NULL_TREE, 1, 1, 2);  record_function_format (get_identifier ("fscanf"), NULL_TREE, 1, 2, 3);  record_function_format (get_identifier ("sscanf"), NULL_TREE, 1, 2, 3);  record_function_format (get_identifier ("vprintf"), NULL_TREE, 0, 1, 0);  record_function_format (get_identifier ("vfprintf"), NULL_TREE, 0, 2, 0);  record_function_format (get_identifier ("vsprintf"), NULL_TREE, 0, 2, 0);}/* Record information for argument format checking.  FUNCTION_IDENT is   the identifier node for the name of the function to check (its decl   need not exist yet).  IS_SCAN is true for scanf-type format checking;   false indicates printf-style format checking.  FORMAT_NUM is the number   of the argument which is the format control string (starting from 1).   FIRST_ARG_NUM is the number of the first actual argument to check   against teh format string, or zero if no checking is not be done   (e.g. for varargs such as vfprintf).  */voidrecord_function_format (name, assembler_name, is_scan,			format_num, first_arg_num)      tree name;      tree assembler_name;      int is_scan;      int format_num;      int first_arg_num;{  function_format_info *info;  /* Re-use existing structure if it's there.  */  for (info = function_format_list; info; info = info->next)    {      if (info->name == name && info->assembler_name == assembler_name)	break;    }  if (! info)    {      info = (function_format_info *) xmalloc (sizeof (function_format_info));      info->next = function_format_list;      function_format_list = info;      info->name = name;      info->assembler_name = assembler_name;    }  info->is_scan = is_scan;  info->format_num = format_num;  info->first_arg_num = first_arg_num;}static char	tfaff[] = "too few arguments for format";/* Check the argument list of a call to printf, scanf, etc.   NAME is the function identifier.   ASSEMBLER_NAME is the function's assembler identifier.   (Either NAME or ASSEMBLER_NAME, but not both, may be NULL_TREE.)   PARAMS is the list of argument values.  */voidcheck_function_format (name, assembler_name, params)     tree name;     tree assembler_name;     tree params;{  function_format_info *info;  /* See if this function is a format function.  */  for (info = function_format_list; info; info = info->next)    {      if (info->assembler_name	  ? (info->assembler_name == assembler_name)	  : (info->name == name))	{	  /* Yup; check it.  */	  check_format_info (info, params);	  break;	}    }}/* Check the argument list of a call to printf, scanf, etc.   INFO points to the function_format_info structure.   PARAMS is the list of argument values.  */static voidcheck_format_info (info, params)     function_format_info *info;     tree params;{  int i;  int arg_num;  int suppressed, wide, precise;  int length_char;  int format_char;  int format_length;  tree format_tree;  tree cur_param;  tree cur_type;  tree wanted_type;  tree first_fillin_param;  char *format_chars;  format_char_info *fci;  static char message[132];  char flag_chars[8];  int has_operand_number = 0;  /* Skip to format argument.  If the argument isn't available, there's

⌨️ 快捷键说明

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