summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2007-11-04 21:09:32 -0800
committerH. Peter Anvin <hpa@zytor.com>2007-11-04 21:10:42 -0800
commit9c98769a33c4e8e9acbdce9dde602d8fdaca0e9e (patch)
treeea3fa08e77df945d68f9bd94c264ade8349b5d84
parentdd462c8f44ba1256d98b4bc1868c52be79ac5acc (diff)
downloadnasm-9c98769a33c4e8e9acbdce9dde602d8fdaca0e9e.tar.gz
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.
-rw-r--r--eval.c7
-rw-r--r--parser.c22
-rw-r--r--test/insnlbl.asm10
3 files changed, 35 insertions, 4 deletions
diff --git a/eval.c b/eval.c
index 2be18a6e..3fc9732d 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 9b7f6176..8011733c 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 00000000..5c163846
--- /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