commit: 7b7eea9df68211a613ac1c375a9f0b1b7f8e35e2
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Sat Jan 10 17:47:51 2026 +0000
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Sat Jan 10 19:41:59 2026 +0000
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=7b7eea9d
libq/array: rewrite with cleaner API
Hide internal details of the list from external consumers. Require a
flow of array_new() ... array_append() ... array_get() ... array_free()
instead of externally (stack) allocated array structures.
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>
applets.h | 6 +-
libq/array.c | 222 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
libq/array.h | 63 +++++++++--------
libq/dep.c | 4 +-
libq/dep.h | 4 +-
libq/set.c | 5 +-
libq/set.h | 8 +--
libq/tree.c | 10 +--
main.c | 49 ++++++-------
q.c | 23 ++-----
qcheck.c | 13 ++--
qdepends.c | 38 ++++------
qkeyword.c | 14 ++--
qlist.c | 5 +-
qlop.c | 60 +++++-----------
qmanifest.c | 12 +++-
qpkg.c | 5 +-
qsize.c | 13 ++--
qwhich.c | 8 +--
19 files changed, 323 insertions(+), 239 deletions(-)
diff --git a/applets.h b/applets.h
index bb8323d..fc4e27c 100644
--- a/applets.h
+++ b/applets.h
@@ -179,9 +179,9 @@ extern set *features;
extern set *ev_use;
extern char *install_mask;
extern char *binpkg_format;
-extern array_t *overlays;
-extern array_t *overlay_names;
-extern array_t *overlay_src;
+extern array *overlays;
+extern array *overlay_names;
+extern array *overlay_src;
extern char *main_overlay;
extern int twidth;
extern bool nocolor;
diff --git a/libq/array.c b/libq/array.c
index ac459c9..2c85eb8 100644
--- a/libq/array.c
+++ b/libq/array.c
@@ -17,67 +17,211 @@
#define ARRAY_INC_SIZE 32
-void *xarrayget(array_t *arr, size_t idx)
+struct array_t {
+ void **eles;
+ size_t len;
+ size_t siz;
+};
+
+/* allocates a new array */
+array *array_new(void)
+{
+ return xzalloc(sizeof(array));
+}
+
+/* frees an array without freeing any of the data stored in the array */
+void array_free(array *arr)
+{
+ if (arr == NULL)
+ return;
+
+ free(arr->eles);
+ free(arr);
+}
+
+/* frees the array and all the data pointed to by all of its elements
+ * if the callback free function is NULL, free() is used */
+void array_deepfree(array *arr, array_free_cb *func)
{
- if (idx >= arr->num)
+ size_t i;
+
+ if (arr == NULL)
+ return;
+
+ if (func == NULL)
+ func = &free;
+
+ for (i = 0; i < arr->len; i++)
+ func(arr->eles[i]);
+
+ array_free(arr);
+}
+
+/* appends the given pointer to the list, no copying of data takes place
+ * returns the pointer */
+void *array_append(array *arr, void *data)
+{
+ size_t n;
+
+ if (arr == NULL)
return NULL;
- return arr->eles[idx];
+
+ n = arr->len++;
+
+ if (arr->len > arr->siz)
+ {
+ arr->siz += ARRAY_INC_SIZE;
+ arr->eles = xrealloc(arr->eles, arr->siz *
sizeof(arr->eles[0]));
+ }
+
+ return arr->eles[n] = data;
}
-/* Push a pointer to memory we already hold and don't want to release. Do not
- * mix xarraypush_ptr usage with the other push funcs which duplicate memory.
- * The free stage won't know which pointers to release directly.
- */
-void *xarraypush_ptr(array_t *arr, void *ele)
+/* copies data of len bytes and appends to the array
+ * returns the pointer to the copied data */
+void *array_append_copy(array *arr, const void *data, size_t len)
{
- size_t n = arr->num++;
- if (arr->num > arr->len) {
- arr->len += ARRAY_INC_SIZE;
- arr->eles = xrealloc_array(arr->eles, arr->len, sizeof(ele));
+ void *ret = NULL;
+
+ if (data != NULL &&
+ len > 0)
+ {
+ ret = xmemdup(data, len);
}
- arr->eles[n] = ele;
- return ele;
+
+ if (array_append(arr, ret) == NULL &&
+ ret != NULL)
+ {
+ free(ret);
+ ret = NULL;
+ }
+
+ return ret;
}
-void *xarraypush(array_t *arr, const void *ele, size_t ele_len)
+/* removes the given element from the array and returns the pointer to
+ * the data removed from the array
+ * the caller should ensure the pointer is freed if necessary */
+void *array_remove(array *arr, size_t elem)
{
- return xarraypush_ptr(arr, xmemdup(ele, ele_len));
+ void *ret;
+
+ if (arr == NULL ||
+ elem >= arr->len)
+ {
+ return NULL;
+ }
+
+ ret = arr->eles[elem];
+ arr->len--;
+ if (elem < arr->len)
+ {
+ memmove(&arr->eles[elem], &arr->eles[elem + 1],
+ sizeof(arr->eles[0]) * (arr->len - elem));
+ }
+
+ return ret;
}
-void xarraysort(array_t *arr, int (*compar)(const void *, const void *))
+/* frees the element at offset elem and removes it from the list, if the
+ * callback free function is NULL, free() is used */
+void array_delete(array *arr, size_t elem, array_free_cb *func)
{
- if (arr->num > 1)
- qsort(arr->eles, arr->num, sizeof(void *), compar);
+ if (arr == NULL)
+ return;
+
+ if (func == NULL)
+ func = &free;
+
+ func(arr->eles[elem]);
+
+ (void)array_remove(arr, elem);
}
-void xarraydelete_ptr(array_t *arr, size_t elem)
+/* returns the number of elements in use */
+size_t array_cnt(array *arr)
{
- arr->num--;
- if (elem < arr->num)
- memmove(&arr->eles[elem], &arr->eles[elem + 1],
- sizeof(arr->eles[0]) * (arr->num - elem));
- arr->eles[arr->num] = NULL;
+ if (arr == NULL)
+ return 0;
+
+ return arr->len;
}
-void xarraydelete(array_t *arr, size_t elem)
+/* returns the element at the given offset, or NULL when no such element
+ * exists
+ * note that NULL can also be returned if the element has the value of
+ * NULL, so if the caller wants to know the difference, it should check
+ * the input is sane using array_cnt() */
+void *array_get(array *arr, size_t elem)
{
- free(arr->eles[elem]);
- xarraydelete_ptr(arr, elem);
+ if (arr == NULL)
+ return NULL;
+
+ if (arr->len <= elem)
+ return NULL;
+
+ return arr->eles[elem];
}
-/* Useful for people who call xarraypush_ptr as it does not free any of the
- * pointers in the eles list.
- */
-void xarrayfree_int(array_t *arr)
+/* sorts the elements in the array using the given comparator */
+void array_sort(array *arr, int (*compar)(const void *, const void *))
{
- free(arr->eles);
- VALP_CLEAR(arr);
+ if (arr != NULL &&
+ arr->len > 1)
+ {
+ qsort(arr->eles, arr->len, sizeof(void *), compar);
+ }
}
-void xarrayfree(array_t *arr)
+/* binary search over the array, returning the first element for which
+ * compar(needle, elem(N)) returns 0
+ * note that this function assumes the array is sorted in a way
+ * compatible with compar, the caller should ensure this
+ * returns the found element, if any, and its offset in retoff when set
+ * note that if the found element is NULL, the caller should retrieve
+ * and compare the element at retoff to check if the value was found */
+void *array_binsearch
+(
+ array *arr,
+ void *needle,
+ int (*compar)(const void *, const void *),
+ size_t *retoff
+)
{
- size_t n;
- for (n = 0; n < arr->num; ++n)
- free(arr->eles[n]);
- xarrayfree_int(arr);
+ size_t low;
+ size_t high;
+ size_t elem;
+ int cmp;
+
+ if (arr == NULL ||
+ compar == NULL)
+ {
+ return NULL;
+ }
+
+ low = 0;
+ high = arr->len;
+
+ while (low != high)
+ {
+ elem = low + ((high - low) / 2);
+ cmp = compar(needle, arr->eles[elem]);
+ if (cmp == 0)
+ {
+ if (retoff != NULL)
+ *retoff = elem;
+ return arr->eles[elem];
+ }
+ else if (cmp < 0)
+ {
+ high = elem;
+ }
+ else if (cmp > 0)
+ {
+ low = elem + 1;
+ }
+ }
+
+ *retoff = 0;
+ return NULL;
}
diff --git a/libq/array.h b/libq/array.h
index cb84d1c..7268019 100644
--- a/libq/array.h
+++ b/libq/array.h
@@ -12,34 +12,43 @@
#include <string.h> /* strlen in push_str */
-typedef struct {
- void **eles;
- size_t num;
- size_t len;
-} array_t;
-
-#define xrealloc_array(ptr, size, ele_size) xrealloc(ptr, (size) * (ele_size))
-/* The assignment after the check is unfortunate as we do a non-NULL check (we
- * already do not permit pushing of NULL pointers), but we can't put it in the
- * increment phase as that will cause a load beyond the bounds of valid memory.
- */
-/* TODO: remove ele = NULL after checking all consumers don't rely on this */
+#define xarrayget(A,I) array_get(A,I)
+#define xarraypush_ptr(A,E) array_append(A,E)
+#define xarraypush(A,E,L) array_append_copy(A,E,L)
+#define xarraypush_str(A,S) array_append_copy(A,S,strlen(S)+1/*NUL*/)
+#define xarraysort(A,C) array_sort(A,C)
+#define xarraydelete_ptr(A,E) array_remove(A,E)
+#define xarraydelete(A,E) array_delete(A,E,NULL)
+#define xarrayfree_int(A) array_free(A)
+#define xarrayfree(A) array_deepfree(A,NULL)
+
+/* new 2026 interface to array */
+typedef struct array_t array;
+typedef void (array_free_cb)(void *priv);
+
+array *array_new(void);
+void array_free(array *arr);
+void array_deepfree(array *arr, array_free_cb *func);
+void *array_append(array *arr, void *data);
+void *array_append_copy(array *arr, const void *data, size_t len);
+void *array_remove(array *arr, size_t elem);
+void array_delete(array *arr, size_t elem, array_free_cb *func);
+size_t array_cnt(array *arr);
+void *array_get(array *arr, size_t elem);
+void array_sort(array *arr, int (*compar)(const void *, const void *));
+void *array_binsearch(array *arr, void *needle, int (*compar)(const void *,
const void *), size_t *retoff);
+
+#define array_append_strcpy(A,S) array_append_copy(A,S,strlen(S)+1/*NUL*/)
+
#define array_for_each(arr, n, ele) \
- for (n = 0, ele = NULL; n < array_cnt(arr) && (ele = (arr)->eles[n]);
n++)
+ for (n = 0, ele = NULL; \
+ (n < array_cnt(arr) && \
+ (ele = array_get(arr, n))); \
+ n++)
#define array_for_each_rev(arr, n, ele) \
- for (n = array_cnt(arr); n-- > 0 && (ele = (arr)->eles[n]); /*nothing*/)
-#define array_get_elem(arr, n) (arr->eles[n])
-#define array_cnt(arr) (arr)->num
-#define xarraypush_str(arr, ele) xarraypush(arr, ele, strlen(ele) + 1 /*NUL*/)
-#define xarraypush_struct(arr, ele) xarraypush(arr, ele, sizeof(*(ele)))
-
-void *xarrayget(array_t *arr, size_t idx);
-void *xarraypush_ptr(array_t *arr, void *ele);
-void *xarraypush(array_t *arr, const void *ele, size_t ele_len);
-void xarraysort(array_t *arr, int (*compar)(const void *, const void *));
-void xarraydelete_ptr(array_t *arr, size_t elem);
-void xarraydelete(array_t *arr, size_t elem);
-void xarrayfree_int(array_t *arr);
-void xarrayfree(array_t *arr);
+ for (n = array_cnt(arr), ele = NULL; \
+ (n-- > 0 && \
+ (ele = array_get(arr, n))); \
+ /*nothing*/)
#endif
diff --git a/libq/dep.c b/libq/dep.c
index 6684861..fd9a284 100644
--- a/libq/dep.c
+++ b/libq/dep.c
@@ -230,7 +230,7 @@ dep_print_tree(
FILE *fp,
const dep_node *root,
size_t space,
- array_t *hlatoms,
+ array *hlatoms,
const char *hlcolor,
int verbose)
{
@@ -377,7 +377,7 @@ dep_resolve_tree(dep_node *root, tree_ctx *t)
}
void
-dep_flatten_tree(dep_node *root, array_t *out)
+dep_flatten_tree(dep_node *root, array *out)
{
if (root->type != DEP_NULL) {
if (root->type == DEP_NORM) {
diff --git a/libq/dep.h b/libq/dep.h
index abcbaea..18bb903 100644
--- a/libq/dep.h
+++ b/libq/dep.h
@@ -47,10 +47,10 @@ typedef struct _dep_node dep_node;
#endif
dep_node *dep_grow_tree(const char *depend);
-void dep_print_tree(FILE *fp, const dep_node *root, size_t space, array_t *m,
const char *c, int verbose);
+void dep_print_tree(FILE *fp, const dep_node *root, size_t space, array *m,
const char *c, int verbose);
void dep_resolve_tree(dep_node *root, tree_ctx *t);
void dep_burn_tree(dep_node *root);
void dep_prune_use(dep_node *root, set *use);
-void dep_flatten_tree(dep_node *root, array_t *out);
+void dep_flatten_tree(dep_node *root, array *out);
#endif
diff --git a/libq/set.c b/libq/set.c
index d865b63..e198503 100644
--- a/libq/set.c
+++ b/libq/set.c
@@ -16,6 +16,7 @@
#include <xalloc.h>
#include "set.h"
+#include "array.h"
static unsigned int
fnv1a32(const char *s)
@@ -284,7 +285,7 @@ list_set(set *q, char ***l)
}
size_t
-array_set(set *q, array_t *ret)
+array_set(set *q, array *ret)
{
int i;
set_elem *w;
@@ -302,7 +303,7 @@ array_set(set *q, array_t *ret)
}
size_t
-values_set(set *q, array_t *ret)
+values_set(set *q, array *ret)
{
int i;
set_elem *w;
diff --git a/libq/set.h b/libq/set.h
index 9d321d2..2175b0a 100644
--- a/libq/set.h
+++ b/libq/set.h
@@ -11,10 +11,10 @@
#include "array.h"
-typedef struct elem_t set_elem;
+typedef struct setelem_t set_elem;
typedef struct set_t set;
-struct elem_t {
+struct setelem_t {
char *name;
unsigned int hash; /* FNV1a32 */
void *val;
@@ -35,8 +35,8 @@ const char *contains_set(const char *name, set *q);
void *get_set(const char *name, set *q);
void *del_set(const char *s, set *q, bool *removed);
size_t list_set(set *q, char ***l);
-size_t array_set(set *q, array_t *ret);
-size_t values_set(set *q, array_t *ret);
+size_t array_set(set *q, array *ret);
+size_t values_set(set *q, array *ret);
size_t cnt_set(set *q);
void free_set(set *q);
void clear_set(set *q);
diff --git a/libq/tree.c b/libq/tree.c
index 561ad6a..5d6ba9d 100644
--- a/libq/tree.c
+++ b/libq/tree.c
@@ -246,13 +246,10 @@ void
tree_close(tree_ctx *ctx)
{
if (ctx->cache.categories != NULL) {
- array_t t_s;
- array_t *t = &t_s;
+ array *t = array_new();
size_t n;
tree_cat_ctx *cat;
- VAL_CLEAR(t_s);
-
values_set(ctx->cache.categories, t);
free_set(ctx->cache.categories);
ctx->cache.categories = NULL; /* must happen before close_cat
*/
@@ -2301,12 +2298,9 @@ tree_foreach_pkg_int
ctx->do_sort = false;
if (postsort) {
- array_t cats_s;
- array_t *cats = &cats_s;
+ array *cats = array_new();
size_t n;
- VAL_CLEAR(cats_s);
-
/* should never happen, but perhaps a tree implementation
* populated something, then don't leak it */
if (ctx->cache.categories != NULL)
diff --git a/main.c b/main.c
index fcb3fe1..78d550d 100644
--- a/main.c
+++ b/main.c
@@ -46,9 +46,9 @@ set *features;
set *ev_use;
char *install_mask;
char *binpkg_format;
-array_t *overlays;
-array_t *overlay_names;
-array_t *overlay_src;
+array *overlays;
+array *overlay_names;
+array *overlay_src;
static char *portedb;
static char *eprefix;
@@ -935,16 +935,18 @@ read_one_repos_conf(const char *repos_conf, char
**primary)
}
if (overlay != NULL) {
/* replace overlay */
- ele = array_get_elem(overlay_src, n);
- free(ele);
- array_get_elem(overlay_src, n) =
xstrdup(repos_conf);
- ele = array_get_elem(overlays, n);
- free(ele);
- ele = array_get_elem(overlays, n) = xstrdup(e);
+ array_delete(overlay_src, n, NULL);
+ array_append_strcpy(overlay_src, repos_conf);
+
+ ele = array_remove(overlay_names, n);
+ array_append(overlay_names, ele);
+
+ array_delete(overlays, n, NULL);
+ ele = array_append_strcpy(overlays, e);
} else {
- ele = xarraypush_str(overlays, e);
- overlay = xarraypush_str(overlay_names, repo);
- xarraypush_str(overlay_src, repos_conf);
+ ele = array_append_strcpy(overlays, e);
+ overlay = array_append_strcpy(overlay_names,
repo);
+ array_append_strcpy(overlay_src, repos_conf);
}
if (main_repo && strcmp(repo, main_repo) == 0)
*primary = overlay;
@@ -1044,7 +1046,7 @@ initialize_portage_env(void)
array_for_each(overlay_names, n, overlay) {
if (overlay == primary_overlay) {
snprintf(pathbuf, sizeof(pathbuf),
"%s/profiles/package.mask",
- (char
*)array_get_elem(overlays, n));
+ (char *)array_get(overlays, n));
read_portage_file(pathbuf + 1, PMASK_FILE,
package_masks);
break;
}
@@ -1195,10 +1197,10 @@ initialize_portage_env(void)
if (overlay == NULL)
i = 0;
}
- main_overlay = array_get_elem(overlays, i);
+ main_overlay = array_get(overlays, i);
/* set source for PORTDIR var */
free(var->src);
- var->src = xstrdup((char *)array_get_elem(overlay_src, i));
+ var->src = xstrdup((char *)array_get(overlay_src, i));
}
/* Make sure ROOT always ends in a slash */
@@ -1221,13 +1223,10 @@ initialize_portage_env(void)
fprintf(stderr, "%s = %s\n", var->name,
*var->value.s);
break;
case _Q_ISET: {
- array_t vals_s;
- array_t *vals = &vals_s;
+ array *vals = array_new();
size_t n;
char *val;
- VAL_CLEAR(vals_s);
-
fprintf(stderr, "%s = ", var->name);
array_set(*var->value.t, vals);
array_for_each(vals, n, val) {
@@ -1254,9 +1253,6 @@ int main(int argc, char **argv)
struct stat st;
struct winsize winsz;
int i;
- array_t overlays_s;
- array_t overlay_names_s;
- array_t overlay_src_s;
warnout = stderr;
IF_DEBUG(init_coredumps());
@@ -1265,12 +1261,9 @@ int main(int argc, char **argv)
/* ensure any err/warn doesn't use unitialised vars */
color_clear();
- VAL_CLEAR(overlays_s);
- VAL_CLEAR(overlay_names_s);
- VAL_CLEAR(overlay_src_s);
- overlays = &overlays_s;
- overlay_names = &overlay_names_s;
- overlay_src = &overlay_src_s;
+ overlays = array_new();
+ overlay_names = array_new();
+ overlay_src = array_new();
/* initialise all the properties with their default value */
for (i = 0; vars_to_read[i].name; ++i) {
diff --git a/q.c b/q.c
index 69b0273..2fd57a5 100644
--- a/q.c
+++ b/q.c
@@ -633,13 +633,10 @@ int q_main(int argc, char **argv)
printf("%s\"%s\"%s", RED,
*var->value.s, NORM);
break;
case _Q_ISET: {
- array_t vals_s;
- array_t *vals = &vals_s;
+ array *vals = array_new();
size_t n;
char *val;
- VAL_CLEAR(vals_s);
-
printf("%s\"", RED);
array_set(*var->value.t, vals);
array_for_each(vals, n, val) {
@@ -673,13 +670,10 @@ int q_main(int argc, char **argv)
printf("%s%s%s", RED,
*var->value.s, NORM);
break;
case _Q_ISET: {
- array_t vals_s;
- array_t *vals = &vals_s;
+ array *vals = array_new();
size_t n;
char *val;
- VAL_CLEAR(vals_s);
-
array_set(*var->value.t, vals);
array_for_each(vals, n, val) {
printf("%s%s", n == 0 ?
RED : " ", val);
@@ -699,10 +693,8 @@ int q_main(int argc, char **argv)
}
if (print_masks) {
- array_t masks_s;
- array_t files_s;
- array_t *masks = &masks_s;
- array_t *files = &files_s;
+ array *masks = array_new();
+ array *files = array_new();
char *mask;
size_t n;
int j;
@@ -715,9 +707,6 @@ int q_main(int argc, char **argv)
depend_atom *atom;
depend_atom *qatom;
- VAL_CLEAR(masks_s);
- VAL_CLEAR(files_s);
-
array_set(package_masks, masks);
values_set(package_masks, files);
@@ -741,7 +730,7 @@ int q_main(int argc, char **argv)
continue;
if (verbose > 1) {
- char *mfile = (char *)array_get_elem(files, n);
+ char *mfile = (char *)array_get(files, n);
char *l;
char *s = NULL;
long line = 0;
@@ -790,7 +779,7 @@ int q_main(int argc, char **argv)
atom));
if (verbose == 1) {
- printf(" [%s%s]\n", portroot, (char
*)array_get_elem(files, n));
+ printf(" [%s%s]\n", portroot, (char
*)array_get(files, n));
} else {
printf("\n");
}
diff --git a/qcheck.c b/qcheck.c
index 86707c9..9ca2ed9 100644
--- a/qcheck.c
+++ b/qcheck.c
@@ -59,8 +59,8 @@ static const char * const qcheck_opts_help[] = {
#define qcprintf(fmt, args...) do { if (!state->bad_only) printf(fmt, ##
args); } while (0)
struct qcheck_opt_state {
- array_t *atoms;
- array_t *regex_arr;
+ array *atoms;
+ array *regex_arr;
bool bad_only;
bool qc_update;
bool chk_afk;
@@ -431,11 +431,9 @@ int qcheck_main(int argc, char **argv)
int ret;
tree_ctx *vdb;
depend_atom *atom;
- array_t regex_arr;
- array_t atoms;
struct qcheck_opt_state state = {
- .atoms = &atoms,
- .regex_arr = ®ex_arr,
+ .atoms = array_new(),
+ .regex_arr = array_new(),
.bad_only = false,
.qc_update = false,
.chk_afk = true,
@@ -446,9 +444,6 @@ int qcheck_main(int argc, char **argv)
.fmt = NULL,
};
- VAL_CLEAR(regex_arr);
- VAL_CLEAR(atoms);
-
while ((ret = GETOPT_LONG(QCHECK, qcheck, "")) != -1) {
switch (ret) {
COMMON_GETOPTS_CASES(qcheck)
diff --git a/qdepends.c b/qdepends.c
index cb2aec7..3d36c98 100644
--- a/qdepends.c
+++ b/qdepends.c
@@ -58,8 +58,7 @@ static const char * const qdepends_opts_help[] = {
/* structures / types / etc ... */
struct qdepends_opt_state {
unsigned int qmode;
- array_t *atoms;
- array_t *deps;
+ array *atoms;
set *udeps;
char *depend;
size_t depend_len;
@@ -119,6 +118,7 @@ qdepends_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
depend_atom *atom;
depend_atom *datom;
depend_atom *fatom;
+ array *deps;
bool firstmatch = false;
char buf[_Q_PATH_MAX];
const char **dfile;
@@ -165,7 +165,6 @@ qdepends_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
printf("%s:", atom_format(state->format, datom));
}
- xarrayfree_int(state->deps);
clear_set(state->udeps);
#define get_depstr(X) \
@@ -193,6 +192,8 @@ qdepends_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
if (state->resolve)
dep_resolve_tree(dep_tree, state->rtree);
+ deps = array_new();
+
if (state->qmode & QMODE_TREE &&
!(state->qmode & QMODE_REVERSE) &&
verbose)
@@ -208,7 +209,7 @@ qdepends_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
if (depstr != NULL) {
dep_node *dep_vdb =
dep_grow_tree(depstr);
if (dep_vdb != NULL) {
-
dep_flatten_tree(dep_vdb, state->deps);
+
dep_flatten_tree(dep_vdb, deps);
dep_burn_tree(dep_vdb);
} else {
warn("failed to parse
VDB depstring from %s\n",
@@ -222,12 +223,12 @@ qdepends_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
} else {
if (state->qmode & QMODE_FILTERUSE)
dep_prune_use(dep_tree, ev_use);
- dep_flatten_tree(dep_tree, state->deps);
+ dep_flatten_tree(dep_tree, deps);
}
if (verbose) {
if (state->qmode & QMODE_REVERSE) {
- array_for_each(state->deps, m, atom) {
+ array_for_each(deps, m, atom) {
array_for_each(state->atoms, n, fatom) {
if (atom_compare(atom, fatom)
== EQUAL) {
fatom = NULL;
@@ -255,13 +256,13 @@ qdepends_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
}
} else {
printf("\n%s=\"\n", *dfile);
- dep_print_tree(stdout, dep_tree, 1, state->deps,
+ dep_print_tree(stdout, dep_tree, 1, deps,
GREEN, verbose > 1);
printf("\"");
}
} else {
if (state->qmode & QMODE_REVERSE) {
- array_for_each(state->deps, m, atom) {
+ array_for_each(deps, m, atom) {
array_for_each(state->atoms, n, fatom) {
if (atom_compare(atom, fatom)
== EQUAL) {
fatom = NULL;
@@ -289,15 +290,13 @@ qdepends_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
}
}
} else {
- array_for_each(state->deps, m, atom)
+ array_for_each(deps, m, atom)
state->udeps =
add_set_unique(atom_to_string(atom),
state->udeps, NULL);
}
}
- array_for_each(state->deps, m, atom)
- atom_implode(atom);
- xarrayfree_int(state->deps);
+ array_deepfree(deps, (array_free_cb *)atom_implode);
dep_burn_tree(dep_tree);
}
if (verbose && ret == 1)
@@ -320,11 +319,8 @@ qdepends_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
int qdepends_main(int argc, char **argv)
{
depend_atom *atom;
- array_t atoms;
- array_t deps;
struct qdepends_opt_state state = {
- .atoms = &atoms,
- .deps = &deps,
+ .atoms = array_new(),
.udeps = create_set(),
.qmode = 0,
.format = "%[CATEGORY]%[PF]",
@@ -336,9 +332,6 @@ int qdepends_main(int argc, char **argv)
int ret;
bool do_pretty = false;
- VAL_CLEAR(atoms);
- VAL_CLEAR(deps);
-
if (quiet)
state.format = "%[CATEGORY]%[PN]";
@@ -382,6 +375,7 @@ int qdepends_main(int argc, char **argv)
if ((argc == optind) && !do_pretty) {
free_set(state.udeps);
+ array_free(state.atoms);
qdepends_usage(EXIT_FAILURE);
}
@@ -395,6 +389,7 @@ int qdepends_main(int argc, char **argv)
if (optind < argc)
fprintf(stdout, "\n");
}
+ array_free(state.atoms);
free_set(state.udeps);
return ret;
}
@@ -461,10 +456,7 @@ int qdepends_main(int argc, char **argv)
if (state.depend != NULL)
free(state.depend);
- array_for_each(state.atoms, i, atom)
- atom_implode(atom);
- xarrayfree_int(state.atoms);
- xarrayfree_int(state.deps);
+ array_deepfree(state.atoms, (array_free_cb *)atom_implode);
free_set(state.udeps);
if (!ret)
diff --git a/qkeyword.c b/qkeyword.c
index fb14ce3..76bc7cc 100644
--- a/qkeyword.c
+++ b/qkeyword.c
@@ -235,7 +235,7 @@ qkeyword_kw(tree_pkg_ctx *pkg_ctx, void *priv, int what)
{
qkeyword_data *data = (qkeyword_data *)priv;
depend_atom *atom;
- array_t *masks;
+ array *masks;
if (data->keywordsbuf[qkeyword_test_arch] == what)
{
@@ -898,23 +898,21 @@ int qkeyword_main(int argc, char **argv)
/* prepare masks for easy(er) matching by key-ing on CAT/PN */
{
- array_t masks_s;
- array_t *masks;
- array_t *bucket;
- array_t *ebuck;
+ array *masks;
+ array *bucket;
+ array *ebuck;
size_t n;
char *mask;
depend_atom *atom;
- VAL_CLEAR(masks_s);
- masks = &masks_s;
+ masks = array_new();
pmasks = create_set();
array_set(package_masks, masks);
array_for_each(masks, n, mask) {
if ((atom = atom_explode(mask)) == NULL)
continue;
- bucket = xzalloc(sizeof(array_t));
+ bucket = array_new();
xarraypush_ptr(bucket, atom);
pmasks = add_set_value(atom_format("%[CAT]%[PN]", atom),
bucket,
(void **)&ebuck, pmasks);
diff --git a/qlist.c b/qlist.c
index 19c8d44..d63c810 100644
--- a/qlist.c
+++ b/qlist.c
@@ -251,15 +251,12 @@ qlist_match(
}
if (applymasks) {
- array_t masks_s;
- array_t *masks = &masks_s;
+ array *masks = array_new();
depend_atom *matom;
char *mask;
size_t n;
bool match = false;
- VAL_CLEAR(masks_s);
-
array_set(package_masks, masks);
array_for_each(masks, n, mask) {
diff --git a/qlop.c b/qlop.c
index 5de8e83..b1eb074 100644
--- a/qlop.c
+++ b/qlop.c
@@ -415,7 +415,7 @@ deal with e.g. merging python-3.6 with 3.9 installed as
well.
static int do_emerge_log(
const char *log,
struct qlop_mode *flags,
- array_t *atoms,
+ array *atoms,
time_t tbegin,
time_t tend)
{
@@ -435,10 +435,8 @@ static int do_emerge_log(
depend_atom *atom;
depend_atom *atomw;
depend_atom *upgrade_atom = NULL;
- array_t merge_matches_s;
- array_t unmerge_matches_s;
- array_t *merge_matches = &merge_matches_s;
- array_t *unmerge_matches = &unmerge_matches_s;
+ array *merge_matches = array_new();
+ array *unmerge_matches = array_new();
set *merge_averages = create_set();
set *unmerge_averages = create_set();
set *atomset = NULL;
@@ -451,9 +449,6 @@ static int do_emerge_log(
struct pkg_match *pkgw;
#define strpfx(X, Y) strncmp(X, Y, sizeof(Y) - 1)
- VAL_CLEAR(merge_matches_s);
- VAL_CLEAR(unmerge_matches_s);
-
/* support relative path in here and now, when using ROOT, stick to
* it, turning relative into a moot point */
if (portroot[1] == '\0')
@@ -523,10 +518,7 @@ static int do_emerge_log(
* "valid" one, such that dummy emerge calls
(e.g.
* emerge -pv foo) are ignored */
if (last_merge != tstart_emerge) {
- array_t vals_s;
- array_t *vals = &vals_s;
-
- VAL_CLEAR(vals_s);
+ array *vals = array_new();
values_set(atomset, vals);
array_for_each(vals, i, atomw)
@@ -595,15 +587,15 @@ static int do_emerge_log(
sync_start = 0;
while ((i = array_cnt(merge_matches)) > 0) {
i--;
- pkgw = xarrayget(merge_matches, i);
+ pkgw = array_remove(merge_matches, i);
atom_implode(pkgw->atom);
- xarraydelete(merge_matches, i);
+ free(pkgw);
}
while ((i = array_cnt(unmerge_matches)) > 0) {
i--;
- pkgw = xarrayget(unmerge_matches, i);
+ pkgw = array_remove(unmerge_matches, i);
atom_implode(pkgw->atom);
- xarraydelete(unmerge_matches, i);
+ free(pkgw);
}
}
}
@@ -1185,10 +1177,7 @@ static int do_emerge_log(
size_t total_merges = 0;
size_t total_unmerges = 0;
time_t total_time = (time_t)0;
- array_t avgs_s;
- array_t *avgs = &avgs_s;
-
- VAL_CLEAR(avgs_s);
+ array *avgs = array_new();
values_set(merge_averages, avgs);
xarraysort(avgs, pkg_sort_cb);
@@ -1202,6 +1191,7 @@ static int do_emerge_log(
}
xarrayfree_int(avgs);
+ avgs = array_new();
values_set(unmerge_averages, avgs);
xarraysort(avgs, pkg_sort_cb);
array_for_each(avgs, i, pkg) {
@@ -1239,15 +1229,12 @@ static int do_emerge_log(
printf("\n");
}
} else if (flags->do_predict) {
- array_t avgs_s;
- array_t *avgs = &avgs_s;
+ array *avgs = array_new();
enum { P_INIT = 0, P_SREV, P_SRCH } pkgstate;
size_t j;
time_t ptime;
char found;
- VAL_CLEAR(avgs_s);
-
values_set(merge_averages, avgs);
xarraysort(avgs, pkg_sort_cb);
xarraysort(atoms, atom_compar_cb);
@@ -1355,10 +1342,7 @@ static int do_emerge_log(
}
{
- array_t t_s;
- array_t *t = &t_s;
-
- VAL_CLEAR(t_s);
+ array *t = array_new();
values_set(merge_averages, t);
array_for_each(t, i, pkgw) {
@@ -1366,6 +1350,7 @@ static int do_emerge_log(
free(pkgw);
}
xarrayfree_int(t);
+ t = array_new();
values_set(unmerge_averages, t);
array_for_each(t, i, pkgw) {
atom_implode(pkgw->atom);
@@ -1386,10 +1371,7 @@ static int do_emerge_log(
}
xarrayfree(unmerge_matches);
if (atomset != NULL) {
- array_t t_s;
- array_t *t = &t_s;
-
- VAL_CLEAR(t_s);
+ array *t = array_new();
values_set(atomset, t);
array_for_each(t, i, atom)
@@ -1402,7 +1384,7 @@ static int do_emerge_log(
/* scan through /proc for running merges, this requires portage user
* or root */
-static array_t *probe_proc(array_t *atoms)
+static array *probe_proc(array *atoms)
{
struct dirent **procs = NULL;
int procslen;
@@ -1418,14 +1400,11 @@ static array_t *probe_proc(array_t *atoms)
ssize_t rpathlen;
char *p;
depend_atom *atom;
- array_t ret_atoms_s;
- array_t *ret_atoms = &ret_atoms_s;
+ array *ret_atoms = array_new();
size_t i;
char *cmdline = NULL;
size_t cmdlinesize = 0;
- VAL_CLEAR(ret_atoms_s);
-
/* /proc/<pid>/path/<[0-9]+link>
* /proc/<pid>/fd/<[0-9]+link> */
if ((procslen = scandir("/proc", &procs, NULL, NULL)) > 0) {
@@ -1608,12 +1587,9 @@ int qlop_main(int argc, char **argv)
char *p;
char *q;
depend_atom *atom;
- array_t atoms_s;
- array_t *atoms = &atoms_s;
+ array *atoms = array_new();
int runningmode = 0;
- VAL_CLEAR(atoms_s);
-
start_time = -1;
end_time = -1;
m.do_time = 0;
@@ -1806,7 +1782,7 @@ int qlop_main(int argc, char **argv)
end_time = LONG_MAX;
if (m.do_running) {
- array_t *new_atoms = NULL;
+ array *new_atoms = NULL;
if (runningmode > 1) {
warn("running without /proc scanning, heuristics only");
diff --git a/qmanifest.c b/qmanifest.c
index cbf9459..e018d35 100644
--- a/qmanifest.c
+++ b/qmanifest.c
@@ -1775,8 +1775,16 @@ qmanifest_main(int argc, char **argv)
repolen = 0;
snprintf(path, sizeof(path),
"%s/profiles/repo_name", overlay);
if (eat_file(path, &repo, &repolen)) {
- free(array_get_elem(overlays, n));
- array_get_elem(overlays, n) = repo;
+ void *name;
+ void *src;
+
+ array_delete(overlays, n, NULL);
+ name = array_remove(overlay_names, n);
+ src = array_remove(overlay_src, n);
+
+ array_append(overlays, repo);
+ array_append(overlay_names, name);
+ array_append(overlay_src, src);
} else {
free(repo);
}
diff --git a/qpkg.c b/qpkg.c
index da15171..51cb3bc 100644
--- a/qpkg.c
+++ b/qpkg.c
@@ -78,8 +78,7 @@ qpkg_clean(qpkg_cb_args *args)
uint64_t num_all_bytes = 0;
set *known_pkgs = NULL;
set *bin_pkgs = NULL;
- array_t bins_s;
- array_t *bins = &bins_s;
+ array *bins = array_new();
tree_ctx *t;
tree_ctx *pkgs;
char *binatomstr;
@@ -90,8 +89,6 @@ qpkg_clean(qpkg_cb_args *args)
if (pkgs == NULL)
return 1;
- VAL_CLEAR(bins_s);
-
bin_pkgs = tree_get_atoms(pkgs, true, bin_pkgs);
if (bin_pkgs == NULL)
return 1;
diff --git a/qsize.c b/qsize.c
index d74ebe6..b154d4b 100644
--- a/qsize.c
+++ b/qsize.c
@@ -81,7 +81,7 @@ static const char * const qsize_opts_help[] = {
#define qsize_usage(ret) usage(ret, QSIZE_FLAGS, qsize_long_opts,
qsize_opts_help, NULL, lookup_applet_idx("qsize"))
struct qsize_opt_state {
- array_t *atoms;
+ array *atoms;
char **argv;
char search_all;
char fs_size;
@@ -89,7 +89,7 @@ struct qsize_opt_state {
char summary_only;
size_t disp_units;
const char *str_disp_units;
- array_t *ignore_regexp;
+ array *ignore_regexp;
const char *fmt;
bool need_full_atom:1;
@@ -189,18 +189,16 @@ int qsize_main(int argc, char **argv)
size_t i;
int ret;
tree_ctx *vdb;
- array_t ignore_regexp;
- array_t atoms;
depend_atom *atom;
struct qsize_opt_state state = {
- .atoms = &atoms,
+ .atoms = array_new(),
.search_all = 0,
.fs_size = 0,
.summary = 0,
.summary_only = 0,
.disp_units = 0,
.str_disp_units = NULL,
- .ignore_regexp = &ignore_regexp,
+ .ignore_regexp = array_new(),
.uniq_files = create_set(),
.num_all_files = 0,
.num_all_nonfiles = 0,
@@ -210,9 +208,6 @@ int qsize_main(int argc, char **argv)
.fmt = NULL,
};
- VAL_CLEAR(ignore_regexp);
- VAL_CLEAR(atoms);
-
while ((ret = GETOPT_LONG(QSIZE, qsize, "")) != -1) {
switch (ret) {
COMMON_GETOPTS_CASES(qsize)
diff --git a/qwhich.c b/qwhich.c
index 610eb30..7cf691d 100644
--- a/qwhich.c
+++ b/qwhich.c
@@ -71,10 +71,8 @@ struct qwhich_mode {
int qwhich_main(int argc, char **argv)
{
depend_atom *atom;
- array_t atoms_s;
- array_t trees_s;
- array_t *atoms = &atoms_s;
- array_t *trees = &trees_s;
+ array *atoms = array_new();
+ array *trees = array_new();
struct qwhich_mode m;
struct tree_match_ctx *tmc;
struct tree_match_ctx *tmcw;
@@ -90,8 +88,6 @@ int qwhich_main(int argc, char **argv)
const char *ext;
VAL_CLEAR(m);
- VAL_CLEAR(atoms_s);
- VAL_CLEAR(trees_s);
while ((ret = GETOPT_LONG(QWHICH, qwhich, "")) != -1) {
switch (ret) {