aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-11-10 10:41:12 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2017-11-10 10:42:12 +0200
commit3299cf1ccb1c596969fcfd91253e10d5482eacf9 (patch)
tree871608720ac6050713cb2fecf5d3dcfd86aee938
parentb1258b6d6e9e0482b37e86977ffc779e14c75b9f (diff)
downloadgrecs-3299cf1ccb1c596969fcfd91253e10d5482eacf9.tar.gz
grecs-3299cf1ccb1c596969fcfd91253e10d5482eacf9.tar.bz2
Pull fixes to wordsplit 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.
-rw-r--r--include/wordsplit.h13
-rw-r--r--src/wordsplit.c75
-rw-r--r--tests/wordsplit.at69
-rw-r--r--tests/wsp.c21
4 files changed, 155 insertions, 23 deletions
diff --git a/include/wordsplit.h b/include/wordsplit.h
index a7f6dd5..eed88bc 100644
--- a/include/wordsplit.h
+++ b/include/wordsplit.h
@@ -237,3 +237,14 @@ void wordsplit_free_words (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);
diff --git a/src/wordsplit.c b/src/wordsplit.c
index 9381ae7..4884a22 100644
--- a/src/wordsplit.c
+++ b/src/wordsplit.c
@@ -676,3 +676,31 @@ wordsplit_finish (struct wordsplit *wsp)
+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 */
@@ -1017,3 +1045,5 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
- if (rc == WRDSE_OK && value[0] == 0 && defstr && defstr[-1] == ':')
+ if (rc == WRDSE_OK
+ && (!value || value[0] == 0)
+ && defstr && defstr[-1] == ':')
{
@@ -1334,3 +1364,2 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
rc = _wsplt_subsplit (wsp, &ws, str, j,
- WRDSF_NOVAR | WRDSF_NOCMD |
WRDSF_WS | WRDSF_QUOTE);
@@ -2067,11 +2096,18 @@ wordsplit_c_quote_copy (char *dst, const char *src, int quote_hex)
+
+/* This structure describes a single expansion phase */
struct exptab
{
- char *descr;
- int flag;
- int opt;
- int (*expansion) (struct wordsplit *wsp);
+ char *descr; /* Textual description (for debugging) */
+ int flag; /* WRDSF_ bit that controls this phase */
+ int opt; /* Entry-specific options (see EXPOPT_ flags below */
+ 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
+/* Coalesce the input list before running the expansion. */
#define EXPOPT_COALESCE 0x02
@@ -2079,4 +2115,10 @@ struct exptab
static struct exptab exptab[] = {
- { N_("WS trimming"), WRDSF_WS, 0, wordsplit_trimws },
- { N_("tilde expansion"), WRDSF_PATHEXPAND, 0, wordsplit_tildexpand },
+ { N_("WS trimming"), WRDSF_WS, 0,
+ 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,
@@ -2085,7 +2127,6 @@ static struct exptab exptab[] = {
wsnode_quoteremoval },
- { N_("command substitution"), WRDSF_NOCMD, EXPOPT_NEG|EXPOPT_COALESCE,
- wordsplit_cmdexp },
{ N_("coalesce list"), 0, EXPOPT_NEG|EXPOPT_COALESCE,
NULL },
- { N_("path expansion"), WRDSF_PATHEXPAND, 0, wordsplit_pathexpand },
+ { N_("path expansion"), WRDSF_PATHEXPAND, 0,
+ wordsplit_pathexpand },
{ NULL }
@@ -2103,2 +2144,3 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start)
return wsp->ws_errno;
+ wsp->ws_endp = wsp->ws_len;
}
@@ -2284,4 +2326,4 @@ wordsplit_free (struct wordsplit *ws)
-void
-wordsplit_getwords (struct wordsplit *ws, size_t *wordc, char ***wordv)
+int
+wordsplit_get_words (struct wordsplit *ws, size_t *wordc, char ***wordv)
{
@@ -2289,4 +2331,7 @@ wordsplit_getwords (struct wordsplit *ws, size_t *wordc, char ***wordv)
(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;
+
ws->ws_wordv = NULL;
@@ -2294,2 +2339,4 @@ wordsplit_getwords (struct wordsplit *ws, size_t *wordc, char ***wordv)
ws->ws_wordn = 0;
+
+ return 0;
}
diff --git a/tests/wordsplit.at b/tests/wordsplit.at
index 895a392..49d47e9 100644
--- a/tests/wordsplit.at
+++ b/tests/wordsplit.at
@@ -639,2 +639,10 @@ NF: 1
+TESTWSP([incremental nosplit],[],[incremental nosplit],
+[incremental "input test" line
+],
+[NF: 1
+0: "incremental \"input test\" line"
+],
+[input exhausted
+])
@@ -719,3 +727,3 @@ mkdir dir
DIR=dir wsp -nocmd -novar<<'EOT'
-begin $(find $DIR) end
+begin $DIR $(find $DIR) end
EOT
@@ -723,7 +731,8 @@ EOT
[0],
-[NF: 4
+[NF: 5
0: begin
1: dir
-2: dir/file
-3: end
+2: dir
+3: dir/file
+4: end
])
@@ -737,4 +746,4 @@ mkdir dir
-DIR=dir wsp -nocmd -novar<<'EOT'
-"begin($(find $DIR))end"
+DIR=dir BEGIN=begin wsp -nocmd -novar<<'EOT'
+"${BEGIN}($(find $DIR))end"
EOT
@@ -746,3 +755,23 @@ EOT
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])
@@ -822,2 +851,28 @@ 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])
diff --git a/tests/wsp.c b/tests/wsp.c
index e8eb9c6..84efc13 100644
--- a/tests/wsp.c
+++ b/tests/wsp.c
@@ -93,3 +93,3 @@ help ()
- printf ("usage: %s [options] [VAR=VALUE...]\n", progname);
+ printf ("usage: %s [options] [VAR=VALUE...] [-- EXTRA...]\n", progname);
printf ("options are:\n");
@@ -336,2 +336,4 @@ main (int argc, char **argv)
int use_env = env_sys;
+ int appendc = 0;
+ char **appendv = NULL;
@@ -348,2 +350,8 @@ main (int argc, char **argv)
{
+ if (opt[1] == '-' && opt[2] == 0)
+ {
+ appendc = argc - i - 1;
+ appendv = argv + i + 1;
+ break;
+ }
negate = 1;
@@ -606,2 +614,13 @@ main (int argc, char **argv)
+ 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);

Return to:

Send suggestions and report system problems to the System administrator.