📄 eval.c
字号:
return NULL;
while (i == '|') {
i = scan(scpriv, tokval);
f = expr1(critical);
if (!f)
return NULL;
if (!(is_simple(e) || is_just_unknown(e)) ||
!(is_simple(f) || is_just_unknown(f))) {
error(ERR_NONFATAL, "`|' operator may only be applied to"
" scalar values");
}
if (is_just_unknown(e) || is_just_unknown(f))
e = unknown_expr();
else
e = scalarvect(reloc_value(e) | reloc_value(f));
}
return e;
}
static expr *expr1(int critical)
{
expr *e, *f;
e = expr2(critical);
if (!e)
return NULL;
while (i == '^') {
i = scan(scpriv, tokval);
f = expr2(critical);
if (!f)
return NULL;
if (!(is_simple(e) || is_just_unknown(e)) ||
!(is_simple(f) || is_just_unknown(f))) {
error(ERR_NONFATAL, "`^' operator may only be applied to"
" scalar values");
}
if (is_just_unknown(e) || is_just_unknown(f))
e = unknown_expr();
else
e = scalarvect(reloc_value(e) ^ reloc_value(f));
}
return e;
}
static expr *expr2(int critical)
{
expr *e, *f;
e = expr3(critical);
if (!e)
return NULL;
while (i == '&') {
i = scan(scpriv, tokval);
f = expr3(critical);
if (!f)
return NULL;
if (!(is_simple(e) || is_just_unknown(e)) ||
!(is_simple(f) || is_just_unknown(f))) {
error(ERR_NONFATAL, "`&' operator may only be applied to"
" scalar values");
}
if (is_just_unknown(e) || is_just_unknown(f))
e = unknown_expr();
else
e = scalarvect(reloc_value(e) & reloc_value(f));
}
return e;
}
static expr *expr3(int critical)
{
expr *e, *f;
e = expr4(critical);
if (!e)
return NULL;
while (i == TOKEN_SHL || i == TOKEN_SHR) {
int j = i;
i = scan(scpriv, tokval);
f = expr4(critical);
if (!f)
return NULL;
if (!(is_simple(e) || is_just_unknown(e)) ||
!(is_simple(f) || is_just_unknown(f))) {
error(ERR_NONFATAL, "shift operator may only be applied to"
" scalar values");
} else if (is_just_unknown(e) || is_just_unknown(f)) {
e = unknown_expr();
} else
switch (j) {
case TOKEN_SHL:
e = scalarvect(reloc_value(e) << reloc_value(f));
break;
case TOKEN_SHR:
e = scalarvect(((unsigned long)reloc_value(e)) >>
reloc_value(f));
break;
}
}
return e;
}
static expr *expr4(int critical)
{
expr *e, *f;
e = expr5(critical);
if (!e)
return NULL;
while (i == '+' || i == '-') {
int j = i;
i = scan(scpriv, tokval);
f = expr5(critical);
if (!f)
return NULL;
switch (j) {
case '+':
e = add_vectors(e, f);
break;
case '-':
e = add_vectors(e, scalar_mult(f, -1L, FALSE));
break;
}
}
return e;
}
static expr *expr5(int critical)
{
expr *e, *f;
e = expr6(critical);
if (!e)
return NULL;
while (i == '*' || i == '/' || i == '%' ||
i == TOKEN_SDIV || i == TOKEN_SMOD) {
int j = i;
i = scan(scpriv, tokval);
f = expr6(critical);
if (!f)
return NULL;
if (j != '*' && (!(is_simple(e) || is_just_unknown(e)) ||
!(is_simple(f) || is_just_unknown(f)))) {
error(ERR_NONFATAL, "division operator may only be applied to"
" scalar values");
return NULL;
}
if (j != '*' && !is_unknown(f) && reloc_value(f) == 0) {
error(ERR_NONFATAL, "division by zero");
return NULL;
}
switch (j) {
case '*':
if (is_simple(e))
e = scalar_mult(f, reloc_value(e), TRUE);
else if (is_simple(f))
e = scalar_mult(e, reloc_value(f), TRUE);
else if (is_just_unknown(e) && is_just_unknown(f))
e = unknown_expr();
else {
error(ERR_NONFATAL, "unable to multiply two "
"non-scalar objects");
return NULL;
}
break;
case '/':
if (is_just_unknown(e) || is_just_unknown(f))
e = unknown_expr();
else
e = scalarvect(((unsigned long)reloc_value(e)) /
((unsigned long)reloc_value(f)));
break;
case '%':
if (is_just_unknown(e) || is_just_unknown(f))
e = unknown_expr();
else
e = scalarvect(((unsigned long)reloc_value(e)) %
((unsigned long)reloc_value(f)));
break;
case TOKEN_SDIV:
if (is_just_unknown(e) || is_just_unknown(f))
e = unknown_expr();
else
e = scalarvect(((signed long)reloc_value(e)) /
((signed long)reloc_value(f)));
break;
case TOKEN_SMOD:
if (is_just_unknown(e) || is_just_unknown(f))
e = unknown_expr();
else
e = scalarvect(((signed long)reloc_value(e)) %
((signed long)reloc_value(f)));
break;
}
}
return e;
}
static expr *expr6(int critical)
{
long type;
expr *e;
long label_seg, label_ofs;
if (i == '-') {
i = scan(scpriv, tokval);
e = expr6(critical);
if (!e)
return NULL;
return scalar_mult(e, -1L, FALSE);
} else if (i == '+') {
i = scan(scpriv, tokval);
return expr6(critical);
} else if (i == '~') {
i = scan(scpriv, tokval);
e = expr6(critical);
if (!e)
return NULL;
if (is_just_unknown(e))
return unknown_expr();
else if (!is_simple(e)) {
error(ERR_NONFATAL, "`~' operator may only be applied to"
" scalar values");
return NULL;
}
return scalarvect(~reloc_value(e));
} else if (i == TOKEN_SEG) {
i = scan(scpriv, tokval);
e = expr6(critical);
if (!e)
return NULL;
e = segment_part(e);
if (!e)
return NULL;
if (is_unknown(e) && critical) {
error(ERR_NONFATAL, "unable to determine segment base");
return NULL;
}
return e;
} else if (i == '(') {
i = scan(scpriv, tokval);
e = bexpr(critical);
if (!e)
return NULL;
if (i != ')') {
error(ERR_NONFATAL, "expecting `)'");
return NULL;
}
i = scan(scpriv, tokval);
return e;
} else if (i == TOKEN_NUM || i == TOKEN_REG || i == TOKEN_ID ||
i == TOKEN_HERE || i == TOKEN_BASE) {
begintemp();
switch (i) {
case TOKEN_NUM:
addtotemp(EXPR_SIMPLE, tokval->t_integer);
break;
case TOKEN_REG:
addtotemp(tokval->t_integer, 1L);
if (hint && hint->type == EAH_NOHINT)
hint->base = tokval->t_integer, hint->type = EAH_MAKEBASE;
break;
case TOKEN_ID:
case TOKEN_HERE:
case TOKEN_BASE:
/*
* If !location->known, this indicates that no
* symbol, Here or Base references are valid because we
* are in preprocess-only mode.
*/
if (!location->known) {
error(ERR_NONFATAL,
"%s not supported in preprocess-only mode",
(i == TOKEN_ID ? "symbol references" :
i == TOKEN_HERE ? "`$'" : "`$$'"));
addtotemp(EXPR_UNKNOWN, 1L);
break;
}
type = EXPR_SIMPLE; /* might get overridden by UNKNOWN */
if (i == TOKEN_BASE) {
label_seg = in_abs_seg ? abs_seg : location->segment;
label_ofs = 0;
} else if (i == TOKEN_HERE) {
label_seg = in_abs_seg ? abs_seg : location->segment;
label_ofs = in_abs_seg ? abs_offset : location->offset;
} else {
if (!labelfunc(tokval->t_charptr, &label_seg, &label_ofs)) {
if (critical == 2) {
error(ERR_NONFATAL, "symbol `%s' undefined",
tokval->t_charptr);
return NULL;
} else if (critical == 1) {
error(ERR_NONFATAL,
"symbol `%s' not defined before use",
tokval->t_charptr);
return NULL;
} else {
if (opflags)
*opflags |= 1;
type = EXPR_UNKNOWN;
label_seg = NO_SEG;
label_ofs = 1;
}
}
if (opflags && is_extern(tokval->t_charptr))
*opflags |= OPFLAG_EXTERN;
}
addtotemp(type, label_ofs);
if (label_seg != NO_SEG)
addtotemp(EXPR_SEGBASE + label_seg, 1L);
break;
}
i = scan(scpriv, tokval);
return finishtemp();
} else {
error(ERR_NONFATAL, "expression syntax error");
return NULL;
}
}
void eval_global_info(struct ofmt *output, lfunc lookup_label,
loc_t * locp)
{
outfmt = output;
labelfunc = lookup_label;
location = locp;
}
expr *evaluate(scanner sc, void *scprivate, struct tokenval *tv,
int *fwref, int critical, efunc report_error,
struct eval_hints *hints)
{
expr *e;
expr *f = NULL;
hint = hints;
if (hint)
hint->type = EAH_NOHINT;
if (critical & CRITICAL) {
critical &= ~CRITICAL;
bexpr = rexp0;
} else
bexpr = expr0;
scan = sc;
scpriv = scprivate;
tokval = tv;
error = report_error;
opflags = fwref;
if (tokval->t_type == TOKEN_INVALID)
i = scan(scpriv, tokval);
else
i = tokval->t_type;
while (ntempexprs) /* initialise temporary storage */
nasm_free(tempexprs[--ntempexprs]);
e = bexpr(critical);
if (!e)
return NULL;
if (i == TOKEN_WRT) {
i = scan(scpriv, tokval); /* eat the WRT */
f = expr6(critical);
if (!f)
return NULL;
}
e = scalar_mult(e, 1L, FALSE); /* strip far-absolute segment part */
if (f) {
expr *g;
if (is_just_unknown(f))
g = unknown_expr();
else {
long value;
begintemp();
if (!is_reloc(f)) {
error(ERR_NONFATAL, "invalid right-hand operand to WRT");
return NULL;
}
value = reloc_seg(f);
if (value == NO_SEG)
value = reloc_value(f) | SEG_ABS;
else if (!(value & SEG_ABS) && !(value % 2) && critical) {
error(ERR_NONFATAL, "invalid right-hand operand to WRT");
return NULL;
}
addtotemp(EXPR_WRT, value);
g = finishtemp();
}
e = add_vectors(e, g);
}
return e;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -