summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2019-06-13 11:20:20 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2019-06-13 11:20:20 (GMT)
commit12304127b52650588877f00b0c4b32dae083e852 (patch) (side-by-side diff)
treee6a2fa21b66d16a82a7913933b88bd091f633dc6
parentdbe318987cf3a36fe63893205d3df0dc3be7fa4a (diff)
downloadgrecs-12304127b52650588877f00b0c4b32dae083e852.tar.gz
grecs-12304127b52650588877f00b0c4b32dae083e852.tar.bz2
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.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--include/wordsplit.h3
-rw-r--r--src/wordsplit.c70
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,16 +1067,39 @@ 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

Return to:

Send suggestions and report system problems to the System administrator.