mirror of
git://git.gnu.org.ua/wordsplit.git
synced 2025-04-26 00:29:54 +03:00
Rewrite positional parameters implementation
This improves 3e07e3ad * include/wordsplit.h (ws_paramv,ws_paramc) (ws_parambuf,ws_paramidx,ws_paramsiz): New fields. (WRDSO_PARAMV,WRDSO_PARAM_NEGIDX): New options. (WRDSE_BADPARAM): New error code. (wordsplit_free_parambuf): New proto. * src/wordsplit.c (wordsplit_init): Initialize new fields. (wsplt_assign_var): Fix double-free and memory leak. (expvar): Expand positional parameters. (begin_var_p): Add '#' (wordsplit_free_envbuf): Fix condition. (wordsplit_free_parambuf): New function. (wordsplit_free): Call wordsplit_free_parambuf. (_wordsplit_errstr): New error description. * tests/wordsplit.at: Update wsp invocations. Test positional parameters. * tests/wsp.c: Rewrite.
This commit is contained in:
parent
c01a4a61e8
commit
c884936422
4 changed files with 705 additions and 472 deletions
|
@ -75,6 +75,16 @@ struct wordsplit
|
||||||
char **ws_envbuf; /* Storage for variables */
|
char **ws_envbuf; /* Storage for variables */
|
||||||
size_t ws_envidx; /* Index of first free slot */
|
size_t ws_envidx; /* Index of first free slot */
|
||||||
size_t ws_envsiz; /* Size of the ws_envbuf array */
|
size_t ws_envsiz; /* Size of the ws_envbuf array */
|
||||||
|
|
||||||
|
char const **ws_paramv; /* [WRDSO_PARAMV] User-supplied positional
|
||||||
|
parameters */
|
||||||
|
size_t ws_paramc; /* Number of positional parameters */
|
||||||
|
|
||||||
|
/* Temporary storage for parameters. Works similarly to ws_enbuf.
|
||||||
|
*/
|
||||||
|
char **ws_parambuf;
|
||||||
|
size_t ws_paramidx;
|
||||||
|
size_t ws_paramsiz;
|
||||||
|
|
||||||
int (*ws_getvar) (char **ret, const char *var, size_t len, void *clos);
|
int (*ws_getvar) (char **ret, const char *var, size_t len, void *clos);
|
||||||
/* [Input] (WRDSF_GETVAR, !WRDSF_NOVAR) Looks up
|
/* [Input] (WRDSF_GETVAR, !WRDSF_NOVAR) Looks up
|
||||||
|
@ -99,7 +109,7 @@ struct wordsplit
|
||||||
|
|
||||||
See ws_getvar for a discussion of possible
|
See ws_getvar for a discussion of possible
|
||||||
return values. */
|
return values. */
|
||||||
|
|
||||||
const char *ws_input; /* Input string (the S argument to wordsplit. */
|
const char *ws_input; /* Input string (the S argument to wordsplit. */
|
||||||
size_t ws_len; /* Length of ws_input. */
|
size_t ws_len; /* Length of ws_input. */
|
||||||
size_t ws_endp; /* Points past the last processed byte in
|
size_t ws_endp; /* Points past the last processed byte in
|
||||||
|
@ -226,6 +236,12 @@ struct wordsplit
|
||||||
$(echo foo bar) */
|
$(echo foo bar) */
|
||||||
#define WRDSO_NOCMDSPLIT 0x00002000
|
#define WRDSO_NOCMDSPLIT 0x00002000
|
||||||
|
|
||||||
|
/* Enable positional parameters */
|
||||||
|
#define WRDSO_PARAMV 0x00004000
|
||||||
|
/* Enable negative positional indices (${-1} is the last positional
|
||||||
|
parameter) */
|
||||||
|
#define WRDSO_PARAM_NEGIDX 0x00008000
|
||||||
|
|
||||||
#define WRDSO_BSKEEP WRDSO_BSKEEP_WORD
|
#define WRDSO_BSKEEP WRDSO_BSKEEP_WORD
|
||||||
#define WRDSO_OESC WRDSO_OESC_WORD
|
#define WRDSO_OESC WRDSO_OESC_WORD
|
||||||
#define WRDSO_XESC WRDSO_XESC_WORD
|
#define WRDSO_XESC WRDSO_XESC_WORD
|
||||||
|
@ -250,12 +266,14 @@ struct wordsplit
|
||||||
#define WRDSE_PAREN 7
|
#define WRDSE_PAREN 7
|
||||||
#define WRDSE_GLOBERR 8
|
#define WRDSE_GLOBERR 8
|
||||||
#define WRDSE_USERERR 9
|
#define WRDSE_USERERR 9
|
||||||
|
#define WRDSE_BADPARAM 10
|
||||||
|
|
||||||
int wordsplit (const char *s, wordsplit_t *ws, int flags);
|
int wordsplit (const char *s, wordsplit_t *ws, int flags);
|
||||||
int wordsplit_len (const char *s, size_t len, wordsplit_t *ws, int flags);
|
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_free_parambuf (struct wordsplit *ws);
|
||||||
int wordsplit_get_words (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)
|
static inline void wordsplit_getwords (wordsplit_t *ws, size_t *wordc, char ***wordv)
|
||||||
|
|
201
src/wordsplit.c
201
src/wordsplit.c
|
@ -1,5 +1,5 @@
|
||||||
/* wordsplit - a word splitter
|
/* wordsplit - a word splitter
|
||||||
Copyright (C) 2009-2018 Sergey Poznyakoff
|
Copyright (C) 2009-2019 Sergey Poznyakoff
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it
|
This program is free software; you can redistribute it and/or modify it
|
||||||
under the terms of the GNU General Public License as published by the
|
under the terms of the GNU General Public License as published by the
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#if ENABLE_NLS
|
#if ENABLE_NLS
|
||||||
# include <gettext.h>
|
# include <gettext.h>
|
||||||
|
@ -56,6 +57,9 @@
|
||||||
#define WSP_RETURN_DELIMS(wsp) \
|
#define WSP_RETURN_DELIMS(wsp) \
|
||||||
((wsp)->ws_flags & WRDSF_RETURN_DELIMS || ((wsp)->ws_options & WRDSO_MAXWORDS))
|
((wsp)->ws_flags & WRDSF_RETURN_DELIMS || ((wsp)->ws_options & WRDSO_MAXWORDS))
|
||||||
|
|
||||||
|
#define to_num(c) \
|
||||||
|
(ISDIGIT(c) ? c - '0' : (ISXDIGIT(c) ? toupper(c) - 'A' + 10 : 255 ))
|
||||||
|
|
||||||
#define ALLOC_INIT 128
|
#define ALLOC_INIT 128
|
||||||
#define ALLOC_INCR 128
|
#define ALLOC_INCR 128
|
||||||
|
|
||||||
|
@ -284,6 +288,14 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
|
||||||
wsp->ws_options |= WRDSO_BSKEEP_QUOTE;
|
wsp->ws_options |= WRDSO_BSKEEP_QUOTE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(wsp->ws_options & WRDSO_PARAMV))
|
||||||
|
{
|
||||||
|
wsp->ws_paramv = NULL;
|
||||||
|
wsp->ws_paramc = 0;
|
||||||
|
}
|
||||||
|
wsp->ws_paramidx = wsp->ws_paramsiz = 0;
|
||||||
|
wsp->ws_parambuf = NULL;
|
||||||
|
|
||||||
wsp->ws_endp = 0;
|
wsp->ws_endp = 0;
|
||||||
wsp->ws_wordi = 0;
|
wsp->ws_wordi = 0;
|
||||||
|
@ -1036,7 +1048,7 @@ wordsplit_find_env (struct wordsplit *wsp, const char *name, size_t len,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
|
wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
|
||||||
char *value)
|
char const *value)
|
||||||
{
|
{
|
||||||
int n = (wsp->ws_flags & WRDSF_ENV_KV) ? 2 : 1;
|
int n = (wsp->ws_flags & WRDSF_ENV_KV) ? 2 : 1;
|
||||||
char *v;
|
char *v;
|
||||||
|
@ -1071,7 +1083,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
|
||||||
{
|
{
|
||||||
for (; j > 1; j--)
|
for (; j > 1; j--)
|
||||||
free (newenv[j-1]);
|
free (newenv[j-1]);
|
||||||
free (newenv[j-1]);
|
free (newenv);
|
||||||
return _wsplt_nomem (wsp);
|
return _wsplt_nomem (wsp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1142,6 +1154,70 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
|
||||||
return WRDSE_OK;
|
return WRDSE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
wsplt_assign_param (struct wordsplit *wsp, int param_idx, char *value)
|
||||||
|
{
|
||||||
|
char *v;
|
||||||
|
|
||||||
|
if (param_idx < 0)
|
||||||
|
return WRDSE_BADPARAM;
|
||||||
|
if (param_idx == wsp->ws_paramc)
|
||||||
|
{
|
||||||
|
char **parambuf;
|
||||||
|
if (!wsp->ws_parambuf)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
parambuf = calloc ((size_t)param_idx + 1, sizeof (parambuf[0]));
|
||||||
|
if (!parambuf)
|
||||||
|
return _wsplt_nomem (wsp);
|
||||||
|
|
||||||
|
for (i = 0; i < wsp->ws_paramc; i++)
|
||||||
|
{
|
||||||
|
parambuf[i] = strdup (wsp->ws_paramv[i]);
|
||||||
|
if (!parambuf[i])
|
||||||
|
{
|
||||||
|
for (; i > 1; i--)
|
||||||
|
free (parambuf[i-1]);
|
||||||
|
free (parambuf);
|
||||||
|
return _wsplt_nomem (wsp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wsp->ws_parambuf = parambuf;
|
||||||
|
wsp->ws_paramidx = param_idx;
|
||||||
|
wsp->ws_paramsiz = param_idx + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t n = wsp->ws_paramsiz;
|
||||||
|
|
||||||
|
if ((size_t) -1 / 3 * 2 / sizeof (wsp->ws_parambuf[0]) <= n)
|
||||||
|
return _wsplt_nomem (wsp);
|
||||||
|
n += (n + 1) / 2;
|
||||||
|
parambuf = realloc (wsp->ws_parambuf, n * sizeof (wsp->ws_parambuf[0]));
|
||||||
|
if (!parambuf)
|
||||||
|
return _wsplt_nomem (wsp);
|
||||||
|
wsp->ws_parambuf = parambuf;
|
||||||
|
wsp->ws_paramsiz = n;
|
||||||
|
wsp->ws_parambuf[param_idx] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsp->ws_paramv = (const char**) wsp->ws_parambuf;
|
||||||
|
wsp->ws_paramc = param_idx + 1;
|
||||||
|
}
|
||||||
|
else if (param_idx > wsp->ws_paramc)
|
||||||
|
return WRDSE_BADPARAM;
|
||||||
|
|
||||||
|
v = strdup (value);
|
||||||
|
if (!v)
|
||||||
|
return _wsplt_nomem (wsp);
|
||||||
|
|
||||||
|
free (wsp->ws_parambuf[param_idx]);
|
||||||
|
wsp->ws_parambuf[param_idx] = v;
|
||||||
|
return WRDSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Recover from what looked like a variable reference, but turned out
|
/* Recover from what looked like a variable reference, but turned out
|
||||||
not to be one. STR points to first character after '$'. */
|
not to be one. STR points to first character after '$'. */
|
||||||
static int
|
static int
|
||||||
|
@ -1177,6 +1253,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
|
||||||
const char *start = str - 1;
|
const char *start = str - 1;
|
||||||
int rc;
|
int rc;
|
||||||
struct wordsplit ws;
|
struct wordsplit ws;
|
||||||
|
int is_param = 0;
|
||||||
|
long param_idx = 0;
|
||||||
|
|
||||||
if (ISVARBEG (str[0]))
|
if (ISVARBEG (str[0]))
|
||||||
{
|
{
|
||||||
|
@ -1185,16 +1263,39 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
|
||||||
break;
|
break;
|
||||||
*pend = str + i - 1;
|
*pend = str + i - 1;
|
||||||
}
|
}
|
||||||
else if (ISDIGIT (str[0]))
|
else if ((wsp->ws_options & WRDSO_PARAMV) && ISDIGIT (str[0]))
|
||||||
{
|
{
|
||||||
i = 1;
|
i = 1;
|
||||||
*pend = str;
|
*pend = str;
|
||||||
|
is_param = 1;
|
||||||
|
param_idx = to_num (str[0]);
|
||||||
}
|
}
|
||||||
else if (str[0] == '{' && (ISVARBEG (str[1]) || ISDIGIT (str[1])))
|
else if ((wsp->ws_options & WRDSO_PARAMV) && str[0] == '#')
|
||||||
|
{
|
||||||
|
char b[16];
|
||||||
|
snprintf (b, sizeof(b), "%d", (int) wsp->ws_paramc);
|
||||||
|
value = strdup (b);
|
||||||
|
if (!value)
|
||||||
|
return _wsplt_nomem (wsp);
|
||||||
|
if (wsnode_new (wsp, &newnode))
|
||||||
|
return 1;
|
||||||
|
wsnode_insert (wsp, newnode, *ptail, 0);
|
||||||
|
*ptail = newnode;
|
||||||
|
newnode->flags = _WSNF_WORD | _WSNF_NOEXPAND | flg;
|
||||||
|
newnode->v.word = value;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (str[0] == '{'
|
||||||
|
&& (ISVARBEG (str[1])
|
||||||
|
|| (is_param = (((wsp->ws_options & WRDSO_PARAMV)
|
||||||
|
&& ISDIGIT (str[1]))
|
||||||
|
|| ((wsp->ws_options & WRDSO_PARAM_NEGIDX)
|
||||||
|
&& (str[1] == '-'
|
||||||
|
&& ISDIGIT (str[2]))))) != 0))
|
||||||
{
|
{
|
||||||
str++;
|
str++;
|
||||||
len--;
|
len--;
|
||||||
for (i = 1; i < len; i++)
|
for (i = str[0] == '-' ? 1 : 0; i < len; i++)
|
||||||
{
|
{
|
||||||
if (str[i] == ':')
|
if (str[i] == ':')
|
||||||
{
|
{
|
||||||
|
@ -1222,9 +1323,16 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
|
||||||
*pend = str + j;
|
*pend = str + j;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (ISDIGIT (str[1]))
|
else if (is_param)
|
||||||
{
|
{
|
||||||
if (!ISDIGIT (str[i]))
|
if (ISDIGIT (str[i]))
|
||||||
|
{
|
||||||
|
param_idx = param_idx * 10 + to_num (str[i]);
|
||||||
|
if ((str[0] == '-' && -param_idx < INT_MIN)
|
||||||
|
|| param_idx > INT_MAX)
|
||||||
|
return expvar_recover (wsp, str - 1, ptail, pend, flg);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return expvar_recover (wsp, str - 1, ptail, pend, flg);
|
return expvar_recover (wsp, str - 1, ptail, pend, flg);
|
||||||
}
|
}
|
||||||
|
@ -1234,6 +1342,10 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
|
||||||
return expvar_recover (wsp, str - 1, ptail, pend, flg);
|
return expvar_recover (wsp, str - 1, ptail, pend, flg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_param && str[0] == '-')
|
||||||
|
param_idx = wsp->ws_paramc - param_idx;
|
||||||
|
|
||||||
if (i == len)
|
if (i == len)
|
||||||
return _wsplt_seterr (wsp, WRDSE_CBRACE);
|
return _wsplt_seterr (wsp, WRDSE_CBRACE);
|
||||||
}
|
}
|
||||||
|
@ -1254,23 +1366,39 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rc = wordsplit_find_env (wsp, str, i, &vptr);
|
if (is_param)
|
||||||
if (rc == WRDSE_OK)
|
|
||||||
{
|
{
|
||||||
if (vptr)
|
if (param_idx >= 0 && param_idx < wsp->ws_paramc)
|
||||||
{
|
{
|
||||||
value = strdup (vptr);
|
value = strdup (wsp->ws_paramv[param_idx]);
|
||||||
if (!value)
|
if (!value)
|
||||||
rc = WRDSE_NOSPACE;
|
rc = WRDSE_NOSPACE;
|
||||||
|
else
|
||||||
|
rc = WRDSE_OK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
rc = WRDSE_UNDEF;
|
rc = WRDSE_UNDEF;
|
||||||
}
|
}
|
||||||
else if (wsp->ws_flags & WRDSF_GETVAR)
|
|
||||||
rc = wsp->ws_getvar (&value, str, i, wsp->ws_closure);
|
|
||||||
else
|
else
|
||||||
rc = WRDSE_UNDEF;
|
{
|
||||||
|
rc = wordsplit_find_env (wsp, str, i, &vptr);
|
||||||
|
if (rc == WRDSE_OK)
|
||||||
|
{
|
||||||
|
if (vptr)
|
||||||
|
{
|
||||||
|
value = strdup (vptr);
|
||||||
|
if (!value)
|
||||||
|
rc = WRDSE_NOSPACE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rc = WRDSE_UNDEF;
|
||||||
|
}
|
||||||
|
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
|
if (rc == WRDSE_OK
|
||||||
&& (!value || value[0] == 0)
|
&& (!value || value[0] == 0)
|
||||||
&& defstr && defstr[-1] == ':')
|
&& defstr && defstr[-1] == ':')
|
||||||
|
@ -1321,7 +1449,17 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
|
||||||
wordsplit_free (&ws);
|
wordsplit_free (&ws);
|
||||||
|
|
||||||
if (defstr[-1] == '=')
|
if (defstr[-1] == '=')
|
||||||
wsplt_assign_var (wsp, str, i, value);
|
{
|
||||||
|
if (is_param)
|
||||||
|
rc = wsplt_assign_param (wsp, param_idx, value);
|
||||||
|
else
|
||||||
|
rc = wsplt_assign_var (wsp, str, i, value);
|
||||||
|
}
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
free (value);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1458,7 +1596,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
|
||||||
static int
|
static int
|
||||||
begin_var_p (int c)
|
begin_var_p (int c)
|
||||||
{
|
{
|
||||||
return c == '{' || ISVARBEG (c) || ISDIGIT (c);
|
return c == '{' || c == '#' || ISVARBEG (c) || ISDIGIT (c);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -2106,9 +2244,6 @@ scan_word (struct wordsplit *wsp, size_t start, int consume_all)
|
||||||
return _WRDS_OK;
|
return _WRDS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define to_num(c) \
|
|
||||||
(ISDIGIT(c) ? c - '0' : (ISXDIGIT(c) ? toupper(c) - 'A' + 10 : 255 ))
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
xtonum (int *pval, const char *src, int base, int cnt)
|
xtonum (int *pval, const char *src, int base, int cnt)
|
||||||
{
|
{
|
||||||
|
@ -2498,7 +2633,7 @@ wordsplit_free_words (struct wordsplit *ws)
|
||||||
void
|
void
|
||||||
wordsplit_free_envbuf (struct wordsplit *ws)
|
wordsplit_free_envbuf (struct wordsplit *ws)
|
||||||
{
|
{
|
||||||
if (ws->ws_flags & WRDSF_NOCMD)
|
if (!(ws->ws_flags & WRDSF_ENV))
|
||||||
return;
|
return;
|
||||||
if (ws->ws_envbuf)
|
if (ws->ws_envbuf)
|
||||||
{
|
{
|
||||||
|
@ -2512,6 +2647,23 @@ wordsplit_free_envbuf (struct wordsplit *ws)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wordsplit_free_parambuf (struct wordsplit *ws)
|
||||||
|
{
|
||||||
|
if (!(ws->ws_options & WRDSO_PARAMV))
|
||||||
|
return;
|
||||||
|
if (ws->ws_parambuf)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; ws->ws_parambuf[i]; i++)
|
||||||
|
free (ws->ws_parambuf[i]);
|
||||||
|
free (ws->ws_parambuf);
|
||||||
|
ws->ws_paramidx = ws->ws_paramsiz = 0;
|
||||||
|
ws->ws_parambuf = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wordsplit_clearerr (struct wordsplit *ws)
|
wordsplit_clearerr (struct wordsplit *ws)
|
||||||
{
|
{
|
||||||
|
@ -2529,6 +2681,7 @@ wordsplit_free (struct wordsplit *ws)
|
||||||
free (ws->ws_wordv);
|
free (ws->ws_wordv);
|
||||||
ws->ws_wordv = NULL;
|
ws->ws_wordv = NULL;
|
||||||
wordsplit_free_envbuf (ws);
|
wordsplit_free_envbuf (ws);
|
||||||
|
wordsplit_free_parambuf (ws);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -2557,7 +2710,9 @@ const char *_wordsplit_errstr[] = {
|
||||||
N_("undefined variable"),
|
N_("undefined variable"),
|
||||||
N_("input exhausted"),
|
N_("input exhausted"),
|
||||||
N_("unbalanced parenthesis"),
|
N_("unbalanced parenthesis"),
|
||||||
N_("globbing error")
|
N_("globbing error"),
|
||||||
|
N_("user-defined error"),
|
||||||
|
N_("invalid parameter number in assignment")
|
||||||
};
|
};
|
||||||
int _wordsplit_nerrs =
|
int _wordsplit_nerrs =
|
||||||
sizeof (_wordsplit_errstr) / sizeof (_wordsplit_errstr[0]);
|
sizeof (_wordsplit_errstr) / sizeof (_wordsplit_errstr[0]);
|
||||||
|
|
|
@ -108,7 +108,7 @@ WSPGROUP()
|
||||||
dnl ------------------------------------------------------------
|
dnl ------------------------------------------------------------
|
||||||
dnl Test worsplit-specific behavior
|
dnl Test worsplit-specific behavior
|
||||||
dnl ------------------------------------------------------------
|
dnl ------------------------------------------------------------
|
||||||
TESTWSP([append],[wsp-append],[append],
|
TESTWSP([append],[wsp-append],[-append],
|
||||||
[jeden dwa trzy
|
[jeden dwa trzy
|
||||||
cztery
|
cztery
|
||||||
piec szesc],
|
piec szesc],
|
||||||
|
@ -133,7 +133,7 @@ NF: 6
|
||||||
TOTAL: 2
|
TOTAL: 2
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([dooffs],[wsp-doofs ],[dooffs 3 jeden dwa trzy],
|
TESTWSP([dooffs],[wsp-doofs ],[-dooffs jeden dwa trzy],
|
||||||
[cztery piec],
|
[cztery piec],
|
||||||
[NF: 2 (3)
|
[NF: 2 (3)
|
||||||
(0): jeden
|
(0): jeden
|
||||||
|
@ -214,7 +214,7 @@ TOTAL: 3
|
||||||
[],
|
[],
|
||||||
[unset FOO;])
|
[unset FOO;])
|
||||||
|
|
||||||
TESTWSP([undefined variables 2],[],[keepundef],
|
TESTWSP([undefined variables 2],[],[-keepundef],
|
||||||
[a $FOO test a${FOO}b],
|
[a $FOO test a${FOO}b],
|
||||||
[NF: 4
|
[NF: 4
|
||||||
0: a
|
0: a
|
||||||
|
@ -226,7 +226,7 @@ TOTAL: 4
|
||||||
[],
|
[],
|
||||||
[unset FOO;])
|
[unset FOO;])
|
||||||
|
|
||||||
TESTWSP([warn about undefined variables],[],[warnundef],
|
TESTWSP([warn about undefined variables],[],[-warnundef],
|
||||||
[$FOO],
|
[$FOO],
|
||||||
[NF: 0
|
[NF: 0
|
||||||
TOTAL: 0
|
TOTAL: 0
|
||||||
|
@ -235,14 +235,14 @@ TOTAL: 0
|
||||||
],
|
],
|
||||||
[unset FOO;])
|
[unset FOO;])
|
||||||
|
|
||||||
TESTWSP([bail out on undefined variables],[],[undef],
|
TESTWSP([bail out on undefined variables],[],[-undef],
|
||||||
[$FOO],
|
[$FOO],
|
||||||
[],
|
[],
|
||||||
[undefined variable
|
[undefined variable
|
||||||
],
|
],
|
||||||
[unset FOO;])
|
[unset FOO;])
|
||||||
|
|
||||||
TESTWSP([disable variable expansion],[],[novar],
|
TESTWSP([disable variable expansion],[],[-novar],
|
||||||
[$FOO],
|
[$FOO],
|
||||||
[NF: 1
|
[NF: 1
|
||||||
0: $FOO
|
0: $FOO
|
||||||
|
@ -252,7 +252,7 @@ TOTAL: 1
|
||||||
[FOO=bar])
|
[FOO=bar])
|
||||||
|
|
||||||
TESTWSP([K/V environment],[wsp-env-kv wsp-env_kv],
|
TESTWSP([K/V environment],[wsp-env-kv wsp-env_kv],
|
||||||
[env_kv],
|
[-env_kv],
|
||||||
[$FOO a$BAZ],
|
[$FOO a$BAZ],
|
||||||
[NF: 2
|
[NF: 2
|
||||||
0: bar
|
0: bar
|
||||||
|
@ -262,7 +262,7 @@ TOTAL: 2
|
||||||
[],
|
[],
|
||||||
[FOO=bar BAZ=qux])
|
[FOO=bar BAZ=qux])
|
||||||
|
|
||||||
TESTWSP([nosplit with variable expansion],[wsp-var-nosplit],[nosplit],
|
TESTWSP([nosplit with variable expansion],[wsp-var-nosplit],[-nosplit],
|
||||||
[a $FOO test],
|
[a $FOO test],
|
||||||
[NF: 1
|
[NF: 1
|
||||||
0: "a variable expansion test\n"
|
0: "a variable expansion test\n"
|
||||||
|
@ -271,7 +271,7 @@ TOTAL: 1
|
||||||
[],
|
[],
|
||||||
[FOO="variable expansion"])
|
[FOO="variable expansion"])
|
||||||
|
|
||||||
TESTWSP([nosplit without variable expansion],[],[nosplit novar],
|
TESTWSP([nosplit without variable expansion],[],[-nosplit -novar],
|
||||||
[a $FOO test],
|
[a $FOO test],
|
||||||
[NF: 1
|
[NF: 1
|
||||||
0: "a $FOO test\n"
|
0: "a $FOO test\n"
|
||||||
|
@ -280,7 +280,7 @@ TOTAL: 1
|
||||||
[],
|
[],
|
||||||
[FOO="variable expansion"])
|
[FOO="variable expansion"])
|
||||||
|
|
||||||
TESTWSP([nosplit: empty expansion],[],[nosplit trimnl],
|
TESTWSP([nosplit: empty expansion],[],[-nosplit -trimnl],
|
||||||
[$FOO],
|
[$FOO],
|
||||||
[NF: 1
|
[NF: 1
|
||||||
0: ""
|
0: ""
|
||||||
|
@ -289,15 +289,6 @@ TOTAL: 1
|
||||||
[],
|
[],
|
||||||
[FOO=""])
|
[FOO=""])
|
||||||
|
|
||||||
TESTWSP([default value (defined)],[],[],
|
|
||||||
[${FOO:-bar}],
|
|
||||||
[NF: 1
|
|
||||||
0: qux
|
|
||||||
TOTAL: 1
|
|
||||||
],
|
|
||||||
[],
|
|
||||||
[FOO=qux])
|
|
||||||
|
|
||||||
TESTWSP([default value],[],[],
|
TESTWSP([default value],[],[],
|
||||||
[${FOO:-bar}],
|
[${FOO:-bar}],
|
||||||
[NF: 1
|
[NF: 1
|
||||||
|
@ -451,7 +442,7 @@ TOTAL: 2
|
||||||
|
|
||||||
WSPGROUP()
|
WSPGROUP()
|
||||||
|
|
||||||
TESTWSP([ignore quotes],[wsp-ignore-quotes ],[-quote],
|
TESTWSP([ignore quotes],[wsp-ignore-quotes ],[-noquote],
|
||||||
["a text"],
|
["a text"],
|
||||||
[NF: 2
|
[NF: 2
|
||||||
0: "\"a"
|
0: "\"a"
|
||||||
|
@ -462,7 +453,7 @@ TOTAL: 2
|
||||||
WSPGROUP(wsp-delim)
|
WSPGROUP(wsp-delim)
|
||||||
|
|
||||||
TESTWSP([custom delimiters (squeeze)],[],
|
TESTWSP([custom delimiters (squeeze)],[],
|
||||||
[delim : -ws trimnl],
|
[-delim : -nows -trimnl],
|
||||||
[semicolon: separated::list: of :words],
|
[semicolon: separated::list: of :words],
|
||||||
[NF: 5
|
[NF: 5
|
||||||
0: semicolon
|
0: semicolon
|
||||||
|
@ -474,7 +465,7 @@ TOTAL: 5
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([custom delimiters (no squeeze)],[],
|
TESTWSP([custom delimiters (no squeeze)],[],
|
||||||
[delim : -ws -squeeze_delims trimnl],
|
[-delim : -nows -nosqueeze_delims -trimnl],
|
||||||
[semicolon: separated::list: of :words],
|
[semicolon: separated::list: of :words],
|
||||||
[NF: 6
|
[NF: 6
|
||||||
0: semicolon
|
0: semicolon
|
||||||
|
@ -487,7 +478,7 @@ TOTAL: 6
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([custom, with returned delimiters],[],
|
TESTWSP([custom, with returned delimiters],[],
|
||||||
[delim : -ws trimnl return_delims],
|
[-delim : -nows -trimnl -return_delims],
|
||||||
[semicolon: separated::list: of :words],
|
[semicolon: separated::list: of :words],
|
||||||
[NF: 9
|
[NF: 9
|
||||||
0: semicolon
|
0: semicolon
|
||||||
|
@ -503,7 +494,7 @@ TOTAL: 9
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([custom, with returned & squeezed delimiters],[],
|
TESTWSP([custom, with returned & squeezed delimiters],[],
|
||||||
[delim : -ws trimnl return_delims -squeeze_delims],
|
[-delim : -nows -trimnl -return_delims -nosqueeze_delims],
|
||||||
[semicolon: separated::list: of :words],
|
[semicolon: separated::list: of :words],
|
||||||
[NF: 10
|
[NF: 10
|
||||||
0: semicolon
|
0: semicolon
|
||||||
|
@ -521,7 +512,7 @@ TOTAL: 10
|
||||||
|
|
||||||
WSPGROUP(wsp-sed)
|
WSPGROUP(wsp-sed)
|
||||||
|
|
||||||
TESTWSP([sed expressions],[],[sed],
|
TESTWSP([sed expressions],[],[-sed],
|
||||||
[arg1 s/foo/bar/g;s/bar baz/quz quux/ arg2],
|
[arg1 s/foo/bar/g;s/bar baz/quz quux/ arg2],
|
||||||
[NF: 3
|
[NF: 3
|
||||||
0: arg1
|
0: arg1
|
||||||
|
@ -532,7 +523,7 @@ TOTAL: 3
|
||||||
|
|
||||||
WSPGROUP()
|
WSPGROUP()
|
||||||
|
|
||||||
TESTWSP([C escapes on],[wcp-c-escape],[cescapes],
|
TESTWSP([C escapes on],[wcp-c-escape],[-cescapes],
|
||||||
[a\ttab form\ffeed and new\nline],
|
[a\ttab form\ffeed and new\nline],
|
||||||
[NF: 4
|
[NF: 4
|
||||||
0: a\ttab
|
0: a\ttab
|
||||||
|
@ -542,7 +533,7 @@ TESTWSP([C escapes on],[wcp-c-escape],[cescapes],
|
||||||
TOTAL: 4
|
TOTAL: 4
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([C escapes off],[wcp-c-escape-off],[-cescapes],
|
TESTWSP([C escapes off],[wcp-c-escape-off],[-nocescapes],
|
||||||
[a\ttab form\ffeed and new\nline],
|
[a\ttab form\ffeed and new\nline],
|
||||||
[NF: 4
|
[NF: 4
|
||||||
0: attab
|
0: attab
|
||||||
|
@ -552,7 +543,7 @@ TESTWSP([C escapes off],[wcp-c-escape-off],[-cescapes],
|
||||||
TOTAL: 4
|
TOTAL: 4
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([ws elimination],[wsp-ws-elim],[delim ' ()' ws return_delims],
|
TESTWSP([ws elimination],[wsp-ws-elim],[-delim ' ()' -ws -return_delims],
|
||||||
[( list items )],
|
[( list items )],
|
||||||
[NF: 4
|
[NF: 4
|
||||||
0: (
|
0: (
|
||||||
|
@ -563,7 +554,7 @@ TOTAL: 4
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([ws elimination + return delim],[wsp-ws-elim-ret],
|
TESTWSP([ws elimination + return delim],[wsp-ws-elim-ret],
|
||||||
[-default novar nocmd delim ":," return_delims ws dquote],
|
[-nodefault -novar -nocmd -delim ":," -return_delims -ws -dquote],
|
||||||
["foo" : "bar", "quux" : "baaz" ],
|
["foo" : "bar", "quux" : "baaz" ],
|
||||||
[NF: 7
|
[NF: 7
|
||||||
0: foo
|
0: foo
|
||||||
|
@ -576,7 +567,7 @@ TESTWSP([ws elimination + return delim],[wsp-ws-elim-ret],
|
||||||
TOTAL: 7
|
TOTAL: 7
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([empty quotes],[wsp-empty-quotes],[delim : ws return_delims],
|
TESTWSP([empty quotes],[wsp-empty-quotes],[-delim : -ws -return_delims],
|
||||||
[t=""],
|
[t=""],
|
||||||
[NF: 1
|
[NF: 1
|
||||||
0: t=
|
0: t=
|
||||||
|
@ -584,7 +575,7 @@ TOTAL: 1
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([delimiter following empty quotes],
|
TESTWSP([delimiter following empty quotes],
|
||||||
[],[delim : ws return_delims],
|
[],[-delim : -ws -return_delims],
|
||||||
[t="":r],
|
[t="":r],
|
||||||
[NF: 3
|
[NF: 3
|
||||||
0: t=
|
0: t=
|
||||||
|
@ -595,7 +586,7 @@ TOTAL: 3
|
||||||
|
|
||||||
TESTWSP([suppress ws trimming within quotes],
|
TESTWSP([suppress ws trimming within quotes],
|
||||||
[],
|
[],
|
||||||
[default delim , ws return_delims],
|
[-default -delim , -ws -return_delims],
|
||||||
[nocomponent,nonewline, formatfield="In message %{text}, "],
|
[nocomponent,nonewline, formatfield="In message %{text}, "],
|
||||||
[NF: 5
|
[NF: 5
|
||||||
0: nocomponent
|
0: nocomponent
|
||||||
|
@ -608,7 +599,7 @@ TOTAL: 5
|
||||||
|
|
||||||
TESTWSP([unescape],
|
TESTWSP([unescape],
|
||||||
[wsp-unescape wsp-unescape-simple],
|
[wsp-unescape wsp-unescape-simple],
|
||||||
[-default novar nocmd quote escape ':+:\\""'],
|
[-nodefault -novar -nocmd -quote -escape ':+:\\""'],
|
||||||
[\Seen "quote \"" "bs \\"],
|
[\Seen "quote \"" "bs \\"],
|
||||||
[NF: 3
|
[NF: 3
|
||||||
0: \\Seen
|
0: \\Seen
|
||||||
|
@ -619,7 +610,7 @@ TOTAL: 3
|
||||||
|
|
||||||
TESTWSP([unescape: word/quote],
|
TESTWSP([unescape: word/quote],
|
||||||
[wsp-unescape wsp-unescape-word],
|
[wsp-unescape wsp-unescape-word],
|
||||||
[-default novar nocmd quote escape-word '\\""' escape-quote ':+0x:\\""'],
|
[-nodefault -novar -nocmd -quote -escape-word '\\""' -escape-quote ':+0x:\\""'],
|
||||||
[\Seen "quote \"" "bs \\" "3\x31 \101" 3\x31 \101],
|
[\Seen "quote \"" "bs \\" "3\x31 \101" 3\x31 \101],
|
||||||
[NF: 6
|
[NF: 6
|
||||||
0: Seen
|
0: Seen
|
||||||
|
@ -631,7 +622,7 @@ TESTWSP([unescape: word/quote],
|
||||||
TOTAL: 6
|
TOTAL: 6
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([dquote],[],[-default novar nocmd dquote],
|
TESTWSP([dquote],[],[-nodefault -novar -nocmd -dquote],
|
||||||
[a "quoted example" isn't it],
|
[a "quoted example" isn't it],
|
||||||
[NF: 4
|
[NF: 4
|
||||||
0: a
|
0: a
|
||||||
|
@ -641,7 +632,7 @@ TESTWSP([dquote],[],[-default novar nocmd dquote],
|
||||||
TOTAL: 4
|
TOTAL: 4
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([squote],[],[-default novar nocmd squote],
|
TESTWSP([squote],[],[-nodefault -novar -nocmd -squote],
|
||||||
[a 'quoted example' isn"t it],
|
[a 'quoted example' isn"t it],
|
||||||
[NF: 4
|
[NF: 4
|
||||||
0: a
|
0: a
|
||||||
|
@ -653,7 +644,7 @@ TOTAL: 4
|
||||||
|
|
||||||
WSPGROUP(wsp-incr)
|
WSPGROUP(wsp-incr)
|
||||||
|
|
||||||
TESTWSP([incremental],[],[incremental],
|
TESTWSP([incremental],[],[-incremental],
|
||||||
[incremental "input test" line
|
[incremental "input test" line
|
||||||
|
|
||||||
|
|
||||||
|
@ -671,7 +662,7 @@ TOTAL: 3
|
||||||
[input exhausted
|
[input exhausted
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([incremental append],[],[incremental append],
|
TESTWSP([incremental append],[],[-incremental -append],
|
||||||
[incremental "input test" line
|
[incremental "input test" line
|
||||||
|
|
||||||
|
|
||||||
|
@ -693,7 +684,7 @@ TOTAL: 3
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([incremental ws],
|
TESTWSP([incremental ws],
|
||||||
[],[return_delims -squeeze_delims incremental ws],
|
[],[-return_delims -nosqueeze_delims -incremental -ws],
|
||||||
[a list test
|
[a list test
|
||||||
|
|
||||||
|
|
||||||
|
@ -711,7 +702,7 @@ TOTAL: 3
|
||||||
[input exhausted
|
[input exhausted
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([incremental nosplit],[],[incremental nosplit],
|
TESTWSP([incremental nosplit],[],[-incremental -nosplit],
|
||||||
[incremental "input test" line
|
[incremental "input test" line
|
||||||
],
|
],
|
||||||
[NF: 1
|
[NF: 1
|
||||||
|
@ -721,7 +712,7 @@ TOTAL: 1
|
||||||
[input exhausted
|
[input exhausted
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([simple command substitution],[],[-nocmd],
|
TESTWSP([simple command substitution],[],[-cmd],
|
||||||
[begin $(words a b) end],
|
[begin $(words a b) end],
|
||||||
[NF: 4
|
[NF: 4
|
||||||
0: begin
|
0: begin
|
||||||
|
@ -731,7 +722,7 @@ TESTWSP([simple command substitution],[],[-nocmd],
|
||||||
TOTAL: 4
|
TOTAL: 4
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([quoted command substitution],[],[-nocmd],
|
TESTWSP([quoted command substitution],[],[-cmd],
|
||||||
[begin "$(words a b)" end],
|
[begin "$(words a b)" end],
|
||||||
[NF: 3
|
[NF: 3
|
||||||
0: begin
|
0: begin
|
||||||
|
@ -740,7 +731,7 @@ TESTWSP([quoted command substitution],[],[-nocmd],
|
||||||
TOTAL: 3
|
TOTAL: 3
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([coalesced command substitution],[],[-nocmd],
|
TESTWSP([coalesced command substitution],[],[-cmd],
|
||||||
[begin($(words a b))end],
|
[begin($(words a b))end],
|
||||||
[NF: 2
|
[NF: 2
|
||||||
0: begin(a
|
0: begin(a
|
||||||
|
@ -748,14 +739,14 @@ TESTWSP([coalesced command substitution],[],[-nocmd],
|
||||||
TOTAL: 2
|
TOTAL: 2
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([quoted coalesced command substitution],[],[-nocmd],
|
TESTWSP([quoted coalesced command substitution],[],[-cmd],
|
||||||
["begin($(words a b))end"],
|
["begin($(words a b))end"],
|
||||||
[NF: 1
|
[NF: 1
|
||||||
0: "begin(a b)end"
|
0: "begin(a b)end"
|
||||||
TOTAL: 1
|
TOTAL: 1
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([variable and command substitution],[],[-nocmd -novar],
|
TESTWSP([variable and command substitution],[],[-cmd -var],
|
||||||
[begin $X $(words $X $Y) end],
|
[begin $X $(words $X $Y) end],
|
||||||
[NF: 5
|
[NF: 5
|
||||||
0: begin
|
0: begin
|
||||||
|
@ -766,14 +757,14 @@ TESTWSP([variable and command substitution],[],[-nocmd -novar],
|
||||||
TOTAL: 5
|
TOTAL: 5
|
||||||
],[],[X=a Y=b])
|
],[],[X=a Y=b])
|
||||||
|
|
||||||
TESTWSP([variable expansion and command substitution in quotes],[],[-nocmd -novar],
|
TESTWSP([variable expansion and command substitution in quotes],[],[-cmd -var],
|
||||||
["${BEGIN}($(words $X $Y))end"],
|
["${BEGIN}($(words $X $Y))end"],
|
||||||
[NF: 1
|
[NF: 1
|
||||||
0: "begin(a b)end"
|
0: "begin(a b)end"
|
||||||
TOTAL: 1
|
TOTAL: 1
|
||||||
],[],[X=a Y=b BEGIN=begin])
|
],[],[X=a Y=b BEGIN=begin])
|
||||||
|
|
||||||
TESTWSP([nested commands],[],[-nocmd -novar],
|
TESTWSP([nested commands],[],[-cmd -var],
|
||||||
[$(words output $(words in$SUFFIX text) end)],
|
[$(words output $(words in$SUFFIX text) end)],
|
||||||
[NF: 4
|
[NF: 4
|
||||||
0: output
|
0: output
|
||||||
|
@ -792,7 +783,7 @@ mkdir dir
|
||||||
> dir/2.c
|
> dir/2.c
|
||||||
> dir/3.b
|
> dir/3.b
|
||||||
|
|
||||||
wsp pathexpand<<'EOT'
|
wsp -pathexpand<<'EOT'
|
||||||
begin dir/*.c end
|
begin dir/*.c end
|
||||||
EOT
|
EOT
|
||||||
],
|
],
|
||||||
|
@ -813,7 +804,7 @@ mkdir dir
|
||||||
> dir/1.c
|
> dir/1.c
|
||||||
> dir/2.b
|
> dir/2.b
|
||||||
|
|
||||||
wsp pathexpand<<'EOT'
|
wsp -pathexpand<<'EOT'
|
||||||
begin dir/*.d end
|
begin dir/*.d end
|
||||||
EOT
|
EOT
|
||||||
],
|
],
|
||||||
|
@ -833,7 +824,7 @@ mkdir dir
|
||||||
> dir/1.c
|
> dir/1.c
|
||||||
> dir/2.b
|
> dir/2.b
|
||||||
|
|
||||||
wsp pathexpand nullglob<<'EOT'
|
wsp -pathexpand -nullglob<<'EOT'
|
||||||
begin dir/*.d end
|
begin dir/*.d end
|
||||||
EOT
|
EOT
|
||||||
],
|
],
|
||||||
|
@ -852,7 +843,7 @@ mkdir dir
|
||||||
> dir/1.c
|
> dir/1.c
|
||||||
> dir/2.b
|
> dir/2.b
|
||||||
|
|
||||||
wsp pathexpand failglob<<'EOT'
|
wsp -pathexpand -failglob<<'EOT'
|
||||||
begin dir/*.d end
|
begin dir/*.d end
|
||||||
EOT
|
EOT
|
||||||
],
|
],
|
||||||
|
@ -862,7 +853,7 @@ EOT
|
||||||
])
|
])
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
TESTWSP([append],[],[-- extra arguments follow],
|
TESTWSP([append],[],[-append-args extra arguments follow],
|
||||||
[some words and],
|
[some words and],
|
||||||
[NF: 6
|
[NF: 6
|
||||||
0: some
|
0: some
|
||||||
|
@ -875,7 +866,7 @@ TOTAL: 3
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([append + dooffs + env],[],
|
TESTWSP([append + dooffs + env],[],
|
||||||
[-env dooffs 2 preface words V=2 -- extra arguments follow],
|
[-env none -dooffs preface words -- V=2 -append-args extra arguments follow],
|
||||||
[some words and var=$V],
|
[some words and var=$V],
|
||||||
[NF: 7 (2)
|
[NF: 7 (2)
|
||||||
(0): preface
|
(0): preface
|
||||||
|
@ -892,7 +883,7 @@ TOTAL: 4
|
||||||
|
|
||||||
# Maxwords
|
# Maxwords
|
||||||
TESTWSP([maxwords],[],
|
TESTWSP([maxwords],[],
|
||||||
[trimnl maxwords 3],
|
[-trimnl -maxwords 3],
|
||||||
[ws_maxwords limits the number of returned words],
|
[ws_maxwords limits the number of returned words],
|
||||||
[NF: 3
|
[NF: 3
|
||||||
0: ws_maxwords
|
0: ws_maxwords
|
||||||
|
@ -902,7 +893,7 @@ TOTAL: 3
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([maxwords return_delims],[],
|
TESTWSP([maxwords return_delims],[],
|
||||||
[trimnl maxwords 8 return_delims delim :-],
|
[-trimnl -maxwords 8 -return_delims -delim :-],
|
||||||
[foo:::bar-:baz-quux:ux:zu],
|
[foo:::bar-:baz-quux:ux:zu],
|
||||||
[NF: 8
|
[NF: 8
|
||||||
0: foo
|
0: foo
|
||||||
|
@ -917,7 +908,7 @@ TOTAL: 8
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([maxwords return_delims -squeeze_delims],[],
|
TESTWSP([maxwords return_delims -squeeze_delims],[],
|
||||||
[trimnl maxwords 8 return_delims -squeeze_delims delim :-],
|
[-trimnl -maxwords 8 -return_delims -nosqueeze_delims -delim :-],
|
||||||
[foo:::bar-:baz:qux-],
|
[foo:::bar-:baz:qux-],
|
||||||
[NF: 8
|
[NF: 8
|
||||||
0: foo
|
0: foo
|
||||||
|
@ -932,7 +923,7 @@ TOTAL: 8
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([maxwords incremental],[],
|
TESTWSP([maxwords incremental],[],
|
||||||
[trimnl maxwords 3 incremental],
|
[-trimnl -maxwords 3 -incremental],
|
||||||
[foo bar baz qux uz
|
[foo bar baz qux uz
|
||||||
|
|
||||||
|
|
||||||
|
@ -950,7 +941,7 @@ TOTAL: 3
|
||||||
[input exhausted
|
[input exhausted
|
||||||
]))
|
]))
|
||||||
|
|
||||||
TESTWSP([variable nosplit],[],[novar novarsplit],
|
TESTWSP([variable nosplit],[],[-novar -novarsplit],
|
||||||
[begin ${VAR:- a b} end],
|
[begin ${VAR:- a b} end],
|
||||||
[NF: 3
|
[NF: 3
|
||||||
0: begin
|
0: begin
|
||||||
|
@ -959,7 +950,7 @@ TESTWSP([variable nosplit],[],[novar novarsplit],
|
||||||
TOTAL: 3
|
TOTAL: 3
|
||||||
])
|
])
|
||||||
|
|
||||||
TESTWSP([command nosplit],[],[nocmd nocmdsplit],
|
TESTWSP([command nosplit],[],[-nocmd -nocmdsplit],
|
||||||
[begin $(words a b) end],
|
[begin $(words a b) end],
|
||||||
[NF: 3
|
[NF: 3
|
||||||
0: begin
|
0: begin
|
||||||
|
@ -968,6 +959,19 @@ TESTWSP([command nosplit],[],[nocmd nocmdsplit],
|
||||||
TOTAL: 3
|
TOTAL: 3
|
||||||
])
|
])
|
||||||
|
|
||||||
|
TESTWSP([positional parameters],[],[one two three four five six seven eight nine ten eleven twelve],
|
||||||
|
[$0 $5 ${10}
|
||||||
|
$#],
|
||||||
|
[NF: 3
|
||||||
|
0: one
|
||||||
|
1: six
|
||||||
|
2: eleven
|
||||||
|
TOTAL: 3
|
||||||
|
NF: 1
|
||||||
|
0: 12
|
||||||
|
TOTAL: 1
|
||||||
|
])
|
||||||
|
|
||||||
m4_popdef([TESTWSP])
|
m4_popdef([TESTWSP])
|
||||||
m4_popdef([wspnum])
|
m4_popdef([wspnum])
|
||||||
m4_popdef([wspid])
|
m4_popdef([wspid])
|
||||||
|
|
834
tests/wsp.c
834
tests/wsp.c
|
@ -1,5 +1,5 @@
|
||||||
/* grecs - Gray's Extensible Configuration System
|
/* grecs - Gray's Extensible Configuration System
|
||||||
Copyright (C) 2014-2016 Sergey Poznyakoff
|
Copyright (C) 2014-2019 Sergey Poznyakoff
|
||||||
|
|
||||||
Grecs is free software; you can redistribute it and/or modify it
|
Grecs is free software; you can redistribute it and/or modify it
|
||||||
under the terms of the GNU General Public License as published by the
|
under the terms of the GNU General Public License as published by the
|
||||||
|
@ -29,99 +29,408 @@ extern char **environ;
|
||||||
|
|
||||||
char *progname;
|
char *progname;
|
||||||
|
|
||||||
struct kwd
|
/* Global options */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
TRIMNL_OPTION = 0x01, /* Remove trailing newline */
|
||||||
|
PLAINTEXT_OPTION = 0x02 /* Print intput verbatim (no escapes) */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Environment types */
|
||||||
|
enum env_type
|
||||||
|
{
|
||||||
|
env_none, /* No environment */
|
||||||
|
env_null, /* Null environment */
|
||||||
|
env_sys /* Use system environment */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wsclosure
|
||||||
{
|
{
|
||||||
const char *name;
|
int options; /* Global options */
|
||||||
int tok;
|
struct wordsplit ws; /* The wordsplit structure */
|
||||||
|
int wsflags; /* Wordsplit flags */
|
||||||
|
enum env_type env_type; /* Environment type */
|
||||||
|
int offarg; /* Index of the first of the initial words in
|
||||||
|
the argv array. The ws.ws_dooffs field gives
|
||||||
|
the number of such variables. Forces the
|
||||||
|
WRDSF_DOOFFS flag. */
|
||||||
|
char **fenvbase; /* Environment for testing the ws_getenv function */
|
||||||
|
int fenvidx; /* Number of variables in fenvbase */
|
||||||
|
int fenvmax; /* Size of fenbase (entries) */
|
||||||
|
int append_start; /* First argument to append (index in argv) */
|
||||||
|
int append_count; /* Number of arguments to append */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kwd bool_keytab[] = {
|
/* Command line option types */
|
||||||
{ "append", WRDSF_APPEND },
|
enum
|
||||||
/*{ "reuse", WRDSF_REUSE },*/
|
{
|
||||||
{ "undef", WRDSF_UNDEF },
|
ws_no_argument, /* Option requires no arguments */
|
||||||
{ "novar", WRDSF_NOVAR },
|
ws_boolean, /* Option is boolean (can be prefixed with -no) */
|
||||||
{ "nocmd", WRDSF_NOCMD },
|
ws_required_argument, /* Option requires one argument */
|
||||||
{ "ws", WRDSF_WS },
|
ws_multiple_arguments /* Option takes multiple arguments, terminated with
|
||||||
{ "quote", WRDSF_QUOTE },
|
"--" or end of argument list */
|
||||||
{ "squote", WRDSF_SQUOTE },
|
};
|
||||||
{ "dquote", WRDSF_DQUOTE },
|
|
||||||
{ "squeeze_delims", WRDSF_SQUEEZE_DELIMS },
|
/* Structure describing a single command-line option */
|
||||||
{ "return_delims", WRDSF_RETURN_DELIMS },
|
struct wsopt
|
||||||
{ "sed", WRDSF_SED_EXPR },
|
{
|
||||||
{ "debug", WRDSF_SHOWDBG },
|
const char *name; /* Option name */
|
||||||
{ "nosplit", WRDSF_NOSPLIT },
|
int tok; /* Corresponding flag */
|
||||||
{ "keepundef", WRDSF_KEEPUNDEF },
|
int arg; /* Option type (see the enum above) */
|
||||||
{ "warnundef", WRDSF_WARNUNDEF },
|
void (*setfn) (int tok, int neg, char *arg, struct wsclosure *wsc);
|
||||||
{ "cescapes", WRDSF_CESCAPES },
|
/* Setter function */
|
||||||
{ "default", WRDSF_DEFFLAGS },
|
|
||||||
{ "env_kv", WRDSF_ENV_KV },
|
|
||||||
{ "incremental", WRDSF_INCREMENTAL },
|
|
||||||
{ "pathexpand", WRDSF_PATHEXPAND },
|
|
||||||
{ NULL, 0 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kwd opt_keytab[] = {
|
/* Index of the next argument in the argv */
|
||||||
{ "nullglob", WRDSO_NULLGLOB },
|
static int wsoptind = -1;
|
||||||
{ "failglob", WRDSO_FAILGLOB },
|
|
||||||
{ "dotglob", WRDSO_DOTGLOB },
|
|
||||||
{ "bskeep_words", WRDSO_BSKEEP_WORD },
|
|
||||||
{ "bskeep_quote", WRDSO_BSKEEP_QUOTE },
|
|
||||||
{ "bskeep", WRDSO_BSKEEP_WORD|WRDSO_BSKEEP_QUOTE },
|
|
||||||
{ "novarsplit", WRDSO_NOVARSPLIT },
|
|
||||||
{ "nocmdsplit", WRDSO_NOCMDSPLIT },
|
|
||||||
{ NULL, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct kwd string_keytab[] = {
|
|
||||||
{ "delim", WRDSF_DELIM },
|
|
||||||
{ "comment", WRDSF_COMMENT },
|
|
||||||
{ "escape", WRDSF_ESCAPE },
|
|
||||||
{ NULL, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/* Parse next argument from the command line. Return EOF on end of arguments
|
||||||
|
or when the "--" argument is seen. */
|
||||||
static int
|
static int
|
||||||
kwxlat (struct kwd *kwp, const char *str, int *res)
|
getwsopt (int argc, char **argv, struct wsopt *wso, struct wsclosure *wsc)
|
||||||
{
|
{
|
||||||
for (; kwp->name; kwp++)
|
int negate = 0;
|
||||||
if (strcmp (kwp->name, str) == 0)
|
char *opt;
|
||||||
{
|
|
||||||
*res = kwp->tok;
|
if (wsoptind == -1)
|
||||||
return 0;
|
wsoptind = 1;
|
||||||
}
|
if (wsoptind == argc)
|
||||||
return -1;
|
return EOF;
|
||||||
|
|
||||||
|
opt = argv[wsoptind++];
|
||||||
|
if (strcmp (opt, "--") == 0)
|
||||||
|
return EOF;
|
||||||
|
if (*opt != '-')
|
||||||
|
{
|
||||||
|
if (strchr (opt, '='))
|
||||||
|
{
|
||||||
|
assert (wsc->fenvidx < wsc->fenvmax - 1);
|
||||||
|
wsc->fenvbase[wsc->fenvidx++] = opt;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
wsoptind--;
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
opt++; /* skip past initial dash */
|
||||||
|
if (strncmp (opt, "no-", 3) == 0)
|
||||||
|
{
|
||||||
|
negate = 1;
|
||||||
|
opt += 3;
|
||||||
|
}
|
||||||
|
else if (strncmp (opt, "no", 2) == 0)
|
||||||
|
{
|
||||||
|
negate = 1;
|
||||||
|
opt += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; wso->name; wso++)
|
||||||
|
{
|
||||||
|
if (wso->arg == ws_boolean && wso->name[0] == 'n' && wso->name[1] == 'o'
|
||||||
|
&& strcmp (wso->name + 2, opt) == 0)
|
||||||
|
{
|
||||||
|
negate ^= 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (strcmp (wso->name, opt) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wso->name)
|
||||||
|
{
|
||||||
|
char *arg;
|
||||||
|
if (wso->arg == ws_multiple_arguments)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (wsoptind == argc)
|
||||||
|
break;
|
||||||
|
arg = argv[wsoptind++];
|
||||||
|
if (strcmp (arg, "--") == 0)
|
||||||
|
break;
|
||||||
|
wso->setfn (wso->tok, negate, arg, wsc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (wso->arg == ws_required_argument)
|
||||||
|
{
|
||||||
|
if (wsoptind == argc)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s: missing arguments for -%s\n",
|
||||||
|
progname, opt);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
arg = argv[wsoptind++];
|
||||||
|
}
|
||||||
|
wso->setfn (wso->tok, negate, arg, wsc);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf (stderr, "%s: unrecognized option: -%s\n",
|
||||||
|
progname, opt);
|
||||||
|
fprintf (stderr, "%s: try %s -help for more detail\n",
|
||||||
|
progname, progname);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setter functions for various options */
|
||||||
|
|
||||||
|
static void
|
||||||
|
setfn_flag (int flag, int neg, char *arg, struct wsclosure *wsc)
|
||||||
|
{
|
||||||
|
if (neg)
|
||||||
|
wsc->wsflags &= ~flag;
|
||||||
|
else
|
||||||
|
wsc->wsflags |= flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
help ()
|
setfn_option (int flag, int neg, char *arg, struct wsclosure *wsc)
|
||||||
|
{
|
||||||
|
wsc->wsflags |= WRDSF_OPTIONS;
|
||||||
|
if (neg)
|
||||||
|
wsc->ws.ws_options &= ~flag;
|
||||||
|
else
|
||||||
|
wsc->ws.ws_options |= flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setfn_delim (int flag, int neg, char *arg, struct wsclosure *wsc)
|
||||||
|
{
|
||||||
|
wsc->wsflags |= flag;
|
||||||
|
wsc->ws.ws_delim = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setfn_comment (int flag, int neg, char *arg, struct wsclosure *wsc)
|
||||||
|
{
|
||||||
|
wsc->wsflags |= flag;
|
||||||
|
wsc->ws.ws_comment = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_escape_string (wordsplit_t *ws, int *wsflags, int q, const char *str)
|
||||||
|
{
|
||||||
|
if (*str == ':')
|
||||||
|
{
|
||||||
|
while (*++str != ':')
|
||||||
|
{
|
||||||
|
int f;
|
||||||
|
switch (*str)
|
||||||
|
{
|
||||||
|
case '+':
|
||||||
|
f = WRDSO_BSKEEP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '0':
|
||||||
|
f = WRDSO_OESC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
f = WRDSO_XESC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf (stderr, "%s: invalid escape flag near %s\n",
|
||||||
|
progname, str);
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
WRDSO_ESC_SET (ws, q, f);
|
||||||
|
}
|
||||||
|
*wsflags |= WRDSF_OPTIONS;
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
ws->ws_escape[q] = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setfn_escape (int flag, int neg, char *arg, struct wsclosure *wsc)
|
||||||
|
{
|
||||||
|
wsc->wsflags |= flag;
|
||||||
|
set_escape_string (&wsc->ws, &wsc->wsflags, 0, arg);
|
||||||
|
set_escape_string (&wsc->ws, &wsc->wsflags, 1, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setfn_escape_qw (char *arg, int quote, struct wsclosure *wsc)
|
||||||
|
{
|
||||||
|
if (!(wsc->wsflags & WRDSF_ESCAPE))
|
||||||
|
{
|
||||||
|
wsc->wsflags |= WRDSF_ESCAPE;
|
||||||
|
wsc->ws.ws_escape[!quote] = NULL;
|
||||||
|
}
|
||||||
|
set_escape_string (&wsc->ws, &wsc->wsflags, quote, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setfn_escape_word (int flag, int neg, char *arg, struct wsclosure *wsc)
|
||||||
|
{
|
||||||
|
setfn_escape_qw (arg, 0, wsc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setfn_escape_quote (int flag, int neg, char *arg, struct wsclosure *wsc)
|
||||||
|
{
|
||||||
|
setfn_escape_qw (arg, 1, wsc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setfn_maxwords (int flag, int neg, char *arg, struct wsclosure *wsc)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
wsc->wsflags |= WRDSF_OPTIONS;
|
||||||
|
wsc->ws.ws_options |= WRDSO_MAXWORDS;
|
||||||
|
|
||||||
|
wsc->ws.ws_maxwords = strtoul (arg, &p, 10);
|
||||||
|
if (*p)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s: invalid number: %s\n", progname, arg);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setfn_global (int flag, int neg, char *arg, struct wsclosure *wsc)
|
||||||
|
{
|
||||||
|
if (neg)
|
||||||
|
wsc->options &= ~flag;
|
||||||
|
else
|
||||||
|
wsc->options |= flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setfn_env (int flag, int neg, char *arg, struct wsclosure *wsc)
|
||||||
|
{
|
||||||
|
if (strcmp (arg, "none") == 0)
|
||||||
|
wsc->env_type = env_none;
|
||||||
|
else if (strcmp (arg, "null") == 0)
|
||||||
|
wsc->env_type = env_null;
|
||||||
|
else if (strcmp (arg, "sys") == 0)
|
||||||
|
wsc->env_type = env_sys;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s: environment flag: %s\n", progname, arg);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setfn_dooffs (int flag, int neg, char *arg, struct wsclosure *wsc)
|
||||||
|
{
|
||||||
|
if (!(wsc->wsflags & flag))
|
||||||
|
{
|
||||||
|
wsc->wsflags |= flag;
|
||||||
|
wsc->offarg = wsoptind - 1;
|
||||||
|
wsc->ws.ws_offs = 0;
|
||||||
|
}
|
||||||
|
wsc->ws.ws_offs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setfn_append (int flag, int neg, char *arg, struct wsclosure *wsc)
|
||||||
|
{
|
||||||
|
if (wsc->append_count == 0)
|
||||||
|
wsc->append_start = wsoptind - 1;
|
||||||
|
wsc->append_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void help (void);
|
||||||
|
|
||||||
|
static void
|
||||||
|
setfn_help (int flag, int neg, char *arg, struct wsclosure *wsc)
|
||||||
|
{
|
||||||
|
help ();
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Available options: */
|
||||||
|
struct wsopt opttab[] = {
|
||||||
|
/* Global options */
|
||||||
|
{ "trimnl", TRIMNL_OPTION, ws_boolean, setfn_global },
|
||||||
|
{ "plaintext", PLAINTEXT_OPTION, ws_boolean, setfn_global },
|
||||||
|
{ "env", 0, ws_required_argument, setfn_env },
|
||||||
|
|
||||||
|
/* Wordsplit flags */
|
||||||
|
{ "append", WRDSF_APPEND, ws_boolean, setfn_flag },
|
||||||
|
/*{ "reuse", WRDSF_REUSE, ws_boolean, setfn_flag },*/
|
||||||
|
{ "undef", WRDSF_UNDEF, ws_boolean, setfn_flag },
|
||||||
|
{ "novar", WRDSF_NOVAR, ws_boolean, setfn_flag },
|
||||||
|
{ "nocmd", WRDSF_NOCMD, ws_boolean, setfn_flag },
|
||||||
|
{ "ws", WRDSF_WS, ws_boolean, setfn_flag },
|
||||||
|
{ "quote", WRDSF_QUOTE, ws_boolean, setfn_flag },
|
||||||
|
{ "squote", WRDSF_SQUOTE, ws_boolean, setfn_flag },
|
||||||
|
{ "dquote", WRDSF_DQUOTE, ws_boolean, setfn_flag },
|
||||||
|
{ "squeeze_delims", WRDSF_SQUEEZE_DELIMS, ws_boolean, setfn_flag },
|
||||||
|
{ "return_delims", WRDSF_RETURN_DELIMS, ws_boolean, setfn_flag },
|
||||||
|
{ "sed", WRDSF_SED_EXPR, ws_boolean, setfn_flag },
|
||||||
|
{ "debug", WRDSF_SHOWDBG, ws_boolean, setfn_flag },
|
||||||
|
{ "nosplit", WRDSF_NOSPLIT, ws_boolean, setfn_flag },
|
||||||
|
{ "keepundef", WRDSF_KEEPUNDEF, ws_boolean, setfn_flag },
|
||||||
|
{ "warnundef", WRDSF_WARNUNDEF, ws_boolean, setfn_flag },
|
||||||
|
{ "cescapes", WRDSF_CESCAPES, ws_boolean, setfn_flag },
|
||||||
|
{ "default", WRDSF_DEFFLAGS, ws_boolean, setfn_flag },
|
||||||
|
{ "env_kv", WRDSF_ENV_KV, ws_boolean, setfn_flag },
|
||||||
|
{ "incremental", WRDSF_INCREMENTAL, ws_boolean, setfn_flag },
|
||||||
|
{ "pathexpand", WRDSF_PATHEXPAND, ws_boolean, setfn_flag },
|
||||||
|
{ "default", WRDSF_DEFFLAGS, ws_boolean, setfn_flag },
|
||||||
|
/* Wordsplit options */
|
||||||
|
{ "nullglob", WRDSO_NULLGLOB, ws_boolean, setfn_option },
|
||||||
|
{ "failglob", WRDSO_FAILGLOB, ws_boolean, setfn_option },
|
||||||
|
{ "dotglob", WRDSO_DOTGLOB, ws_boolean, setfn_option },
|
||||||
|
{ "bskeep_words", WRDSO_BSKEEP_WORD, ws_boolean, setfn_option },
|
||||||
|
{ "bskeep_quote", WRDSO_BSKEEP_QUOTE, ws_boolean, setfn_option },
|
||||||
|
{ "bskeep", WRDSO_BSKEEP_WORD|WRDSO_BSKEEP_QUOTE,
|
||||||
|
ws_boolean, setfn_option },
|
||||||
|
{ "novarsplit", WRDSO_NOVARSPLIT, ws_boolean, setfn_option },
|
||||||
|
{ "nocmdsplit", WRDSO_NOCMDSPLIT, ws_boolean, setfn_option },
|
||||||
|
{ "maxwords", WRDSO_MAXWORDS, ws_required_argument, setfn_maxwords },
|
||||||
|
/* String options */
|
||||||
|
{ "delim", WRDSF_DELIM, ws_required_argument, setfn_delim },
|
||||||
|
{ "comment", WRDSF_COMMENT,ws_required_argument, setfn_comment },
|
||||||
|
{ "escape", WRDSF_ESCAPE, ws_required_argument, setfn_escape },
|
||||||
|
{ "escape-word", WRDSF_ESCAPE, ws_required_argument, setfn_escape_word },
|
||||||
|
{ "escape-quote", WRDSF_ESCAPE, ws_required_argument, setfn_escape_quote },
|
||||||
|
|
||||||
|
{ "dooffs", WRDSF_DOOFFS, ws_multiple_arguments, setfn_dooffs },
|
||||||
|
{ "append-args", 0, ws_multiple_arguments, setfn_append },
|
||||||
|
|
||||||
|
{ "help", 0, ws_no_argument, setfn_help },
|
||||||
|
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
help (void)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
printf ("usage: %s [options] [VAR=VALUE...] [-- EXTRA...]\n", progname);
|
printf ("usage: %s [options] [VAR=VALUE...] [-- EXTRA...]\n", progname);
|
||||||
printf ("options are:\n");
|
printf ("options are:\n");
|
||||||
printf (" [-]trimnl\n");
|
for (i = 0; opttab[i].name; i++)
|
||||||
printf (" [-]plaintext\n");
|
|
||||||
printf (" -env\n");
|
|
||||||
printf (" env sys|none|null\n");
|
|
||||||
putchar ('\n');
|
|
||||||
for (i = 0; bool_keytab[i].name; i++)
|
|
||||||
printf (" [-]%s\n", bool_keytab[i].name);
|
|
||||||
putchar ('\n');
|
|
||||||
for (i = 0; string_keytab[i].name; i++)
|
|
||||||
{
|
{
|
||||||
printf (" -%s\n", string_keytab[i].name);
|
printf (" -");
|
||||||
printf (" %s ARG\n", string_keytab[i].name);
|
if (opttab[i].arg == ws_boolean)
|
||||||
}
|
printf ("[no]");
|
||||||
printf (" escape-word ARG\n");
|
if (strncmp (opttab[i].name, "no", 2) == 0)
|
||||||
printf (" escape-quote ARG\n");
|
printf ("%s", opttab[i].name + 2);
|
||||||
putchar ('\n');
|
else
|
||||||
for (i = 0; opt_keytab[i].name; i++)
|
printf ("%s", opttab[i].name);
|
||||||
{
|
switch (opttab[i].arg)
|
||||||
printf (" [-]%s\n", opt_keytab[i].name);
|
{
|
||||||
|
case ws_no_argument:
|
||||||
|
case ws_boolean:
|
||||||
|
break;
|
||||||
|
case ws_required_argument:
|
||||||
|
printf(" ARG");
|
||||||
|
break;
|
||||||
|
case ws_multiple_arguments:
|
||||||
|
printf(" ARGS... --");
|
||||||
|
}
|
||||||
|
putchar ('\n');
|
||||||
}
|
}
|
||||||
putchar ('\n');
|
putchar ('\n');
|
||||||
printf (" -dooffs\n");
|
|
||||||
printf (" dooffs COUNT ARGS...\n");
|
|
||||||
exit (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -299,326 +608,71 @@ wsp_runcmd (char **ret, const char *str, size_t len, char **argv, void *closure)
|
||||||
return WRDSE_USERERR;
|
return WRDSE_USERERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum env_type
|
|
||||||
{
|
|
||||||
env_none,
|
|
||||||
env_null,
|
|
||||||
env_sys
|
|
||||||
};
|
|
||||||
|
|
||||||
struct kwd env_keytab[] = {
|
|
||||||
{ "none", env_none },
|
|
||||||
{ "null", env_null },
|
|
||||||
{ "sys", env_sys },
|
|
||||||
{ NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_escape_string (wordsplit_t *ws, int *wsflags, int q, const char *str)
|
|
||||||
{
|
|
||||||
if (*str == ':')
|
|
||||||
{
|
|
||||||
while (*++str != ':')
|
|
||||||
{
|
|
||||||
int f;
|
|
||||||
switch (*str)
|
|
||||||
{
|
|
||||||
case '+':
|
|
||||||
f = WRDSO_BSKEEP;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '0':
|
|
||||||
f = WRDSO_OESC;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'x':
|
|
||||||
f = WRDSO_XESC;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
fprintf (stderr, "%s: invalid escape flag near %s\n",
|
|
||||||
progname, str);
|
|
||||||
abort ();
|
|
||||||
}
|
|
||||||
WRDSO_ESC_SET (ws, q, f);
|
|
||||||
}
|
|
||||||
*wsflags |= WRDSF_OPTIONS;
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
ws->ws_escape[q] = str;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
struct wsclosure wsc;
|
||||||
|
char *fenvbase[128];
|
||||||
char buf[1024], *ptr, *saved_ptr;
|
char buf[1024], *ptr, *saved_ptr;
|
||||||
int i, offarg = 0;
|
int next_call = 0;
|
||||||
int trimnl_option = 0;
|
|
||||||
int plaintext_option = 0;
|
wsc.options = 0;
|
||||||
int wsflags = (WRDSF_DEFFLAGS & ~WRDSF_NOVAR) |
|
wsc.wsflags = 0;
|
||||||
|
wsc.env_type = env_sys;
|
||||||
|
wsc.offarg = 0;
|
||||||
|
wsc.fenvbase = fenvbase;
|
||||||
|
wsc.fenvmax = sizeof (fenvbase) / sizeof (fenvbase[0]);
|
||||||
|
wsc.fenvidx = 0;
|
||||||
|
wsc.ws.ws_options = 0;
|
||||||
|
wsc.wsflags = (WRDSF_DEFFLAGS & ~WRDSF_NOVAR) |
|
||||||
WRDSF_ENOMEMABRT |
|
WRDSF_ENOMEMABRT |
|
||||||
WRDSF_SHOWERR;
|
WRDSF_SHOWERR;
|
||||||
wordsplit_t ws;
|
wsc.append_count = 0;
|
||||||
int next_call = 0;
|
|
||||||
char *fenvbase[128];
|
|
||||||
size_t fenvidx = 0;
|
|
||||||
size_t fenvmax = sizeof (fenvbase) / sizeof (fenvbase[0]);
|
|
||||||
int use_env = env_sys;
|
|
||||||
int appendc = 0;
|
|
||||||
char **appendv = NULL;
|
|
||||||
|
|
||||||
progname = argv[0];
|
progname = argv[0];
|
||||||
|
while (getwsopt (argc, argv, opttab, &wsc) != EOF)
|
||||||
|
;
|
||||||
|
|
||||||
ws.ws_options = 0;
|
if (wsc.fenvidx > 0)
|
||||||
for (i = 1; i < argc; i++)
|
|
||||||
{
|
{
|
||||||
char *opt = argv[i];
|
wsc.fenvbase[wsc.fenvidx] = NULL;
|
||||||
int negate;
|
wsc.wsflags |= WRDSF_GETVAR | WRDSF_CLOSURE;
|
||||||
int flag;
|
wsc.ws.ws_getvar = wsp_getvar;
|
||||||
|
wsc.ws.ws_closure = fenvbase;
|
||||||
if (opt[0] == '-')
|
|
||||||
{
|
|
||||||
if (opt[1] == '-' && opt[2] == 0)
|
|
||||||
{
|
|
||||||
appendc = argc - i - 1;
|
|
||||||
appendv = argv + i + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
negate = 1;
|
|
||||||
opt++;
|
|
||||||
}
|
|
||||||
else if (opt[0] == '+')
|
|
||||||
{
|
|
||||||
negate = 0;
|
|
||||||
opt++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
negate = 0;
|
|
||||||
|
|
||||||
if (strcmp (opt, "h") == 0 ||
|
|
||||||
strcmp (opt, "help") == 0 ||
|
|
||||||
strcmp (opt, "-help") == 0)
|
|
||||||
{
|
|
||||||
help ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp (opt, "trimnl") == 0)
|
|
||||||
{
|
|
||||||
trimnl_option = !negate;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp (opt, "plaintext") == 0)
|
|
||||||
{
|
|
||||||
plaintext_option = !negate;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp (opt, "env") == 0)
|
|
||||||
{
|
|
||||||
if (negate)
|
|
||||||
use_env = env_none;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
if (i == argc)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "%s: missing argument for env\n",
|
|
||||||
progname);
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kwxlat (env_keytab, argv[i], &use_env))
|
|
||||||
{
|
|
||||||
fprintf (stderr, "%s: invalid argument for env\n",
|
|
||||||
progname);
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kwxlat (bool_keytab, opt, &flag) == 0)
|
|
||||||
{
|
|
||||||
if (negate)
|
|
||||||
wsflags &= ~flag;
|
|
||||||
else
|
|
||||||
wsflags |= flag;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kwxlat (string_keytab, opt, &flag) == 0)
|
|
||||||
{
|
|
||||||
if (negate)
|
|
||||||
wsflags &= ~flag;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
if (i == argc)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "%s: missing argument for %s\n",
|
|
||||||
progname, opt);
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (flag)
|
|
||||||
{
|
|
||||||
case WRDSF_DELIM:
|
|
||||||
ws.ws_delim = argv[i];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WRDSF_COMMENT:
|
|
||||||
ws.ws_comment = argv[i];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WRDSF_ESCAPE:
|
|
||||||
set_escape_string (&ws, &wsflags, 0, argv[i]);
|
|
||||||
set_escape_string (&ws, &wsflags, 1, argv[i]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
wsflags |= flag;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp (opt, "escape-word") == 0
|
|
||||||
|| strcmp (opt, "escape-quote") == 0)
|
|
||||||
{
|
|
||||||
int q = opt[7] == 'q';
|
|
||||||
|
|
||||||
i++;
|
|
||||||
if (i == argc)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "%s: missing argument for %s\n",
|
|
||||||
progname, opt);
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
if (!(wsflags & WRDSF_ESCAPE))
|
|
||||||
{
|
|
||||||
wsflags |= WRDSF_ESCAPE;
|
|
||||||
ws.ws_escape[!q] = NULL;
|
|
||||||
}
|
|
||||||
set_escape_string (&ws, &wsflags, q, argv[i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp (opt, "dooffs") == 0)
|
|
||||||
{
|
|
||||||
if (negate)
|
|
||||||
wsflags &= ~WRDSF_DOOFFS;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if (i == argc)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "%s: missing arguments for %s\n",
|
|
||||||
progname, opt);
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
ws.ws_offs = strtoul (argv[i], &p, 10);
|
|
||||||
if (*p)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "%s: invalid number: %s\n",
|
|
||||||
progname, argv[i]);
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
if (i + ws.ws_offs > argc)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "%s: not enough arguments for %s\n",
|
|
||||||
progname, opt);
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
offarg = i;
|
|
||||||
i += ws.ws_offs - 1;
|
|
||||||
wsflags |= WRDSF_DOOFFS;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kwxlat (opt_keytab, opt, &flag) == 0)
|
|
||||||
{
|
|
||||||
wsflags |= WRDSF_OPTIONS;
|
|
||||||
if (negate)
|
|
||||||
ws.ws_options &= ~flag;
|
|
||||||
else
|
|
||||||
ws.ws_options |= flag;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp (opt, "maxwords") == 0)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
wsflags |= WRDSF_OPTIONS;
|
|
||||||
ws.ws_options |= WRDSO_MAXWORDS;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if (i == argc)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "%s: missing arguments for %s\n",
|
|
||||||
progname, opt);
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
ws.ws_maxwords = strtoul (argv[i], &p, 10);
|
|
||||||
if (*p)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "%s: invalid number: %s\n",
|
|
||||||
progname, argv[i]);
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strchr (opt, '='))
|
|
||||||
{
|
|
||||||
assert (fenvidx < fenvmax - 1);
|
|
||||||
fenvbase[fenvidx++] = opt;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf (stderr, "%s: unrecognized argument: %s\n",
|
|
||||||
progname, opt);
|
|
||||||
exit (1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fenvidx)
|
if (wsoptind < argc)
|
||||||
{
|
{
|
||||||
fenvbase[fenvidx] = NULL;
|
wsc.ws.ws_paramc = argc - wsoptind;
|
||||||
wsflags |= WRDSF_GETVAR | WRDSF_CLOSURE;
|
wsc.ws.ws_paramv = (char const **) (argv + wsoptind);
|
||||||
ws.ws_getvar = wsp_getvar;
|
wsc.ws.ws_options |= WRDSO_PARAMV|WRDSO_PARAM_NEGIDX;
|
||||||
ws.ws_closure = fenvbase;
|
wsc.wsflags |= WRDSF_OPTIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (use_env)
|
switch (wsc.env_type)
|
||||||
{
|
{
|
||||||
case env_null:
|
case env_null:
|
||||||
wsflags |= WRDSF_ENV;
|
wsc.wsflags |= WRDSF_ENV;
|
||||||
ws.ws_env = NULL;
|
wsc.ws.ws_env = NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case env_none:
|
case env_none:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case env_sys:
|
case env_sys:
|
||||||
wsflags |= WRDSF_ENV;
|
wsc.wsflags |= WRDSF_ENV;
|
||||||
if (wsflags & WRDSF_ENV_KV)
|
if (wsc.wsflags & WRDSF_ENV_KV)
|
||||||
ws.ws_env = (const char **) make_env_kv ();
|
wsc.ws.ws_env = (const char **) make_env_kv ();
|
||||||
else
|
else
|
||||||
ws.ws_env = (const char **) environ;
|
wsc.ws.ws_env = (const char **) environ;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(wsflags & WRDSF_NOCMD))
|
if (!(wsc.wsflags & WRDSF_NOCMD))
|
||||||
ws.ws_command = wsp_runcmd;
|
wsc.ws.ws_command = wsp_runcmd;
|
||||||
|
|
||||||
if (wsflags & WRDSF_INCREMENTAL)
|
if (wsc.wsflags & WRDSF_INCREMENTAL)
|
||||||
trimnl_option = 1;
|
wsc.options |= TRIMNL_OPTION;
|
||||||
|
|
||||||
next_call = 0;
|
next_call = 0;
|
||||||
while ((ptr = fgets (buf, sizeof (buf), stdin)))
|
while ((ptr = fgets (buf, sizeof (buf), stdin)))
|
||||||
|
@ -626,14 +680,14 @@ main (int argc, char **argv)
|
||||||
int rc;
|
int rc;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if (trimnl_option)
|
if (wsc.options & TRIMNL_OPTION)
|
||||||
{
|
{
|
||||||
size_t len = strlen (ptr);
|
size_t len = strlen (ptr);
|
||||||
if (len && ptr[len-1] == '\n')
|
if (len && ptr[len-1] == '\n')
|
||||||
ptr[len-1] = 0;
|
ptr[len-1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wsflags & WRDSF_INCREMENTAL)
|
if (wsc.wsflags & WRDSF_INCREMENTAL)
|
||||||
{
|
{
|
||||||
if (next_call)
|
if (next_call)
|
||||||
{
|
{
|
||||||
|
@ -651,50 +705,52 @@ main (int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = wordsplit (ptr, &ws, wsflags);
|
rc = wordsplit (ptr, &wsc.ws, wsc.wsflags);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
if (!(wsflags & WRDSF_SHOWERR))
|
if (!(wsc.wsflags & WRDSF_SHOWERR))
|
||||||
wordsplit_perror (&ws);
|
wordsplit_perror (&wsc.ws);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offarg)
|
if (wsc.offarg)
|
||||||
{
|
{
|
||||||
for (i = 0; i < ws.ws_offs; i++)
|
size_t i;
|
||||||
ws.ws_wordv[i] = argv[offarg + i];
|
for (i = 0; i < wsc.ws.ws_offs; i++)
|
||||||
offarg = 0;
|
wsc.ws.ws_wordv[i] = argv[wsc.offarg + i];
|
||||||
|
wsc.offarg = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appendc)
|
if (wsc.append_count)
|
||||||
{
|
{
|
||||||
rc = wordsplit_append (&ws, appendc, appendv);
|
rc = wordsplit_append (&wsc.ws, wsc.append_count,
|
||||||
|
argv + wsc.append_start);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
if (!(wsflags & WRDSF_SHOWERR))
|
if (!(wsc.wsflags & WRDSF_SHOWERR))
|
||||||
wordsplit_perror (&ws);
|
wordsplit_perror (&wsc.ws);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wsflags |= WRDSF_REUSE | (ws.ws_flags & WRDSF_ENV);
|
wsc.wsflags |= WRDSF_REUSE;
|
||||||
printf ("NF: %lu", (unsigned long) ws.ws_wordc);
|
printf ("NF: %lu", (unsigned long) wsc.ws.ws_wordc);
|
||||||
if (wsflags & WRDSF_DOOFFS)
|
if (wsc.wsflags & WRDSF_DOOFFS)
|
||||||
printf (" (%lu)", (unsigned long) ws.ws_offs);
|
printf (" (%lu)", (unsigned long) wsc.ws.ws_offs);
|
||||||
putchar ('\n');
|
putchar ('\n');
|
||||||
for (i = 0; i < ws.ws_offs; i++)
|
for (i = 0; i < wsc.ws.ws_offs; i++)
|
||||||
{
|
{
|
||||||
printf ("(%lu): ", (unsigned long) i);
|
printf ("(%lu): ", (unsigned long) i);
|
||||||
print_qword (ws.ws_wordv[i], plaintext_option);
|
print_qword (wsc.ws.ws_wordv[i], wsc.options & PLAINTEXT_OPTION);
|
||||||
putchar ('\n');
|
putchar ('\n');
|
||||||
}
|
}
|
||||||
for (; i < ws.ws_offs + ws.ws_wordc; i++)
|
for (; i < wsc.ws.ws_offs + wsc.ws.ws_wordc; i++)
|
||||||
{
|
{
|
||||||
printf ("%lu: ", (unsigned long) i);
|
printf ("%lu: ", (unsigned long) i);
|
||||||
print_qword (ws.ws_wordv[i], plaintext_option);
|
print_qword (wsc.ws.ws_wordv[i], wsc.options & PLAINTEXT_OPTION);
|
||||||
putchar ('\n');
|
putchar ('\n');
|
||||||
}
|
}
|
||||||
printf ("TOTAL: %lu\n", (unsigned long) ws.ws_wordi);
|
printf ("TOTAL: %lu\n", (unsigned long) wsc.ws.ws_wordi);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue