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

📄 c-common.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines shared by all languages that are variants of C.   Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  */#include "config.h"#include "tree.h"#include "c-lex.h"#include "c-tree.h"#include "flags.h"#include "obstack.h"#include <stdio.h>#include <ctype.h>extern struct obstack permanent_obstack;enum attrs {A_PACKED, A_NOCOMMON, A_NORETURN, A_CONST, A_T_UNION,	    A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED,	    A_UNUSED, A_FORMAT, A_WEAK, A_ALIAS};static void declare_hidden_char_array	PROTO((char *, char *));static void add_attribute		PROTO((enum attrs, char *,					       int, int, int));static void init_attributes		PROTO((void));/* Make bindings for __FUNCTION__ and __PRETTY_FUNCTION__.  */voiddeclare_function_name (){  char *name, *printable_name;  if (current_function_decl == NULL)    {      name = "";      printable_name = "top level";    }  else    {      char *kind = "function";      if (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE)	kind = "method";      /* Allow functions to be nameless (such as artificial ones).  */      if (DECL_NAME (current_function_decl))        name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));      else	name = "";      printable_name = (*decl_printable_name) (current_function_decl, &kind);    }  declare_hidden_char_array ("__FUNCTION__", name);  declare_hidden_char_array ("__PRETTY_FUNCTION__", printable_name);}static voiddeclare_hidden_char_array (name, value)     char *name, *value;{  tree decl, type, init;  int vlen;  /* If the default size of char arrays isn't big enough for the name,     or if we want to give warnings for large objects, make a bigger one.  */  vlen = strlen (value) + 1;  type = char_array_type_node;  if (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TREE_TYPE (type))) < vlen      || warn_larger_than)    type = build_array_type (char_type_node,			     build_index_type (build_int_2 (vlen, 0)));  push_obstacks_nochange ();  decl = build_decl (VAR_DECL, get_identifier (name), type);  TREE_STATIC (decl) = 1;  TREE_READONLY (decl) = 1;  TREE_ASM_WRITTEN (decl) = 1;  DECL_SOURCE_LINE (decl) = 0;  DECL_ARTIFICIAL (decl) = 1;  DECL_IN_SYSTEM_HEADER (decl) = 1;  DECL_IGNORED_P (decl) = 1;  init = build_string (vlen, value);  TREE_TYPE (init) = type;  DECL_INITIAL (decl) = init;  finish_decl (pushdecl (decl), init, NULL_TREE);}/* Given a chain of STRING_CST nodes,   concatenate them into one STRING_CST   and give it a suitable array-of-chars data type.  */treecombine_strings (strings)     tree strings;{  register tree value, t;  register int length = 1;  int wide_length = 0;  int wide_flag = 0;  int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;  int nchars;  if (TREE_CHAIN (strings))    {      /* More than one in the chain, so concatenate.  */      register char *p, *q;      /* Don't include the \0 at the end of each substring,	 except for the last one.	 Count wide strings and ordinary strings separately.  */      for (t = strings; t; t = TREE_CHAIN (t))	{	  if (TREE_TYPE (t) == wchar_array_type_node)	    {	      wide_length += (TREE_STRING_LENGTH (t) - wchar_bytes);	      wide_flag = 1;	    }	  else	    length += (TREE_STRING_LENGTH (t) - 1);	}      /* If anything is wide, the non-wides will be converted,	 which makes them take more space.  */      if (wide_flag)	length = length * wchar_bytes + wide_length;      p = savealloc (length);      /* Copy the individual strings into the new combined string.	 If the combined string is wide, convert the chars to ints	 for any individual strings that are not wide.  */      q = p;      for (t = strings; t; t = TREE_CHAIN (t))	{	  int len = (TREE_STRING_LENGTH (t)		     - ((TREE_TYPE (t) == wchar_array_type_node)			? wchar_bytes : 1));	  if ((TREE_TYPE (t) == wchar_array_type_node) == wide_flag)	    {	      bcopy (TREE_STRING_POINTER (t), q, len);	      q += len;	    }	  else	    {	      int i;	      for (i = 0; i < len; i++)		((int *) q)[i] = TREE_STRING_POINTER (t)[i];	      q += len * wchar_bytes;	    }	}      if (wide_flag)	{	  int i;	  for (i = 0; i < wchar_bytes; i++)	    *q++ = 0;	}      else	*q = 0;      value = make_node (STRING_CST);      TREE_STRING_POINTER (value) = p;      TREE_STRING_LENGTH (value) = length;      TREE_CONSTANT (value) = 1;    }  else    {      value = strings;      length = TREE_STRING_LENGTH (value);      if (TREE_TYPE (value) == wchar_array_type_node)	wide_flag = 1;    }  /* Compute the number of elements, for the array type.  */   nchars = wide_flag ? length / wchar_bytes : length;  /* Create the array type for the string constant.     -Wwrite-strings says make the string constant an array of const char     so that copying it to a non-const pointer will get a warning.  */  if (warn_write_strings      && (! flag_traditional  && ! flag_writable_strings))    {      tree elements	= build_type_variant (wide_flag ? wchar_type_node : char_type_node,			      1, 0);      TREE_TYPE (value)	= build_array_type (elements,			    build_index_type (build_int_2 (nchars - 1, 0)));    }  else    TREE_TYPE (value)      = build_array_type (wide_flag ? wchar_type_node : char_type_node,			  build_index_type (build_int_2 (nchars - 1, 0)));  TREE_CONSTANT (value) = 1;  TREE_STATIC (value) = 1;  return value;}/* To speed up processing of attributes, we maintain an array of   IDENTIFIER_NODES and the corresponding attribute types.  *//* Array to hold attribute information.  */static struct {enum attrs id; tree name; int min, max, decl_req;} attrtab[50];static int attrtab_idx = 0;/* Add an entry to the attribute table above.  */static voidadd_attribute (id, string, min_len, max_len, decl_req)     enum attrs id;     char *string;     int min_len, max_len;     int decl_req;{  char buf[100];  attrtab[attrtab_idx].id = id;  attrtab[attrtab_idx].name = get_identifier (string);  attrtab[attrtab_idx].min = min_len;  attrtab[attrtab_idx].max = max_len;  attrtab[attrtab_idx++].decl_req = decl_req;  sprintf (buf, "__%s__", string);  attrtab[attrtab_idx].id = id;  attrtab[attrtab_idx].name = get_identifier (buf);  attrtab[attrtab_idx].min = min_len;  attrtab[attrtab_idx].max = max_len;  attrtab[attrtab_idx++].decl_req = decl_req;}/* Initialize attribute table.  */static voidinit_attributes (){  add_attribute (A_PACKED, "packed", 0, 0, 0);  add_attribute (A_NOCOMMON, "nocommon", 0, 0, 1);  add_attribute (A_NORETURN, "noreturn", 0, 0, 1);  add_attribute (A_NORETURN, "volatile", 0, 0, 1);  add_attribute (A_UNUSED, "unused", 0, 0, 1);  add_attribute (A_CONST, "const", 0, 0, 1);  add_attribute (A_T_UNION, "transparent_union", 0, 0, 0);  add_attribute (A_CONSTRUCTOR, "constructor", 0, 0, 1);  add_attribute (A_DESTRUCTOR, "destructor", 0, 0, 1);  add_attribute (A_MODE, "mode", 1, 1, 1);  add_attribute (A_SECTION, "section", 1, 1, 1);  add_attribute (A_ALIGNED, "aligned", 0, 1, 0);  add_attribute (A_FORMAT, "format", 3, 3, 1);  add_attribute (A_WEAK, "weak", 0, 0, 1);  add_attribute (A_ALIAS, "alias", 1, 1, 1);}/* Process the attributes listed in ATTRIBUTES and PREFIX_ATTRIBUTES   and install them in NODE, which is either a DECL (including a TYPE_DECL)   or a TYPE.  PREFIX_ATTRIBUTES can appear after the declaration specifiers   and declaration modifiers but before the declaration proper. */voiddecl_attributes (node, attributes, prefix_attributes)     tree node, attributes, prefix_attributes;{  tree decl = 0, type;  int is_type;  tree a;  if (attrtab_idx == 0)    init_attributes ();  if (TREE_CODE_CLASS (TREE_CODE (node)) == 'd')    {      decl = node;      type = TREE_TYPE (decl);      is_type = TREE_CODE (node) == TYPE_DECL;    }  else if (TREE_CODE_CLASS (TREE_CODE (node)) == 't')    type = node, is_type = 1;  attributes = chainon (prefix_attributes, attributes);  for (a = attributes; a; a = TREE_CHAIN (a))    {      tree name = TREE_PURPOSE (a);      tree args = TREE_VALUE (a);      int i;      enum attrs id;            for (i = 0; i < attrtab_idx; i++)	if (attrtab[i].name == name)	  break;      if (i == attrtab_idx)	{	  if (! valid_machine_attribute (name, args, decl, type))	    warning ("`%s' attribute directive ignored",		     IDENTIFIER_POINTER (name));	  continue;	}      else if (attrtab[i].decl_req && decl == 0)	{	  warning ("`%s' attribute does not apply to types",		   IDENTIFIER_POINTER (name));	  continue;	}      else if (list_length (args) < attrtab[i].min	       || list_length (args) > attrtab[i].max)	{	  error ("wrong number of arguments specified for `%s' attribute",		 IDENTIFIER_POINTER (name));	  continue;	}      id = attrtab[i].id;      switch (id)	{	case A_PACKED:	  if (is_type)	    TYPE_PACKED (type) = 1;	  else if (TREE_CODE (decl) == FIELD_DECL)	    DECL_PACKED (decl) = 1;	  /* We can't set DECL_PACKED for a VAR_DECL, because the bit is	     used for DECL_REGISTER.  It wouldn't mean anything anyway.  */	  else	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_NOCOMMON:	  if (TREE_CODE (decl) == VAR_DECL)	    DECL_COMMON (decl) = 0;	  else	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_NORETURN:	  if (TREE_CODE (decl) == FUNCTION_DECL)	    TREE_THIS_VOLATILE (decl) = 1;	  else if (TREE_CODE (type) == POINTER_TYPE		   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)	    TREE_TYPE (decl) = type 	      = build_pointer_type		(build_type_variant (TREE_TYPE (type),				     TREE_READONLY (TREE_TYPE (type)), 1));	  else	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_UNUSED:	  if (TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == VAR_DECL	      || TREE_CODE (decl) == FUNCTION_DECL)	    TREE_USED (decl) = 1;	  else	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_CONST:	  if (TREE_CODE (decl) == FUNCTION_DECL)	    TREE_READONLY (decl) = 1;	  else if (TREE_CODE (type) == POINTER_TYPE		   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)	    TREE_TYPE (decl) = type	      = build_pointer_type		(build_type_variant (TREE_TYPE (type), 1,				     TREE_THIS_VOLATILE (TREE_TYPE (type))));	  else	    warning ( "`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_T_UNION:	  if (is_type	      && TREE_CODE (type) == UNION_TYPE	      && (decl == 0		  || TYPE_MODE (type) == DECL_MODE (TYPE_FIELDS (type))))	    TYPE_TRANSPARENT_UNION (type) = 1;	  else if (decl != 0 && TREE_CODE (decl) == PARM_DECL		   && TREE_CODE (type) == UNION_TYPE		   && TYPE_MODE (type) == DECL_MODE (TYPE_FIELDS (type)))	    DECL_TRANSPARENT_UNION (decl) = 1;	  else	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_CONSTRUCTOR:	  if (TREE_CODE (decl) == FUNCTION_DECL	      && TREE_CODE (type) == FUNCTION_TYPE	      && decl_function_context (decl) == 0)	    {	      DECL_STATIC_CONSTRUCTOR (decl) = 1;	      TREE_USED (decl) = 1;	    }	  else	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_DESTRUCTOR:	  if (TREE_CODE (decl) == FUNCTION_DECL	      && TREE_CODE (type) == FUNCTION_TYPE	      && decl_function_context (decl) == 0)	    {	      DECL_STATIC_DESTRUCTOR (decl) = 1;	      TREE_USED (decl) = 1;	    }	  else	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_MODE:	  if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  else	    {	      int j;	      char *p = IDENTIFIER_POINTER (TREE_VALUE (args));	      int len = strlen (p);	      enum machine_mode mode = VOIDmode;	      tree typefm;

⌨️ 快捷键说明

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