diff options
author | H. Peter Anvin <hpa@zytor.com> | 2007-11-04 21:09:32 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2007-11-04 21:10:42 -0800 |
commit | 9c98769a33c4e8e9acbdce9dde602d8fdaca0e9e (patch) | |
tree | ea3fa08e77df945d68f9bd94c264ade8349b5d84 | |
parent | dd462c8f44ba1256d98b4bc1868c52be79ac5acc (diff) | |
download | nasm-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.c | 7 | ||||
-rw-r--r-- | parser.c | 22 | ||||
-rw-r--r-- | test/insnlbl.asm | 10 |
3 files changed, 35 insertions, 4 deletions
@@ -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) { 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 |