summaryrefslogtreecommitdiffabout
path: root/src/wordsplit.c
Side-by-side diff
Diffstat (limited to 'src/wordsplit.c') (more/less context) (ignore whitespace changes)
-rw-r--r--src/wordsplit.c201
1 files changed, 178 insertions, 23 deletions
diff --git a/src/wordsplit.c b/src/wordsplit.c
index 521a1eb..6a33636 100644
--- a/src/wordsplit.c
+++ b/src/wordsplit.c
@@ -1,3 +1,3 @@
/* wordsplit - a word splitter
- Copyright (C) 2009-2018 Sergey Poznyakoff
+ Copyright (C) 2009-2019 Sergey Poznyakoff
@@ -29,2 +29,3 @@
#include <glob.h>
+#include <limits.h>
@@ -58,2 +59,5 @@
+#define to_num(c) \
+ (ISDIGIT(c) ? c - '0' : (ISXDIGIT(c) ? toupper(c) - 'A' + 10 : 255 ))
+
#define ALLOC_INIT 128
@@ -286,2 +290,10 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
}
+
+ 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;
@@ -1038,3 +1050,3 @@ static int
wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
- char *value)
+ char const *value)
{
@@ -1073,3 +1085,3 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
free (newenv[j-1]);
- free (newenv[j-1]);
+ free (newenv);
return _wsplt_nomem (wsp);
@@ -1144,2 +1156,66 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
+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
@@ -1179,2 +1255,4 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
struct wordsplit ws;
+ int is_param = 0;
+ long param_idx = 0;
@@ -1187,3 +1265,3 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
}
- else if (ISDIGIT (str[0]))
+ else if ((wsp->ws_options & WRDSO_PARAMV) && ISDIGIT (str[0]))
{
@@ -1191,4 +1269,27 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
*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))
{
@@ -1196,3 +1297,3 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
len--;
- for (i = 1; i < len; i++)
+ for (i = str[0] == '-' ? 1 : 0; i < len; i++)
{
@@ -1224,5 +1325,12 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
}
- 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
{
@@ -1236,2 +1344,6 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
}
+
+ if (is_param && str[0] == '-')
+ param_idx = wsp->ws_paramc - param_idx;
+
if (i == len)
@@ -1256,10 +1368,11 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
{
- rc = wordsplit_find_env (wsp, str, i, &vptr);
- if (rc == WRDSE_OK)
+ if (is_param)
{
- if (vptr)
+ if (param_idx >= 0 && param_idx < wsp->ws_paramc)
{
- value = strdup (vptr);
+ value = strdup (wsp->ws_paramv[param_idx]);
if (!value)
rc = WRDSE_NOSPACE;
+ else
+ rc = WRDSE_OK;
}
@@ -1268,7 +1381,22 @@ 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;
-
+ {
+ 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
@@ -1323,3 +1451,13 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
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;
+ }
}
@@ -1460,3 +1598,3 @@ begin_var_p (int c)
{
- return c == '{' || ISVARBEG (c) || ISDIGIT (c);
+ return c == '{' || c == '#' || ISVARBEG (c) || ISDIGIT (c);
}
@@ -2108,5 +2246,2 @@ scan_word (struct wordsplit *wsp, size_t start, int consume_all)
-#define to_num(c) \
- (ISDIGIT(c) ? c - '0' : (ISXDIGIT(c) ? toupper(c) - 'A' + 10 : 255 ))
-
static int
@@ -2500,3 +2635,3 @@ wordsplit_free_envbuf (struct wordsplit *ws)
{
- if (ws->ws_flags & WRDSF_NOCMD)
+ if (!(ws->ws_flags & WRDSF_ENV))
return;
@@ -2515,2 +2650,19 @@ 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
wordsplit_clearerr (struct wordsplit *ws)
@@ -2531,2 +2683,3 @@ wordsplit_free (struct wordsplit *ws)
wordsplit_free_envbuf (ws);
+ wordsplit_free_parambuf (ws);
}
@@ -2559,3 +2712,5 @@ const char *_wordsplit_errstr[] = {
N_("unbalanced parenthesis"),
- N_("globbing error")
+ N_("globbing error"),
+ N_("user-defined error"),
+ N_("invalid parameter number in assignment")
};

Return to:

Send suggestions and report system problems to the System administrator.