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.
This commit is contained in:
Sergey Poznyakoff 2019-05-15 16:37:09 +03:00
parent 070813ec0e
commit e4bd61ae6b
3 changed files with 44 additions and 6 deletions

View file

@ -110,7 +110,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
ws_input. */ ws_input. */
@ -118,6 +118,10 @@ struct wordsplit
char *ws_usererr; /* Points to textual description of char *ws_usererr; /* Points to textual description of
the error, if ws_errno is WRDSE_USERERR. Must the error, if ws_errno is WRDSE_USERERR. Must
be allocated with malloc(3). */ be allocated with malloc(3). */
char *ws_errctx; /* Context in which the error occurred:
For WRDSE_UNDEF - name of the undefined variable,
For WRDSE_GLOBERR - pattern that caused error.
*/
struct wordsplit_node *ws_head, *ws_tail; struct wordsplit_node *ws_head, *ws_tail;
/* Doubly-linked list of parsed out nodes. */ /* Doubly-linked list of parsed out nodes. */
char ws_sep[2]; /* Temporary storage used during splitting */ char ws_sep[2]; /* Temporary storage used during splitting */

View file

@ -107,6 +107,30 @@ _wsplt_nomem (struct wordsplit *wsp)
return wsp->ws_errno; 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, static int wordsplit_run (const char *command, size_t length,
struct wordsplit *wsp, struct wordsplit *wsp,
int flags, int lvl); int flags, int lvl);
@ -307,6 +331,8 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
wordsplit_free_nodes (wsp); wordsplit_free_nodes (wsp);
wsp->ws_head = wsp->ws_tail = NULL; wsp->ws_head = wsp->ws_tail = NULL;
wsp->ws_errctx = NULL;
wordsplit_init0 (wsp); wordsplit_init0 (wsp);
return 0; return 0;
@ -1575,7 +1601,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
} }
else if (wsp->ws_flags & WRDSF_UNDEF) else if (wsp->ws_flags & WRDSF_UNDEF)
{ {
_wsplt_seterr (wsp, WRDSE_UNDEF); _wsplt_setctxerr (wsp, WRDSE_UNDEF, str, *pend - str + 1);
return 1; return 1;
} }
else else
@ -1680,7 +1706,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 memchr("{#@*", c, 4) != NULL || ISVARBEG (c) || ISDIGIT (c); return memchr ("{#@*", c, 4) != NULL || ISVARBEG (c) || ISDIGIT (c);
} }
static int static int
@ -2098,7 +2124,7 @@ wordsplit_pathexpand (struct wordsplit *wsp)
default: default:
free (pattern); free (pattern);
return _wsplt_seterr (wsp, WRDSE_GLOBERR); return _wsplt_setctxerr (wsp, WRDSE_GLOBERR, pattern, slen);
} }
prev = p; prev = p;
@ -2754,12 +2780,17 @@ wordsplit_clearerr (struct wordsplit *ws)
if (ws->ws_errno == WRDSE_USERERR) if (ws->ws_errno == WRDSE_USERERR)
free (ws->ws_usererr); free (ws->ws_usererr);
ws->ws_usererr = NULL; ws->ws_usererr = NULL;
free (ws->ws_errctx);
ws->ws_errctx = NULL;
ws->ws_errno = WRDSE_OK; ws->ws_errno = WRDSE_OK;
} }
void void
wordsplit_free (struct wordsplit *ws) wordsplit_free (struct wordsplit *ws)
{ {
wordsplit_clearerr (ws);
wordsplit_free_nodes (ws); wordsplit_free_nodes (ws);
wordsplit_free_words (ws); wordsplit_free_words (ws);
free (ws->ws_wordv); free (ws->ws_wordv);
@ -2823,6 +2854,9 @@ wordsplit_perror (struct wordsplit *wsp)
break; break;
default: 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));
} }
} }

View file

@ -238,7 +238,7 @@ TOTAL: 0
TESTWSP([bail out on undefined variables],[],[-undef], TESTWSP([bail out on undefined variables],[],[-undef],
[$FOO], [$FOO],
[], [],
[undefined variable [undefined variable: FOO
], ],
[unset FOO;]) [unset FOO;])