diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-05-15 16:41:28 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-05-15 16:41:28 +0300 |
commit | 4c2792654a68b8680b6f4b8dc0e0d6ebc0daf770 (patch) | |
tree | 93fbf66778f9fcb0aad645127c97144d0dc3c549 | |
parent | cdcc7119e408ad143202a5e626804e042525f028 (diff) | |
download | rush-4c2792654a68b8680b6f4b8dc0e0d6ebc0daf770.tar.gz rush-4c2792654a68b8680b6f4b8dc0e0d6ebc0daf770.tar.bz2 |
Report names of undefined variables
* lib/wordsplit.c: Import from grecs 20899f65
* lib/wordsplit.h: Likewise.
* src/map.c (rush_ws_error): New function.
(rush_expand_string): Set ws.ws_error. Use error context when
reporting WRDSE_UNDEF.
* src/rush.c (main): Use reparse_cmdline.
* src/rush.h (rush_ws_error): New proto.
* tests/undef.at: Update.
-rw-r--r-- | lib/wordsplit.c | 48 | ||||
-rw-r--r-- | lib/wordsplit.h | 6 | ||||
-rw-r--r-- | src/map.c | 14 | ||||
-rw-r--r-- | src/rush.c | 16 | ||||
-rw-r--r-- | src/rush.h | 1 | ||||
-rw-r--r-- | tests/undef.at | 2 |
6 files changed, 67 insertions, 20 deletions
diff --git a/lib/wordsplit.c b/lib/wordsplit.c index 4e633fa..6dba914 100644 --- a/lib/wordsplit.c +++ b/lib/wordsplit.c @@ -107,6 +107,30 @@ _wsplt_nomem (struct wordsplit *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); @@ -307,6 +331,8 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len, wordsplit_free_nodes (wsp); wsp->ws_head = wsp->ws_tail = NULL; + wsp->ws_errctx = NULL; + wordsplit_init0 (wsp); return 0; @@ -837,7 +863,7 @@ wordsplit_finish (struct wordsplit *wsp) } else { - wsp->ws_error = WRDSE_EOF; + wsp->ws_errno = WRDSE_EOF; return WRDSE_EOF; } goto again; @@ -1163,7 +1189,7 @@ wsplt_assign_param (struct wordsplit *wsp, int param_idx, char *value) char *v; if (param_idx < 0) - return WRDSE_BADPARAM; + return _wsplt_seterr (wsp, WRDSE_BADPARAM); if (param_idx == wsp->ws_paramc) { char **parambuf; @@ -1210,7 +1236,7 @@ wsplt_assign_param (struct wordsplit *wsp, int param_idx, char *value) wsp->ws_paramc = param_idx + 1; } else if (param_idx > wsp->ws_paramc) - return WRDSE_BADPARAM; + return _wsplt_seterr (wsp, WRDSE_BADPARAM); v = strdup (value); if (!v) @@ -1575,7 +1601,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, } else if (wsp->ws_flags & WRDSF_UNDEF) { - _wsplt_seterr (wsp, WRDSE_UNDEF); + _wsplt_setctxerr (wsp, WRDSE_UNDEF, str, *pend - str + 1); return 1; } else @@ -1680,7 +1706,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, 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 @@ -2098,7 +2124,7 @@ wordsplit_pathexpand (struct wordsplit *wsp) default: free (pattern); - return _wsplt_seterr (wsp, WRDSE_GLOBERR); + return _wsplt_setctxerr (wsp, WRDSE_GLOBERR, pattern, slen); } prev = p; @@ -2754,12 +2780,17 @@ 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); @@ -2823,6 +2854,9 @@ wordsplit_perror (struct wordsplit *wsp) 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/lib/wordsplit.h b/lib/wordsplit.h index 2fac3c6..0d6eef3 100644 --- a/lib/wordsplit.h +++ b/lib/wordsplit.h @@ -110,7 +110,7 @@ struct wordsplit 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. */ @@ -118,6 +118,10 @@ struct wordsplit 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 */ @@ -255,6 +255,15 @@ getvar(char **ret, const char *var, size_t len, void *clos) return WRDSE_OK; } +void +rush_ws_error (const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vlogmsg(LOG_ERR, fmt, ap); + va_end(ap); +} + char * rush_expand_string(const char *string, struct rush_request *req) { @@ -264,6 +273,7 @@ rush_expand_string(const char *string, struct rush_request *req) | (expand_undefined ? 0: WRDSF_UNDEF) | WRDSF_GETVAR | WRDSF_CLOSURE + | WRDSF_ERROR | WRDSF_OPTIONS; char *result; @@ -271,6 +281,7 @@ rush_expand_string(const char *string, struct rush_request *req) ws.ws_closure = req; ws.ws_paramv = (char const**) req->argv; ws.ws_paramc = req->argc; + ws.ws_error = rush_ws_error; ws.ws_options = WRDSO_BSKEEP_QUOTE | WRDSO_NOCMDSPLIT | WRDSO_PARAMV | WRDSO_PARAM_NEGIDX; if (req->var_kv) { @@ -283,7 +294,8 @@ rush_expand_string(const char *string, struct rush_request *req) case 0: break; case WRDSE_UNDEF: - die(config_error, &req->i18n, "%s", wordsplit_strerror(&ws)); + die(config_error, &req->i18n, "%s: %s", + wordsplit_strerror(&ws), ws.ws_errctx); break; default: die(system_error, &req->i18n, "%s", wordsplit_strerror(&ws)); @@ -658,6 +658,11 @@ rush_transform(struct transform_node *node, struct rush_request *req) /* Environment variable */ die(system_error, NULL, _("environment transformation is not yet implemented")); + + case target_readonly: + die(system_error, NULL, + _("INTERNAL ERROR at %s:%d: can't modify read-only target"), + __FILE__, __LINE__); } switch (node->type) { @@ -1033,7 +1038,6 @@ main(int argc, char **argv) uid_t uid; struct rush_rule *rule; struct rush_request req; - struct wordsplit ws; rush_set_program_name(argv[0]); rush_i18n_init(); @@ -1110,16 +1114,8 @@ main(int argc, char **argv) } req.cmdline = xstrdup(command); - - ws.ws_options = WRDSO_NOVARSPLIT | WRDSO_NOCMDSPLIT; - if (wordsplit(req.cmdline, &ws, WRDSF_DEFFLAGS|WRDSF_OPTIONS)) - die(system_error, NULL, - _("wordsplit(%s) failed: %s"), - req.cmdline, wordsplit_strerror(&ws)); - wordsplit_get_words(&ws, &req.argc, &req.argv); - wordsplit_free(&ws); - request_set_env(&req); + reparse_cmdline(&req); req.pw = rush_pw; req.umask = 022; @@ -362,6 +362,7 @@ char *rush_expand_string(const char *string, struct rush_request *req); char **rush_getvarptr(struct rush_request *req, char const *varname); void rush_request_delvar(struct rush_request *req, char const *varname); enum transform_target_type rush_variable_target(char const *varname); +void rush_ws_error (const char *fmt, ...); /* dump.c */ void dump_request(struct rush_request *req, FILE *fp); diff --git a/tests/undef.at b/tests/undef.at index 015dd52..bb79176 100644 --- a/tests/undef.at +++ b/tests/undef.at @@ -27,7 +27,7 @@ rule first [ls], [1], [], -[rush: Error: undefined variable +[rush: Error: undefined variable: COMMAND ]) AT_RUSH_TEST([ |