there is one thing I don"t quite understand about the implementation of the glibc wordexp interface.
API is as follows:
int wordexp (const char *words, wordexp_t *pwordexp, int flags)
take a look at the implementation of glibc. When flag is WRDE_REUSE, pwordexp, will be released first and then calloc will be called to re-apply for memory. How to reuse the original memory of pwordexp in this operation?
the code snippet is as follows:
int
wordexp (const char *words, wordexp_t *pwordexp, int flags)
{
size_t words_offset;
size_t word_length;
size_t max_length;
char *word = w_newword (&word_length, &max_length);
int error;
char *ifs;
char ifs_white[4];
wordexp_t old_word = *pwordexp;
if (flags & WRDE_REUSE) /*** pwordexp->we_wordv ***/
{
/* Minimal implementation of WRDE_REUSE for now */
wordfree (pwordexp);
old_word.we_wordv = NULL;
}
if ((flags & WRDE_APPEND) == 0)
{
pwordexp->we_wordc = 0;
if (flags & WRDE_DOOFFS)
{
pwordexp->we_wordv = calloc (1 + pwordexp->we_offs, sizeof (char *));
if (pwordexp->we_wordv == NULL)
{
error = WRDE_NOSPACE;
goto do_error;
}
}
else
{
pwordexp->we_wordv = calloc (1, sizeof (char *)); /*** callocwe_wordv ***/
if (pwordexp->we_wordv == NULL)
{
error = WRDE_NOSPACE;
goto do_error;
}
pwordexp->we_offs = 0;
}
}
The source code of wordfree is as follows:
void
wordfree (wordexp_t *pwordexp)
{
/* wordexp can set pwordexp to NULL */
if (pwordexp && pwordexp->we_wordv)
{
char **wordv = pwordexp->we_wordv;
for (wordv += pwordexp->we_offs; *wordv; PPwordv)
free (*wordv);
free (pwordexp->we_wordv);
pwordexp->we_wordv = NULL;
}
}
flags enumeration:
enum
{
WRDE_DOOFFS = (1 << 0), /* Insert PWORDEXP->we_offs NULLs. */
WRDE_APPEND = (1 << 1), /* Append to results of a previous call. */
WRDE_NOCMD = (1 << 2), /* Don"t do command substitution. */
WRDE_REUSE = (1 << 3), /* Reuse storage in PWORDEXP. */
WRDE_SHOWERR = (1 << 4), /* Don"t redirect stderr to /dev/null. */
WRDE_UNDEF = (1 << 5), /* Error for expanding undefined variables. */
__WRDE_FLAGS = (WRDE_DOOFFS | WRDE_APPEND | WRDE_NOCMD |
WRDE_REUSE | WRDE_SHOWERR | WRDE_UNDEF)
};
complete source code: https://code.woboq.org/usersp.