summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-06-09 20:45:19 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-06-09 20:45:19 -0700
commit11627049aec88e21b6a9cbdef10984868d4ca3fe (patch)
tree1d6a223214cc0425ea11d3e2314b68d4030c2db6
parentfcb8909749b2a159ba7f32fec7df8e465a974f77 (diff)
downloadnasm-11627049aec88e21b6a9cbdef10984868d4ca3fe.tar.gz
nasm-11627049aec88e21b6a9cbdef10984868d4ca3fe.tar.bz2
nasm-11627049aec88e21b6a9cbdef10984868d4ca3fe.zip
Make strings a first-class token type; defer evaluation
Make strings a proper, first-class token type, instead of relying on the "TOKEN_NUM with tv_charptr" hack. Only convert a string to a number if requested in an expression context; this also makes it possible to actually issue a warning when it overflows.
-rw-r--r--eval.c9
-rw-r--r--nasm.h11
-rw-r--r--parser.c2
-rw-r--r--preproc.c27
-rw-r--r--stdscan.c8
5 files changed, 30 insertions, 27 deletions
diff --git a/eval.c b/eval.c
index d20578b..eb5af88 100644
--- a/eval.c
+++ b/eval.c
@@ -668,6 +668,8 @@ static expr *expr6(int critical)
expr *e;
int32_t label_seg;
int64_t label_ofs;
+ int64_t tmpval;
+ bool rn_warn;
char *scope;
switch (i) {
@@ -741,6 +743,7 @@ static expr *expr6(int critical)
return e;
case TOKEN_NUM:
+ case TOKEN_STR:
case TOKEN_REG:
case TOKEN_ID:
case TOKEN_INSN: /* Opcodes that occur here are really labels */
@@ -751,6 +754,12 @@ static expr *expr6(int critical)
case TOKEN_NUM:
addtotemp(EXPR_SIMPLE, tokval->t_integer);
break;
+ case TOKEN_STR:
+ tmpval = readstrnum(tokval->t_charptr, tokval->t_inttwo, &rn_warn);
+ if (rn_warn)
+ error(ERR_WARNING|ERR_PASS1, "character constant too long");
+ addtotemp(EXPR_SIMPLE, tmpval);
+ break;
case TOKEN_REG:
addtotemp(tokval->t_integer, 1L);
if (hint && hint->type == EAH_NOHINT)
diff --git a/nasm.h b/nasm.h
index 384fb65..fedf858 100644
--- a/nasm.h
+++ b/nasm.h
@@ -165,8 +165,14 @@ enum token_type { /* token types, other than chars */
TOKEN_INVALID = -1, /* a placeholder value */
TOKEN_EOS = 0, /* end of string */
TOKEN_EQ = '=', TOKEN_GT = '>', TOKEN_LT = '<', /* aliases */
- TOKEN_ID = 256, TOKEN_NUM, TOKEN_REG, TOKEN_INSN, /* major token types */
- TOKEN_ERRNUM, /* numeric constant with error in */
+ TOKEN_ID = 256, /* identifier */
+ TOKEN_NUM, /* numeric constant */
+ TOKEN_ERRNUM, /* malformed numeric constant */
+ TOKEN_STR, /* string constant */
+ TOKEN_ERRSTR, /* unterminated string constant */
+ TOKEN_FLOAT, /* floating-point constant */
+ TOKEN_REG, /* register name */
+ TOKEN_INSN, /* instruction name */
TOKEN_HERE, TOKEN_BASE, /* $ and $$ */
TOKEN_SPECIAL, /* BYTE, WORD, DWORD, QWORD, FAR, NEAR, etc */
TOKEN_PREFIX, /* A32, O16, LOCK, REPNZ, TIMES, etc */
@@ -175,7 +181,6 @@ enum token_type { /* token types, other than chars */
TOKEN_GE, TOKEN_LE, TOKEN_NE, /* >=, <= and <> (!= is same as <>) */
TOKEN_DBL_AND, TOKEN_DBL_OR, TOKEN_DBL_XOR, /* &&, || and ^^ */
TOKEN_SEG, TOKEN_WRT, /* SEG and WRT */
- TOKEN_FLOAT, /* floating-point constant */
TOKEN_FLOATIZE, /* __floatX__ */
};
diff --git a/parser.c b/parser.c
index c188095..6fb7e3c 100644
--- a/parser.c
+++ b/parser.c
@@ -356,7 +356,7 @@ restart_parse:
eop->type = EOT_NOTHING;
oper_num++;
- if (i == TOKEN_NUM && tokval.t_charptr && is_comma_next()) {
+ if (i == TOKEN_STR && is_comma_next()) {
eop->type = EOT_DB_STRING;
eop->stringval = tokval.t_charptr;
eop->stringlen = tokval.t_inttwo;
diff --git a/preproc.c b/preproc.c
index b34710d..ec45bd4 100644
--- a/preproc.c
+++ b/preproc.c
@@ -1134,10 +1134,11 @@ static int ppscan(void *private_data, struct tokenval *tokval)
if (tline->type == TOK_NUMBER) {
bool rn_error;
tokval->t_integer = readnum(tline->text, &rn_error);
- if (rn_error)
- return tokval->t_type = TOKEN_ERRNUM; /* some malformation occurred */
tokval->t_charptr = tline->text;
- return tokval->t_type = TOKEN_NUM;
+ if (rn_error)
+ return tokval->t_type = TOKEN_ERRNUM;
+ else
+ return tokval->t_type = TOKEN_NUM;
}
if (tline->type == TOK_FLOAT) {
@@ -1146,23 +1147,15 @@ static int ppscan(void *private_data, struct tokenval *tokval)
if (tline->type == TOK_STRING) {
char bq, *ep;
- bool errquote;
- bool rn_warn;
- size_t l;
bq = tline->text[0];
- l = nasm_unquote(tline->text, &ep);
- if (ep[0] != bq || ep[1] != '\0')
- errquote = true;
+ tokval->t_charptr = tline->text;
+ tokval->t_inttwo = nasm_unquote(tline->text, &ep);
- if (errquote)
- return tokval->t_type = TOKEN_ERRNUM;
-
- tokval->t_integer = readstrnum(tline->text, l, &rn_warn);
- if (rn_warn)
- error(ERR_WARNING | ERR_PASS1, "character constant too long");
- tokval->t_charptr = NULL;
- return tokval->t_type = TOKEN_NUM;
+ if (ep[0] != bq || ep[1] != '\0')
+ return tokval->t_type = TOKEN_ERRSTR;
+ else
+ return tokval->t_type = TOKEN_STR;
}
if (tline->type == TOK_OTHER) {
diff --git a/stdscan.c b/stdscan.c
index 4db1368..f0d165f 100644
--- a/stdscan.c
+++ b/stdscan.c
@@ -177,17 +177,13 @@ int stdscan(void *private_data, struct tokenval *tv)
} else if (*stdscan_bufptr == '\'' || *stdscan_bufptr == '"' ||
*stdscan_bufptr == '`') {
/* a quoted string */
- bool rn_warn;
char start_quote = *stdscan_bufptr;
tv->t_charptr = stdscan_bufptr;
tv->t_inttwo = nasm_unquote(tv->t_charptr, &stdscan_bufptr);
if (*stdscan_bufptr != start_quote)
- return tv->t_type = TOKEN_ERRNUM;
+ return tv->t_type = TOKEN_ERRSTR;
stdscan_bufptr++; /* Skip final quote */
- tv->t_integer = readstrnum(tv->t_charptr, tv->t_inttwo, &rn_warn);
- /* Issue: can't readily check rn_warn, because we might be in
- a db family context... */
- return tv->t_type = TOKEN_NUM;
+ return tv->t_type = TOKEN_STR;
} else if (*stdscan_bufptr == ';') {
/* a comment has happened - stay */
return tv->t_type = 0;