expr.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,924 行 · 第 1/4 页

C
1,924
字号
    }  else if (!small)    {      /* We saw a lot of digits. manufacture a bignum the hard way.  */      LITTLENUM_TYPE *leader;	/* -> high order littlenum of the bignum.  */      LITTLENUM_TYPE *pointer;	/* -> littlenum we are frobbing now.  */      long carry;      leader = generic_bignum;      generic_bignum[0] = 0;      generic_bignum[1] = 0;      generic_bignum[2] = 0;      generic_bignum[3] = 0;      input_line_pointer = start;	/* -> 1st digit.  */      c = *input_line_pointer++;      for (; (carry = hex_value (c)) < maxdig; c = *input_line_pointer++)	{	  for (pointer = generic_bignum; pointer <= leader; pointer++)	    {	      long work;	      work = carry + radix * *pointer;	      *pointer = work & LITTLENUM_MASK;	      carry = work >> LITTLENUM_NUMBER_OF_BITS;	    }	  if (carry)	    {	      if (leader < generic_bignum + SIZE_OF_LARGE_NUMBER - 1)		{		  /* Room to grow a longer bignum.  */		  *++leader = carry;		}	    }	}      /* Again, c is char after number.  */      /* input_line_pointer -> after c.  */      know (LITTLENUM_NUMBER_OF_BITS == 16);      if (leader < generic_bignum + 2)	{	  /* Will fit into 32 bits.  */	  number = generic_bignum_to_int32 ();	  small = 1;	}#ifdef BFD64      else if (leader < generic_bignum + 4)	{	  /* Will fit into 64 bits.  */	  number = generic_bignum_to_int64 ();	  small = 1;	}#endif      else	{	  /* Number of littlenums in the bignum.  */	  number = leader - generic_bignum + 1;	}    }  if ((NUMBERS_WITH_SUFFIX || flag_m68k_mri)      && suffix != NULL      && input_line_pointer - 1 == suffix)    c = *input_line_pointer++;  if (small)    {      /* Here with number, in correct radix. c is the next char.	 Note that unlike un*x, we allow "011f" "0x9f" to both mean	 the same as the (conventional) "9f".	 This is simply easier than checking for strict canonical	 form.  Syntax sux!  */      if (LOCAL_LABELS_FB && c == 'b')	{	  /* Backward ref to local label.	     Because it is backward, expect it to be defined.  */	  /* Construct a local label.  */	  name = fb_label_name ((int) number, 0);	  /* Seen before, or symbol is defined: OK.  */	  symbolP = symbol_find (name);	  if ((symbolP != NULL) && (S_IS_DEFINED (symbolP)))	    {	      /* Local labels are never absolute.  Don't waste time		 checking absoluteness.  */	      know (SEG_NORMAL (S_GET_SEGMENT (symbolP)));	      expressionP->X_op = O_symbol;	      expressionP->X_add_symbol = symbolP;	    }	  else	    {	      /* Either not seen or not defined.  */	      /* @@ Should print out the original string instead of		 the parsed number.  */	      as_bad (_("backw. ref to unknown label \"%d:\", 0 assumed."),		      (int) number);	      expressionP->X_op = O_constant;	    }	  expressionP->X_add_number = 0;	}			/* case 'b' */      else if (LOCAL_LABELS_FB && c == 'f')	{	  /* Forward reference.  Expect symbol to be undefined or	     unknown.  undefined: seen it before.  unknown: never seen	     it before.	     Construct a local label name, then an undefined symbol.	     Don't create a xseg frag for it: caller may do that.	     Just return it as never seen before.  */	  name = fb_label_name ((int) number, 1);	  symbolP = symbol_find_or_make (name);	  /* We have no need to check symbol properties.  */#ifndef many_segments	  /* Since "know" puts its arg into a "string", we	     can't have newlines in the argument.  */	  know (S_GET_SEGMENT (symbolP) == undefined_section || S_GET_SEGMENT (symbolP) == text_section || S_GET_SEGMENT (symbolP) == data_section);#endif	  expressionP->X_op = O_symbol;	  expressionP->X_add_symbol = symbolP;	  expressionP->X_add_number = 0;	}			/* case 'f' */      else if (LOCAL_LABELS_DOLLAR && c == '$')	{	  /* If the dollar label is *currently* defined, then this is just	     another reference to it.  If it is not *currently* defined,	     then this is a fresh instantiation of that number, so create	     it.  */	  if (dollar_label_defined ((long) number))	    {	      name = dollar_label_name ((long) number, 0);	      symbolP = symbol_find (name);	      know (symbolP != NULL);	    }	  else	    {	      name = dollar_label_name ((long) number, 1);	      symbolP = symbol_find_or_make (name);	    }	  expressionP->X_op = O_symbol;	  expressionP->X_add_symbol = symbolP;	  expressionP->X_add_number = 0;	}			/* case '$' */      else	{	  expressionP->X_op = O_constant;#ifdef TARGET_WORD_SIZE	  /* Sign extend NUMBER.  */	  number |= (-(number >> (TARGET_WORD_SIZE - 1))) << (TARGET_WORD_SIZE - 1);#endif	  expressionP->X_add_number = number;	  input_line_pointer--;	/* Restore following character.  */	}			/* Really just a number.  */    }  else    {      /* Not a small number.  */      expressionP->X_op = O_big;      expressionP->X_add_number = number;	/* Number of littlenums.  */      input_line_pointer--;	/* -> char following number.  */    }}/* Parse an MRI multi character constant.  */static voidmri_char_constant (expressionP)     expressionS *expressionP;{  int i;  if (*input_line_pointer == '\''      && input_line_pointer[1] != '\'')    {      expressionP->X_op = O_constant;      expressionP->X_add_number = 0;      return;    }  /* In order to get the correct byte ordering, we must build the     number in reverse.  */  for (i = SIZE_OF_LARGE_NUMBER - 1; i >= 0; i--)    {      int j;      generic_bignum[i] = 0;      for (j = 0; j < CHARS_PER_LITTLENUM; j++)	{	  if (*input_line_pointer == '\'')	    {	      if (input_line_pointer[1] != '\'')		break;	      ++input_line_pointer;	    }	  generic_bignum[i] <<= 8;	  generic_bignum[i] += *input_line_pointer;	  ++input_line_pointer;	}      if (i < SIZE_OF_LARGE_NUMBER - 1)	{	  /* If there is more than one littlenum, left justify the             last one to make it match the earlier ones.  If there is             only one, we can just use the value directly.  */	  for (; j < CHARS_PER_LITTLENUM; j++)	    generic_bignum[i] <<= 8;	}      if (*input_line_pointer == '\''	  && input_line_pointer[1] != '\'')	break;    }  if (i < 0)    {      as_bad (_("Character constant too large"));      i = 0;    }  if (i > 0)    {      int c;      int j;      c = SIZE_OF_LARGE_NUMBER - i;      for (j = 0; j < c; j++)	generic_bignum[j] = generic_bignum[i + j];      i = c;    }  know (LITTLENUM_NUMBER_OF_BITS == 16);  if (i > 2)    {      expressionP->X_op = O_big;      expressionP->X_add_number = i;    }  else    {      expressionP->X_op = O_constant;      if (i < 2)	expressionP->X_add_number = generic_bignum[0] & LITTLENUM_MASK;      else	expressionP->X_add_number =	  (((generic_bignum[1] & LITTLENUM_MASK)	    << LITTLENUM_NUMBER_OF_BITS)	   | (generic_bignum[0] & LITTLENUM_MASK));    }  /* Skip the final closing quote.  */  ++input_line_pointer;}/* Return an expression representing the current location.  This   handles the magic symbol `.'.  */static voidcurrent_location (expressionp)     expressionS *expressionp;{  if (now_seg == absolute_section)    {      expressionp->X_op = O_constant;      expressionp->X_add_number = abs_section_offset;    }  else    {      symbolS *symbolp;      symbolp = symbol_new (FAKE_LABEL_NAME, now_seg,			    (valueT) frag_now_fix (),			    frag_now);      expressionp->X_op = O_symbol;      expressionp->X_add_symbol = symbolp;      expressionp->X_add_number = 0;    }}/* In:	Input_line_pointer points to 1st char of operand, which may	be a space.   Out:	A expressionS.	The operand may have been empty: in this case X_op == O_absent.	Input_line_pointer->(next non-blank) char after operand.  */static segToperand (expressionP)     expressionS *expressionP;{  char c;  symbolS *symbolP;	/* Points to symbol.  */  char *name;		/* Points to name of symbol.  */  segT segment;  /* All integers are regarded as unsigned unless they are negated.     This is because the only thing which cares whether a number is     unsigned is the code in emit_expr which extends constants into     bignums.  It should only sign extend negative numbers, so that     something like ``.quad 0x80000000'' is not sign extended even     though it appears negative if valueT is 32 bits.  */  expressionP->X_unsigned = 1;  /* Digits, assume it is a bignum.  */  SKIP_WHITESPACE ();		/* Leading whitespace is part of operand.  */  c = *input_line_pointer++;	/* input_line_pointer -> past char in c.  */  if (is_end_of_line[(unsigned char) c])    goto eol;  switch (c)    {    case '1':    case '2':    case '3':    case '4':    case '5':    case '6':    case '7':    case '8':    case '9':      input_line_pointer--;      integer_constant ((NUMBERS_WITH_SUFFIX || flag_m68k_mri)			? 0 : 10,                        expressionP);      break;#ifdef LITERAL_PREFIXDOLLAR_HEX    case '$':      integer_constant (16, expressionP);      break;#endif#ifdef LITERAL_PREFIXPERCENT_BIN    case '%':      integer_constant (2, expressionP);      break;#endif    case '0':      /* Non-decimal radix.  */      if (NUMBERS_WITH_SUFFIX || flag_m68k_mri)	{	  char *s;	  /* Check for a hex constant.  */	  for (s = input_line_pointer; hex_p (*s); s++)	    ;	  if (*s == 'h' || *s == 'H')	    {	      --input_line_pointer;	      integer_constant (0, expressionP);	      break;	    }	}      c = *input_line_pointer;      switch (c)	{	case 'o':	case 'O':	case 'q':	case 'Q':	case '8':	case '9':	  if (NUMBERS_WITH_SUFFIX || flag_m68k_mri)	    {	      integer_constant (0, expressionP);	      break;	    }	  /* Fall through.  */	default:	default_case:	  if (c && strchr (FLT_CHARS, c))	    {	      input_line_pointer++;	      floating_constant (expressionP);	      expressionP->X_add_number =		- (isupper ((unsigned char) c) ? tolower (c) : c);	    }	  else	    {	      /* The string was only zero.  */	      expressionP->X_op = O_constant;	      expressionP->X_add_number = 0;	    }	  break;	case 'x':	case 'X':	  if (flag_m68k_mri)	    goto default_case;	  input_line_pointer++;	  integer_constant (16, expressionP);	  break;	case 'b':	  if (LOCAL_LABELS_FB && ! (flag_m68k_mri || NUMBERS_WITH_SUFFIX))	    {	      /* This code used to check for '+' and '-' here, and, in		 some conditions, fall through to call		 integer_constant.  However, that didn't make sense,		 as integer_constant only accepts digits.  */	      /* Some of our code elsewhere does permit digits greater		 than the expected base; for consistency, do the same		 here.  */	      if (input_line_pointer[1] < '0'		  || input_line_pointer[1] > '9')		{		  /* Parse this as a back reference to label 0.  */		  input_line_pointer--;		  integer_constant (10, expressionP);		  break;		}	      /* Otherwise, parse this as a binary number.  */	    }	  /* Fall through.  */	case 'B':	  input_line_pointer++;	  if (flag_m68k_mri || NUMBERS_WITH_SUFFIX)	    goto default_case;	  integer_constant (2, expressionP);	  break;	case '0':	case '1':	case '2':	case '3':	case '4':	case '5':	case '6':	case '7':	  integer_constant ((flag_m68k_mri || NUMBERS_WITH_SUFFIX)			    ? 0 : 8,			    expressionP);	  break;	case 'f':	  if (LOCAL_LABELS_FB)	    {	      /* If it says "0f" and it could possibly be a floating point		 number, make it one.  Otherwise, make it a local label,		 and try to deal with parsing the rest later.  */	      if (!input_line_pointer[1]		  || (is_end_of_line[0xff & input_line_pointer[1]])		  || strchr (FLT_CHARS, 'f') == NULL)		goto is_0f_label;	      {		char *cp = input_line_pointer + 1;		int r = atof_generic (&cp, ".", EXP_CHARS,				      &generic_floating_point_number);		switch (r)		  {		  case 0:		  case ERROR_EXPONENT_OVERFLOW:		    if (*cp == 'f' || *cp == 'b')		      /* Looks like a difference expression.  */		      goto is_0f_label;		    else if (cp == input_line_pointer + 1)		      /* No characters has been accepted -- looks like			 end of operand.  */		      goto is_0f_label;		    else		      goto is_0f_float;		  default:		    as_fatal (_("expr.c(operand): bad atof_generic return val %d"),			      r);		  }	      }	      /* Okay, now we've sorted it out.  We resume at one of these		 two labels, depending on what we've decided we're probably		 looking at.  */	    is_0f_label:	      input_line_pointer--;	      integer_constant (10, expressionP);	      break;

⌨️ 快捷键说明

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