aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2019-05-15 16:37:09 +0300
committerSergey Poznyakoff <gray@gnu.org>2019-05-15 16:37:09 +0300
commit20899f652a904b510b2c7d3507b75d1399416485 (patch)
tree44f221b132d16f229fb991a03451d7039fb5f726 /src
parent7dbea4b03426d8a81dbc6563b96aa760e719f5a8 (diff)
downloadgrecs-20899f652a904b510b2c7d3507b75d1399416485.tar.gz
grecs-20899f652a904b510b2c7d3507b75d1399416485.tar.bz2
wordsplit: introduce error context
* include/wordsplit.h (wordsplit) <ws_errctx>: New field. * src/wordsplit.c (wordsplit_init): Initialize ws_errctx. (expvar,wordsplit_pathexpand): Save error context. (wordsplit_clearerr): Free error context. (wordsplit_perror): Use error context if available. * tests/wordsplit.at: Reflect changes.
Diffstat (limited to 'src')
-rw-r--r--src/wordsplit.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/src/wordsplit.c b/src/wordsplit.c
index af747b3..6dba914 100644
--- a/src/wordsplit.c
+++ b/src/wordsplit.c
@@ -98,24 +98,48 @@ _wsplt_nomem (struct wordsplit *wsp)
errno = ENOMEM;
wsp->ws_errno = WRDSE_NOSPACE;
if (wsp->ws_flags & WRDSF_ENOMEMABRT)
wsp->ws_alloc_die (wsp);
if (wsp->ws_flags & WRDSF_SHOWERR)
wordsplit_perror (wsp);
if (!(wsp->ws_flags & WRDSF_REUSE))
wordsplit_free (wsp);
wordsplit_free_nodes (wsp);
return wsp->ws_errno;
}
+static void
+_wsplt_store_errctx (struct wordsplit *wsp, char const *str, size_t len)
+{
+ free (wsp->ws_errctx);
+ wsp->ws_errctx = malloc (len + 1);
+ if (!wsp->ws_errctx)
+ {
+ wsp->ws_error ("%s",
+ _("memory exhausted while trying to store error subject"));
+ }
+ else
+ {
+ memcpy (wsp->ws_errctx, str, len);
+ wsp->ws_errctx[len] = 0;
+ }
+}
+
+static inline int
+_wsplt_setctxerr (struct wordsplit *wsp, int ec, char const *str, size_t len)
+{
+ _wsplt_store_errctx (wsp, str, len);
+ return _wsplt_seterr (wsp, ec);
+}
+
static int wordsplit_run (const char *command, size_t length,
struct wordsplit *wsp,
int flags, int lvl);
static int wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
int flags);
static int wordsplit_process_list (struct wordsplit *wsp, size_t start);
static int wordsplit_finish (struct wordsplit *wsp);
static int
_wsplt_subsplit (struct wordsplit *wsp, struct wordsplit *wss,
char const *str, int len,
@@ -298,24 +322,26 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
wsp->ws_paramc = 0;
}
wsp->ws_paramidx = wsp->ws_paramsiz = 0;
wsp->ws_parambuf = NULL;
wsp->ws_endp = 0;
wsp->ws_wordi = 0;
if (wsp->ws_flags & WRDSF_REUSE)
wordsplit_free_nodes (wsp);
wsp->ws_head = wsp->ws_tail = NULL;
+ wsp->ws_errctx = NULL;
+
wordsplit_init0 (wsp);
return 0;
}
static int
alloc_space (struct wordsplit *wsp, size_t count)
{
size_t offs = (wsp->ws_flags & WRDSF_DOOFFS) ? wsp->ws_offs : 0;
char **ptr;
size_t newalloc;
@@ -1566,25 +1592,25 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
(int) i, str, ws.ws_wordv[0]);
else
wsp->ws_error ("%.*s: %.*s",
(int) i, str, (int) size, defstr);
wordsplit_free (&ws);
}
}
value = NULL;
}
}
else if (wsp->ws_flags & WRDSF_UNDEF)
{
- _wsplt_seterr (wsp, WRDSE_UNDEF);
+ _wsplt_setctxerr (wsp, WRDSE_UNDEF, str, *pend - str + 1);
return 1;
}
else
{
if (wsp->ws_flags & WRDSF_WARNUNDEF)
wsp->ws_error (_("warning: undefined variable `%.*s'"),
(int) i, str);
if (wsp->ws_flags & WRDSF_KEEPUNDEF)
value = NULL;
else
{
value = strdup ("");
@@ -1671,25 +1697,25 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
if (wsnode_new (wsp, &newnode))
return 1;
wsnode_insert (wsp, newnode, *ptail, 0);
*ptail = newnode;
newnode->flags = _WSNF_NULL;
}
return 0;
}
static int
begin_var_p (int c)
{
- return memchr("{#@*", c, 4) != NULL || ISVARBEG (c) || ISDIGIT (c);
+ return memchr ("{#@*", c, 4) != NULL || ISVARBEG (c) || ISDIGIT (c);
}
static int
node_expand (struct wordsplit *wsp, struct wordsplit_node *node,
int (*beg_p) (int),
int (*ws_exp_fn) (struct wordsplit *wsp,
const char *str, size_t len,
struct wordsplit_node **ptail,
const char **pend,
int flg))
{
const char *str = wsnode_ptr (wsp, node);
@@ -2089,25 +2115,25 @@ wordsplit_pathexpand (struct wordsplit *wsp)
pattern);
free (pattern);
wsp->ws_usererr = strdup (buf);
if (!wsp->ws_usererr)
return _wsplt_nomem (wsp);
else
return _wsplt_seterr (wsp, WRDSE_USERERR);
}
continue;
default:
free (pattern);
- return _wsplt_seterr (wsp, WRDSE_GLOBERR);
+ return _wsplt_setctxerr (wsp, WRDSE_GLOBERR, pattern, slen);
}
prev = p;
for (i = 0; i < g.gl_pathc; i++)
{
struct wordsplit_node *newnode;
char *newstr;
if (wsnode_new (wsp, &newnode))
return 1;
newstr = strdup (g.gl_pathv[i]);
if (!newstr)
@@ -2745,30 +2771,35 @@ wordsplit_free_parambuf (struct wordsplit *ws)
free (ws->ws_parambuf);
ws->ws_paramidx = ws->ws_paramsiz = 0;
ws->ws_parambuf = NULL;
}
}
void
wordsplit_clearerr (struct wordsplit *ws)
{
if (ws->ws_errno == WRDSE_USERERR)
free (ws->ws_usererr);
ws->ws_usererr = NULL;
+
+ free (ws->ws_errctx);
+ ws->ws_errctx = NULL;
+
ws->ws_errno = WRDSE_OK;
}
void
wordsplit_free (struct wordsplit *ws)
{
+ wordsplit_clearerr (ws);
wordsplit_free_nodes (ws);
wordsplit_free_words (ws);
free (ws->ws_wordv);
ws->ws_wordv = NULL;
wordsplit_free_envbuf (ws);
wordsplit_free_parambuf (ws);
}
int
wordsplit_get_words (struct wordsplit *ws, size_t *wordc, char ***wordv)
{
char **p = realloc (ws->ws_wordv,
@@ -2814,15 +2845,18 @@ wordsplit_strerror (struct wordsplit *ws)
void
wordsplit_perror (struct wordsplit *wsp)
{
switch (wsp->ws_errno)
{
case WRDSE_QUOTE:
wsp->ws_error (_("missing closing %c (start near #%lu)"),
wsp->ws_input[wsp->ws_endp],
(unsigned long) wsp->ws_endp);
break;
default:
- wsp->ws_error ("%s", wordsplit_strerror (wsp));
+ if (wsp->ws_errctx)
+ wsp->ws_error ("%s: %s", wordsplit_strerror (wsp), wsp->ws_errctx);
+ else
+ wsp->ws_error ("%s", wordsplit_strerror (wsp));
}
}

Return to:

Send suggestions and report system problems to the System administrator.