void local_colon( int n) /* just saw "n:" */ { local_label_counter [n] ++; colon (local_label_name (n, 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) */