?? asm.c
字號(hào):
}
}
else {
/* can't imagine any other kind of operand */
expressionP->X_seg = SEG_NONE;
InputPointer--;
}
/*
* It is more 'efficient' to clean up the expressions when they are created.
* Doing it here saves lines of code.
*/
clean_up_expression(expressionP);
SKIP_WHITESPACE(); /* -> 1st char after operand. */
know(*InputPointer != ' ');
return (expressionP->X_seg);
} /* operand */
/* Internal. Simplify a struct expression for use by AsmExpression()
* In: address of a expressionS.
* The X_seg field of the expressionS may only take certain values.
* Now, we permit SEG_PASS1 to make code smaller & faster.
* Elsewise we waste time special-case testing. Sigh. Ditto SEG_NONE.
* Out: expressionS may have been modified:
* 'foo-foo' symbol references cancelled to 0,
* which changes X_seg from SEG_DIFFERENCE to SEG_ABSOLUTE;
* Unused fields zeroed to help AsmExpression().
*/
static void clean_up_expression(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->SymbolValue == expressionP->X_add_symbol->SymbolValue)) {
expressionP->X_subtract_symbol = NULL;
expressionP->X_add_symbol = NULL;
expressionP->X_seg = SEG_ABSOLUTE;
}
break;
default:
InternalError(1103);
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 segT expr_part(symbolS **symbol_1_PP,symbolS * 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} */
InternalError(1063);
}
}
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 AsmExpression(RANK,resultP) InputPointer -> 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;
#undef __
#define __ O_illegal
static 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 * / % < >
*/
static const operator_rankT
op_rank[] = {0, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1};
static segT /* Return resultP -> X_seg. */
AsmExpression(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(*InputPointer != ' '); /* Operand() gobbles spaces. */
c_left = *InputPointer; /* Potential operator character. */
op_left = op_encoding[c_left];
while (op_left != O_illegal && op_rank[(int) op_left] > rank) {
InputPointer++; /* -> after 1st character of operator. */
/* Operators "<<" and ">>" have 2 characters. */
if (*InputPointer == c_left && (c_left == '<' || c_left == '>')) {
InputPointer++;
} /* -> after operator. */
if (SEG_NONE == AsmExpression(op_rank[(int) op_left], &right)) {
InternalError(1066);
}
know(*InputPointer != ' ');
c_right = *InputPointer;
op_right = op_encoding[c_right];
if (*InputPointer == c_right && (c_right == '<' || c_right == '>')) {
InputPointer++;
} /* -> after operator. */
know((int) op_right == 0
|| op_rank[(int) op_right] <= op_rank[(int) op_left]);
/* InputPointer -> 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 (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 symbolS *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);
InternalError(1067);
}
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) {
InternalError(1068);
}
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 {
InternalError(1069);
}
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 {
InternalError(1069); /* division par zero */
}
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:
InternalError(1104);
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()
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -