mirror of
git://git.gnu.org.ua/wordsplit.git
synced 2025-04-26 00:29:54 +03:00
Pull fixes from mailutils
This includes the following commits pushed between 2015-09-19 and 2017-10-10: 090c7b9a Allow ws_getvar to set value to NULL and return MU_WRDSE_OK. The value is processed as if it were "", i.e. MU_WRDSE_UNDEF is returned. 64313fdf Fix MU_WRDSF_INCREMENTAL | MU_WRDSF_NOSPLIT 46d7640f Add wordsplit_append function 151eb4b9 Fix nested expansions and command expansions occurring after variable expansions. ad3cc340 Replace void wordsplit_getwords with int wordsplit_get_words. * include/wordsplit.h (wordsplit_get_words): New function. (wordsplit_getwords): Mark as deprecated. (wordsplit_append): New function. * src/wordsplit.c (wordsplit_append): New function. MU 46d7640f. (expvar): Treat NULL value as "". MU 090c7b9a. (expcmd): Allow command and variable expansions in subsplit. (exptab): Change ordering of expansions so that command expansion occurs first. This fixes nested expansions and command expansions occurring after variable expansions. MU 151eb4b9. (wordsplit_process_list): Update wsp->ws_endp in nosplit mode. This fixes wordsplit MU_WRDSF_INCREMENTAL | MU_WRDSF_NOSPLIT. MU 64313fdf. (wordsplit_get_words): New function. MU ad3cc340. * tests/wordsplit.at: Test the above changes. * tests/wsp.c: Accept extra arguments to append using wordsplit_append.
This commit is contained in:
parent
b24ce9fe1e
commit
d97c672079
4 changed files with 155 additions and 23 deletions
|
@ -235,7 +235,18 @@ int wordsplit_len (const char *s, size_t len, wordsplit_t *ws, int flags);
|
||||||
void wordsplit_free (wordsplit_t *ws);
|
void wordsplit_free (wordsplit_t *ws);
|
||||||
void wordsplit_free_words (wordsplit_t *ws);
|
void wordsplit_free_words (wordsplit_t *ws);
|
||||||
void wordsplit_free_envbuf (wordsplit_t *ws);
|
void wordsplit_free_envbuf (wordsplit_t *ws);
|
||||||
void wordsplit_getwords (wordsplit_t *ws, size_t *wordc, char ***wordv);
|
int wordsplit_get_words (wordsplit_t *ws, size_t *wordc, char ***wordv);
|
||||||
|
|
||||||
|
static inline void wordsplit_getwords (wordsplit_t *ws, size_t *wordc, char ***wordv)
|
||||||
|
__attribute__ ((deprecated));
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
wordsplit_getwords (wordsplit_t *ws, size_t *wordc, char ***wordv)
|
||||||
|
{
|
||||||
|
wordsplit_get_words (ws, wordc, wordv);
|
||||||
|
}
|
||||||
|
|
||||||
|
int wordsplit_append (wordsplit_t *wsp, int argc, char **argv);
|
||||||
|
|
||||||
int wordsplit_c_unquote_char (int c);
|
int wordsplit_c_unquote_char (int c);
|
||||||
int wordsplit_c_quote_char (int c);
|
int wordsplit_c_quote_char (int c);
|
||||||
|
|
|
@ -674,7 +674,35 @@ wordsplit_finish (struct wordsplit *wsp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
wordsplit_append (wordsplit_t *wsp, int argc, char **argv)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
rc = alloc_space (wsp, wsp->ws_wordc + argc + 1);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
for (i = 0; i < argc; i++)
|
||||||
|
{
|
||||||
|
char *newstr = strdup (argv[i]);
|
||||||
|
if (!newstr)
|
||||||
|
{
|
||||||
|
while (i > 0)
|
||||||
|
{
|
||||||
|
free (wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc + i - 1]);
|
||||||
|
wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc + i - 1] = NULL;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
return _wsplt_nomem (wsp);
|
||||||
|
}
|
||||||
|
wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc + i] = newstr;
|
||||||
|
}
|
||||||
|
wsp->ws_wordc += i;
|
||||||
|
wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc] = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Variable expansion */
|
/* Variable expansion */
|
||||||
static int
|
static int
|
||||||
node_split_prefix (struct wordsplit *wsp,
|
node_split_prefix (struct wordsplit *wsp,
|
||||||
|
@ -1015,7 +1043,9 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
|
||||||
else
|
else
|
||||||
rc = WRDSE_UNDEF;
|
rc = WRDSE_UNDEF;
|
||||||
|
|
||||||
if (rc == WRDSE_OK && value[0] == 0 && defstr && defstr[-1] == ':')
|
if (rc == WRDSE_OK
|
||||||
|
&& (!value || value[0] == 0)
|
||||||
|
&& defstr && defstr[-1] == ':')
|
||||||
{
|
{
|
||||||
free (value);
|
free (value);
|
||||||
rc = WRDSE_UNDEF;
|
rc = WRDSE_UNDEF;
|
||||||
|
@ -1332,7 +1362,6 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
|
||||||
struct wordsplit ws;
|
struct wordsplit ws;
|
||||||
|
|
||||||
rc = _wsplt_subsplit (wsp, &ws, str, j,
|
rc = _wsplt_subsplit (wsp, &ws, str, j,
|
||||||
WRDSF_NOVAR | WRDSF_NOCMD |
|
|
||||||
WRDSF_WS | WRDSF_QUOTE);
|
WRDSF_WS | WRDSF_QUOTE);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
|
@ -2065,29 +2094,41 @@ wordsplit_c_quote_copy (char *dst, const char *src, int quote_hex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This structure describes a single expansion phase */
|
||||||
struct exptab
|
struct exptab
|
||||||
{
|
{
|
||||||
char *descr;
|
char *descr; /* Textual description (for debugging) */
|
||||||
int flag;
|
int flag; /* WRDSF_ bit that controls this phase */
|
||||||
int opt;
|
int opt; /* Entry-specific options (see EXPOPT_ flags below */
|
||||||
int (*expansion) (struct wordsplit *wsp);
|
int (*expansion) (struct wordsplit *wsp); /* expansion function */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* The following options control expansions: */
|
||||||
|
/* Normally the exptab entry is run if its flag bit is set in struct
|
||||||
|
wordsplit. The EXPOPT_NEG option negates this test so that expansion
|
||||||
|
is performed if its associated flag bit is not set in struct wordsplit. */
|
||||||
#define EXPOPT_NEG 0x01
|
#define EXPOPT_NEG 0x01
|
||||||
|
/* Coalesce the input list before running the expansion. */
|
||||||
#define EXPOPT_COALESCE 0x02
|
#define EXPOPT_COALESCE 0x02
|
||||||
|
|
||||||
static struct exptab exptab[] = {
|
static struct exptab exptab[] = {
|
||||||
{ N_("WS trimming"), WRDSF_WS, 0, wordsplit_trimws },
|
{ N_("WS trimming"), WRDSF_WS, 0,
|
||||||
{ N_("tilde expansion"), WRDSF_PATHEXPAND, 0, wordsplit_tildexpand },
|
wordsplit_trimws },
|
||||||
|
{ N_("command substitution"), WRDSF_NOCMD, EXPOPT_NEG|EXPOPT_COALESCE,
|
||||||
|
wordsplit_cmdexp },
|
||||||
|
{ N_("coalesce list"), 0, EXPOPT_NEG|EXPOPT_COALESCE,
|
||||||
|
NULL },
|
||||||
|
{ N_("tilde expansion"), WRDSF_PATHEXPAND, 0,
|
||||||
|
wordsplit_tildexpand },
|
||||||
{ N_("variable expansion"), WRDSF_NOVAR, EXPOPT_NEG,
|
{ N_("variable expansion"), WRDSF_NOVAR, EXPOPT_NEG,
|
||||||
wordsplit_varexp },
|
wordsplit_varexp },
|
||||||
{ N_("quote removal"), 0, EXPOPT_NEG,
|
{ N_("quote removal"), 0, EXPOPT_NEG,
|
||||||
wsnode_quoteremoval },
|
wsnode_quoteremoval },
|
||||||
{ N_("command substitution"), WRDSF_NOCMD, EXPOPT_NEG|EXPOPT_COALESCE,
|
|
||||||
wordsplit_cmdexp },
|
|
||||||
{ N_("coalesce list"), 0, EXPOPT_NEG|EXPOPT_COALESCE,
|
{ N_("coalesce list"), 0, EXPOPT_NEG|EXPOPT_COALESCE,
|
||||||
NULL },
|
NULL },
|
||||||
{ N_("path expansion"), WRDSF_PATHEXPAND, 0, wordsplit_pathexpand },
|
{ N_("path expansion"), WRDSF_PATHEXPAND, 0,
|
||||||
|
wordsplit_pathexpand },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2101,6 +2142,7 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start)
|
||||||
/* Treat entire input as a quoted argument */
|
/* Treat entire input as a quoted argument */
|
||||||
if (wordsplit_add_segm (wsp, start, wsp->ws_len, _WSNF_QUOTE))
|
if (wordsplit_add_segm (wsp, start, wsp->ws_len, _WSNF_QUOTE))
|
||||||
return wsp->ws_errno;
|
return wsp->ws_errno;
|
||||||
|
wsp->ws_endp = wsp->ws_len;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2282,16 +2324,21 @@ wordsplit_free (struct wordsplit *ws)
|
||||||
wordsplit_free_envbuf (ws);
|
wordsplit_free_envbuf (ws);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
wordsplit_getwords (struct wordsplit *ws, size_t *wordc, char ***wordv)
|
wordsplit_get_words (struct wordsplit *ws, size_t *wordc, char ***wordv)
|
||||||
{
|
{
|
||||||
char **p = realloc (ws->ws_wordv,
|
char **p = realloc (ws->ws_wordv,
|
||||||
(ws->ws_wordc + 1) * sizeof (ws->ws_wordv[0]));
|
(ws->ws_wordc + 1) * sizeof (ws->ws_wordv[0]));
|
||||||
*wordv = p ? p : ws->ws_wordv;
|
if (!p)
|
||||||
|
return -1;
|
||||||
|
*wordv = p;
|
||||||
*wordc = ws->ws_wordc;
|
*wordc = ws->ws_wordc;
|
||||||
|
|
||||||
ws->ws_wordv = NULL;
|
ws->ws_wordv = NULL;
|
||||||
ws->ws_wordc = 0;
|
ws->ws_wordc = 0;
|
||||||
ws->ws_wordn = 0;
|
ws->ws_wordn = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *_wordsplit_errstr[] = {
|
const char *_wordsplit_errstr[] = {
|
||||||
|
|
|
@ -637,6 +637,14 @@ NF: 1
|
||||||
[input exhausted
|
[input exhausted
|
||||||
])
|
])
|
||||||
|
|
||||||
|
TESTWSP([incremental nosplit],[],[incremental nosplit],
|
||||||
|
[incremental "input test" line
|
||||||
|
],
|
||||||
|
[NF: 1
|
||||||
|
0: "incremental \"input test\" line"
|
||||||
|
],
|
||||||
|
[input exhausted
|
||||||
|
])
|
||||||
|
|
||||||
dnl Something that doesn't fit into TESTWSP
|
dnl Something that doesn't fit into TESTWSP
|
||||||
|
|
||||||
|
@ -717,15 +725,16 @@ mkdir dir
|
||||||
> dir/file
|
> dir/file
|
||||||
|
|
||||||
DIR=dir wsp -nocmd -novar<<'EOT'
|
DIR=dir wsp -nocmd -novar<<'EOT'
|
||||||
begin $(find $DIR) end
|
begin $DIR $(find $DIR) end
|
||||||
EOT
|
EOT
|
||||||
],
|
],
|
||||||
[0],
|
[0],
|
||||||
[NF: 4
|
[NF: 5
|
||||||
0: begin
|
0: begin
|
||||||
1: dir
|
1: dir
|
||||||
2: dir/file
|
2: dir
|
||||||
3: end
|
3: dir/file
|
||||||
|
4: end
|
||||||
])
|
])
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
|
@ -735,8 +744,8 @@ AT_CHECK([
|
||||||
mkdir dir
|
mkdir dir
|
||||||
> dir/file
|
> dir/file
|
||||||
|
|
||||||
DIR=dir wsp -nocmd -novar<<'EOT'
|
DIR=dir BEGIN=begin wsp -nocmd -novar<<'EOT'
|
||||||
"begin($(find $DIR))end"
|
"${BEGIN}($(find $DIR))end"
|
||||||
EOT
|
EOT
|
||||||
],
|
],
|
||||||
[0],
|
[0],
|
||||||
|
@ -744,7 +753,27 @@ EOT
|
||||||
0: "begin(dir dir/file)end"
|
0: "begin(dir dir/file)end"
|
||||||
])
|
])
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
|
AT_SETUP([nested commands])
|
||||||
|
AT_KEYWORDS([wordsplit wsp wsp-cmd])
|
||||||
|
AT_CHECK([
|
||||||
|
AT_DATA([input],[foo
|
||||||
|
bar
|
||||||
|
baz
|
||||||
|
])
|
||||||
|
SUFFIX=put wsp -nocmd -novar <<'EOT'
|
||||||
|
$(echo output $(cat in$SUFFIX))
|
||||||
|
EOT
|
||||||
|
],
|
||||||
|
[0],
|
||||||
|
[NF: 4
|
||||||
|
0: output
|
||||||
|
1: foo
|
||||||
|
2: bar
|
||||||
|
3: baz
|
||||||
|
])
|
||||||
|
AT_CLEANUP
|
||||||
|
|
||||||
AT_SETUP([pathname expansion])
|
AT_SETUP([pathname expansion])
|
||||||
AT_KEYWORDS([wordsplit wsp wsp-path wsp-path-1])
|
AT_KEYWORDS([wordsplit wsp wsp-path wsp-path-1])
|
||||||
AT_CHECK([
|
AT_CHECK([
|
||||||
|
@ -820,6 +849,32 @@ EOT
|
||||||
])
|
])
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
|
TESTWSP([append],[],[-- extra arguments follow],
|
||||||
|
[some words and],
|
||||||
|
[NF: 6
|
||||||
|
0: some
|
||||||
|
1: words
|
||||||
|
2: and
|
||||||
|
3: extra
|
||||||
|
4: arguments
|
||||||
|
5: follow
|
||||||
|
])
|
||||||
|
|
||||||
|
TESTWSP([append + dooffs + env],[],
|
||||||
|
[dooffs 2 preface words V=2 -- extra arguments follow],
|
||||||
|
[some words and var=$V],
|
||||||
|
[NF: 7 (2)
|
||||||
|
(0): preface
|
||||||
|
(1): words
|
||||||
|
2: some
|
||||||
|
3: words
|
||||||
|
4: and
|
||||||
|
5: var=2
|
||||||
|
6: extra
|
||||||
|
7: arguments
|
||||||
|
8: follow
|
||||||
|
])
|
||||||
|
|
||||||
m4_popdef([TESTWSP])
|
m4_popdef([TESTWSP])
|
||||||
m4_popdef([wspnum])
|
m4_popdef([wspnum])
|
||||||
m4_popdef([wspid])
|
m4_popdef([wspid])
|
||||||
|
|
21
tests/wsp.c
21
tests/wsp.c
|
@ -91,7 +91,7 @@ help ()
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
printf ("usage: %s [options] [VAR=VALUE...]\n", progname);
|
printf ("usage: %s [options] [VAR=VALUE...] [-- EXTRA...]\n", progname);
|
||||||
printf ("options are:\n");
|
printf ("options are:\n");
|
||||||
printf (" [-]trimnl\n");
|
printf (" [-]trimnl\n");
|
||||||
printf (" [-]plaintext\n");
|
printf (" [-]plaintext\n");
|
||||||
|
@ -334,6 +334,8 @@ main (int argc, char **argv)
|
||||||
size_t fenvidx = 0;
|
size_t fenvidx = 0;
|
||||||
size_t fenvmax = sizeof (fenvbase) / sizeof (fenvbase[0]);
|
size_t fenvmax = sizeof (fenvbase) / sizeof (fenvbase[0]);
|
||||||
int use_env = env_sys;
|
int use_env = env_sys;
|
||||||
|
int appendc = 0;
|
||||||
|
char **appendv = NULL;
|
||||||
|
|
||||||
progname = argv[0];
|
progname = argv[0];
|
||||||
|
|
||||||
|
@ -346,6 +348,12 @@ main (int argc, char **argv)
|
||||||
|
|
||||||
if (opt[0] == '-')
|
if (opt[0] == '-')
|
||||||
{
|
{
|
||||||
|
if (opt[1] == '-' && opt[2] == 0)
|
||||||
|
{
|
||||||
|
appendc = argc - i - 1;
|
||||||
|
appendv = argv + i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
negate = 1;
|
negate = 1;
|
||||||
opt++;
|
opt++;
|
||||||
}
|
}
|
||||||
|
@ -604,6 +612,17 @@ main (int argc, char **argv)
|
||||||
offarg = 0;
|
offarg = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (appendc)
|
||||||
|
{
|
||||||
|
rc = wordsplit_append (&ws, appendc, appendv);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
if (!(wsflags & WRDSF_SHOWERR))
|
||||||
|
wordsplit_perror (&ws);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wsflags |= WRDSF_REUSE | (ws.ws_flags & WRDSF_ENV);
|
wsflags |= WRDSF_REUSE | (ws.ws_flags & WRDSF_ENV);
|
||||||
printf ("NF: %lu", (unsigned long) ws.ws_wordc);
|
printf ("NF: %lu", (unsigned long) ws.ws_wordc);
|
||||||
if (wsflags & WRDSF_DOOFFS)
|
if (wsflags & WRDSF_DOOFFS)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue