aboutsummaryrefslogtreecommitdiffstats
path: root/asm/preproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'asm/preproc.c')
-rw-r--r--asm/preproc.c621
1 files changed, 319 insertions, 302 deletions
diff --git a/asm/preproc.c b/asm/preproc.c
index 6c623327..c94f9b68 100644
--- a/asm/preproc.c
+++ b/asm/preproc.c
@@ -81,7 +81,6 @@ typedef struct MMacro MMacro;
typedef struct MMacroInvocation MMacroInvocation;
typedef struct Context Context;
typedef struct Token Token;
-typedef struct Blocks Blocks;
typedef struct Line Line;
typedef struct Include Include;
typedef struct Cond Cond;
@@ -494,16 +493,20 @@ static macros_t *extrastdmac;
static bool *use_loaded;
/*
- * Tokens are allocated in blocks to improve speed
+ * Tokens are allocated in blocks to improve speed. Set the blocksize
+ * to 0 to use regular nasm_malloc(); this is useful for debugging.
*/
#define TOKEN_BLOCKSIZE 4096
-static Token *freeTokens = NULL;
+
+#if TOKEN_BLOCKSIZE
+typedef struct Blocks Blocks;
struct Blocks {
Blocks *next;
void *chunk;
};
-
static Blocks blocks = { NULL, NULL };
+static Token *freeTokens = NULL;
+#endif
/*
* Forward declarations.
@@ -515,22 +518,55 @@ static Token *expand_id(Token * tline);
static Context *get_ctx(const char *name, const char **namep);
static Token *make_tok_num(int64_t val);
static Token *make_tok_qstr(const char *str);
-static void *new_Block(size_t size);
-static void delete_Blocks(void);
static Token *new_Token(Token * next, enum pp_token_type type,
const char *text, size_t txtlen);
static Token *dup_Token(Token *next, const Token *src);
+static Token *new_White(Token *next);
static Token *delete_Token(Token * t);
static const struct use_package *
get_use_pkg(Token *t, const char *dname, bool *err);
-/*
- * Macros for safe checking of token pointers, avoid *(NULL)
- */
-#define tok_type_(x,t) ((x) && (x)->type == (t))
-#define skip_white_(x) ((x) = (tok_type_((x), TOK_WHITESPACE) ? (x)->next : (x)))
-#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
-#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
+/* Safe test for token type, false on x == NULL */
+static inline bool tok_type(const Token *x, enum pp_token_type t)
+{
+ return x && x->type == t;
+}
+
+/* Whitespace token? */
+static inline bool tok_white(const Token *x)
+{
+ return tok_type(x, TOK_WHITESPACE);
+}
+
+/* Skip past any whitespace */
+static inline Token *skip_white(Token *x)
+{
+ while (tok_white(x))
+ x = x->next;
+
+ return x;
+}
+
+/* Delete any whitespace */
+static Token *zap_white(Token *x)
+{
+ while (tok_white(x))
+ x = delete_Token(x);
+
+ return x;
+}
+
+/* Single special character tests */
+static inline bool tok_is(const Token *x, char c)
+{
+ return x && x->type == TOK_OTHER && x->len == 1 && x->text[0] == c;
+}
+
+/* True if any other kind of token that "c", but not NULL */
+static inline bool tok_isnt(const Token *x, char c)
+{
+ return x && (x->type != TOK_OTHER || x->len != 1 || x->text[0] != c);
+}
/*
* In-place reverse a list of tokens.
@@ -1155,10 +1191,9 @@ static Token *tokenize(char *line)
}
} else if (nasm_isidstart(*p) || (*p == '$' && nasm_isidstart(p[1]))) {
type = TOK_ID;
- p++;
- while (*p && nasm_isidchar(*p))
- p++;
- } else if (nasm_isquote(*p)) {
+ while (nasm_isidchar(*++p))
+ ;
+ } else if (nasm_isquote(*p)) {
/*
* A string token.
*/
@@ -1308,31 +1343,40 @@ static Token *tokenize(char *line)
return list;
}
+#if TOKEN_BLOCKSIZE
/*
* this function allocates a new managed block of memory and
* returns a pointer to the block. The managed blocks are
* deleted only all at once by the delete_Blocks function.
*/
-static void *new_Block(size_t size)
+static void new_Block(void)
{
Blocks *b = &blocks;
+ int i;
/* first, get to the end of the linked list */
while (b->next)
b = b->next;
/* now allocate the requested chunk */
- b->chunk = nasm_malloc(size);
+ b->chunk = nasm_malloc(TOKEN_BLOCKSIZE * sizeof(Token));
/* now allocate a new block for the next request */
b->next = nasm_zalloc(sizeof(Blocks));
- return b->chunk;
+
+ freeTokens = b->chunk;
+ for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
+ freeTokens[i].next = &freeTokens[i + 1];
+
+ freeTokens[i].next = NULL;
}
+#endif
/*
* this function deletes all managed blocks of memory
*/
static void delete_Blocks(void)
{
+#if TOKEN_BLOCKSIZE
Blocks *a, *b = &blocks;
/*
@@ -1349,6 +1393,9 @@ static void delete_Blocks(void)
nasm_free(a);
}
memset(&blocks, 0, sizeof(blocks));
+
+ freeTokens = NULL;
+#endif
}
/*
@@ -1359,16 +1406,15 @@ static Token *new_Token(Token * next, enum pp_token_type type,
const char *text, size_t txtlen)
{
Token *t;
- int i;
- if (!freeTokens) {
- freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
- for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
- freeTokens[i].next = &freeTokens[i + 1];
- freeTokens[i].next = NULL;
- }
+#if TOKEN_BLOCKSIZE
+ if (!freeTokens)
+ new_Block();
t = freeTokens;
freeTokens = t->next;
+#else
+ t = nasm_malloc(sizeof *t);
+#endif
t->next = next;
t->type = type;
if (type == TOK_WHITESPACE || !text) {
@@ -1390,12 +1436,22 @@ static Token *dup_Token(Token *next, const Token *src)
return new_Token(next, src->type, src->text, src->len);
}
+static Token *new_White(Token *next)
+{
+ return new_Token(next, TOK_WHITESPACE, NULL, 0);
+}
+
static Token *delete_Token(Token * t)
{
Token *next = t->next;
+
nasm_free(t->text);
+#if TOKEN_BLOCKSIZE
t->next = freeTokens;
freeTokens = t;
+#else
+ nasm_free(t);
+#endif
return next;
}
@@ -1622,8 +1678,8 @@ static bool pp_get_boolean_option(Token *tline, bool defval)
struct tokenval tokval;
expr *evalresult;
- skip_white_(tline);
- if (!tline || !tline->type)
+ tline = skip_white(tline);
+ if (!tline)
return true;
if (tline->type == TOK_ID) {
@@ -1929,21 +1985,21 @@ static void count_mmac_params(Token * t, int *nparamp, Token ***paramsp)
params = nasm_malloc(paramsize * sizeof(*params));
params[0] = NULL;
- while (skip_white_(t)) {
+ while ((t = skip_white(t))) {
/* 2 slots for captured label and NULL */
if (nparam+2 >= paramsize) {
paramsize += PARAM_DELTA;
params = nasm_realloc(params, sizeof(*params) * paramsize);
}
brace = 0;
- if (tok_is_(t, "{"))
+ if (tok_is(t, '{'))
brace++;
params[++nparam] = t;
if (brace) {
- while (brace && (t = t->next) != NULL) {
- if (tok_is_(t, "{"))
+ while (brace && (t = t->next)) {
+ if (tok_is(t, '{'))
brace++;
- else if (tok_is_(t, "}"))
+ else if (tok_is(t, '}'))
brace--;
}
@@ -1952,21 +2008,17 @@ static void count_mmac_params(Token * t, int *nparamp, Token ***paramsp)
* Now we've found the closing brace, look further
* for the comma.
*/
- t = t->next;
- skip_white_(t);
- if (tok_isnt_(t, ",")) {
+ t = skip_white(t->next);
+ if (!tok_is(t, ','))
nasm_nonfatal("braces do not enclose all of macro parameter");
- while (tok_isnt_(t, ","))
- t = t->next;
- }
}
- } else {
- while (tok_isnt_(t, ","))
- t = t->next;
- }
- if (t) { /* got a comma/brace */
- t = t->next; /* eat the comma */
}
+
+ while (tok_isnt(t, ','))
+ t = t->next;
+
+ if (t) /* got a comma */
+ t = t->next; /* eat the comma */
}
params[nparam+1] = NULL;
@@ -1999,7 +2051,7 @@ static enum cond_state if_condition(Token * tline, enum preproc_token ct)
case PP_IFCTX:
j = false; /* have we matched yet? */
while (true) {
- skip_white_(tline);
+ tline = skip_white(tline);
if (!tline)
break;
if (tline->type != TOK_ID) {
@@ -2016,7 +2068,7 @@ static enum cond_state if_condition(Token * tline, enum preproc_token ct)
case PP_IFDEF:
j = false; /* have we matched yet? */
while (tline) {
- skip_white_(tline);
+ tline = skip_white(tline);
if (!tline || (tline->type != TOK_ID &&
(tline->type != TOK_PREPROC_ID ||
tline->text[1] != '$'))) {
@@ -2034,7 +2086,7 @@ static enum cond_state if_condition(Token * tline, enum preproc_token ct)
tline = expand_smacro(tline);
j = false; /* have we matched yet? */
while (tline) {
- skip_white_(tline);
+ tline = skip_white(tline);
if (!tline || (tline->type != TOK_ID &&
tline->type != TOK_STRING &&
(tline->type != TOK_PREPROC_ID ||
@@ -2060,7 +2112,7 @@ static enum cond_state if_condition(Token * tline, enum preproc_token ct)
case PP_IFIDN:
tline = expand_smacro(tline);
t = tt = tline;
- while (tok_isnt_(tt, ","))
+ while (tok_isnt(tt, ','))
tt = tt->next;
if (!tt) {
nasm_nonfatal("`%s' expects two comma-separated arguments",
@@ -2117,9 +2169,9 @@ static enum cond_state if_condition(Token * tline, enum preproc_token ct)
bool found = false;
MMacro searching, *mmac;
- skip_white_(tline);
+ tline = skip_white(tline);
tline = expand_id(tline);
- if (!tok_type_(tline, TOK_ID)) {
+ if (!tok_type(tline, TOK_ID)) {
nasm_nonfatal("`%s' expects a macro name", dname);
goto fail;
}
@@ -2129,20 +2181,20 @@ static enum cond_state if_condition(Token * tline, enum preproc_token ct)
searching.nparam_min = 0;
searching.nparam_max = INT_MAX;
tline = expand_smacro(tline->next);
- skip_white_(tline);
+ tline = skip_white(tline);
if (!tline) {
- } else if (!tok_type_(tline, TOK_NUMBER)) {
+ } else if (!tok_type(tline, TOK_NUMBER)) {
nasm_nonfatal("`%s' expects a parameter count or nothing",
dname);
} else {
searching.nparam_min = searching.nparam_max =
read_param_count(tline->text);
}
- if (tline && tok_is_(tline->next, "-")) {
+ if (tline && tok_is(tline->next, '-')) {
tline = tline->next->next;
- if (tok_is_(tline, "*"))
+ if (tok_is(tline, '*'))
searching.nparam_max = INT_MAX;
- else if (!tok_type_(tline, TOK_NUMBER))
+ else if (!tok_type(tline, TOK_NUMBER))
nasm_nonfatal("`%s' expects a parameter count after `-'",
dname);
else {
@@ -2153,7 +2205,7 @@ static enum cond_state if_condition(Token * tline, enum preproc_token ct)
}
}
}
- if (tline && tok_is_(tline->next, "+")) {
+ if (tline && tok_is(tline->next, '+')) {
tline = tline->next;
searching.plus = true;
}
@@ -2189,35 +2241,27 @@ static enum cond_state if_condition(Token * tline, enum preproc_token ct)
iftype:
t = tline = expand_smacro(tline);
- while (tok_type_(t, TOK_WHITESPACE) ||
- (needtype == TOK_NUMBER &&
- tok_type_(t, TOK_OTHER) &&
- (t->text[0] == '-' || t->text[0] == '+') &&
- !t->text[1]))
+ while (tok_white(t) ||
+ (needtype == TOK_NUMBER && (tok_is(t, '-') | tok_is(t, '+'))))
t = t->next;
- j = tok_type_(t, needtype);
+ j = tok_type(t, needtype);
break;
case PP_IFTOKEN:
- t = tline = expand_smacro(tline);
- while (tok_type_(t, TOK_WHITESPACE))
- t = t->next;
+ tline = expand_smacro(tline);
+ t = skip_white(tline);
j = false;
if (t) {
- t = t->next; /* Skip the actual token */
- while (tok_type_(t, TOK_WHITESPACE))
- t = t->next;
- j = !t; /* Should be nothing left */
+ t = skip_white(t->next); /* Skip the actual token + whitespace */
+ j = !t;
}
break;
case PP_IFEMPTY:
- t = tline = expand_smacro(tline);
- while (tok_type_(t, TOK_WHITESPACE))
- t = t->next;
-
+ tline = expand_smacro(tline);
+ t = skip_white(tline);
j = !t; /* Should be empty */
break;
@@ -2404,7 +2448,7 @@ static int parse_smacro_template(Token ***tpp, SMacro *tmpl)
* This ambiguity was inherited from C.
*/
- if (!tok_is_(t, "("))
+ if (!tok_is(t, '('))
goto finish;
if (tmpl) {
@@ -2649,9 +2693,9 @@ static void undef_smacro(const char *mname, bool undefalias)
static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
{
tline = tline->next;
- skip_white_(tline);
+ tline = skip_white(tline);
tline = expand_id(tline);
- if (!tok_type_(tline, TOK_ID)) {
+ if (!tok_type(tline, TOK_ID)) {
nasm_nonfatal("`%s' expects a macro name", directive);
return false;
}
@@ -2666,16 +2710,16 @@ static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
def->nparam_max = 0;
tline = expand_smacro(tline->next);
- skip_white_(tline);
- if (!tok_type_(tline, TOK_NUMBER))
+ tline = skip_white(tline);
+ if (!tok_type(tline, TOK_NUMBER))
nasm_nonfatal("`%s' expects a parameter count", directive);
else
def->nparam_min = def->nparam_max = read_param_count(tline->text);
- if (tline && tok_is_(tline->next, "-")) {
+ if (tline && tok_is(tline->next, '-')) {
tline = tline->next->next;
- if (tok_is_(tline, "*")) {
+ if (tok_is(tline, '*')) {
def->nparam_max = INT_MAX;
- } else if (!tok_type_(tline, TOK_NUMBER)) {
+ } else if (!tok_type(tline, TOK_NUMBER)) {
nasm_nonfatal("`%s' expects a parameter count after `-'", directive);
} else {
def->nparam_max = read_param_count(tline->text);
@@ -2685,11 +2729,11 @@ static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
}
}
}
- if (tline && tok_is_(tline->next, "+")) {
+ if (tline && tok_is(tline->next, '+')) {
tline = tline->next;
def->plus = true;
}
- if (tline && tok_type_(tline->next, TOK_ID) &&
+ if (tline && tok_type(tline->next, TOK_ID) &&
!nasm_stricmp(tline->next->text, ".nolist")) {
tline = tline->next;
def->nolist = !list_option('f') || istk->nolist;
@@ -2743,7 +2787,7 @@ static void do_pragma_preproc(Token *tline)
{
/* Skip to the real stuff */
tline = tline->next;
- skip_white_(tline);
+ tline = skip_white(tline);
if (!tline)
return;
@@ -2762,7 +2806,7 @@ static char *get_id(Token **tp, const char *dname)
Token *t = *tp;
t = t->next; /* Skip directive */
- skip_white_(t);
+ t = skip_white(t);
t = expand_id(t);
if (!is_macro_id(t)) {
@@ -2771,7 +2815,7 @@ static char *get_id(Token **tp, const char *dname)
}
id = t->text;
- skip_white_(t);
+ t = skip_white(t);
*tp = t;
return id;
}
@@ -2784,7 +2828,7 @@ get_use_pkg(Token *t, const char *dname, bool *err)
*err = false;
- skip_white_(t);
+ t = skip_white(t);
t = expand_smacro(t);
@@ -2805,7 +2849,7 @@ get_use_pkg(Token *t, const char *dname, bool *err)
}
t = t->next;
- skip_white_(t);
+ t = skip_white(t);
if (t)
nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
@@ -2855,8 +2899,8 @@ static int do_directive(Token *tline, Token **output)
*output = NULL; /* No output generated */
origline = tline;
- skip_white_(tline);
- if (!tline || !tok_type_(tline, TOK_PREPROC_ID) ||
+ tline = skip_white(tline);
+ if (!tline || !tok_type(tline, TOK_PREPROC_ID) ||
(tline->text[0] && (tline->text[1] == '%' ||
tline->text[1] == '$' ||
tline->text[1] == '!')))
@@ -2936,13 +2980,8 @@ static int do_directive(Token *tline, Token **output)
t = tline;
tline = tline->next;
t->next = NULL;
- tline = expand_smacro(tline);
- while (tok_type_(tline, TOK_WHITESPACE)) {
- t = tline;
- tline = tline->next;
- delete_Token(t);
- }
- if (tok_type_(tline, TOK_ID)) {
+ tline = zap_white(expand_smacro(tline));
+ if (tok_type(tline, TOK_ID)) {
if (!nasm_stricmp(tline->text, "preproc")) {
/* Preprocessor pragma */
do_pragma_preproc(tline);
@@ -2956,7 +2995,7 @@ static int do_directive(Token *tline, Token **output)
t->next = new_Token(NULL, TOK_OTHER, "]", 1);
/* Prepend "[pragma " */
- t = new_Token(tline, TOK_WHITESPACE, NULL, 0);
+ t = new_White(tline);
t = new_Token(t, TOK_ID, "pragma", 6);
t = new_Token(t, TOK_OTHER, "[", 1);
tline = t;
@@ -2970,9 +3009,7 @@ static int do_directive(Token *tline, Token **output)
* default is for a 16-bit stack, and this can be overriden with
* %stacksize large.
*/
- tline = tline->next;
- if (tline && tline->type == TOK_WHITESPACE)
- tline = tline->next;
+ tline = skip_white(tline->next);
if (!tline || tline->type != TOK_ID) {
nasm_nonfatal("`%s' missing size parameter", dname);
}
@@ -3021,9 +3058,7 @@ static int do_directive(Token *tline, Token **output)
int size = StackSize;
/* Find the argument name */
- tline = tline->next;
- if (tline && tline->type == TOK_WHITESPACE)
- tline = tline->next;
+ tline = skip_white(tline->next);
if (!tline || tline->type != TOK_ID) {
nasm_nonfatal("`%s' missing argument parameter", dname);
goto done;
@@ -3064,10 +3099,8 @@ static int do_directive(Token *tline, Token **output)
offset += size;
/* Move to the next argument in the list */
- tline = tline->next;
- if (tline && tline->type == TOK_WHITESPACE)
- tline = tline->next;
- } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
+ tline = skip_white(tline->next);
+ } while (tok_is(tline, ','));
ArgOffset = offset;
break;
@@ -3087,9 +3120,7 @@ static int do_directive(Token *tline, Token **output)
int size = StackSize;
/* Find the argument name */
- tline = tline->next;
- if (tline && tline->type == TOK_WHITESPACE)
- tline = tline->next;
+ tline = skip_white(tline->next);
if (!tline || tline->type != TOK_ID) {
nasm_nonfatal("`%s' missing argument parameter", dname);
goto done;
@@ -3136,10 +3167,8 @@ static int do_directive(Token *tline, Token **output)
do_directive(tokenize(directive), output);
/* Move to the next argument in the list */
- tline = tline->next;
- if (tline && tline->type == TOK_WHITESPACE)
- tline = tline->next;
- } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
+ tline = skip_white(tline->next);
+ } while (tok_is(tline, ','));
LocalOffset = offset;
break;
@@ -3152,7 +3181,7 @@ static int do_directive(Token *tline, Token **output)
case PP_DEPEND:
t = tline->next = expand_smacro(tline->next);
- skip_white_(t);
+ t = skip_white(t);
if (!t || (t->type != TOK_STRING &&
t->type != TOK_INTERNAL_STRING)) {
nasm_nonfatal("`%s' expects a file name", dname);
@@ -3168,7 +3197,7 @@ static int do_directive(Token *tline, Token **output)
case PP_INCLUDE:
t = tline->next = expand_smacro(tline->next);
- skip_white_(t);
+ t = skip_white(t);
if (!t || (t->type != TOK_STRING &&
t->type != TOK_INTERNAL_STRING)) {
@@ -3232,10 +3261,10 @@ static int do_directive(Token *tline, Token **output)
case PP_REPL:
case PP_POP:
tline = tline->next;
- skip_white_(tline);
+ tline = skip_white(tline);
tline = expand_id(tline);
if (tline) {
- if (!tok_type_(tline, TOK_ID)) {
+ if (!tok_type(tline, TOK_ID)) {
nasm_nonfatal("`%s' expects a context identifier",
pp_directives[i]);
goto done;
@@ -3295,10 +3324,10 @@ issue_error:
/* Only error out if this is the final pass */
tline->next = expand_smacro(tline->next);
tline = tline->next;
- skip_white_(tline);
+ tline = skip_white(tline);
t = tline ? tline->next : NULL;
- skip_white_(t);
- if (tok_type_(tline, TOK_STRING) && !t) {
+ t = skip_white(t);
+ if (tok_type(tline, TOK_STRING) && !t) {
/* The line contains only a quoted string */
p = tline->text;
nasm_unquote(p, NULL); /* Ignore NUL character truncation */
@@ -3503,7 +3532,7 @@ issue_error:
}
case PP_ROTATE:
- if (tline->next && tline->next->type == TOK_WHITESPACE)
+ while (tok_white(tline->next))
tline = tline->next;
if (!tline->next) {
free_tlist(origline);
@@ -3547,16 +3576,11 @@ issue_error:
MMacro *tmp_defining;
nolist = false;
- do {
- tline = tline->next;
- } while (tok_type_(tline, TOK_WHITESPACE));
-
- if (tok_type_(tline, TOK_ID) &&
+ tline = skip_white(tline->next);
+ if (tok_type(tline, TOK_ID) &&
nasm_stricmp(tline->text, ".nolist") == 0) {
nolist = !list_option('f') || istk->nolist;
- do {
- tline = tline->next;
- } while (tok_type_(tline, TOK_WHITESPACE));
+ tline = skip_white(tline->next);
}
if (tline) {
@@ -3677,7 +3701,7 @@ issue_error:
tt = macro_start->next;
macro_start->next = NULL;
tline = tline->next;
- skip_white_(tline);
+ tline = skip_white(tline);
if (tline && tline->type) {
nasm_warn(WARN_OTHER,
"trailing garbage after aliasing identifier ignored");
@@ -3739,9 +3763,7 @@ issue_error:
tline = expand_smacro(tline->next);
last->next = NULL;
- while (tok_type_(tline, TOK_WHITESPACE))
- tline = delete_Token(tline);
-
+ tline = zap_white(tline);
p = detoken(tline, false);
macro_start = make_tok_qstr(p);
nasm_free(p);
@@ -3762,11 +3784,9 @@ issue_error:
tline = expand_smacro(tline->next);
last->next = NULL;
- t = tline;
- while (tok_type_(t, TOK_WHITESPACE))
- t = t->next;
+ t = skip_white(tline);
/* t should now point to the string */
- if (!tok_type_(t, TOK_STRING)) {
+ if (!tok_type(t, TOK_STRING)) {
nasm_nonfatal("`%s' requires string as second parameter", dname);
free_tlist(tline);
goto done;
@@ -3800,10 +3820,7 @@ issue_error:
tline = expand_smacro(tline->next);
last->next = NULL;
- t = tline;
- while (tok_type_(t, TOK_WHITESPACE))
- t = t->next;
-
+ t = skip_white(tline);
if (!t || (t->type != TOK_STRING &&
t->type != TOK_INTERNAL_STRING)) {
nasm_nonfatal("`%s' expects a file name", dname);
@@ -3839,11 +3856,9 @@ issue_error:
tline = expand_smacro(tline->next);
last->next = NULL;
- t = tline;
- while (tok_type_(t, TOK_WHITESPACE))
- t = t->next;
+ t = skip_white(tline);
/* t should now point to the string */
- if (!tok_type_(t, TOK_STRING)) {
+ if (!tok_type(t, TOK_STRING)) {
nasm_nonfatal("`%s' requires string as second parameter", dname);
free_tlist(tline);
free_tlist(origline);
@@ -3922,11 +3937,11 @@ issue_error:
if (tline) /* skip expanded id */
t = tline->next;
- while (tok_type_(t, TOK_WHITESPACE))
- t = t->next;
+
+ t = skip_white(t);
/* t should now point to the string */
- if (!tok_type_(t, TOK_STRING)) {
+ if (!tok_type(t, TOK_STRING)) {
nasm_nonfatal("`%s' requires string as second parameter", dname);
free_tlist(tline);
goto done;
@@ -3946,8 +3961,7 @@ issue_error:
}
start = evalresult->value - 1;
- while (tok_type_(pps.tptr, TOK_WHITESPACE))
- pps.tptr = pps.tptr->next;
+ pps.tptr = skip_white(pps.tptr);
if (!pps.tptr) {
count = 1; /* Backwards compatibility: one character */
} else {
@@ -4040,24 +4054,24 @@ issue_error:
goto done;
tline = tline->next;
- skip_white_(tline);
- if (!tok_type_(tline, TOK_NUMBER)) {
+ tline = skip_white(tline);
+ if (!tok_type(tline, TOK_NUMBER)) {
nasm_nonfatal("`%s' expects line number", dname);
goto done;
}
k = readnum(tline->text, &err);
m = 1;
tline = tline->next;
- if (tok_is_(tline, "+")) {
+ if (tok_is(tline, '+')) {
tline = tline->next;
- if (!tok_type_(tline, TOK_NUMBER)) {
+ if (!tok_type(tline, TOK_NUMBER)) {
nasm_nonfatal("`%s' expects line increment", dname);
goto done;
}
m = readnum(tline->text, &err);
tline = tline->next;
}
- skip_white_(tline);
+ tline = skip_white(tline);
src_set_linnum(k);
istk->lineinc = m;
if (tline) {
@@ -4085,13 +4099,13 @@ static int find_cc(Token * t)
if (!t)
return -1; /* Probably a %+ without a space */
- skip_white_(t);
+ t = skip_white(t);
if (!t)
return -1;
if (t->type != TOK_ID)
return -1;
tt = t->next;
- skip_white_(tt);
+ tt = skip_white(tt);
if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
return -1;
@@ -4108,7 +4122,7 @@ static int find_cc(Token * t)
static bool paste_tokens(Token **head, const struct tokseq_match *m,
size_t mnum, bool handle_explicit)
{
- Token *tok, *next, **prev_next, **prev_nonspace;
+ Token *tok, *t, *next, **prev_next, **prev_nonspace;
bool pasted = false;
char *buf, *p;
size_t len, i;
@@ -4128,7 +4142,7 @@ static bool paste_tokens(Token **head, const struct tokseq_match *m,
tok = *head;
prev_next = NULL;
- if (!tok_type_(tok, TOK_WHITESPACE) && !tok_type_(tok, TOK_PASTE))
+ if (!tok_white(tok) && !tok_type(tok, TOK_PASTE))
prev_nonspace = head;
else
prev_nonspace = NULL;
@@ -4138,26 +4152,33 @@ static bool paste_tokens(Token **head, const struct tokseq_match *m,
switch (tok->type) {
case TOK_WHITESPACE:
/* Zap redundant whitespaces */
- while (tok_type_(next, TOK_WHITESPACE))
- next = delete_Token(next);
- tok->next = next;
+ next = zap_white(next);
break;
case TOK_PASTE:
/* Explicit pasting */
if (!handle_explicit)
break;
- next = delete_Token(tok);
- while (tok_type_(next, TOK_WHITESPACE))
- next = delete_Token(next);
+ /* Left pasting token is start of line */
+ if (!prev_nonspace) {
+ nasm_nonfatal("No lvalue found on pasting");
+ tok = delete_Token(tok);
+ break;
+ }
+
+ pasted = true;
+ t = *prev_nonspace;
- if (!pasted)
- pasted = true;
+ /* Delete leading whitespace */
+ next = zap_white(t->next);
- /* Left pasting token is start of line */
- if (!prev_nonspace)
- nasm_fatal("No lvalue found on pasting");
+ /* Delete the %+ token itself */
+ nasm_assert(next == tok);
+ next = delete_Token(next);
+
+ /* Delete trailing whitespace */
+ next = zap_white(next);
/*
* No ending token, this might happen in two
@@ -4173,41 +4194,33 @@ static bool paste_tokens(Token **head, const struct tokseq_match *m,
* whitespace after paste token.
*/
if (!next) {
- /*
- * Zap ending space tokens and that's all.
- */
- tok = (*prev_nonspace)->next;
- while (tok_type_(tok, TOK_WHITESPACE))
- tok = delete_Token(tok);
- tok = *prev_nonspace;
- tok->next = NULL;
+ tok = NULL; /* End of line */
break;
}
- tok = *prev_nonspace;
- while (tok_type_(tok, TOK_WHITESPACE))
- tok = delete_Token(tok);
- len = strlen(tok->text);
- len += strlen(next->text);
-
- p = buf = nasm_malloc(len + 1);
- strcpy(p, tok->text);
- p = strchr(p, '\0');
- strcpy(p, next->text);
-
- delete_Token(tok);
-
- tok = tokenize(buf);
+ p = buf = nasm_malloc(t->len + next->len + 1);
+ p = mempcpy(p, t->text, t->len);
+ p = mempcpy(p, next->text, next->len);
+ *p = '\0';
+ delete_Token(t);
+ t = tokenize(buf);
nasm_free(buf);
- *prev_nonspace = tok;
- while (tok && tok->next)
- tok = tok->next;
+ if (unlikely(!t)) {
+ /*
+ * No output at all? Replace with a single whitespace.
+ * This should never happen.
+ */
+ t = new_White(NULL);
+ }
- tok->next = delete_Token(next);
+ /* We want to restart from the head of the pasted token */
+ *prev_nonspace = tok = t;
+ while (t->next)
+ t = t->next; /* Find the last token produced */
- /* Restart from pasted tokens head */
- tok = *prev_nonspace;
+ /* Delete the second token and attach to the end of the list */
+ t->next = delete_Token(next);
break;
default:
@@ -4218,7 +4231,7 @@ static bool paste_tokens(Token **head, const struct tokseq_match *m,
len = 0;
while (next && PP_CONCAT_MATCH(next, m[i].mask_tail)) {
- len += strlen(next->text);
+ len += next->len;
next = next->next;
}
@@ -4226,17 +4239,16 @@ static bool paste_tokens(Token **head, const struct tokseq_match *m,
if (tok == next || len == 0)
break;
- len += strlen(tok->text);
+ len += tok->len;
p = buf = nasm_malloc(len + 1);
- strcpy(p, tok->text);
- p = strchr(p, '\0');
+ p = mempcpy(p, tok->text, tok->len);
tok = delete_Token(tok);
while (tok != next) {
if (PP_CONCAT_MATCH(tok, m[i].mask_tail)) {
- strcpy(p, tok->text);
- p = strchr(p, '\0');
+ p = mempcpy(p, tok->text, tok->len);
+ tok = delete_Token(tok);
}
tok = delete_Token(tok);
}
@@ -4257,8 +4269,7 @@ static bool paste_tokens(Token **head, const struct tokseq_match *m,
tok = tok->next;
tok->next = next;
- if (!pasted)
- pasted = true;
+ pasted = true;
/* Restart from pasted tokens head */
tok = prev_next ? *prev_next : *head;
@@ -4269,9 +4280,8 @@ static bool paste_tokens(Token **head, const struct tokseq_match *m,
prev_next = &tok->next;
- if (tok->next &&
- !tok_type_(tok->next, TOK_WHITESPACE) &&
- !tok_type_(tok->next, TOK_PASTE))
+ if (tok->next && !tok_white(tok->next) &&
+ !tok_type(tok->next, TOK_PASTE))
prev_nonspace = prev_next;
tok = tok->next;
@@ -4336,7 +4346,7 @@ static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
goto err;
head = dup_Token(NULL, tm);
tt = &head->next, tm = tm->next;
- while (tok_isnt_(tm, ",")) {
+ while (tok_isnt(tm, ',')) {
t = dup_Token(NULL, tm);
*tt = t, tt = &t->next, tm = tm->next;
}
@@ -4347,7 +4357,7 @@ static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
*tt = t, tt = &t->next;
j = (i + mac->rotate) % mac->nparam;
tm = mac->params[j+1];
- while (tok_isnt_(tm, ",")) {
+ while (tok_isnt(tm, ',')) {
t = dup_Token(NULL, tm);
*tt = t, tt = &t->next, tm = tm->next;
}
@@ -4358,7 +4368,7 @@ static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
*tt = t, tt = &t->next;
j = (i + mac->rotate) % mac->nparam;
tm = mac->params[j+1];
- while (tok_isnt_(tm, ",")) {
+ while (!tok_isnt(tm, ',')) {
t = dup_Token(NULL, tm);
*tt = t, tt = &t->next, tm = tm->next;
}
@@ -4601,8 +4611,8 @@ static Token *expand_smacro_noreset(Token * tline);
* a macro at all, it is simply copied to the output and the pointer
* advanced. tpp should be a pointer to a pointer (usually the next
* pointer of the previous token) to the first token. **tpp is updated
- * to point to the last token of the expansion, and *tpp updated to
- * point to the next pointer of the first token of the expansion.
+ * to point to the first token of the expansion, and *tpp updated to
+ * point to the next pointer of the last token of the expansion.
*
* If the expansion is empty, *tpp will be unchanged but **tpp will
* be advanced past the macro call.
@@ -4613,18 +4623,18 @@ static SMacro *expand_one_smacro(Token ***tpp)
{
Token **params = NULL;
const char *mname;
- Token *tline = **tpp;
Token *mstart = **tpp;
+ Token *tline = mstart;
SMacro *head, *m;
int i;
- Token *t, *tup, *ttail;
+ Token *t, *tup, *tafter;
int nparam = 0;
bool cond_comma;
if (!tline)
return false; /* Empty line, nothing to do */
- mname = tline->text;
+ mname = mstart->text;
smacro_deadman.total--;
smacro_deadman.levels--;
@@ -4684,8 +4694,8 @@ static SMacro *expand_one_smacro(Token ***tpp)
int paren, brackets;
tline = tline->next;
- skip_white_(tline);
- if (!tok_is_(tline, "(")) {
+ tline = skip_white(tline);
+ if (!tok_is(tline, '(')) {
/*
* This macro wasn't called with parameters: ignore
* the call. (Behaviour borrowed from gnu cpp.)
@@ -4877,13 +4887,12 @@ static SMacro *expand_one_smacro(Token ***tpp)
bad_bracket |= bracketed && !brackets;
if (white) {
- *pep = t = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
+ *pep = t = new_White(NULL);
pep = &t->next;
white = 0;
}
*pep = t = dup_Token(NULL, tline);
pep = &t->next;
- white = 0;
}
}
@@ -4934,31 +4943,52 @@ static SMacro *expand_one_smacro(Token ***tpp)
}
}
- t = tline;
- tline = tline->next; /* Remove the macro call from the input */
- t->next = NULL;
-
/* Note: we own the expansion this returns. */
t = m->expand(m, params, nparam);
+ tafter = tline->next; /* Skip past the macro call */
+ tline->next = NULL; /* Truncate list at the macro call end */
+ tline = tafter;
+
tup = NULL;
- ttail = NULL; /* Pointer to the last token of the expansion */
cond_comma = false;
while (t) {
enum pp_token_type type = t->type;
Token *tnext = t->next;
- Token **tp;
switch (type) {
case TOK_PREPROC_Q:
+ delete_Token(t);
+ t = dup_Token(tline, mstart);
+ break;
+
case TOK_PREPROC_QQ:
- t->type = TOK_ID;
+ {
+ size_t len = strlen(m->name);
+ char *p;
+
nasm_free(t->text);
- t->text = nasm_strdup(type == TOK_PREPROC_QQ ? m->name : mname);
- t->len = nasm_last_string_len();
+ t->type = mstart->type;
+ if (t->type == TOK_PREPROC_ID) {
+ const char *pep; /* prefix end pointer */
+ size_t plen; /* prefix length */
+
+ get_ctx(mstart->text, &pep);
+ plen = pep - mstart->text;
+
+ t->len = len + plen;
+ t->text = p = nasm_malloc(t->len + 1);
+ p = mempcpy(p, mstart->text, plen);
+ } else {
+ t->len = len;
+ t->text = p = nasm_malloc(len + 1);
+ }
+ p = mempcpy(p, m->name, len);
+ *p = '\0';
t->next = tline;
break;
+ }
case TOK_COND_COMMA:
delete_Token(t);
@@ -4967,18 +4997,18 @@ static SMacro *expand_one_smacro(Token ***tpp)
case TOK_ID:
case TOK_PREPROC_ID:
+ {
/*
* Chain this into the target line *before* expanding,
* that way we pick up any arguments to the new macro call,
* if applicable.
*/
+ Token **tp = &t;
t->next = tline;
- tp = &t;
expand_one_smacro(&tp);
- if (t == tline)
- t = NULL; /* Null expansion */
+ tline = *tp; /* First token left after any macro call */
break;
-
+ }
default:
if (is_smac_param(t->type)) {
int param = smac_nparam(t->type);
@@ -4994,11 +5024,11 @@ static SMacro *expand_one_smacro(Token ***tpp)
}
if (t) {
- if (t->type != TOK_WHITESPACE)
- cond_comma = true;
+ Token *endt = tline;
+
tline = t;
- if (!ttail)
- ttail = t;
+ while (!cond_comma && t && t != endt)
+ cond_comma = t->type != TOK_WHITESPACE;
}
if (tnext) {
@@ -5010,8 +5040,8 @@ static SMacro *expand_one_smacro(Token ***tpp)
}
**tpp = tline;
- if (ttail)
- *tpp = &ttail->next;
+ for (t = tline; t != tafter; t = t->next)
+ *tpp = &t->next;
m->in_progress = false;
@@ -5049,25 +5079,21 @@ static Token *expand_smacro(Token *tline)
return expand_smacro_noreset(tline);
}
-static Token *expand_smacro_noreset(Token * tline)
+static Token *expand_smacro_noreset(Token *org_tline)
{
- Token *t, **tail, *thead;
- Token *org_tline = tline;
+ Token *tline;
bool expanded;
+ if (!org_tline)
+ return NULL; /* Empty input */
+
/*
* Trick: we should avoid changing the start token pointer since it can
* be contained in "next" field of other token. Because of this
* we allocate a copy of first token and work with it; at the end of
* routine we copy it back
*/
- if (org_tline) {
- tline = new_Token(org_tline->next, org_tline->type,
- org_tline->text, 0);
- nasm_free(org_tline->text);
- org_tline->text = NULL;
- }
-
+ tline = dup_Token(org_tline->next, org_tline);
/*
* Pretend that we always end up doing expansion on the first pass;
@@ -5076,7 +5102,6 @@ static Token *expand_smacro_noreset(Token * tline)
* look up the macro "MACROTAIL", which we don't want.
*/
expanded = true;
- thead = tline;
while (true) {
static const struct tokseq_match tmatch[] = {
{
@@ -5087,15 +5112,13 @@ static Token *expand_smacro_noreset(Token * tline)
PP_CONCAT_MASK(TOK_NUMBER) /* tail */
}
};
+ Token **tail = &tline;
- tail = &thead;
- while ((t = *tail)) /* main token loop */
+ while (*tail) /* main token loop */
expanded |= !!expand_one_smacro(&tail);
- if (!expanded) {
- tline = thead;
+ if (!expanded)
break; /* Done! */
- }
/*
* Now scan the entire line and look for successive TOK_IDs
@@ -5104,33 +5127,28 @@ static Token *expand_smacro_noreset(Token * tline)
* Also we look for %+ tokens and concatenate the tokens
* before and after them (without white spaces in between).
*/
- if (!paste_tokens(&thead, tmatch, ARRAY_SIZE(tmatch), true)) {
- tline = thead;
- break;
- }
+ if (!paste_tokens(&tline, tmatch, ARRAY_SIZE(tmatch), true))
+ break; /* Done again! */
+
expanded = false;
}
- if (org_tline) {
- if (thead) {
- *org_tline = *thead;
- /* since we just gave text to org_line, don't free it */
- thead->text = NULL;
- delete_Token(thead);
- } else {
- /*
- * The expression expanded to empty line;
- * we can't return NULL because of the "trick" above.
- * Just set the line to a single WHITESPACE token.
- */
- memset(org_tline, 0, sizeof(*org_tline));
- org_tline->text = NULL;
- org_tline->type = TOK_WHITESPACE;
- }
- thead = org_tline;
+ if (tline) {
+ *org_tline = *tline;
+ /* since we just gave text to org_tline, don't free it */
+ tline->text = NULL;
+ delete_Token(tline);
+ } else {
+ /*
+ * The expression expanded to empty line;
+ * we can't return NULL because of the "trick" above.
+ * Just set the line to a single WHITESPACE token.
+ */
+ nasm_zero(*org_tline);
+ org_tline->type = TOK_WHITESPACE;
}
- return thead;
+ return org_tline;
}
/*
@@ -5420,9 +5438,9 @@ static int expand_mmacro(Token * tline)
int nparam = 0;
t = tline;
- skip_white_(t);
- /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
- if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
+ t = skip_white(t);
+ /* if (!tok_type(t, TOK_ID)) Lino 02/25/02 */
+ if (!tok_type(t, TOK_ID) && !tok_type(t, TOK_PREPROC_ID))
return 0;
m = is_mmacro(t, &nparam, &params);
if (m) {
@@ -5437,15 +5455,15 @@ static int expand_mmacro(Token * tline)
*/
label = last = t;
t = t->next;
- if (tok_type_(t, TOK_WHITESPACE))
+ if (tok_white(t))
last = t, t = t->next;
- if (tok_is_(t, ":")) {
+ if (tok_is(t, ':')) {
dont_prepend = true;
last = t, t = t->next;
- if (tok_type_(t, TOK_WHITESPACE))
+ if (tok_white(t))
last = t, t = t->next;
}
- if (!tok_type_(t, TOK_ID) || !(m = is_mmacro(t, &nparam, &params)))
+ if (!tok_type(t, TOK_ID) || !(m = is_mmacro(t, &nparam, &params)))
return 0;
last->next = NULL;
mname = t->text;
@@ -5477,22 +5495,22 @@ static int expand_mmacro(Token * tline)
int brace = 0;
bool comma = !m->plus || i < nparam;
- skip_white_(t);
- if (tok_is_(t, "{"))
+ t = skip_white(t);
+ if (tok_is(t, '{'))
t = t->next, brace++, comma = false;
params[i] = t;
while (t) {
if (comma) {
/* Check if we hit a comma that ends this argument */
- if (tok_is_(t, ","))
- break;
- else if (t->type == TOK_WHITESPACE && tok_is_(t->next, ","))
+ Token *tns = skip_white(t);
+ if (tok_is(tns, ','))
break;
}
- if (brace && t->type == TOK_OTHER) {
- if (t->text[0] == '{')
+ if (brace && t->type == TOK_OTHER && t->len == 1) {
+ const char c = t->text[0];
+ if (c == '{')
brace++; /* ... or a nested opening brace */
- else if (t->text[0] == '}')
+ else if (c == '}')
if (!--brace)
break; /* ... or a brace */
}
@@ -6106,7 +6124,6 @@ static void pp_cleanup_session(void)
free_llist(predef);
predef = NULL;
delete_Blocks();
- freeTokens = NULL;
ipath_list = NULL;
}
@@ -6121,7 +6138,7 @@ static void pp_pre_include(char *fname)
Line *l;
name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
- space = new_Token(name, TOK_WHITESPACE, NULL, 0);
+ space = new_White(name);
inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
l = nasm_malloc(sizeof(Line));
@@ -6138,7 +6155,7 @@ static void pp_pre_define(char *definition)
char *equals;
equals = strchr(definition, '=');
- space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
+ space = new_White(NULL);
def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
if (equals)
*equals = ' ';
@@ -6162,7 +6179,7 @@ static void pp_pre_undefine(char *definition)
Token *def, *space;
Line *l;
- space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
+ space = new_White(NULL);
def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
space->next = tokenize(definition);
@@ -6183,7 +6200,7 @@ static void pp_pre_command(const char *what, char *string)
def = tokenize(string);
if (what) {
cmd = nasm_strcat(what[0] == '%' ? "" : "%", what);
- space = new_Token(def, TOK_WHITESPACE, NULL, 0);
+ space = new_White(def);
def = new_Token(space, TOK_PREPROC_ID, cmd, 0);
}