aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Groffen <grobian@gentoo.org>2021-11-13 15:04:49 +0100
committerFabian Groffen <grobian@gentoo.org>2021-11-13 15:04:49 +0100
commit4dd3b20b0ade46b207f869572a20fbe2ec24a4f1 (patch)
tree90cd9fdf911ec2d4a6ec6e68bb7157301f31d8b8
parentmain: parse/populate USE var (diff)
downloadportage-utils-4dd3b20b0ade46b207f869572a20fbe2ec24a4f1.tar.gz
portage-utils-4dd3b20b0ade46b207f869572a20fbe2ec24a4f1.tar.bz2
portage-utils-4dd3b20b0ade46b207f869572a20fbe2ec24a4f1.zip
main: parse USE-flags into a set
In order to efficiently, and correctly, get a list of USE-flags that are in effect, use a SET instead of an "incremental" string which sort of relies on order. Signed-off-by: Fabian Groffen <grobian@gentoo.org>
-rw-r--r--applets.h2
-rw-r--r--main.c115
-rw-r--r--main.h5
-rw-r--r--q.c35
4 files changed, 130 insertions, 27 deletions
diff --git a/applets.h b/applets.h
index be5aad6b..fa53359d 100644
--- a/applets.h
+++ b/applets.h
@@ -171,7 +171,7 @@ extern char *binhost;
extern char *pkgdir;
extern char *port_tmpdir;
extern char *features;
-extern char *ev_use;
+extern set *ev_use;
extern char *install_mask;
extern DEFINE_ARRAY(overlays);
extern DEFINE_ARRAY(overlay_names);
diff --git a/main.c b/main.c
index 6a79eef4..1d78f079 100644
--- a/main.c
+++ b/main.c
@@ -42,7 +42,7 @@ char *binhost;
char *pkgdir;
char *port_tmpdir;
char *features;
-char *ev_use;
+set *ev_use;
char *install_mask;
DECLARE_ARRAY(overlays);
DECLARE_ARRAY(overlay_names);
@@ -249,8 +249,9 @@ static void
strincr_var(const char *name, const char *s, char **value, size_t *value_len)
{
size_t len;
- char *p, *nv;
- char brace;
+ char *p;
+ char *nv;
+ char brace;
len = strlen(s);
*value = xrealloc(*value, *value_len + len + 2);
@@ -259,9 +260,6 @@ strincr_var(const char *name, const char *s, char **value, size_t *value_len)
*nv++ = ' ';
memcpy(nv, s, len + 1);
- while ((p = strstr(nv, "-*")) != NULL)
- memset(*value, ' ', p - *value + 2);
-
/* This function is mainly used by the startup code for parsing
make.conf and stacking variables remove.
variables can be in the form of ${v} or $v
@@ -295,11 +293,64 @@ strincr_var(const char *name, const char *s, char **value, size_t *value_len)
}
}
+ while ((p = strstr(nv, "-*")) != NULL)
+ memset(*value, ' ', p - *value + 2);
+
remove_extra_space(*value);
*value_len = strlen(*value);
/* we should sort here */
}
+static void
+setincr_var(const char *s, set **vals)
+{
+ int i;
+ int argc;
+ char **argv;
+ bool ignore;
+
+ /* This tries to mimick parsing of portage envvars and the stacking
+ * thereof. In particular USE and FEATURES, where also negation can
+ * happen (- prefix). Variables are supported in form of ${v} or
+ * $v, but there's no actual replacement happening, we just ignore
+ * any of such forms.
+ * works:
+ * FEATURES="${FEATURES} foo"
+ * FEATURES="$FEATURES foo"
+ * FEATURES="baz bar -* foo"
+ *
+ * wont work:
+ * FEATURES="${OTHERVAR} foo"
+ * FEATURES="-* ${FEATURES}"
+ */
+
+ if (s == NULL || *s == '\0')
+ return;
+
+ /* break up input */
+ makeargv(s, &argc, &argv);
+
+ for (i = 1 /* skip executable name */; i < argc; i++) {
+ if (argv[i][0] == '-' && *vals != NULL) {
+ /* handle negation, when the respective value isn't set, we
+ * simply ignore/drop it */
+ if (argv[i][1] == '*') {
+ clear_set(*vals);
+ } else {
+ del_set(&argv[i][1], *vals, &ignore);
+ }
+ } else if (argv[i][0] == '$') {
+ /* detect ${var} or $var, simply ignore it completely, for
+ * all of these should be stacked, so re-including whatever
+ * there is shouldn't make much sense */
+ } else {
+ *vals = add_set_unique(argv[i], *vals, &ignore);
+ }
+ }
+
+ freeargv(argc, argv);
+}
+
static env_vars *
get_portage_env_var(env_vars *vars, const char *name)
{
@@ -329,6 +380,7 @@ set_portage_env_var(env_vars *var, const char *value, const char *src)
var->src = xstrdup(src);
break;
case _Q_ISTR:
+ case _Q_ISET:
if (strcmp(var->src, STR_DEFAULT) != 0) {
size_t l = strlen(var->src) + 2 + strlen(src) + 1;
char *p = xmalloc(sizeof(char) * l);
@@ -342,7 +394,10 @@ set_portage_env_var(env_vars *var, const char *value, const char *src)
free(var->src);
var->src = xstrdup(src);
}
- strincr_var(var->name, value, var->value.s, &var->value_len);
+ if (var->type == _Q_ISTR)
+ strincr_var(var->name, value, var->value.s, &var->value_len);
+ else
+ setincr_var(value, var->value.t);
break;
}
}
@@ -612,10 +667,12 @@ env_vars vars_to_read[] = {
.default_value = d, \
.src = NULL, \
},
-#define _Q_EVS(t, V, v, d) \
- _Q_EV(t, V, .value.s = &v, .value_len = sizeof(d) - 1, d)
-#define _Q_EVB(t, V, v, d) \
- _Q_EV(t, V, .value.b = &v, .value_len = 0, d)
+#define _Q_EVS(t, V, v, D) \
+ _Q_EV(t, V, .value.s = &v, .value_len = sizeof(D) - 1, D)
+#define _Q_EVB(t, V, v, D) \
+ _Q_EV(t, V, .value.b = &v, .value_len = 0, D)
+#define _Q_EVT(T, V, v, D) \
+ _Q_EV(T, V, .value.t = &v, .value_len = 0, D)
_Q_EVS(STR, ROOT, portroot, "/")
_Q_EVS(STR, ACCEPT_LICENSE, accept_license, "")
@@ -626,7 +683,7 @@ env_vars vars_to_read[] = {
_Q_EVS(ISTR, CONFIG_PROTECT_MASK, config_protect_mask, "")
_Q_EVB(BOOL, NOCOLOR, nocolor, 0)
_Q_EVS(ISTR, FEATURES, features, "")
- _Q_EVS(ISTR, USE, ev_use, "")
+ _Q_EVT(ISET, USE, ev_use, NULL)
_Q_EVS(STR, EPREFIX, eprefix, CONFIG_EPREFIX)
_Q_EVS(STR, EMERGE_LOG_DIR, portlogdir, CONFIG_EPREFIX "var/log")
_Q_EVS(STR, PORTDIR, main_overlay, CONFIG_EPREFIX "var/db/repos/gentoo")
@@ -819,8 +876,12 @@ initialize_portage_env(void)
/* initialize all the properties with their default value */
for (i = 0; vars_to_read[i].name; ++i) {
var = &vars_to_read[i];
- if (var->type != _Q_BOOL)
- *var->value.s = xstrdup(var->default_value);
+ switch (var->type) {
+ case _Q_BOOL: *var->value.b = var->default_value; break;
+ case _Q_STR:
+ case _Q_ISTR: *var->value.s = xstrdup(var->default_value); break;
+ case _Q_ISET: *var->value.t = (set *)var->default_value; break;
+ }
var->src = xstrdup(STR_DEFAULT);
}
@@ -895,7 +956,7 @@ initialize_portage_env(void)
char *svar;
var = &vars_to_read[i];
- if (var->type == _Q_BOOL)
+ if (var->type != _Q_STR)
continue;
while ((svar = strchr(*var->value.s, '$'))) {
@@ -1023,11 +1084,27 @@ initialize_portage_env(void)
if (getenv("DEBUG")) {
for (i = 0; vars_to_read[i].name; ++i) {
var = &vars_to_read[i];
- fprintf(stderr, "%s = ", var->name);
switch (var->type) {
- case _Q_BOOL: fprintf(stderr, "%i\n", *var->value.b); break;
- case _Q_STR:
- case _Q_ISTR: fprintf(stderr, "%s\n", *var->value.s); break;
+ case _Q_BOOL:
+ fprintf(stderr, "%s = %d\n", var->name, *var->value.b);
+ break;
+ case _Q_STR:
+ case _Q_ISTR:
+ fprintf(stderr, "%s = %s\n", var->name, *var->value.s);
+ break;
+ case _Q_ISET: {
+ DECLARE_ARRAY(vals);
+ size_t n;
+ char *val;
+
+ fprintf(stderr, "%s = ", var->name);
+ array_set(*var->value.t, vals);
+ array_for_each(vals, n, val) {
+ fprintf(stderr, "%s ", val);
+ }
+ fprintf(stderr, "\n");
+ xarrayfree_int(vals);
+ } break;
}
}
}
diff --git a/main.h b/main.h
index 35b95abb..a1b2afc9 100644
--- a/main.h
+++ b/main.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2005-2019 Gentoo Foundation
+ * Copyright 2005-2021 Gentoo Foundation
* Distributed under the terms of the GNU General Public License v2
*
* Copyright 2005-2010 Ned Ludd - <solar@gentoo.org>
@@ -146,7 +146,7 @@ extern FILE *warnout;
#define errp(fmt, args...) _err(warnp, fmt , ## args)
#define errfp(fmt, args...) _err(warnfp, fmt, ## args)
-typedef enum { _Q_BOOL, _Q_STR, _Q_ISTR } var_types;
+typedef enum { _Q_BOOL, _Q_STR, _Q_ISTR, _Q_ISET } var_types;
typedef struct {
const char *name;
const size_t name_len;
@@ -154,6 +154,7 @@ typedef struct {
union {
char **s;
bool *b;
+ set **t;
} value;
size_t value_len;
const char *default_value;
diff --git a/q.c b/q.c
index e514b0cb..c9df5f71 100644
--- a/q.c
+++ b/q.c
@@ -242,10 +242,23 @@ int q_main(int argc, char **argv)
printf("%s%s%s",
YELLOW, *var->value.b ? "1" : "0", NORM);
break;
- case _Q_STR:
- case _Q_ISTR:
+ case _Q_STR:
+ case _Q_ISTR:
printf("%s\"%s\"%s", RED, *var->value.s, NORM);
break;
+ case _Q_ISET: {
+ DECLARE_ARRAY(vals);
+ size_t n;
+ char *val;
+
+ printf("%s\"", RED);
+ array_set(*var->value.t, vals);
+ array_for_each(vals, n, val) {
+ printf("%s%s", n == 0 ? "" : " ", val);
+ }
+ xarrayfree_int(vals);
+ printf("\"%s", NORM);
+ } break;
}
if (verbose)
printf(" [%s]\n", var->src);
@@ -264,12 +277,24 @@ int q_main(int argc, char **argv)
switch (var->type) {
case _Q_BOOL:
printf("%s%s%s",
- YELLOW, *var->value.b ? "1" : "0", NORM);
+ YELLOW, *var->value.b ? "1" : "0", NORM);
break;
- case _Q_STR:
- case _Q_ISTR:
+ case _Q_STR:
+ case _Q_ISTR:
printf("%s%s%s", RED, *var->value.s, NORM);
break;
+ case _Q_ISET: {
+ DECLARE_ARRAY(vals);
+ size_t n;
+ char *val;
+
+ array_set(*var->value.t, vals);
+ array_for_each(vals, n, val) {
+ printf("%s%s", n == 0 ? RED : " ", val);
+ }
+ xarrayfree_int(vals);
+ printf("%s", NORM);
+ } break;
}
if (verbose)
printf(" [%s]\n", var->src);