Permit opcode names as labels as long as they are followed by a colon

Permit opcode names to be used as labels if and only if they are
succeeded by a colon.  Opcode names occurring when parsing expressions
are all treated as labels; a leading colon occurred when parsing an
instruction forces a parser restart with the instruction forcibly
treated as an identifier.
This commit is contained in:
H. Peter Anvin 2007-11-04 21:09:32 -08:00
parent dd462c8f44
commit 9c98769a33
3 changed files with 35 additions and 4 deletions

7
eval.c

@ -741,6 +741,7 @@ static expr *expr6(int critical)
case TOKEN_NUM:
case TOKEN_REG:
case TOKEN_ID:
case TOKEN_INSN: /* Opcodes that occur here are really labels */
case TOKEN_HERE:
case TOKEN_BASE:
begintemp();
@ -754,6 +755,7 @@ static expr *expr6(int critical)
hint->base = tokval->t_integer, hint->type = EAH_MAKEBASE;
break;
case TOKEN_ID:
case TOKEN_INSN:
case TOKEN_HERE:
case TOKEN_BASE:
/*
@ -764,8 +766,9 @@ static expr *expr6(int critical)
if (!location->known) {
error(ERR_NONFATAL,
"%s not supported in preprocess-only mode",
(i == TOKEN_ID ? "symbol references" :
i == TOKEN_HERE ? "`$'" : "`$$'"));
(i == TOKEN_HERE ? "`$'" :
i == TOKEN_BASE ? "`$$'" :
"symbol references"));
addtotemp(EXPR_UNKNOWN, 1L);
break;
}

@ -171,7 +171,11 @@ insn *parse_line(int pass, char *buffer, insn * result,
int critical;
struct eval_hints hints;
int j;
bool first;
bool insn_is_label = false;
restart_parse:
first = true;
result->forw_ref = false;
error = errfunc;
@ -195,7 +199,9 @@ insn *parse_line(int pass, char *buffer, insn * result,
return result;
}
if (i == TOKEN_ID) { /* there's a label here */
if (i == TOKEN_ID || (insn_is_label && i == TOKEN_INSN)) {
/* there's a label here */
first = false;
result->label = tokval.t_charptr;
i = stdscan(NULL, &tokval);
if (i == ':') { /* skip over the optional colon */
@ -229,6 +235,8 @@ insn *parse_line(int pass, char *buffer, insn * result,
while (i == TOKEN_PREFIX ||
(i == TOKEN_REG && !(REG_SREG & ~reg_flags[tokval.t_integer])))
{
first = false;
/*
* Handle special case: the TIMES prefix.
*/
@ -259,7 +267,7 @@ insn *parse_line(int pass, char *buffer, insn * result,
int slot = prefix_slot(tokval.t_integer);
if (result->prefixes[slot]) {
if (result->prefixes[slot] == tokval.t_integer)
error(ERR_WARNING,
error(ERR_WARNING,
"instruction has redundant prefixes");
else
error(ERR_NONFATAL,
@ -335,6 +343,11 @@ insn *parse_line(int pass, char *buffer, insn * result,
i = stdscan(NULL, &tokval);
if (i == 0)
break;
else if (first && i == ':') {
insn_is_label = true;
goto restart_parse;
}
first = false;
fixptr = tail;
eop = *tail = nasm_malloc(sizeof(extop));
tail = &eop->next;
@ -507,6 +520,11 @@ insn *parse_line(int pass, char *buffer, insn * result,
i = stdscan(NULL, &tokval);
if (i == 0)
break; /* end of operands: get out of here */
else if (first && i == ':') {
insn_is_label = true;
goto restart_parse;
}
first = false;
result->oprs[operand].type = 0; /* so far, no override */
while (i == TOKEN_SPECIAL) { /* size specifiers */
switch ((int)tokval.t_integer) {

10
test/insnlbl.asm Normal file

@ -0,0 +1,10 @@
;
; Test "instruction as label" -- make opcodes legal as labels if
; they are followed by a colon.
;
do: jmp incbin+2
dw do, add, sub, incbin
add: jmp add-2
sub: jmp do+2
incbin: dw $-sub