aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin (Intel) <hpa@zytor.com>2019-08-09 02:34:21 -0700
committerH. Peter Anvin (Intel) <hpa@zytor.com>2019-08-09 02:34:21 -0700
commit1c21a53e4ed03371df5d9f16359545862bb4820e (patch)
tree7c44b46c5a35a8bcffd1d7698aaaddce6af4d148
parent80ba65e830589b2b4e77112445ab03a3ce1de773 (diff)
downloadnasm-1c21a53e4ed03371df5d9f16359545862bb4820e.tar.gz
nasm-1c21a53e4ed03371df5d9f16359545862bb4820e.tar.xz
nasm-1c21a53e4ed03371df5d9f16359545862bb4820e.zip
preproc: fix parsing of single-line macro arguments, cleanups
The single-line macro argument parsing was completely broken as a comma would not be recognized as an argument separator. In the process of fixing this, make a fair bit of code cleanups. Note: reverse tokens for smacro->expansion doesn't actually make any sense anymore, might reconsider that. This checkin also removes the distinction between "magic" and plain smacros; the only difference is which specific expand method is being invoked. Finally, extend the allocating-string functions such that *all* the allocating string functions support querying the length of the string a posteori. Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
-rw-r--r--asm/preproc.c467
-rw-r--r--include/nasmlib.h18
-rw-r--r--nasmlib/alloc.c18
-rw-r--r--nasmlib/alloc.h2
-rw-r--r--nasmlib/asprintf.c14
-rw-r--r--nasmlib/strlist.c2
6 files changed, 323 insertions, 198 deletions
diff --git a/asm/preproc.c b/asm/preproc.c
index 4a01f979..7a5d11fe 100644
--- a/asm/preproc.c
+++ b/asm/preproc.c
@@ -96,10 +96,10 @@ typedef struct Cond Cond;
*/
/*
- * Function call for a magic smacro
+ * Function call tp obtain the expansion of an smacro
*/
-typedef Token *(*MagicSMacro)(const SMacro *s, Token **params,
- unsigned int nparams, bool *free_expansion);
+typedef Token *(*ExpandSMacro)(const SMacro *s, Token **params,
+ unsigned int nparams);
/*
* Store the definition of a single-line macro.
@@ -108,8 +108,8 @@ struct SMacro {
SMacro *next; /* MUST BE FIRST - see free_smacro() */
char *name;
Token *expansion;
- MagicSMacro magic;
- intorptr magicpvt;
+ ExpandSMacro expand;
+ intorptr expandpvt;
bool *eval_param;
unsigned int nparam;
bool casesense;
@@ -606,6 +606,53 @@ static void free_llist(Line * list)
}
/*
+ * Free an array of linked lists of tokens
+ */
+static void free_tlist_array(Token **array, size_t nlists)
+{
+ Token **listp = array;
+
+ while (nlists--)
+ free_tlist(*listp++);
+
+ nasm_free(array);
+}
+
+/*
+ * Duplicate a linked list of tokens.
+ */
+static Token *dup_tlist(const Token *list, Token ***tailp)
+{
+ Token *newlist = NULL;
+ Token **tailpp = &newlist;
+ const Token *t;
+
+ list_for_each(t, list) {
+ Token *nt;
+ *tailpp = nt = dup_Token(NULL, t);
+ tailpp = &nt->next;
+ }
+
+ if (tailp)
+ *tailp = tailpp;
+
+ return newlist;
+}
+
+/*
+ * Duplicate a linked list of tokens in reverse order
+ */
+static Token *dup_tlist_reverse(const Token *list, Token *tail)
+{
+ const Token *t;
+
+ list_for_each(t, list)
+ tail = dup_Token(tail, t);
+
+ return tail;
+}
+
+/*
* Free an MMacro
*/
static void free_mmacro(MMacro * m)
@@ -779,7 +826,6 @@ static char *line_from_stdmac(void)
stdmacpos = *stdmacnext++;
} else if (do_predef) {
Line *pd, *l;
- Token *head, **tail, *t;
/*
* Nasty hack: here we push the contents of
@@ -789,16 +835,9 @@ static char *line_from_stdmac(void)
* features.
*/
list_for_each(pd, predef) {
- head = NULL;
- tail = &head;
- list_for_each(t, pd->first) {
- *tail = new_Token(NULL, t->type, t->text, 0);
- tail = &(*tail)->next;
- }
-
l = nasm_malloc(sizeof(Line));
l->next = istk->expansion;
- l->first = head;
+ l->first = dup_tlist(pd->first, NULL);
l->finishes = NULL;
istk->expansion = l;
@@ -2023,6 +2062,19 @@ fail:
}
/*
+ * Default smacro expansion routine: just returns a copy of the
+ * expansion list.
+ */
+static Token *
+smacro_expand_default(const SMacro *s, Token **params, unsigned int nparams)
+{
+ (void)params;
+ (void)nparams;
+
+ return dup_tlist(s->expansion, NULL);
+}
+
+/*
* Common code for defining an smacro
*/
static SMacro *define_smacro(Context *ctx, const char *mname,
@@ -2060,6 +2112,7 @@ static SMacro *define_smacro(Context *ctx, const char *mname,
smac->casesense = casesense;
smac->nparam = nparam;
smac->expansion = expansion;
+ smac->expand = smacro_expand_default;
return smac;
}
@@ -3908,10 +3961,10 @@ static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
tm = mac->params[(fst + mac->rotate) % mac->nparam];
if (!tm)
goto err;
- head = new_Token(NULL, tm->type, tm->text, 0);
+ head = dup_Token(NULL, tm);
tt = &head->next, tm = tm->next;
while (tok_isnt_(tm, ",")) {
- t = new_Token(NULL, tm->type, tm->text, 0);
+ t = dup_Token(NULL, tm);
*tt = t, tt = &t->next, tm = tm->next;
}
@@ -3922,7 +3975,7 @@ static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
j = (i + mac->rotate) % mac->nparam;
tm = mac->params[j];
while (tok_isnt_(tm, ",")) {
- t = new_Token(NULL, tm->type, tm->text, 0);
+ t = dup_Token(NULL, tm);
*tt = t, tt = &t->next, tm = tm->next;
}
}
@@ -3933,7 +3986,7 @@ static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
j = (i + mac->rotate) % mac->nparam;
tm = mac->params[j];
while (tok_isnt_(tm, ",")) {
- t = new_Token(NULL, tm->type, tm->text, 0);
+ t = dup_Token(NULL, tm);
*tt = t, tt = &t->next, tm = tm->next;
}
}
@@ -4055,7 +4108,7 @@ static Token *expand_mmac_params(Token * tline)
}
if (tt) {
for (i = 0; i < mac->paramlen[n]; i++) {
- *tail = new_Token(NULL, tt->type, tt->text, 0);
+ *tail = dup_Token(NULL, tt);
tail = &(*tail)->next;
tt = tt->next;
}
@@ -4157,10 +4210,9 @@ static bool expand_one_smacro(Token ***tpp)
Token *tline = **tpp;
Token *mstart = **tpp;
SMacro *head, *m;
- unsigned int nparam, i;
- Token *expansion;
- Token *t;
- bool free_expansion;
+ unsigned int i;
+ Token *t, *tup, *ttail;
+ unsigned int nparam = 0;
if (!tline)
return false; /* Empty line, nothing to do */
@@ -4214,8 +4266,8 @@ static bool expand_one_smacro(Token ***tpp)
* substitute for the parameters when we expand. What a
* pain.
*/
- Token **pep;
- int paren;
+ Token **phead, **pep;
+ int paren = 1;
int white = 0;
int brackets = 0;
bool bracketed = false;
@@ -4237,113 +4289,131 @@ static bool expand_one_smacro(Token ***tpp)
paren = 1;
nparam = 0;
- params = nasm_malloc(sparam * sizeof *params);
- params[0] = NULL;
- pep = &params[0];
+ nasm_newn(params, sparam);
+ phead = pep = &params[0];
+ *pep = NULL;
- while (true) {
- bool skip = false;
+ while (paren) {
+ bool skip;
char ch;
- if (!tline->next) {
+ tline = tline->next;
+
+ if (!tline) {
nasm_nonfatal("macro call expects terminating `)'");
- break;
+ goto not_a_macro;
}
- tline = tline->next;
- ch = (tline->type == TOK_OTHER && !tline->text[1])
- ? tline->text[0] : 0;
+ ch = 0;
+ skip = false;
+
+ switch (tline->type) {
+ case TOK_OTHER:
+ if (!tline->text[1])
+ ch = tline->text[0];
+ break;
+
+ case TOK_WHITESPACE:
+ if (brackets || *phead)
+ white++; /* Keep interior whitespace */
+ skip = true;
+ break;
+
+ default:
+ break;
+ }
- if (!brackets) {
- if (tline->type == TOK_WHITESPACE) {
- if (params[nparam]) {
- /* Keep interior whitespace */
- white++;
+ switch (ch) {
+ case ',':
+ if (!brackets) {
+ if (++nparam >= sparam) {
+ sparam += PARAM_DELTA;
+ params = nasm_realloc(params, sparam * sizeof *params);
}
+ pep = &params[nparam];
+ *pep = NULL;
+ bracketed = false;
skip = true;
}
+ break;
- switch (ch) {
- case ',':
- if (!paren) {
- if (++nparam >= sparam) {
- sparam += PARAM_DELTA;
- params = nasm_realloc(params, sparam * sizeof *params);
- }
- params[nparam] = NULL;
- pep = &params[nparam];
- white = 0;
- bracketed = false;
- }
- break;
+ case '{':
+ if (!bracketed) {
+ bracketed = !*phead;
+ skip = true;
+ }
+ brackets++;
+ break;
- case '{':
- brackets++;
- bracketed = skip = !params[nparam];
- break;
+ case '}':
+ if (brackets > 0) {
+ if (!--brackets)
+ skip = bracketed;
+ }
+ break;
- case '(':
+ case '(':
+ if (!brackets)
paren++;
- break;
+ break;
- case ')':
+ case ')':
+ if (!brackets) {
paren--;
- break;
-
- default:
- break; /* Just advance to the next token */
+ if (!paren) {
+ skip = true;
+ if (nparam > 0 || *phead) {
+ /* Count the final argument unless just () */
+ nparam++;
+ }
+ }
}
- } else {
- if (ch == '}')
- brackets--;
+ break;
- if (brackets == 0)
- skip = bracketed;
+ default:
+ break; /* Normal token */
}
- if (!paren)
- break; /* We are done */
-
if (!skip) {
Token *t;
- if (bracketed && !brackets)
- bad_bracket = true;
+ bad_bracket |= bracketed && !brackets;
if (white) {
- t = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
- *pep = t;
+ *pep = t = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
pep = &t->next;
+ white = 0;
}
-
- t = new_Token(NULL, tline->type, tline->text, 0);
- *pep = t;
+ *pep = t = dup_Token(NULL, tline);
pep = &t->next;
white = 0;
}
}
- nparam++; /* Count the last parameter */
- if (bad_bracket)
- nasm_nonfatal("braces do not enclose all of macro parameter");
+ /*
+ * Look for a macro matching in both name and parameter count.
+ * We already know any matches cannot be anywhere before the
+ * current position of "m", so there is no reason to
+ * backtrack.
+ */
+ while (1) {
+ if (!m) {
+ /*!
+ *!macro-params-single [on] single-line macro calls with wrong parameter count
+ *! warns about \i{single-line macros} being invoked
+ *! with the wrong number of parameters.
+ */
+ nasm_warn(WARN_MACRO_PARAMS_SINGLE,
+ "single-line macro `%s' exists, "
+ "but not taking %d parameter%s",
+ mname, nparam, (nparam == 1) ? "" : "s");
+ goto not_a_macro;
+ }
- /* Look for a macro matching in both name and parameter count */
- while (m && (m->nparam != nparam ||
- mstrcmp(m->name, mname, m->casesense)))
- m = m->next;
+ if (m->nparam == nparam && !mstrcmp(m->name, mname, m->casesense))
+ break; /* It's good */
- if (!m) {
- /*!
- *!macro-params [on] macro calls with wrong parameter count
- *! covers warnings about \i{multi-line macros} being invoked
- *! with the wrong number of parameters. See \k{mlmacover} for an
- *! example of why you might want to disable this warning.
- */
- nasm_warn(WARN_MACRO_PARAMS,
- "macro `%s' exists, "
- "but not taking %d parameters",
- mname, nparam);
- goto not_a_macro;
+ m = m->next;
}
}
@@ -4353,89 +4423,110 @@ static bool expand_one_smacro(Token ***tpp)
/* Expand each parameter */
m->in_progress = true;
- for (i = 0; i < nparam; i++) {
- params[i] = expand_smacro_noreset(params[i]);
-
- if (m->eval_param && m->eval_param[i]) {
- /* Evaluate this parameter as a number */
- struct ppscan pps;
- struct tokenval tokval;
- expr *evalresult;
-
- pps.tptr = params[i];
- pps.ntokens = -1;
- tokval.t_type = TOKEN_INVALID;
- evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
-
- if (!evalresult) {
- /* Nothing meaningful to do */
- } else if (tokval.t_type) {
- nasm_nonfatal("invalid expression in parameter %d of macro `%s'", i, m->name);
- } else if (!is_simple(evalresult)) {
- nasm_nonfatal("non-constant expression in parameter %d of macro `%s'", i, m->name);
- } else {
- free_tlist(params[i]);
- params[i] = make_tok_num(reloc_value(evalresult));
+ if (m->eval_param) {
+ for (i = 0; i < nparam; i++) {
+ if (m->eval_param[i]) {
+ /* Evaluate this parameter as a number */
+ struct ppscan pps;
+ struct tokenval tokval;
+ expr *evalresult;
+ Token *eval_param;
+
+ pps.tptr = eval_param = expand_smacro_noreset(params[i]);
+ pps.ntokens = -1;
+ tokval.t_type = TOKEN_INVALID;
+ evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
+
+ free_tlist(eval_param);
+ params[i] = NULL;
+
+ if (!evalresult) {
+ /* Nothing meaningful to do */
+ } else if (tokval.t_type) {
+ nasm_nonfatal("invalid expression in parameter %d of macro `%s'", i, m->name);
+ } else if (!is_simple(evalresult)) {
+ nasm_nonfatal("non-constant expression in parameter %d of macro `%s'", i, m->name);
+ } else {
+ params[i] = make_tok_num(reloc_value(evalresult));
+ }
}
}
-
- /* Put tokens in reverse order like the expansion list */
- params[i] = reverse_tokens(params[i]);
}
t = tline;
tline = tline->next; /* Remove the macro call from the input */
t->next = NULL;
- if (unlikely(m->magic)) {
- expansion = m->magic(m, params, nparam, &free_expansion);
- } else {
- expansion = m->expansion;
- free_expansion = false;
- }
+ /* Note: we own the expansion this returns. */
+ t = m->expand(m, params, nparam);
- list_for_each(t, expansion) {
- Token *ttt, **tlinep;
- const char *qname;
+ tup = NULL;
+ ttail = NULL; /* Pointer to the last token of the expansion */
+ while (t) {
+ enum pp_token_type type = t->type;
+ Token *tnext = t->next;
+ Token **tp;
- switch (t->type) {
- case TOK_ID:
- case TOK_PREPROC_ID:
- tline = dup_Token(tline, t);
- tlinep = &tline;
- expand_one_smacro(&tlinep);
- break;
+ switch (type) {
case TOK_PREPROC_Q:
- qname = mname;
- goto q_qq;
case TOK_PREPROC_QQ:
- qname = m->name;
- goto q_qq;
- q_qq:
- tline = new_Token(tline, TOK_ID, qname, 0);
+ t->type = TOK_ID;
+ nasm_free(t->text);
+ t->text = nasm_strdup(type == TOK_PREPROC_QQ ? m->name : mname);
+ t->len = nasm_last_string_len();
+ t->next = tline;
+ break;
+
+ 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.
+ */
+ t->next = tline;
+ tp = &t;
+ expand_one_smacro(&tp);
+ if (t == tline)
+ t = NULL; /* Null expansion */
break;
+
default:
if (is_smac_param(t->type)) {
- list_for_each(ttt, params[smac_nparam(t->type)]) {
- tline = dup_Token(tline, ttt);
- }
+ unsigned int param = smac_nparam(t->type);
+ nasm_assert(!tup && param < nparam);
+ delete_Token(t);
+ t = NULL;
+ tup = tnext;
+ tnext = dup_tlist_reverse(params[param], NULL);
} else {
- tline = dup_Token(tline, t);
+ t->next = tline;
}
- break;
+ }
+
+ if (t) {
+ tline = t;
+ if (!ttail)
+ ttail = t;
+ }
+
+ if (tnext) {
+ t = tnext;
+ } else {
+ t = tup;
+ tup = NULL;
}
}
**tpp = tline;
-
- if (free_expansion)
- free_tlist(expansion);
+ if (ttail)
+ *tpp = &ttail->next;
m->in_progress = false;
/* Don't do this until after expansion or we will clobber mname */
free_tlist(mstart);
- nasm_free(params);
+ free_tlist_array(params, nparam);
return true;
/*
@@ -4443,9 +4534,8 @@ static bool expand_one_smacro(Token ***tpp)
* and then advance to the next input token.
*/
not_a_macro:
- if (params)
- nasm_free(params);
*tpp = &mstart->next;
+ free_tlist_array(params, nparam);
return false;
}
@@ -4466,6 +4556,7 @@ static Token *expand_smacro_noreset(Token * tline)
{
Token *t, **tail, *thead;
Token *org_tline = tline;
+ bool expanded;
/*
* Trick: we should avoid changing the start token pointer since it can
@@ -4480,9 +4571,16 @@ static Token *expand_smacro_noreset(Token * tline)
org_tline->text = NULL;
}
- thead = tline;
- while (1) {
+ /*
+ * Pretend that we always end up doing expansion on the first pass;
+ * that way %+ get processed. However, if we process %+ before the
+ * first pass, we end up with things like MACRO %+ TAIL trying to
+ * look up the macro "MACROTAIL", which we don't want.
+ */
+ expanded = true;
+ thead = tline;
+ while (true) {
static const struct tokseq_match tmatch[] = {
{
PP_CONCAT_MASK(TOK_ID) |
@@ -4492,10 +4590,8 @@ static Token *expand_smacro_noreset(Token * tline)
PP_CONCAT_MASK(TOK_NUMBER) /* tail */
}
};
- bool expanded = false;
tail = &thead;
-
while ((t = *tail)) { /* main token loop */
expanded |= expand_one_smacro(&tail);
@@ -4514,6 +4610,8 @@ static Token *expand_smacro_noreset(Token * tline)
* before and after them (without white spaces in between).
*/
paste_tokens(&thead, tmatch, ARRAY_SIZE(tmatch), true);
+
+ expanded = false;
}
if (org_tline) {
@@ -4523,9 +4621,11 @@ static Token *expand_smacro_noreset(Token * tline)
thead->text = NULL;
delete_Token(thead);
} else {
- /* the expression expanded to empty line;
- we can't return NULL for some reasons
- we just set the line to a single WHITESPACE token. */
+ /*
+ * 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;
@@ -4689,10 +4789,15 @@ static MMacro *is_mmacro(Token * tline, Token *** params_array)
/*
* After all that, we didn't find one with the right number of
* parameters. Issue a warning, and fail to expand the macro.
+ *!
+ *!macro-params-multi [on] multi-line macro calls with wrong parameter count
+ *! warns about \i{multi-line macros} being invoked
+ *! with the wrong number of parameters. See \k{mlmacover} for an
+ *! example of why you might want to disable this warning.
*/
- nasm_warn(WARN_MACRO_PARAMS,
- "macro `%s' exists, but not taking %d parameters",
- tline->text, nparam);
+ nasm_warn(WARN_MACRO_PARAMS_MULTI,
+ "multi-line macro `%s' exists, but not taking %d parameter%s",
+ tline->text, nparam, (nparam == 1) ? "" : "s");
nasm_free(params);
return NULL;
}
@@ -4973,41 +5078,38 @@ static void pp_verror(errflags severity, const char *fmt, va_list arg)
}
}
-static Token *stdmac_file(const SMacro *s, Token **params,
- unsigned int nparams, bool *free_expansion)
+static Token *
+stdmac_file(const SMacro *s, Token **params, unsigned int nparams)
{
(void)s;
(void)params;
(void)nparams;
- *free_expansion = true;
return make_tok_qstr(src_get_fname());
}
-static Token *stdmac_line(const SMacro *s, Token **params,
- unsigned int nparams, bool *free_expansion)
+static Token *
+stdmac_line(const SMacro *s, Token **params, unsigned int nparams)
{
(void)s;
(void)params;
(void)nparams;
- *free_expansion = true;
return make_tok_num(src_get_linnum());
}
-static Token *stdmac_bits(const SMacro *s, Token **params,
- unsigned int nparams, bool *free_expansion)
+static Token *
+stdmac_bits(const SMacro *s, Token **params, unsigned int nparams)
{
(void)s;
(void)params;
(void)nparams;
- *free_expansion = true;
return make_tok_num(globalbits);
}
-static Token *stdmac_ptr(const SMacro *s, Token **params,
- unsigned int nparams, bool *free_expansion)
+static Token *
+stdmac_ptr(const SMacro *s, Token **params, unsigned int nparams)
{
const Token *t;
static const Token ptr_word = { NULL, "word", 4, TOK_ID };
@@ -5032,15 +5134,14 @@ static Token *stdmac_ptr(const SMacro *s, Token **params,
panic();
}
- *free_expansion = false;
- return (Token *)t;
+ return dup_Token(NULL, t);
}
/* Add magic standard macros */
struct magic_macros {
const char *name;
int nparams;
- MagicSMacro func;
+ ExpandSMacro func;
};
static const struct magic_macros magic_macros[] =
{
@@ -5058,7 +5159,7 @@ static void pp_add_magic_stdmac(void)
for (m = magic_macros; m->name; m++) {
s = define_smacro(NULL, m->name, true, m->nparams, NULL);
- s->magic = m->func;
+ s->expand = m->func;
}
}
@@ -5179,7 +5280,7 @@ static Token *pp_tokline(void)
list_for_each(t, l->first) {
if (t->text || t->type == TOK_WHITESPACE) {
- tt = *tail = new_Token(NULL, t->type, t->text, 0);
+ tt = *tail = dup_Token(NULL, t);
tail = &tt->next;
}
}
diff --git a/include/nasmlib.h b/include/nasmlib.h
index b8666e67..eb3a637d 100644
--- a/include/nasmlib.h
+++ b/include/nasmlib.h
@@ -87,10 +87,22 @@ char * safe_alloc nasm_vasprintf(const char *fmt, va_list ap);
void * safe_alloc printf_func(2, 3) nasm_axprintf(size_t extra, const char *fmt, ...);
void * safe_alloc nasm_vaxprintf(size_t extra, const char *fmt, va_list ap);
-extern size_t _nasm_aprintf_size;
-static inline size_t nasm_aprintf_size(void)
+/*
+ * nasm_last_string_len() returns the length of the last string allocated
+ * by [v]asprintf, nasm_strdup, nasm_strcat, or nasm_strcatn.
+ *
+ * nasm_last_string_size() returns the equivalent size including the
+ * final NUL.
+ */
+static inline size_t nasm_last_string_len(void)
+{
+ extern size_t _nasm_last_string_size;
+ return _nasm_last_string_size - 1;
+}
+static inline size_t nasm_last_string_size(void)
{
- return _nasm_aprintf_size;
+ extern size_t _nasm_last_string_size;
+ return _nasm_last_string_size;
}
/* Assert the argument is a pointer without evaluating it */
diff --git a/nasmlib/alloc.c b/nasmlib/alloc.c
index ad2cff3d..4e0ff9fe 100644
--- a/nasmlib/alloc.c
+++ b/nasmlib/alloc.c
@@ -40,6 +40,8 @@
#include "error.h"
#include "alloc.h"
+size_t _nasm_last_string_size;
+
no_return nasm_alloc_failed(void)
{
/* If nasm_fatal() gets us back here, then croak hard */
@@ -90,8 +92,9 @@ void nasm_free(void *q)
char *nasm_strdup(const char *s)
{
char *p;
- size_t size = strlen(s) + 1;
+ const size_t size = strlen(s) + 1;
+ _nasm_last_string_size = size;
p = nasm_malloc(size);
return memcpy(p, s, size);
}
@@ -101,6 +104,7 @@ char *nasm_strndup(const char *s, size_t len)
char *p;
len = strnlen(s, len);
+ _nasm_last_string_size = len + 1;
p = nasm_malloc(len+1);
p[len] = '\0';
return memcpy(p, s, len);
@@ -109,11 +113,13 @@ char *nasm_strndup(const char *s, size_t len)
char *nasm_strcat(const char *one, const char *two)
{
char *rslt;
- size_t l1 = strlen(one);
- size_t l2 = strlen(two);
- rslt = nasm_malloc(l1 + l2 + 1);
+ const size_t l1 = strlen(one);
+ const size_t s2 = strlen(two) + 1;
+
+ _nasm_last_string_size = l1 + s2;
+ rslt = nasm_malloc(l1 + s2);
memcpy(rslt, one, l1);
- memcpy(rslt + l1, two, l2+1);
+ memcpy(rslt + l1, two, s2);
return rslt;
}
@@ -150,6 +156,8 @@ char *nasm_strcatn(const char *str1, ...)
}
va_end(ap);
+ _nasm_last_string_size = s;
+
q = rslt = nasm_malloc(s);
p = str1;
diff --git a/nasmlib/alloc.h b/nasmlib/alloc.h
index c599d213..1b896585 100644
--- a/nasmlib/alloc.h
+++ b/nasmlib/alloc.h
@@ -45,4 +45,6 @@ static inline void *validate_ptr(void *p)
return p;
}
+extern size_t _nasm_last_string_size;
+
#endif /* NASMLIB_ALLOC_H */
diff --git a/nasmlib/asprintf.c b/nasmlib/asprintf.c
index be88d491..0b8e49d8 100644
--- a/nasmlib/asprintf.c
+++ b/nasmlib/asprintf.c
@@ -38,16 +38,15 @@
/*
* nasm_[v]asprintf() are variants of the semi-standard [v]asprintf()
* functions, except that we return the pointer instead of a count.
- * The size of the string (including the final NUL!) is available
- * by calling nasm_aprintf_size() afterwards.
+ * The length of the string (with or without the final NUL) is available
+ * by calling nasm_last_string_{len,size}() afterwards.
*
* nasm_[v]axprintf() are similar, but allocates a user-defined amount
* of storage before the string, and returns a pointer to the
- * allocated buffer.
+ * allocated buffer. The size of that area is not included in the value
+ * returned by nasm_last_string_size().
*/
-size_t _nasm_aprintf_size;
-
void *nasm_vaxprintf(size_t extra, const char *fmt, va_list ap)
{
char *strp;
@@ -55,9 +54,12 @@ void *nasm_vaxprintf(size_t extra, const char *fmt, va_list ap)
size_t bytes;
va_copy(xap, ap);
- _nasm_aprintf_size = bytes = vsnprintf(NULL, 0, fmt, xap) + 1;
+ bytes = vsnprintf(NULL, 0, fmt, xap) + 1;
+ _nasm_last_string_size = bytes;
va_end(xap);
+
strp = nasm_malloc(extra+bytes);
+ memset(strp, 0, extra);
vsnprintf(strp+extra, bytes, fmt, ap);
return strp;
}
diff --git a/nasmlib/strlist.c b/nasmlib/strlist.c
index a0687cce..db5a09ab 100644
--- a/nasmlib/strlist.c
+++ b/nasmlib/strlist.c
@@ -109,7 +109,7 @@ strlist_vprintf(struct strlist *list, const char *fmt, va_list ap)
return NULL;
e = nasm_vaxprintf(offsetin(*e, str), fmt, ap);
- e->size = nasm_aprintf_size();
+ e->size = nasm_last_string_size();
if (list->uniq) {
void **dp = hash_findb(&list->hash, e->str, e->size, &hi);