diff options
author | 2021-11-13 15:04:49 +0100 | |
---|---|---|
committer | 2021-11-13 15:04:49 +0100 | |
commit | 4dd3b20b0ade46b207f869572a20fbe2ec24a4f1 (patch) | |
tree | 90cd9fdf911ec2d4a6ec6e68bb7157301f31d8b8 | |
parent | main: parse/populate USE var (diff) | |
download | portage-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.h | 2 | ||||
-rw-r--r-- | main.c | 115 | ||||
-rw-r--r-- | main.h | 5 | ||||
-rw-r--r-- | q.c | 35 |
4 files changed, 130 insertions, 27 deletions
@@ -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); @@ -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; } } } @@ -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; @@ -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); |