summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--NEWS8
-rw-r--r--doc/pies.texi15
-rw-r--r--lib/envop.c51
-rw-r--r--src/pies.c22
4 files changed, 77 insertions, 19 deletions
diff --git a/NEWS b/NEWS
index 4ee1ae5..f5be6dd 100644
--- a/NEWS
+++ b/NEWS
@@ -1,7 +1,7 @@
-GNU Pies NEWS -- history of user-visible changes. 2019-06-06
+GNU Pies NEWS -- history of user-visible changes. 2019-06-07
See the end of file for copying conditions.
Please send Pies bug reports to <bug-pies@gnu.org> or
<bug-pies@gnu.org.ua>
Version 1.3.91 (git)
@@ -52,12 +52,18 @@ Keeps the variable NAME when clearing the environment. Implies
variables matching the pattern are retained.
** set "NAME=VALUE"
Sets the environment variable for the component. VALUE is subject
to variable expansion.
+** eval "VALUE"
+Perform variable expansion on VALUE and discard the result (similar
+to the shell ":" command). Useful for side effects, e.g.:
+
+ eval ${HOME:=/home/t}
+
** unset NAME
Unsets the variable. NAME can be a globbing pattern, in which case all
variables matching the pattern are unset.
Example:
diff --git a/doc/pies.texi b/doc/pies.texi
index 63064e5..4bd2f8f 100644
--- a/doc/pies.texi
+++ b/doc/pies.texi
@@ -1061,12 +1061,13 @@ The compound @code{env} statement has the following syntax:
@example
@group
env @{
clear;
keep @var{pattern};
set "@var{name}=@var{value}";
+ eval "@var{value}";
unset @var{pattern};
@}
@end group
@end example
@end deffn
@@ -1120,12 +1121,26 @@ env @{
set "LD_LIBRARY_PATH=$LD_LIBRARY_PATH$@{LD_LIBRARY_PATH:+:@}$MYLIB";
@}
@end group
@end example
@end deffn
+@deffn {env} eval "@var{value}"
+Perform variable expansion on @var{value} and discard the result. This
+is useful for side-effects. For example, to provide default value for
+the @env{LD_LIBRARY_PATH} variable, one may write:
+
+@example
+@group
+env @{
+ eval "$@{LD_LIBRARY_PATH:=/usr/local/lib@}";
+@}
+@end group
+@end example
+@end deffn
+
@deffn {env} unset @var{pattern}
Unset environment variables matching @var{pattern}. The following
will unset the @env{LOGIN} variable:
@example
unset LOGIN;
diff --git a/lib/envop.c b/lib/envop.c
index ce24b92..93bd425 100644
--- a/lib/envop.c
+++ b/lib/envop.c
@@ -164,19 +164,21 @@ int
environ_set (environ_t *env, char const *name, char const *value)
{
size_t len;
char *def;
struct wordsplit ws;
- if (!name)
+ if (!value)
{
- errno = EINVAL;
- return -1;
+ if (!name)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ return environ_unset (env, name, value);
}
- if (!value)
- return environ_unset (env, name, value);
ws.ws_env = (char const **) env->env_base;
if (wordsplit (value, &ws,
WRDSF_NOSPLIT
| WRDSF_QUOTE
| WRDSF_NOCMD /* FIXME */
@@ -188,13 +190,24 @@ environ_set (environ_t *env, char const *name, char const *value)
int ec = errno;
wordsplit_free (&ws);
errno = ec;
return -1;
}
- if (strcmp (name, ":") == 0)
+ if (ws.ws_envbuf)
+ {
+ free (env->env_base);
+ env->env_base = ws.ws_envbuf;
+ env->env_count = ws.ws_envidx;
+ env->env_max = ws.ws_envsiz;
+ ws.ws_envbuf = NULL;
+ ws.ws_envidx = 0;
+ ws.ws_envsiz = 0;
+ }
+
+ if (name == NULL || strcmp (name, ":") == 0)
{
wordsplit_free (&ws);
return 0;
}
len = strlen (name) + strlen (ws.ws_wordv[0]) + 2;
@@ -331,20 +344,21 @@ valid_envar_name (char const *name)
int
envop_entry_add (struct envop_entry **head,
enum envop_code code, char const *name, char const *value)
{
struct envop_entry *op;
size_t s;
+ char *p;
switch (code)
{
case envop_clear:
break;
case envop_set:
- if (!name || !(*name == ':' || valid_envar_name (name)))
+ if (name && !(*name == ':' || valid_envar_name (name)))
{
errno = EINVAL;
return -1;
}
break;
@@ -356,33 +370,34 @@ envop_entry_add (struct envop_entry **head,
errno = EINVAL;
return -1;
}
s = sizeof (op[0]);
if (name)
- {
- s += strlen (name) + 1;
- if (value)
- s += strlen (value) + 1;
- }
+ s += strlen (name) + 1;
+ if (value)
+ s += strlen (value) + 1;
op = malloc (s);
if (!op)
return -1;
op->next = NULL;
op->code = code;
op->name = NULL;
op->value = NULL;
+
+ p = (char*)(op + 1);
if (name)
{
- op->name = (char*)(op + 1);
+ op->name = p;
strcpy (op->name, name);
- if (value)
- {
- op->value = op->name + strlen (name) + 1;
- strcpy (op->value, value);
- }
+ p += strlen (name) + 1;
+ }
+ if (value)
+ {
+ op->value = p;
+ strcpy (op->value, value);
}
envop_entry_insert (head, op);
return 0;
}
static int
diff --git a/src/pies.c b/src/pies.c
index 1f5fb8f..73d33a0 100644
--- a/src/pies.c
+++ b/src/pies.c
@@ -783,12 +783,28 @@ _cb_env_set (enum grecs_callback_command cmd,
if (envop_entry_add (&comp->envop, envop_set, value->v.string, p))
grecs_error (locus, errno, "envop_entry_add");
return 0;
}
static int
+_cb_env_eval (enum grecs_callback_command cmd,
+ grecs_node_t *node,
+ void *varptr, void *cb_data)
+{
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
+ struct component *comp = varptr;
+
+ if (grecs_assert_node_value_type (cmd, node, GRECS_TYPE_STRING))
+ return 1;
+ if (envop_entry_add (&comp->envop, envop_set, NULL, value->v.string))
+ grecs_error (locus, errno, "envop_entry_add");
+ return 0;
+}
+
+static int
_cb_env_unset (enum grecs_callback_command cmd,
grecs_node_t *node,
void *varptr, void *cb_data)
{
grecs_locus_t *locus = &node->locus;
grecs_value_t *value = node->v.value;
@@ -822,12 +838,18 @@ struct grecs_keyword cb_env_keywords[] = {
{ "set",
N_("name=value"),
N_("Set environment variable. Note, that argument must be quoted."),
grecs_type_string, GRECS_DFLT,
NULL, 0,
_cb_env_set },
+ { "eval",
+ N_("string"),
+ N_("Evaluate string. Useful for side-effects, e.g. eval ${X:=2}."),
+ grecs_type_string, GRECS_DFLT,
+ NULL, 0,
+ _cb_env_eval },
{ "unset",
N_("name"),
N_("Unset environment variable. Name can contain wildcards."),
grecs_type_string, GRECS_DFLT,
NULL, 0,
_cb_env_unset },

Return to:

Send suggestions and report system problems to the System administrator.