diff options
-rw-r--r-- | include/wordsplit.h | 6 | ||||
-rw-r--r-- | src/wordsplit.c | 42 | ||||
-rw-r--r-- | tests/wordsplit.at | 2 |
3 files changed, 44 insertions, 6 deletions
diff --git a/include/wordsplit.h b/include/wordsplit.h index 2fac3c6..0d6eef3 100644 --- a/include/wordsplit.h +++ b/include/wordsplit.h @@ -107,20 +107,24 @@ struct wordsplit the command CMD (LEN bytes long). On input, ARGV contains CMD split out to words. See ws_getvar for a discussion of possible 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_endp; /* Points past the last processed byte in ws_input. */ int ws_errno; /* [Output] Error code, if an error occurred. */ char *ws_usererr; /* Points to textual description of the error, if ws_errno is WRDSE_USERERR. Must 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; /* Doubly-linked list of parsed out nodes. */ char ws_sep[2]; /* Temporary storage used during splitting */ int ws_lvl; /* Invocation nesting level. */ }; diff --git a/src/wordsplit.c b/src/wordsplit.c index af747b3..6dba914 100644 --- a/src/wordsplit.c +++ b/src/wordsplit.c @@ -104,12 +104,36 @@ _wsplt_nomem (struct wordsplit *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); @@ -304,12 +328,14 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len, 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 @@ -1572,13 +1598,13 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, } 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'"), @@ -1677,13 +1703,13 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, 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, @@ -2095,13 +2121,13 @@ wordsplit_pathexpand (struct wordsplit *wsp) 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; @@ -2751,18 +2777,23 @@ wordsplit_free_parambuf (struct wordsplit *ws) 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); @@ -2820,9 +2851,12 @@ wordsplit_perror (struct wordsplit *wsp) 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)); } } diff --git a/tests/wordsplit.at b/tests/wordsplit.at index 0a7d7db..7ecc016 100644 --- a/tests/wordsplit.at +++ b/tests/wordsplit.at @@ -235,13 +235,13 @@ TOTAL: 0 ], [unset FOO;]) TESTWSP([bail out on undefined variables],[],[-undef], [$FOO], [], -[undefined variable +[undefined variable: FOO ], [unset FOO;]) TESTWSP([disable variable expansion],[],[-novar], [$FOO], [NF: 1 |