Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
internal: replace kvec with tllist
Baptiste Daroussin committed 4 years ago
commit 3fdd5e15ef2b7813fac4065083bd96fa8555224e
parent 91b74a4
9 files changed +290 -128
added external/include/tllist.h
@@ -0,0 +1,192 @@
+
#pragma once
+

+
#include <stdlib.h>
+
#include <stddef.h>
+
#include <assert.h>
+

+
#define TLL_PASTE2( a, b) a##b
+
#define TLL_PASTE( a, b) TLL_PASTE2( a, b)
+

+
/* Utility macro to generate a list element struct with a unique struct tag */
+
#define TLL_UNIQUE_INNER_STRUCT(TYPE, ID)      \
+
    struct TLL_PASTE(__tllist_ , ID) {         \
+
        TYPE item;                             \
+
        struct TLL_PASTE(__tllist_, ID) *prev; \
+
        struct TLL_PASTE(__tllist_, ID) *next; \
+
    } *head, *tail;
+

+
/*
+
 * Defines a new typed-list type, or directly instantiate a typed-list variable
+
 *
+
 * Example a, declare a variable (list of integers):
+
 *  tll(int) my_list;
+
 *
+
 * Example b, declare a type, and then use the type:
+
 *   tll(int, my_list_type);
+
 *   struct my_list_type my_list;
+
 */
+
#define tll(TYPE)                                                       \
+
    struct {                                                            \
+
        TLL_UNIQUE_INNER_STRUCT(TYPE, __COUNTER__)                      \
+
        size_t length;                                                  \
+
    }
+

+
/* Initializer: tll(int) my_list = tll_init(); */
+
#define tll_init() {.head = NULL, .tail = NULL, .length = 0}
+

+
/* Length/size of list: printf("size: %zu\n", tll_length(my_list)); */
+
#define tll_length(list) (list).length
+

+
/* Adds a new item to the back of the list */
+
#define tll_push_back(list, new_item)                   \
+
    do {                                                \
+
        tll_insert_after(list, (list).tail, new_item);  \
+
        if ((list).head == NULL)                        \
+
            (list).head = (list).tail;                  \
+
    } while (0)
+

+
/* Adds a new item to the front of the list */
+
#define tll_push_front(list, new_item) \
+
    do {                                                \
+
        tll_insert_before(list, (list).head, new_item); \
+
        if ((list).tail == NULL)                        \
+
            (list).tail = (list).head;                  \
+
    } while (0)
+

+
/*
+
 * Iterates the list. <it> is an iterator pointer. You can access the
+
 * list item with ->item:
+
 *
+
 *   tll(int) my_list = vinit();
+
 *   tll_push_back(my_list, 5);
+
 *
+
 *   tll_foreach(my_list i) {
+
 *       printf("%d\n", i->item);
+
 *   }
+
*/
+
#define tll_foreach(list, it)                                           \
+
    for (__typeof__(*(list).head) *it = (list).head,                    \
+
             *it_next = it != NULL ? it->next : NULL;                   \
+
         it != NULL;                                                    \
+
         it = it_next,                                                  \
+
             it_next = it_next != NULL ? it_next->next : NULL)
+

+
/* Same as tll_foreach(), but iterates backwards */
+
#define tll_rforeach(list, it)                                          \
+
    for (__typeof__(*(list).tail) *it = (list).tail,                    \
+
             *it_prev = it != NULL ? it->prev : NULL;                   \
+
         it != NULL;                                                    \
+
         it = it_prev,                                                  \
+
             it_prev = it_prev != NULL ? it_prev->prev : NULL)
+

+
/*
+
 * Inserts a new item after <it>, which is an iterator. I.e. you can
+
 * only call this from inside a tll_foreach() or tll_rforeach() loop.
+
 */
+
#define tll_insert_after(list, it, new_item) \
+
    do {                                                    \
+
        __typeof__((list).head) __e = malloc(sizeof(*__e)); \
+
        __e->item = (new_item);                             \
+
        __e->prev = (it);                                   \
+
        __e->next = (it) != NULL ? (it)->next : NULL;       \
+
        if ((it) != NULL) {                                 \
+
            if ((it)->next != NULL)                         \
+
                (it)->next->prev = __e;                     \
+
            (it)->next = __e;                               \
+
        }                                                   \
+
        if ((it) == (list).tail)                            \
+
            (list).tail = __e;                              \
+
        (list).length++;                                    \
+
    } while (0)
+

+
/*
+
 * Inserts a new item before <it>, which is an iterator. I.e. you can
+
 * only call this from inside a tll_foreach() or tll_rforeach() loop.
+
 */
+
#define tll_insert_before(list, it, new_item)   \
+
    do {                                                    \
+
        __typeof__((list).head) __e = malloc(sizeof(*__e)); \
+
        __e->item = (new_item);                             \
+
        __e->prev = (it) != NULL ? (it)->prev : NULL;       \
+
        __e->next = (it);                                   \
+
        if ((it) != NULL) {                                 \
+
            if ((it)->prev != NULL)                         \
+
                (it)->prev->next = __e;                     \
+
            (it)->prev = __e;                               \
+
        }                                                   \
+
        if ((it) == (list).head)                            \
+
            (list).head = __e;                              \
+
        (list).length++;                                    \
+
    } while (0)
+

+
/*
+
 * Removes an entry from the list. <it> is an iterator. I.e. you can
+
 * only call this from inside a tll_foreach() or tll_rforeach() loop.
+
 */
+
#define tll_remove(list, it)                              \
+
    do {                                                  \
+
        assert((list).length > 0);                        \
+
        __typeof__((list).head) __prev = it->prev;        \
+
        __typeof__((list).head) __next = it->next;        \
+
        if (__prev != NULL)                               \
+
            __prev->next = __next;                        \
+
        else                                              \
+
            (list).head = __next;                         \
+
        if (__next != NULL)                               \
+
            __next->prev = __prev;                        \
+
        else                                              \
+
            (list).tail = __prev;                         \
+
        free(it);                                         \
+
        (list).length--;                                  \
+
    } while (0)
+

+
/* Same as tll_remove(), but calls free_callback(it->item) */
+
#define tll_remove_and_free(list, it, free_callback)            \
+
    do {                                                        \
+
        free_callback((it)->item);                              \
+
        tll_remove((list), (it));                               \
+
    } while (0)
+

+
#define tll_front(list) (list).head->item
+
#define tll_back(list) (list).tail->item
+

+
/*
+
 * Removes the first element from the list, and returns it (note:
+
 * returns the *actual* item, not an iterator.
+
 */
+
#define tll_pop_front(list) __extension__                  \
+
    ({                                                     \
+
        __typeof__((list).head) it = (list).head;          \
+
        __typeof__((list).head->item) __ret = it->item;    \
+
        tll_remove((list), it);                            \
+
        __ret;                                             \
+
    })
+

+
/* Same as tll_pop_front(), but returns/removes the *last* element */
+
#define tll_pop_back(list) __extension__                                \
+
    ({                                                                  \
+
        __typeof__((list).tail) it = (list).tail;                       \
+
        __typeof__((list).tail->item) __ret = it->item;                 \
+
        tll_remove((list), it);                                         \
+
        __ret;                                                          \
+
    })
+

+
/* Frees the list. This call is *not* needed if the list is already empty. */
+
#define tll_free(list)                          \
+
    do {                                        \
+
        tll_foreach(list, __it)                 \
+
            free(__it);                         \
+
        (list).length = 0;                      \
+
        (list).head = (list).tail = NULL;       \
+
    } while (0)
+

+
/* Same as tll_free(), but also calls free_callback(item) for every item */
+
#define tll_free_and_free(list, free_callback)              \
+
    do {                                                    \
+
        tll_foreach(list, __it) {                           \
+
            free_callback(__it->item);                      \
+
            free(__it);                                     \
+
        }                                                   \
+
        (list).length = 0;                                  \
+
        (list).head = (list).tail = NULL;                   \
+
    } while (0)
modified libpkg/pkg_jobs.c
@@ -64,7 +64,7 @@
#include "private/pkg.h"
#include "private/pkgdb.h"
#include "private/pkg_jobs.h"
-
#include "kvec.h"
+
#include "tllist.h"

extern struct pkg_ctx ctx;

@@ -436,13 +436,12 @@ pkg_jobs_process_add_request(struct pkg_jobs *j)
	struct pkg_dep *d;
	struct pkg *lp;
	int (*deps_func)(const struct pkg *pkg, struct pkg_dep **d);
-
	kvec_t(struct pkg_job_universe_item *) to_process;
+
	tll(struct pkg_job_universe_item *) to_process = tll_init();
	pkghash_it hit;

	if (!upgrade && !reverse)
		return;

-
	kv_init(to_process);
	hit = pkghash_iterator(j->request_add);
	while (pkghash_next(&hit)) {
		req = hit.value;
@@ -482,7 +481,7 @@ pkg_jobs_process_add_request(struct pkg_jobs *j)
			cur = un->prev;
			while (cur != un) {
				if (cur->pkg->type != PKG_INSTALLED) {
-
					kv_push(typeof(un), to_process, un);
+
					tll_push_back(to_process, un);
					break;
				}
				cur = cur->prev;
@@ -491,15 +490,15 @@ pkg_jobs_process_add_request(struct pkg_jobs *j)
	}

	/* Add all items to the request */
-
	for (int i = 0; i < kv_size(to_process); i++) {
-
		un = kv_A(to_process, i);
+
	tll_foreach(to_process, pit) {
+
		un = pit->item;
		pkg_jobs_add_req_from_universe(&j->request_add, un, false, true);
	}
	/* Now recursively process all items checked */
-
	if (kv_size(to_process) > 0)
+
	if (tll_length(to_process) > 0)
		pkg_jobs_process_add_request(j);

-
	kv_destroy(to_process);
+
	tll_free(to_process);
}

/*
@@ -513,13 +512,12 @@ pkg_jobs_process_delete_request(struct pkg_jobs *j)
	struct pkg_dep *d = NULL;
	struct pkg *lp;
	int rc = EPKG_OK;
-
	kvec_t(struct pkg *) to_process;
+
	tll(struct pkg *) to_process = tll_init();
	pkghash_it it;

	if (force)
		return (EPKG_OK);

-
	kv_init(to_process);
	/*
	 * Need to add also all reverse deps here
	 */
@@ -539,7 +537,7 @@ pkg_jobs_process_delete_request(struct pkg_jobs *j)
					   req->item->pkg->name);
					rc = EPKG_FATAL;
				}
-
				kv_push(typeof(lp), to_process, lp);
+
				tll_push_back(to_process, lp);
			}
		}
	}
@@ -547,16 +545,16 @@ pkg_jobs_process_delete_request(struct pkg_jobs *j)
	if (rc == EPKG_FATAL)
		return (rc);

-
	for (int i = 0; i < kv_size(to_process); i++) {
-
		lp = kv_A(to_process, i);
+
	tll_foreach(to_process, pit) {
+
		lp = pit->item;
		if (pkg_jobs_add_req(j, lp) == NULL) {
-
			kv_destroy(to_process);
+
			tll_free(to_process);
			return (EPKG_FATAL);
		}
	}
-
	if (kv_size(to_process) > 0)
+
	if (tll_length(to_process) > 0)
		rc = pkg_jobs_process_delete_request(j);
-
	kv_destroy(to_process);
+
	tll_free(to_process);

	return (rc);
}
modified libpkg/pkg_jobs_universe.c
@@ -43,11 +43,11 @@
#include "private/pkg.h"
#include "private/pkgdb.h"
#include "private/pkg_jobs.h"
-
#include "kvec.h"
+
#include "tllist.h"

#define IS_DELETE(j) ((j)->type == PKG_JOBS_DEINSTALL || (j)->type == PKG_JOBS_AUTOREMOVE)

-
typedef kvec_t(struct pkg *) pkg_chain_t;
+
typedef tll(struct pkg *) pkg_chain_t;

struct pkg *
pkg_jobs_universe_get_local(struct pkg_jobs_universe *universe,
@@ -139,7 +139,7 @@ pkg_jobs_universe_get_remote(struct pkg_jobs_universe *universe,
	while (pkgdb_it_next(it, &pkg, flag) == EPKG_OK) {
		if (result == NULL)
			result = xcalloc(1, sizeof(pkg_chain_t));
-
		kv_prepend(typeof(pkg), *result, pkg);
+
		tll_push_front(*result, pkg);
		pkg = NULL;
	}

@@ -318,8 +318,8 @@ pkg_jobs_universe_process_deps(struct pkg_jobs_universe *universe,

		found = false;
		/* Iteration one */
-
		for (int i = 0; i < kv_size(*rpkgs); i++) {
-
			rpkg = kv_A(*rpkgs, i);
+
		tll_foreach(*rpkgs, rit) {
+
			rpkg = rit->item;

			if (pkg->reponame && rpkg->reponame &&
					strcmp (pkg->reponame, rpkg->reponame) == 0) {
@@ -330,8 +330,8 @@ pkg_jobs_universe_process_deps(struct pkg_jobs_universe *universe,

		/* Fallback if a dependency is not found in the same repo */
		if (!found) {
-
			for (int i = 0; i < kv_size(*rpkgs); i++) {
-
				rpkg = kv_A(*rpkgs, i);
+
			tll_foreach(*rpkgs, rit) {
+
				rpkg = rit->item;

				if (npkg != NULL) {
					/* Set reason for upgrades */
@@ -345,7 +345,7 @@ pkg_jobs_universe_process_deps(struct pkg_jobs_universe *universe,

				/* Special case if we cannot find any package */
				if (npkg == NULL && rc != EPKG_OK) {
-
					kv_destroy(*rpkgs);
+
					tll_free(*rpkgs);
					free(rpkgs);
					return (rc);
				}
@@ -364,13 +364,13 @@ pkg_jobs_universe_process_deps(struct pkg_jobs_universe *universe,

			rc = pkg_jobs_universe_process_item(universe, rpkg, NULL);
			if (npkg == NULL && rc != EPKG_OK) {
-
				kv_destroy(*rpkgs);
+
				tll_free(*rpkgs);
				free(rpkgs);
				return (rc);
			}
		}

-
		kv_destroy(*rpkgs);
+
		tll_free(*rpkgs);
		free(rpkgs);
	}

@@ -1173,7 +1173,7 @@ pkg_jobs_universe_get_upgrade_candidates(struct pkg_jobs_universe *universe,
					PKG_LOAD_REQUIRES|PKG_LOAD_PROVIDES|
					PKG_LOAD_SHLIBS_REQUIRED|PKG_LOAD_SHLIBS_PROVIDED|
					PKG_LOAD_ANNOTATIONS|PKG_LOAD_CONFLICTS;
-
	kvec_t(struct pkg *) candidates;
+
	tll(struct pkg *) candidates = tll_init();

	unit = pkghash_get_value(universe->items, uid);
	if (unit != NULL) {
@@ -1201,7 +1201,6 @@ pkg_jobs_universe_get_upgrade_candidates(struct pkg_jobs_universe *universe,
		universe->j->reponame)) == NULL)
		return (NULL);

-
	kv_init(candidates);
	while (pkgdb_it_next(it, &pkg, flag) == EPKG_OK) {

		if (version != NULL && strcmp(pkg->version, version) != 0)
@@ -1218,7 +1217,7 @@ pkg_jobs_universe_get_upgrade_candidates(struct pkg_jobs_universe *universe,
			else if (pkg_version_change_between(pkg, selected) == PKG_UPGRADE)
				selected = pkg;
		}
-
		kv_prepend(typeof(pkg), candidates, pkg);
+
		tll_push_front(candidates, pkg);
		pkg = NULL;
	}

@@ -1230,20 +1229,17 @@ pkg_jobs_universe_get_upgrade_candidates(struct pkg_jobs_universe *universe,
	}
	if (selected != lp) {
		/* We need to add the whole chain of upgrade candidates */
-
		for (int i = 0; i < kv_size(candidates); i++) {
-
			pkg_jobs_universe_add_pkg(universe, kv_A(candidates, i), force, NULL);
+
		tll_foreach(candidates, cit) {
+
			pkg_jobs_universe_add_pkg(universe, cit->item, force, NULL);
		}
	}
	else {
-
		while (kv_size(candidates) > 0)
-
			pkg_free(kv_pop(candidates));
-
		kv_destroy(candidates);
-

+
		tll_free_and_free(candidates, pkg_free);
		return (NULL);
	}

	unit = pkghash_get_value(universe->items, uid);
-
	kv_destroy(candidates);
+
	tll_free(candidates);

	return (unit);
}
modified libpkg/pkg_solve.c
@@ -35,7 +35,7 @@
#include <string.h>
#include <ctype.h>
#include <math.h>
-
#include <kvec.h>
+
#include <tllist.h>

#include "pkg.h"
#include "private/event.h"
@@ -98,7 +98,7 @@ struct pkg_solve_rule {

struct pkg_solve_problem {
	struct pkg_jobs *j;
-
	kvec_t(struct pkg_solve_rule *) rules;
+
	tll(struct pkg_solve_rule *) rules;
	pkghash *variables_by_uid;
	struct pkg_solve_variable *variables;
	PicoSAT *sat;
@@ -172,12 +172,8 @@ pkg_solve_rule_free(struct pkg_solve_rule *rule)
void
pkg_solve_problem_free(struct pkg_solve_problem *problem)
{
-
	while (kv_size(problem->rules)) {
-
		pkg_solve_rule_free(kv_pop(problem->rules));
-
	}
-

+
	tll_free_and_free(problem->rules, pkg_solve_rule_free);
	pkghash_destroy(problem->variables_by_uid);
-

	picosat_reset(problem->sat);
	free(problem->variables);
	free(problem);
@@ -379,7 +375,7 @@ pkg_solve_add_depend_rule(struct pkg_solve_problem *problem,
		return (EPKG_FATAL);
	}

-
	kv_prepend(typeof(rule), problem->rules, rule);
+
	tll_push_front(problem->rules, rule);

	return (EPKG_OK);
}
@@ -439,7 +435,7 @@ pkg_solve_add_conflict_rule(struct pkg_solve_problem *problem,
		/* !Bx */
		pkg_solve_item_new(rule, curvar, -1);

-
		kv_prepend(typeof(rule), problem->rules, rule);
+
		tll_push_front(problem->rules, rule);
	}

	return (EPKG_OK);
@@ -480,7 +476,7 @@ pkg_solve_add_require_rule(struct pkg_solve_problem *problem,
		}

		if (cnt > 1) {
-
			kv_prepend(typeof(rule), problem->rules, rule);
+
			tll_push_front(problem->rules, rule);
		}
		else {
			/* Missing dependencies... */
@@ -561,7 +557,7 @@ pkg_solve_add_request_rule(struct pkg_solve_problem *problem,
	}

	if (cnt > 1 && var->unit->inhash != 0) {
-
		kv_prepend(typeof(rule), problem->rules, rule);
+
		tll_push_front(problem->rules, rule);
		/* Also need to add pairs of conflicts */
		LL_FOREACH(req->item, item) {
			curvar = pkg_solve_find_var_in_chain(var, item->unit);
@@ -578,7 +574,7 @@ pkg_solve_add_request_rule(struct pkg_solve_problem *problem,
				/* !Bx */
				pkg_solve_item_new(rule, confvar, -1);

-
				kv_prepend(typeof(rule), problem->rules, rule);
+
				tll_push_front(problem->rules, rule);
			}
		}
	}
@@ -620,7 +616,7 @@ pkg_solve_add_chain_rule(struct pkg_solve_problem *problem,
			/* !Ay */
			pkg_solve_item_new(rule, confvar, -1);

-
			kv_prepend(typeof(rule), problem->rules, rule);
+
			tll_push_front(problem->rules, rule);
		}
	}

@@ -749,7 +745,6 @@ pkg_solve_jobs_to_sat(struct pkg_jobs *j)
	problem->nvars = j->universe->nitems;
	problem->variables = xcalloc(problem->nvars, sizeof(struct pkg_solve_variable));
	problem->sat = picosat_init();
-
	kv_init(problem->rules);

	if (problem->sat == NULL) {
		pkg_emit_errno("picosat_init", "pkg_solve_sat_problem");
@@ -783,7 +778,7 @@ pkg_solve_jobs_to_sat(struct pkg_jobs *j)
			goto err;
	}

-
	if (kv_size(problem->rules) == 0)
+
	if (tll_length(problem->rules) == 0)
		pkg_debug(1, "problem has no requests");

	return (problem);
@@ -979,8 +974,8 @@ pkg_solve_sat_problem(struct pkg_solve_problem *problem)
	int attempt = 0;
	struct pkg_solve_variable *var;

-
	for (i = 0; i < kv_size(problem->rules); i++) {
-
		rule = kv_A(problem->rules, i);
+
	tll_foreach(problem->rules, it) {
+
		rule = it->item;

		LL_FOREACH(rule->items, item) {
			picosat_add(problem->sat, item->var->order * item->inverse);
@@ -990,8 +985,8 @@ pkg_solve_sat_problem(struct pkg_solve_problem *problem)
		pkg_debug_print_rule(rule);
	}

-
	for (i = 0; i < kv_size(problem->rules); i++) {
-
		rule = kv_A(problem->rules, i);
+
	tll_foreach(problem->rules, it) {
+
		rule = it->item;
		pkg_solve_set_initial_assumption(problem, rule);
	}

@@ -1023,8 +1018,8 @@ reiterate:

			while (*failed) {
				var = &problem->variables[abs(*failed) - 1];
-
				for (i = 0; i < kv_size(problem->rules); i++) {
-
					rule = kv_A(problem->rules, i);
+
				tll_foreach(problem->rules, it) {
+
					rule = it->item;

					if (rule->reason != PKG_RULE_DEPEND) {
						LL_FOREACH(rule->items, item) {
@@ -1170,8 +1165,8 @@ pkg_solve_dot_export(struct pkg_solve_problem *problem, FILE *file)

	/* Print all variables as nodes */

-
	for (i = 0; i < kv_size(problem->rules); i++) {
-
		rule = kv_A(problem->rules, i);
+
	tll_foreach(problem->rules, rit) {
+
		rule = rit->item;
		struct pkg_solve_item *it = rule->items, *key_elt = NULL;

		switch(rule->reason) {
@@ -1227,10 +1222,10 @@ pkg_solve_dimacs_export(struct pkg_solve_problem *problem, FILE *f)
	struct pkg_solve_rule *rule;
	struct pkg_solve_item *it;

-
	fprintf(f, "p cnf %d %zu\n", (int)problem->nvars, kv_size(problem->rules));
+
	fprintf(f, "p cnf %d %zu\n", (int)problem->nvars, tll_length(problem->rules));

-
	for (unsigned int i = 0; i < kv_size(problem->rules); i++) {
-
		rule = kv_A(problem->rules, i);
+
	tll_foreach(problem->rules, rit) {
+
		rule = rit->item;
		LL_FOREACH(rule->items, it) {
			size_t order = it->var - problem->variables;
			if (order < problem->nvars)
modified libpkg/pkgdb.c
@@ -68,7 +68,7 @@
#include "private/pkgdb.h"
#include "private/utils.h"
#include "private/pkg_deps.h"
-
#include "kvec.h"
+
#include "tllist.h"

#include "private/db_upgrades.h"

@@ -3120,31 +3120,30 @@ pkgdb_begin_solver(struct pkgdb *db)
		"CREATE INDEX pkg_digest_id ON packages(origin, manifestdigest);";
	struct pkgdb_it *it;
	struct pkg *p = NULL;
-
	kvec_t(struct pkg *) pkglist;
+
	tll(struct pkg *) pkglist = tll_init();
	int rc = EPKG_OK;
	int64_t cnt = 0, cur = 0;

	it = pkgdb_query_cond(db, " WHERE manifestdigest IS NULL OR manifestdigest==''",
		NULL, MATCH_ALL);
	if (it != NULL) {
-
		kv_init(pkglist);
		while (pkgdb_it_next(it, &p, PKG_LOAD_BASIC|PKG_LOAD_OPTIONS) == EPKG_OK) {
			pkg_checksum_calculate(p, NULL, false, true, false);
-
			kv_prepend(typeof(p), pkglist, p);
+
			tll_push_front(pkglist, p);
			p = NULL;
			cnt ++;
		}
		pkgdb_it_free(it);

-
		if (kv_size(pkglist) > 0) {
+
		if (tll_length(pkglist) > 0) {
			rc = sql_exec(db->sqlite, update_digests_sql);
			if (rc != EPKG_OK) {
				ERROR_SQLITE(db->sqlite, update_digests_sql);
			}
			else {
				pkg_emit_progress_start("Updating database digests format");
-
				for (int i = 0; i < kv_size(pkglist); i++) {
-
					p = kv_A(pkglist, i);
+
				tll_foreach(pkglist, pit) {
+
					p = pit->item;
					pkg_emit_progress_tick(cur++, cnt);
					rc = run_prstmt(UPDATE_DIGEST, p->digest, p->id);
					if (rc != SQLITE_DONE) {
@@ -3165,9 +3164,7 @@ pkgdb_begin_solver(struct pkgdb *db)
		if (rc == EPKG_OK)
			rc = sql_exec(db->sqlite, solver_sql);

-
		while (kv_size(pkglist) > 0 && (p = kv_pop(pkglist)))
-
			pkg_free(p);
-
		kv_destroy(pkglist);
+
		tll_free_and_free(pkglist, pkg_free);
	} else {
		rc = sql_exec(db->sqlite, solver_sql);
	}
modified src/Makefile.autosetup
@@ -41,6 +41,7 @@ LOCAL_CFLAGS= -I$(top_srcdir)/external/uthash \
		-I$(top_srcdir)/compat \
		-I$(top_srcdir)/external/libucl/klib \
		-I$(top_srcdir)/external/libucl/include \
+
		-I$(top_srcdir)/external/include \
		-I$(top_builddir)/ \
		-I$(top_builddir)/libpkg \
		-DGITHASH=\"@GITHASH@\" \
modified src/clean.c
@@ -49,7 +49,7 @@
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
-
#include <kvec.h>
+
#include <tllist.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
@@ -59,7 +59,7 @@
#include "pkgcli.h"
#include "pkghash.h"

-
typedef kvec_t(char *) dl_list;
+
typedef tll(char *) dl_list;

#define OUT_OF_DATE	(1U<<0)
#define REMOVED		(1U<<1)
@@ -92,36 +92,25 @@ add_to_dellist(int fd, dl_list *dl, const char *cachedir, const char *path)
	relpath = path + strlen(cachedir) + 1;
	if (fstatat(fd, relpath, &st, AT_SYMLINK_NOFOLLOW) != -1 && S_ISREG(st.st_mode))
		sz = st.st_size;
-
	kv_push(char *, *dl, store_path);
+
	tll_push_back(*dl, store_path);

	return (sz);
}

-
static void
-
free_dellist(dl_list *dl)
-
{
-
	unsigned int i;
-

-
	for (i = 0; i < kv_size(*dl); i++)
-
		free(kv_A(*dl, i));
-
	kv_destroy(*dl);
-
}
-

static int
delete_dellist(int fd, const char *cachedir,  dl_list *dl, int total)
{
	struct stat st;
	int retcode = EXIT_SUCCESS;
	int flag = 0;
-
	size_t i;
	unsigned int count = 0, processed = 0;
	char *file, *relpath;

-
	count = kv_size(*dl);
+
	count = tll_length(*dl);
	progressbar_start("Deleting files");
-
	for (i = 0; i < kv_size(*dl); i++) {
+
	tll_foreach(*dl, it) {
		flag = 0;
-
		relpath = file = kv_A(*dl, i);
+
		relpath = file = it->item;
		relpath += strlen(cachedir) + 1;
		if (fstatat(fd, relpath, &st, AT_SYMLINK_NOFOLLOW) == -1) {
			++processed;
@@ -136,7 +125,7 @@ delete_dellist(int fd, const char *cachedir, dl_list *dl, int total)
			retcode = EXIT_FAILURE;
		}
		free(file);
-
		kv_A(*dl, i) = NULL;
+
		it->item = NULL;
		++processed;
		progressbar_tick(processed, total);
	}
@@ -294,7 +283,7 @@ exec_clean(int argc, char **argv)
{
	struct pkgdb	*db = NULL;
	pkghash		*sumlist = NULL;
-
	dl_list		 dl;
+
	dl_list		 dl = tll_init();
	const char	*cachedir;
	bool		 all = false;
	int		 retcode;
@@ -391,8 +380,6 @@ exec_clean(int argc, char **argv)
#endif
#endif

-
	kv_init(dl);
-

	/* Build the list of out-of-date or obsolete packages */

	pkg_manifest_keys_new(&keys);
@@ -400,7 +387,7 @@ exec_clean(int argc, char **argv)
	    &total);
	pkghash_destroy(sumlist);

-
	if (kv_size(dl) == 0) {
+
	if (tll_length(dl) == 0) {
		if (!quiet)
			printf("Nothing to do.\n");
		retcode = EXIT_SUCCESS;
@@ -415,7 +402,7 @@ exec_clean(int argc, char **argv)
	if (!dry_run) {
			if (query_yesno(false,
			  "\nProceed with cleaning the cache? ")) {
-
				retcode = delete_dellist(cachefd, cachedir, &dl, kv_size(dl));
+
				retcode = delete_dellist(cachefd, cachedir, &dl, tll_length(dl));
			}
	} else {
		retcode = EXIT_SUCCESS;
@@ -425,7 +412,7 @@ cleanup:
	pkgdb_release_lock(db, PKGDB_LOCK_READONLY);
	pkgdb_close(db);
	pkg_manifest_keys_free(keys);
-
	free_dellist(&dl);
+
	tll_free_and_free(dl, free);

	if (cachefd != -1)
		close(cachefd);
modified src/event.c
@@ -54,7 +54,7 @@
#ifdef HAVE_LIBUTIL_H
#include <libutil.h>
#endif
-
#include <kvec.h>
+
#include <tllist.h>

#include <bsd_compat.h>

@@ -83,7 +83,7 @@ static int64_t bytes_per_second;
static time_t last_update;
static time_t begin = 0;
static int add_deps_depth;
-
static kvec_t(struct cleanup *) cleanup_list;
+
static tll(struct cleanup *) cleanup_list = tll_init();
static bool signal_handler_installed = false;

/* units for format_size */
@@ -95,13 +95,12 @@ static void
cleanup_handler(int dummy __unused)
{
	struct cleanup *ev;
-
	size_t i;

-
	if (kv_size(cleanup_list) == 0)
+
	if (tll_length(cleanup_list) == 0)
		return;
	warnx("\nsignal received, cleaning up");
-
	for (i = 0; i < kv_size(cleanup_list); i++) {
-
		ev = kv_A(cleanup_list, i);
+
	tll_foreach(cleanup_list, it) {
+
		ev = it->item;
		ev->cb(ev->data);
	}
	exit(1);
@@ -539,7 +538,6 @@ event_callback(void *data, struct pkg_event *ev)
	struct pkg *pkg = NULL, *pkg_new, *pkg_old;
	struct cleanup *evtmp;
	int *debug = data;
-
	size_t i;
	struct pkg_event_conflict *cur_conflict;
	const char *filename, *reponame;

@@ -851,23 +849,22 @@ event_callback(void *data, struct pkg_event *ev)
		break;
	case PKG_EVENT_CLEANUP_CALLBACK_REGISTER:
		if (!signal_handler_installed) {
-
			kv_init(cleanup_list);
			signal(SIGINT, cleanup_handler);
			signal_handler_installed = true;
		}
		evtmp = malloc(sizeof(struct cleanup));
		evtmp->cb = ev->e_cleanup_callback.cleanup_cb;
		evtmp->data = ev->e_cleanup_callback.data;
-
		kv_push(struct cleanup *, cleanup_list, evtmp);
+
		tll_push_back(cleanup_list, evtmp);
		break;
	case PKG_EVENT_CLEANUP_CALLBACK_UNREGISTER:
		if (!signal_handler_installed)
			break;
-
		for (i = 0; i < kv_size(cleanup_list); i++) {
-
			evtmp = kv_A(cleanup_list, i);
+
		tll_foreach(cleanup_list, it) {
+
			evtmp = it->item;
			if (evtmp->cb == ev->e_cleanup_callback.cleanup_cb &&
			    evtmp->data == ev->e_cleanup_callback.data) {
-
				kv_del(struct cleanup *, cleanup_list, i);
+
				tll_remove(cleanup_list, it);
				break;
			}
		}
modified src/which.c
@@ -35,13 +35,15 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
-
#include <kvec.h>
#include <fnmatch.h>

#include <pkg.h>
#include "pkgcli.h"
+
#include <string.h>
+
#include <xmalloc.h>
+
#include <tllist.h>

-
typedef kvec_t(char *) charlist;
+
typedef tll(char *) charlist;

void
usage_which(void)
@@ -56,11 +58,10 @@ int get_match(char **, char **, char *);
static bool
already_in_list(charlist *list, const char *pattern)
{
-
	size_t i;
-

-
	for (i = 0; i < kv_size(*list); i++)
-
		if (strcmp(kv_A(*list, i), pattern) == 0)
+
	tll_foreach(*list, it) {
+
		if (strcmp(it->item, pattern) == 0)
			return (true);
+
	}

	return (false);
}
@@ -76,13 +77,12 @@ exec_which(int argc, char **argv)
	char		*p, *path, *match, *savedpath;
	int		 retcode = EXIT_FAILURE;
	int		 ch, res, pathlen = 0;
-
	size_t		 i;
	bool		 orig = false;
	bool		 glob = false;
	bool		 search = false;
	bool		 search_s = false;
	bool		 show_match = false;
-
	charlist	 patterns;
+
	charlist	 patterns = tll_init();

	struct option longopts[] = {
		{ "glob",		no_argument,	NULL,	'g' },
@@ -146,7 +146,6 @@ exec_which(int argc, char **argv)
	}

	while (argc >= 1) {
-
		kv_init(patterns);
		retcode = EXIT_FAILURE;
		if (search_s) {
			if ((argv[0][0] == '.') || (argv[0][0] == '/')) {
@@ -185,7 +184,7 @@ exec_which(int argc, char **argv)
						/* ensure not not append twice an entry if PATH is messy */
						if (already_in_list(&patterns, pathabs))
							continue;
-
						kv_push(char *, patterns, strdup(pathabs));
+
						tll_push_back(patterns, xstrdup(pathabs));
						free(match);
					}
				}
@@ -195,18 +194,18 @@ exec_which(int argc, char **argv)

		if (!glob && !search) {
			pkg_absolutepath(argv[0], pathabs, sizeof(pathabs), false);
-
			kv_push(char *, patterns, strdup(pathabs));
+
			tll_push_back(patterns, xstrdup(pathabs));
		} else if (!search) {
			if (strlcpy(pathabs, argv[0], sizeof(pathabs)) >= sizeof(pathabs)) {
				retcode = EXIT_FAILURE;
				goto cleanup;
                        }
-
			kv_push(char *, patterns, strdup(pathabs));
+
			tll_push_back(patterns, xstrdup(pathabs));
		}


-
		for (i = 0; i < kv_size(patterns); i++) {
-
			if ((it = pkgdb_query_which(db, kv_A(patterns, i), glob)) == NULL) {
+
		tll_foreach(patterns, item) {
+
			if ((it = pkgdb_query_which(db, item->item, glob)) == NULL) {
				retcode = EXIT_FAILURE;
				goto cleanup;
			}
@@ -219,30 +218,30 @@ exec_which(int argc, char **argv)
				else if (quiet && !orig && !show_match)
					pkg_printf("%n-%v\n", pkg, pkg);
				else if (!quiet && orig && !show_match)
-
					pkg_printf("%S was installed by package %o\n", kv_A(patterns, i), pkg);
+
					pkg_printf("%S was installed by package %o\n", item->item, pkg);
				else if (!quiet && !orig && !show_match)
-
					pkg_printf("%S was installed by package %n-%v\n", kv_A(patterns, i), pkg, pkg);
+
					pkg_printf("%S was installed by package %n-%v\n", item->item, pkg, pkg);
				else if (glob && show_match) {
					if (!quiet)
-
						pkg_printf("%S was glob searched and found in package %n-%v\n", kv_A(patterns, i), pkg, pkg, pkg);
+
						pkg_printf("%S was glob searched and found in package %n-%v\n", item->item, pkg, pkg, pkg);
					while(pkg_files(pkg, &file) == EPKG_OK) {
						pkg_asprintf(&match, "%Fn", file);
						if (match == NULL)
							err(EXIT_FAILURE, "pkg_asprintf");
-
						if(!fnmatch(kv_A(patterns, i), match, 0))
+
						if(!fnmatch(item->item, match, 0))
							printf("%s\n", match);
						free(match);
					}
				}
			}
			if (retcode != EXIT_SUCCESS && !quiet)
-
				printf("%s was not found in the database\n", kv_A(patterns, i));
+
				printf("%s was not found in the database\n", item->item);

			pkg_free(pkg);
			pkgdb_it_free(it);

		}
-
		kv_destroy(patterns);
+
		tll_free_and_free(patterns, free);

		argc--;
		argv++;