From 12304127b52650588877f00b0c4b32dae083e852 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Thu, 13 Jun 2019 14:20:20 +0300 Subject: wordsplit: configurable order of lookups if both WRDSF_ENV and WRDSF_GETVAR are set * lib/wordsplit.h (WRDSO_GETVARPREF): New option. * lib/wordsplit.c (wordsplit_find_env): Rewrite as wsplt_env_lookup wsplt_env_getvar): New function. (expvar): Select preference of wsplt_env_lookup vs. wsplt_env_getvar depending on the value if WRDSO_GETVARPREF option. --- include/wordsplit.h | 3 ++- src/wordsplit.c | 70 +++++++++++++++++++++++++++++++++-------------------- 2 files changed, 46 insertions(+), 27 deletions(-) diff --git a/include/wordsplit.h b/include/wordsplit.h index 0d6eef3..3451979 100644 --- a/include/wordsplit.h +++ b/include/wordsplit.h @@ -216,7 +216,8 @@ struct wordsplit #define WRDSO_FAILGLOB 0x00000002 /* Allow a leading period to be matched by metacharacters. */ #define WRDSO_DOTGLOB 0x00000004 -/* Unused value: 0x00000008 */ +/* Prefer ws_getvar over lookup in ws_env, if both are supplied */ +#define WRDSO_GETVARPREF 0x00000008 /* Keep backslash in unrecognized escape sequences in words */ #define WRDSO_BSKEEP_WORD 0x00000010 /* Handle octal escapes in words */ diff --git a/src/wordsplit.c b/src/wordsplit.c index d01fd43..9179a87 100644 --- a/src/wordsplit.c +++ b/src/wordsplit.c @@ -1034,15 +1034,13 @@ find_closing_paren (const char *str, size_t i, size_t len, size_t *poff, return 1; } -static int -wordsplit_find_env (struct wordsplit *wsp, const char *name, size_t len, - char const **ret) +static char const * +wsplt_env_find (struct wordsplit *wsp, const char *name, size_t len) { size_t i; - if (!(wsp->ws_flags & WRDSF_ENV)) - return WRDSE_UNDEF; - + if (!wsp->ws_env) + return NULL; if (wsp->ws_flags & WRDSF_ENV_KV) { /* A key-value pair environment */ @@ -1050,17 +1048,14 @@ wordsplit_find_env (struct wordsplit *wsp, const char *name, size_t len, { size_t elen = strlen (wsp->ws_env[i]); if (elen == len && memcmp (wsp->ws_env[i], name, elen) == 0) - { - *ret = wsp->ws_env[i + 1]; - return WRDSE_OK; - } + return wsp->ws_env[i + 1]; /* Skip the value. Break the loop if it is NULL. */ i++; if (wsp->ws_env[i] == NULL) break; } } - else if (wsp->ws_env) + else { /* Usual (A=B) environment. */ for (i = 0; wsp->ws_env[i]; i++) @@ -1072,15 +1067,38 @@ wordsplit_find_env (struct wordsplit *wsp, const char *name, size_t len, if (name[j] != var[j]) break; if (j == len && var[j] == '=') - { - *ret = var + j + 1; - return WRDSE_OK; - } + return var + j + 1; + } + } + return NULL; +} + +static int +wsplt_env_lookup (struct wordsplit *wsp, const char *name, size_t len, + char **ret) +{ + if (wsp->ws_flags & WRDSF_ENV) + { + char const *val = wsplt_env_find (wsp, name, len); + if (val) + { + char *retval = strdup (val); + if (!retval) + return WRDSE_NOSPACE; + *ret = retval; + return WRDSE_OK; } } return WRDSE_UNDEF; } +static int +wsplt_env_getvar (struct wordsplit *wsp, const char *name, size_t len, + char **ret) +{ + return wsp->ws_getvar (ret, name, len, wsp->ws_closure); +} + static int wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen, char const *value) @@ -1356,7 +1374,6 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, size_t i = 0; const char *defstr = NULL; char *value; - const char *vptr; struct wordsplit_node *newnode; const char *start = str - 1; int rc; @@ -1497,22 +1514,23 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, } else { - rc = wordsplit_find_env (wsp, str, i, &vptr); - if (rc == WRDSE_OK) + if (wsp->ws_flags & WRDSF_GETVAR) { - if (vptr) + if (wsp->ws_options & WRDSO_GETVARPREF) { - value = strdup (vptr); - if (!value) - rc = WRDSE_NOSPACE; + rc = wsplt_env_getvar (wsp, str, i, &value); + if (rc == WRDSE_UNDEF) + rc = wsplt_env_lookup (wsp, str, i, &value); } else - rc = WRDSE_UNDEF; + { + rc = wsplt_env_lookup (wsp, str, i, &value); + if (rc == WRDSE_UNDEF) + rc = wsplt_env_getvar (wsp, str, i, &value); + } } - else if (wsp->ws_flags & WRDSF_GETVAR) - rc = wsp->ws_getvar (&value, str, i, wsp->ws_closure); else - rc = WRDSE_UNDEF; + rc = wsplt_env_lookup (wsp, str, i, &value); } if (rc == WRDSE_OK -- cgit v1.2.1