summaryrefslogtreecommitdiffabout
path: root/src
authorSergey Poznyakoff <gray@gnu.org.ua>2017-11-10 08:41:12 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2017-11-10 08:42:12 (GMT)
commit3299cf1ccb1c596969fcfd91253e10d5482eacf9 (patch) (side-by-side diff)
tree871608720ac6050713cb2fecf5d3dcfd86aee938 /src
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.
Diffstat (limited to 'src') (more/less context) (ignore whitespace changes)
-rw-r--r--src/wordsplit.c75
1 files changed, 61 insertions, 14 deletions
diff --git a/src/wordsplit.c b/src/wordsplit.c
index 9381ae7..4884a22 100644
--- a/src/wordsplit.c
+++ b/src/wordsplit.c
@@ -671,13 +671,41 @@ wordsplit_finish (struct wordsplit *wsp)
}
wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc] = NULL;
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 */
static int
node_split_prefix (struct wordsplit *wsp,
struct wordsplit_node **ptail,
struct wordsplit_node *node,
size_t beg, size_t len, int flg)
@@ -1012,13 +1040,15 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
}
else if (wsp->ws_flags & WRDSF_GETVAR)
rc = wsp->ws_getvar (&value, str, i, wsp->ws_closure);
else
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);
rc = WRDSE_UNDEF;
}
}
@@ -1329,13 +1359,12 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
*pend = str + j;
if (wsp->ws_options & WRDSO_ARGV)
{
struct wordsplit ws;
rc = _wsplt_subsplit (wsp, &ws, str, j,
- WRDSF_NOVAR | WRDSF_NOCMD |
WRDSF_WS | WRDSF_QUOTE);
if (rc)
{
_wsplt_seterr_sub (wsp, &ws);
wordsplit_free (&ws);
return 1;
@@ -2062,35 +2091,47 @@ 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
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,
wordsplit_varexp },
{ N_("quote removal"), 0, EXPOPT_NEG,
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 }
};
static int
wordsplit_process_list (struct wordsplit *wsp, size_t start)
{
@@ -2098,12 +2139,13 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start)
if (wsp->ws_flags & WRDSF_NOSPLIT)
{
/* Treat entire input as a quoted argument */
if (wordsplit_add_segm (wsp, start, wsp->ws_len, _WSNF_QUOTE))
return wsp->ws_errno;
+ wsp->ws_endp = wsp->ws_len;
}
else
{
int rc;
while ((rc = scan_word (wsp, start)) == _WRDS_OK)
@@ -2279,22 +2321,27 @@ wordsplit_free (struct wordsplit *ws)
wordsplit_free_words (ws);
free (ws->ws_wordv);
ws->ws_wordv = NULL;
wordsplit_free_envbuf (ws);
}
-void
-wordsplit_getwords (struct wordsplit *ws, size_t *wordc, char ***wordv)
+int
+wordsplit_get_words (struct wordsplit *ws, size_t *wordc, char ***wordv)
{
char **p = realloc (ws->ws_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;
ws->ws_wordc = 0;
ws->ws_wordn = 0;
+
+ return 0;
}
const char *_wordsplit_errstr[] = {
N_("no error"),
N_("missing closing quote"),
N_("memory exhausted"),

Return to:

Send suggestions and report system problems to the System administrator.