From 9c98769a33c4e8e9acbdce9dde602d8fdaca0e9e Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 4 Nov 2007 21:09:32 -0800 Subject: [PATCH] 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. --- eval.c | 7 +++++-- parser.c | 22 ++++++++++++++++++++-- test/insnlbl.asm | 10 ++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 test/insnlbl.asm diff --git a/eval.c b/eval.c index 2be18a6..3fc9732 100644 --- a/eval.c +++ b/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; } diff --git a/parser.c b/parser.c index 9b7f617..8011733 100644 --- a/parser.c +++ b/parser.c @@ -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) { diff --git a/test/insnlbl.asm b/test/insnlbl.asm new file mode 100644 index 0000000..5c16384 --- /dev/null +++ b/test/insnlbl.asm @@ -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 -- 2.7.4