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

📄 expr.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
 *	'foo-foo' symbol references cancelled to 0, *		which changes X_seg from SEG_DIFFERENCE to SEG_ABSOLUTE; *	Unused fields zeroed to help expr(). */static voidclean_up_expression (expressionP)     register expressionS * expressionP;{  switch (expressionP -> X_seg)    {    case SEG_NONE:    case SEG_PASS1:      expressionP -> X_add_symbol	= NULL;      expressionP -> X_subtract_symbol	= NULL;      expressionP -> X_add_number	= 0;      break;    case SEG_BIG:    case SEG_ABSOLUTE:      expressionP -> X_subtract_symbol	= NULL;      expressionP -> X_add_symbol	= NULL;      break;    case SEG_TEXT:    case SEG_DATA:    case SEG_BSS:    case SEG_UNKNOWN:      expressionP -> X_subtract_symbol	= NULL;      break;    case SEG_DIFFERENCE:      /*       * It does not hurt to 'cancel' NULL==NULL       * when comparing symbols for 'eq'ness.       * It is faster to re-cancel them to NULL       * than to check for this special case.       */      if (expressionP -> X_subtract_symbol == expressionP -> X_add_symbol          || (   expressionP->X_subtract_symbol	      && expressionP->X_add_symbol  	      && expressionP->X_subtract_symbol->sy_frag==expressionP->X_add_symbol->sy_frag	      && expressionP->X_subtract_symbol->sy_value==expressionP->X_add_symbol->sy_value))	{	  expressionP -> X_subtract_symbol	= NULL;	  expressionP -> X_add_symbol		= NULL;	  expressionP -> X_seg			= SEG_ABSOLUTE;	}      break;    default:      BAD_CASE( expressionP -> X_seg);      break;    }}/* *			expr_part () * * Internal. Made a function because this code is used in 2 places. * Generate error or correct X_?????_symbol of expressionS. *//* * symbol_1 += symbol_2 ... well ... sort of. */static segTexpr_part (symbol_1_PP, symbol_2_P)     struct symbol **	symbol_1_PP;     struct symbol *	symbol_2_P;{  segT			return_value;  know(    (* symbol_1_PP)           		== NULL       || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_TEXT       || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_DATA       || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_BSS       || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF       );  know(      symbol_2_P             == NULL       ||    (symbol_2_P   -> sy_type & N_TYPE) == N_TEXT       ||    (symbol_2_P   -> sy_type & N_TYPE) == N_DATA       ||    (symbol_2_P   -> sy_type & N_TYPE) == N_BSS       ||    (symbol_2_P   -> sy_type & N_TYPE) == N_UNDF       );  if (* symbol_1_PP)    {      if (((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF)	{	  if (symbol_2_P)	    {	      return_value = SEG_PASS1;	      * symbol_1_PP = NULL;	    }	  else	    {	      know( ((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF)	      return_value = SEG_UNKNOWN;	    }	}      else	{	  if (symbol_2_P)	    {	      if ((symbol_2_P -> sy_type & N_TYPE) == N_UNDF)		{		  * symbol_1_PP = NULL;		  return_value = SEG_PASS1;		}	      else		{		  /* {seg1} - {seg2} */		  as_warn( "Expression too complex, 2 symbols forgotten: \"%s\" \"%s\"",			  (* symbol_1_PP) -> sy_name, symbol_2_P -> sy_name );		  * symbol_1_PP = NULL;		  return_value = SEG_ABSOLUTE;		}	    }	  else	    {	      return_value = N_TYPE_seg [(* symbol_1_PP) -> sy_type & N_TYPE];	    }	}    }  else    {				/* (* symbol_1_PP) == NULL */      if (symbol_2_P)	{	  * symbol_1_PP = symbol_2_P;	  return_value = N_TYPE_seg [(symbol_2_P) -> sy_type & N_TYPE];	}      else	{	  * symbol_1_PP = NULL;	  return_value = SEG_ABSOLUTE;	}    }  know(   return_value == SEG_ABSOLUTE			       || return_value == SEG_TEXT			       || return_value == SEG_DATA			       || return_value == SEG_BSS			       || return_value == SEG_UNKNOWN			       || return_value == SEG_PASS1			       );  know(   (* symbol_1_PP) == NULL				       || ((* symbol_1_PP) -> sy_type & N_TYPE) == seg_N_TYPE [(int) return_value] );  return (return_value);}				/* expr_part() *//* Expression parser. *//* * We allow an empty expression, and just assume (absolute,0) silently. * Unary operators and parenthetical expressions are treated as operands. * As usual, Q==quantity==operand, O==operator, X==expression mnemonics. * * We used to do a aho/ullman shift-reduce parser, but the logic got so * warped that I flushed it and wrote a recursive-descent parser instead. * Now things are stable, would anybody like to write a fast parser? * Most expressions are either register (which does not even reach here) * or 1 symbol. Then "symbol+constant" and "symbol-symbol" are common. * So I guess it doesn't really matter how inefficient more complex expressions * are parsed. * * After expr(RANK,resultP) input_line_pointer -> operator of rank <= RANK. * Also, we have consumed any leading or trailing spaces (operand does that) * and done all intervening operators. */typedef enum{O_illegal,			/* (0)  what we get for illegal op */O_multiply,			/* (1)  * */O_divide,			/* (2)  / */O_modulus,			/* (3)  % */O_left_shift,			/* (4)  < */O_right_shift,			/* (5)  > */O_bit_inclusive_or,		/* (6)  | */O_bit_or_not,			/* (7)  ! */O_bit_exclusive_or,		/* (8)  ^ */O_bit_and,			/* (9)  & */O_add,				/* (10) + */O_subtract			/* (11) - */}operatorT;#define __ O_illegalstatic const operatorT op_encoding [256] = {	/* maps ASCII -> operators */__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,__, O_bit_or_not, __, __, __, O_modulus, O_bit_and, __,__, __, O_multiply, O_add, __, O_subtract, __, O_divide,__, __, __, __, __, __, __, __,__, __, __, __, O_left_shift, __, O_right_shift, __,__, __, __, __, __, __, __, __,__, __, __, __, __, __, __, __,__, __, __, __, __, __, __, __,__, __, __, __, __, __, O_bit_exclusive_or, __,__, __, __, __, __, __, __, __,__, __, __, __, __, __, __, __,__, __, __, __, __, __, __, __,__, __, __, __, O_bit_inclusive_or, __, __, __,__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __};/* *	Rank	Examples *	0	operand, (expression) *	1	+ - *	2	& ^ ! | *	3	* / % < > */typedef char operator_rankT;static const operator_rankTop_rank [] = { 0, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1 };segT				/* Return resultP -> X_seg. */expr (rank, resultP)     register operator_rankT	rank; /* Larger # is higher rank. */     register expressionS *	resultP; /* Deliver result here. */{  expressionS		right;  register operatorT	op_left;  register char		c_left;	/* 1st operator character. */  register operatorT	op_right;  register char		c_right;  know( rank >= 0 );  (void)operand (resultP);  know( * input_line_pointer != ' ' ); /* Operand() gobbles spaces. */  c_left = * input_line_pointer; /* Potential operator character. */  op_left = op_encoding [c_left];  while (op_left != O_illegal && op_rank [(int) op_left] > rank)    {      input_line_pointer ++;	/* -> after 1st character of operator. */				/* Operators "<<" and ">>" have 2 characters. */      if (* input_line_pointer == c_left && (c_left == '<' || c_left == '>') )	{	  input_line_pointer ++;	}			/* -> after operator. */      if (SEG_NONE == expr (op_rank[(int) op_left], &right))	{	  as_warn("Missing operand value assumed absolute 0.");	  resultP -> X_add_number	= 0;	  resultP -> X_subtract_symbol	= NULL;	  resultP -> X_add_symbol	= NULL;	  resultP -> X_seg = SEG_ABSOLUTE;	}      know( * input_line_pointer != ' ' );      c_right = * input_line_pointer;      op_right = op_encoding [c_right];      if (* input_line_pointer == c_right && (c_right == '<' || c_right == '>') )	{	  input_line_pointer ++;	}			/* -> after operator. */      know(   (int) op_right == 0	   || op_rank [(int) op_right] <= op_rank[(int) op_left] );      /* input_line_pointer -> after right-hand quantity. */      /* left-hand quantity in resultP */      /* right-hand quantity in right. */      /* operator in op_left. */      if ( resultP -> X_seg == SEG_PASS1 || right . X_seg == SEG_PASS1 )	{	  resultP -> X_seg = SEG_PASS1;	}      else	{	  if ( resultP -> X_seg == SEG_BIG )	    {	      as_warn( "Left operand of %c is a %s.  Integer 0 assumed.",		      c_left, resultP -> X_add_number > 0 ? "bignum" : "float");	      resultP -> X_seg = SEG_ABSOLUTE;	      resultP -> X_add_symbol = 0;	      resultP -> X_subtract_symbol = 0;	      resultP -> X_add_number = 0;	    }	  if ( right . X_seg == SEG_BIG )	    {	      as_warn( "Right operand of %c is a %s.  Integer 0 assumed.",		      c_left, right . X_add_number > 0 ? "bignum" : "float");	      right . X_seg = SEG_ABSOLUTE;	      right . X_add_symbol = 0;	      right . X_subtract_symbol = 0;	      right . X_add_number = 0;	    }	  if ( op_left == O_subtract )	    {	      /*	       * Convert - into + by exchanging symbols and negating number.	       * I know -infinity can't be negated in 2's complement:	       * but then it can't be subtracted either. This trick	       * does not cause any further inaccuracy.	       */	      register struct symbol *	symbolP;	      right . X_add_number      = - right . X_add_number;	      symbolP                   = right . X_add_symbol;	      right . X_add_symbol	= right . X_subtract_symbol;	      right . X_subtract_symbol = symbolP;	      if (symbolP)		{		  right . X_seg		= SEG_DIFFERENCE;		}	      op_left = O_add;	    }	  if ( op_left == O_add )	    {	      segT	seg1;	      segT	seg2;	      	      know(   resultP -> X_seg == SEG_DATA				   || resultP -> X_seg == SEG_TEXT				   || resultP -> X_seg == SEG_BSS				   || resultP -> X_seg == SEG_UNKNOWN				   || resultP -> X_seg == SEG_DIFFERENCE			   || resultP -> X_seg == SEG_ABSOLUTE				   || resultP -> X_seg == SEG_PASS1				   );	      know(     right .  X_seg == SEG_DATA				   ||   right .  X_seg == SEG_TEXT				   ||   right .  X_seg == SEG_BSS				   ||   right .  X_seg == SEG_UNKNOWN				   ||   right .  X_seg == SEG_DIFFERENCE			   ||   right .  X_seg == SEG_ABSOLUTE				   ||   right .  X_seg == SEG_PASS1				   );	      	      clean_up_expression (& right);	      clean_up_expression (resultP);	      seg1 = expr_part (& resultP -> X_add_symbol, right . X_add_symbol);	      seg2 = expr_part (& resultP -> X_subtract_symbol, right . X_subtract_symbol);	      if (seg1 == SEG_PASS1 || seg2 == SEG_PASS1) {		  need_pass_2 = TRUE;		  resultP -> X_seg = SEG_PASS1;	      } else if (seg2 == SEG_ABSOLUTE)		  resultP -> X_seg = seg1;	      else if (   seg1 != SEG_UNKNOWN			&& seg1 != SEG_ABSOLUTE			&& seg2 != SEG_UNKNOWN			&& seg1 != seg2) {		  know( seg2 != SEG_ABSOLUTE );		  know( resultP -> X_subtract_symbol );		  know( seg1 == SEG_TEXT || seg1 == SEG_DATA || seg1== SEG_BSS );		  know( seg2 == SEG_TEXT || seg2 == SEG_DATA || seg2== SEG_BSS );		  know( resultP -> X_add_symbol      );		  know( resultP -> X_subtract_symbol );		  as_warn("Expression too complex: forgetting %s - %s",			  resultP -> X_add_symbol      -> sy_name,			  resultP -> X_subtract_symbol -> sy_name);		  resultP -> X_seg = SEG_ABSOLUTE;		  /* Clean_up_expression() will do the rest. */		} else		  resultP -> X_seg = SEG_DIFFERENCE;	      resultP -> X_add_number += right . X_add_number;	      clean_up_expression (resultP);	    }	  else	    {			/* Not +. */	      if ( resultP -> X_seg == SEG_UNKNOWN || right . X_seg == SEG_UNKNOWN )		{		  resultP -> X_seg = SEG_PASS1;		  need_pass_2 = TRUE;		}	      else		{		  resultP -> X_subtract_symbol = NULL;		  resultP -> X_add_symbol = NULL;		  /* Will be SEG_ABSOLUTE. */		  if ( resultP -> X_seg != SEG_ABSOLUTE || right . X_seg != SEG_ABSOLUTE )		    {		      as_warn( "Relocation error. Absolute 0 assumed.");		      resultP -> X_seg        = SEG_ABSOLUTE;		      resultP -> X_add_number = 0;		    }		  else		    {		      switch ( op_left )			{			case O_bit_inclusive_or:			  resultP -> X_add_number |= right . X_add_number;			  break;			  			case O_modulus:			  if (right . X_add_number)			    {			      resultP -> X_add_number %= right . X_add_number;			    }			  else			    {			      as_warn( "Division by 0. 0 assumed." );			      resultP -> X_add_number = 0;			    }			  break;			  			case O_bit_and:			  resultP -> X_add_number &= right . X_add_number;			  break;			  			case O_multiply:			  resultP -> X_add_number *= right . X_add_number;			  break;			  			case O_divide:			  if (right . X_add_number)			    {			      resultP -> X_add_number /= right . X_add_number;			    }			  else			    {			      as_warn( "Division by 0. 0 assumed." );			      resultP -> X_add_number = 0;			    }			  break;			  			case O_left_shift:			  resultP -> X_add_number <<= right . X_add_number;			  break;			  			case O_right_shift:			  resultP -> X_add_number >>= right . X_add_number;			  break;			  			case O_bit_exclusive_or:			  resultP -> X_add_number ^= right . X_add_number;			  break;			  			case O_bit_or_not:			  resultP -> X_add_number |= ~ right . X_add_number;			  break;			  			default:			  BAD_CASE( op_left );			  break;			} /* switch(operator) */		    }		}		/* If we have to force need_pass_2. */	    }			/* If operator was +. */	}			/* If we didn't set need_pass_2. */      op_left = op_right;    }				/* While next operator is >= this rank. */  return (resultP -> X_seg);}/* *			get_symbol_end() * * This lives here because it belongs equally in expr.c & read.c. * Expr.c is just a branch office read.c anyway, and putting it * here lessens the crowd at read.c. * * Assume input_line_pointer is at start of symbol name. * Advance input_line_pointer past symbol name. * Turn that character into a '\0', returning its former value. * This allows a string compare (RMS wants symbol names to be strings) * of the symbol name. * There will always be a char following symbol name, because all good * lines end in end-of-line. */charget_symbol_end(){  register char c;  while ( is_part_of_name( c = * input_line_pointer ++ ) )    ;  * -- input_line_pointer = 0;  return (c);}/* end: expr.c */

⌨️ 快捷键说明

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