예제 #1
0
void
local_colon(
int n)	/* just saw "n:" */
{
  local_label_counter [n] ++;
  colon (local_label_name (n, 0));
}
예제 #2
0
/*
 * Summary of operand().
 *
 * in:	Input_line_pointer points to 1st char of operand, which may
 *	be a space.
 *
 * out:	A expressionS. X_seg determines how to understand the rest of the
 *	expressionS.
 *	The operand may have been empty: in this case X_seg == SEG_NONE.
 *	Input_line_pointer -> (next non-blank) char after operand.
 *
 */
static
segT
operand(
expressionS *expressionP)
{
    char c, q;
    char *name;	/* points to name of symbol */
    struct symbol *symbolP; /* Points to symbol */


	SKIP_WHITESPACE();	/* Leading whitespace is part of operand. */
	c = *input_line_pointer++;/* Input_line_pointer -> past char in c. */

	if(isdigit(c)){
	    signed_expr_t
			number; /* offset or (absolute) value */
	    int digit;		/* value of next digit in current radix */
				/* invented for humans only, hope */
				/* optimising compiler flushes it! */
	    int radix;		/* 8, 10 or 16 */
				/* 0 means we saw start of a floating- */
				/* point constant. */
	    int maxdig;		/* Highest permitted digit value. */
	    int	too_many_digits;/* If we see >= this number of */
				/* digits, assume it is a bignum. */
	    char *digit_2;	/* -> 2nd digit of number. */
	    int	small;		/* TRUE if fits in 32 bits. */
	    int	force_bignum;	/* TRUE if number is 0xb...  */

	    force_bignum = FALSE;
	    /*
	     * These two initiaizations are to shut up compiler warning as the
	     * may be used with out being set.  There used only if radix != 0
	     * when the number is not a floating-point number.
	     */
	    maxdig = 0;
	    too_many_digits = 0;

	    if(c == '0'){ /* non-decimal radix */
		c = *input_line_pointer++;
		if(c == 'x' || c=='X'){
		    c = *input_line_pointer++; /* read past "0x" or "0X" */
		    maxdig = 16;
		    radix = 16;
		    too_many_digits = 9;
		}
		/*
		 * If we have "0b" and some hex digits then treat it as a hex
		 * number and return a bignum.   This is for hex immediate
		 * bit-patterns for floating-point immediate constants.
		 */
		else if((c == 'b' || c == 'B') &&
			(*input_line_pointer != '\0') &&
			strchr("0123456789abcdefABCDEF",
			       *input_line_pointer) != NULL){
		    force_bignum = TRUE;
		    c = *input_line_pointer++; /* read past "0b" or "0B" */
		    maxdig = 16;
		    radix = 16;
		    too_many_digits = 9;
		}
		else{
		    /*
		     * If it says '0f' and the line ends or it DOESN'T look like
		     * a floating point #, its a local label ref.
		     */
		    if(c == 'f' &&
		       (*input_line_pointer == '\0' ||
			(strchr("+-.0123456789", *input_line_pointer) == NULL &&
			 strchr(md_EXP_CHARS, *input_line_pointer) == NULL) )){
			maxdig = 10;
			radix = 10;
			too_many_digits = 11;
			c = '0';
			input_line_pointer -= 2;
		    }
		    else if(c != '\0' && strchr(md_FLT_CHARS, c) != NULL){
			radix = 0;/* Start of floating-point constant. */
				  /* input_line_pointer -> 1st char of number */
			expressionP->X_add_number =
				- (isupper(c) ? tolower(c) : c);
		    }
		    else{	/* By elimination, assume octal radix. */
			radix = 8;
			maxdig = 10;	/* Un*x sux. Compatibility. */
			too_many_digits = 11;
		    }
		}
		/* c == char after "0" or "0x" or "0X" or "0e" etc.*/
	    }
	    else{
		maxdig = 10;
		radix = 10;
		too_many_digits = 11;
	    }

	    /*
	     * Expressions are now evaluated as 64-bit values so the number
	     * digits allowed is twice that for 32-bit expressions.
	     */
	    too_many_digits *= 2;

	    if(radix != 0){ /* Fixed-point integer constant. */
			    /* May be bignum, or may fit in 32 bits. */
		/*
		 * Most numbers fit into 32 bits, and we want this case to be
		 * fast.  So we pretend it will fit into 32 bits. If, after
		 * making up a 32 bit number, we realize that we have scanned
		 * more digits than comfortably fit into 32 bits, we re-scan the
		 * digits coding them into a bignum.  For decimal and octal
		 * numbers we are conservative: some numbers may be assumed
		 * bignums when in fact they do fit into 32 bits.  Numbers of
		 * any radix can have excess leading zeros: we strive to
		 * recognise this and cast them back into 32 bits.  We must
		 * check that the bignum really is more than 32 bits, and
		 * change it back to a 32-bit number if it fits.  The number we
		 * are looking for is expected to be positive, but if it fits
		 * into 32 bits as an unsigned number, we let it be a 32-bit
		 * number. The cavalier approach is for speed in ordinary cases.
		 */
		digit_2 = input_line_pointer;
		for(number = 0;
		    (digit = hex_value[(int)c]) < maxdig;
		    c = *input_line_pointer++){
		    number = number * radix + digit;
		}
		/* c contains character after number. */
		/* Input_line_pointer -> char after c. */
		small = input_line_pointer - digit_2 < too_many_digits;
		if(force_bignum == TRUE)
		      small = FALSE;
		if(small == FALSE){
		    /*
		     * Manufacture a bignum.
		     */
		    /* -> high order littlenum of the bignum. */
		    LITTLENUM_TYPE *leader;
		    /* -> littlenum we are frobbing now. */
		    LITTLENUM_TYPE *pointer;
		    long carry;

		    leader = generic_bignum;
		    generic_bignum [0] = 0;
		    /* We could just use digit_2, but lets be mnemonic. */
		    input_line_pointer = --digit_2; /* -> 1st digit. */
		    c = *input_line_pointer++;
		    for( ;
			(carry = hex_value[(int)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(BITS_PER_INT == 32); */
		    know(LITTLENUM_NUMBER_OF_BITS == 16);
		    /* Hence the constant "2" in the next line. */
		    if(leader < generic_bignum + 2 && force_bignum == FALSE)
		    {		/* Will fit into 32 bits. */
			number = ((generic_bignum[1] & LITTLENUM_MASK) <<
				   LITTLENUM_NUMBER_OF_BITS) |
			  	  (generic_bignum[0] & LITTLENUM_MASK);
			small = TRUE;
		    }
		    else{
			/* Number of littlenums in the bignum. */
			number = leader - generic_bignum + 1;
		    }
		}
		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.
		     */
		    if(number < 10){
			if(c == 'b'){
			    /*
			     * Backward ref to local label.
			     * Because it is backward, expect it to be DEFINED.
			     */
			    /*
			     * Construct a local label.
			     */
			    name = local_label_name((int)number, 0);
			    symbolP = symbol_table_lookup(name);
			    if((symbolP != NULL) &&
			       (symbolP->sy_type & N_TYPE) != N_UNDF){
				/* Expected path: symbol defined. */
				/* Local labels are never absolute. Don't waste
				   time checking absoluteness. */
				know((symbolP->sy_type & N_TYPE) == N_SECT);
				expressionP->X_add_symbol = symbolP;
				expressionP->X_add_number = 0;
				expressionP->X_seg        = SEG_SECT;
			    }
			    else{ /* Either not seen or not defined. */
				as_warn("Backw. ref to unknown label \"%lld\","
				"0 assumed.", number);
				expressionP->X_add_number = 0;
				expressionP->X_seg        = SEG_ABSOLUTE;
			    }
			}
			else if(c == 'f'){
			    /*
			     * Forward reference. Expect symbol to be
			     * undefined or unknown. Undefined: seen it
			     * before. Unknown: never seen it in this pass.
			     * 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 = local_label_name((int)number, 1);
			    symbolP = symbol_table_lookup(name);
			    if(symbolP != NULL){
				/* We have no need to check symbol
				   properties. */
				know((symbolP->sy_type & N_TYPE) == N_UNDF ||
				     (symbolP->sy_type & N_TYPE) == N_SECT);
			    }
			    else{
				symbolP = symbol_new(name, N_UNDF, 0,0,0,
						     &zero_address_frag);
				symbol_table_insert(symbolP);
			    }
			    expressionP->X_add_symbol      = symbolP;
			    expressionP->X_seg             = SEG_UNKNOWN;
			    expressionP->X_subtract_symbol = NULL;
			    expressionP->X_add_number      = 0;
			}
			else{	/* Really a number, not a local label. */
			    ignore_c_ll_or_ull(c);
			    expressionP->X_add_number = number;
			    expressionP->X_seg        = SEG_ABSOLUTE;
			    input_line_pointer--; /* restore following char */
		        }
		    }
		    else{ /* a number >= 10 */
			ignore_c_ll_or_ull(c);
			expressionP->X_add_number = number;
			expressionP->X_seg        = SEG_ABSOLUTE;
			input_line_pointer--; /* restore following char */
		    }
		} /* not a small number encode returning a bignum */
		else{
		    ignore_c_ll_or_ull(c);
		    expressionP->X_add_number = number;
		    expressionP->X_seg = SEG_BIG;
		    input_line_pointer--; /* -> char following number. */
		} /* if (small) */
	    } /* (If integer constant) */