diff options
-rw-r--r-- | libpkgconf/libpkgconf.h | 2 | ||||
-rw-r--r-- | libpkgconf/libpkgconf.h.orig | 331 | ||||
-rw-r--r-- | libpkgconf/pkg.c | 8 | ||||
-rw-r--r-- | libpkgconf/queue.c | 4 | ||||
-rw-r--r-- | libpkgconf/queue.c.orig | 195 |
5 files changed, 533 insertions, 7 deletions
diff --git a/libpkgconf/libpkgconf.h b/libpkgconf/libpkgconf.h index ac873bf..b07ec68 100644 --- a/libpkgconf/libpkgconf.h +++ b/libpkgconf/libpkgconf.h @@ -128,7 +128,7 @@ struct pkgconf_pkg_ { pkgconf_list_t cflags; pkgconf_list_t cflags_private; - pkgconf_list_t requires; + pkgconf_list_t requires_; /* Keyword in C++20. */ pkgconf_list_t requires_private; pkgconf_list_t conflicts; pkgconf_list_t provides; diff --git a/libpkgconf/libpkgconf.h.orig b/libpkgconf/libpkgconf.h.orig new file mode 100644 index 0000000..ac873bf --- /dev/null +++ b/libpkgconf/libpkgconf.h.orig @@ -0,0 +1,331 @@ +/* + * libpkgconf.h + * Global include file for everything in libpkgconf. + * + * Copyright (c) 2011, 2015 pkgconf authors (see AUTHORS). + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#ifndef LIBPKGCONF__LIBPKGCONF_H +#define LIBPKGCONF__LIBPKGCONF_H + +#include <stdio.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdbool.h> +#include <libpkgconf/iter.h> +#include <libpkgconf/bsdstubs.h> +#include <libpkgconf/libpkgconf-api.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* pkg-config uses ';' on win32 as ':' is part of path */ +#ifdef _WIN32 +#define PKG_CONFIG_PATH_SEP_S ";" +#else +#define PKG_CONFIG_PATH_SEP_S ":" +#endif + +#ifdef _WIN32 +#define PKG_DIR_SEP_S '\\' +#else +#define PKG_DIR_SEP_S '/' +#endif + +#define PKGCONF_BUFSIZE (65535) + +typedef enum { + PKGCONF_CMP_NOT_EQUAL, + PKGCONF_CMP_ANY, + PKGCONF_CMP_LESS_THAN, + PKGCONF_CMP_LESS_THAN_EQUAL, + PKGCONF_CMP_EQUAL, + PKGCONF_CMP_GREATER_THAN, + PKGCONF_CMP_GREATER_THAN_EQUAL +} pkgconf_pkg_comparator_t; + +#define PKGCONF_CMP_COUNT 7 + +typedef struct pkgconf_pkg_ pkgconf_pkg_t; +typedef struct pkgconf_dependency_ pkgconf_dependency_t; +typedef struct pkgconf_tuple_ pkgconf_tuple_t; +typedef struct pkgconf_fragment_ pkgconf_fragment_t; +typedef struct pkgconf_path_ pkgconf_path_t; +typedef struct pkgconf_client_ pkgconf_client_t; + +#define PKGCONF_ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) + +#define PKGCONF_FOREACH_LIST_ENTRY(head, value) \ + for ((value) = (head); (value) != NULL; (value) = (value)->next) + +#define PKGCONF_FOREACH_LIST_ENTRY_SAFE(head, nextiter, value) \ + for ((value) = (head), (nextiter) = (head) != NULL ? (head)->next : NULL; (value) != NULL; (value) = (nextiter), (nextiter) = (nextiter) != NULL ? (nextiter)->next : NULL) + +#define PKGCONF_FOREACH_LIST_ENTRY_REVERSE(tail, value) \ + for ((value) = (tail); (value) != NULL; (value) = (value)->prev) + +struct pkgconf_fragment_ { + pkgconf_node_t iter; + + char type; + char *data; +}; + +struct pkgconf_dependency_ { + pkgconf_node_t iter; + + char *package; + pkgconf_pkg_comparator_t compare; + char *version; + pkgconf_pkg_t *parent; +}; + +struct pkgconf_tuple_ { + pkgconf_node_t iter; + + char *key; + char *value; +}; + +struct pkgconf_path_ { + pkgconf_node_t lnode; + + char *path; + void *handle_path; + void *handle_device; +}; + +#define PKGCONF_PKG_PROPF_NONE 0x00 +#define PKGCONF_PKG_PROPF_STATIC 0x01 +#define PKGCONF_PKG_PROPF_CACHED 0x02 +#define PKGCONF_PKG_PROPF_SEEN 0x04 +#define PKGCONF_PKG_PROPF_UNINSTALLED 0x08 +#define PKGCONF_PKG_PROPF_VIRTUAL 0x10 + +struct pkgconf_pkg_ { + pkgconf_node_t cache_iter; + + int refcount; + char *id; + char *filename; + char *realname; + char *version; + char *description; + char *url; + char *pc_filedir; + + pkgconf_list_t libs; + pkgconf_list_t libs_private; + pkgconf_list_t cflags; + pkgconf_list_t cflags_private; + + pkgconf_list_t requires; + pkgconf_list_t requires_private; + pkgconf_list_t conflicts; + pkgconf_list_t provides; + + pkgconf_list_t vars; + + unsigned int flags; +}; + +typedef bool (*pkgconf_pkg_iteration_func_t)(const pkgconf_pkg_t *pkg, void *data); +typedef void (*pkgconf_pkg_traverse_func_t)(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data); +typedef bool (*pkgconf_queue_apply_func_t)(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth); +typedef bool (*pkgconf_error_handler_func_t)(const char *msg, const pkgconf_client_t *client, const void *data); + +struct pkgconf_client_ { + pkgconf_list_t dir_list; + pkgconf_list_t pkg_cache; + + pkgconf_list_t filter_libdirs; + pkgconf_list_t filter_includedirs; + + pkgconf_list_t global_vars; + + void *error_handler_data; + void *warn_handler_data; + void *trace_handler_data; + + pkgconf_error_handler_func_t error_handler; + pkgconf_error_handler_func_t warn_handler; + pkgconf_error_handler_func_t trace_handler; + + FILE *auditf; + + char *sysroot_dir; + char *buildroot_dir; + + unsigned int flags; + + char *prefix_varname; + + bool already_sent_notice; +}; + +/* client.c */ +PKGCONF_API void pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data); +PKGCONF_API pkgconf_client_t * pkgconf_client_new(pkgconf_error_handler_func_t error_handler, void *error_handler_data); +PKGCONF_API void pkgconf_client_deinit(pkgconf_client_t *client); +PKGCONF_API void pkgconf_client_free(pkgconf_client_t *client); +PKGCONF_API const char *pkgconf_client_get_sysroot_dir(const pkgconf_client_t *client); +PKGCONF_API void pkgconf_client_set_sysroot_dir(pkgconf_client_t *client, const char *sysroot_dir); +PKGCONF_API const char *pkgconf_client_get_buildroot_dir(const pkgconf_client_t *client); +PKGCONF_API void pkgconf_client_set_buildroot_dir(pkgconf_client_t *client, const char *buildroot_dir); +PKGCONF_API unsigned int pkgconf_client_get_flags(const pkgconf_client_t *client); +PKGCONF_API void pkgconf_client_set_flags(pkgconf_client_t *client, unsigned int flags); +PKGCONF_API const char *pkgconf_client_get_prefix_varname(const pkgconf_client_t *client); +PKGCONF_API void pkgconf_client_set_prefix_varname(pkgconf_client_t *client, const char *prefix_varname); +PKGCONF_API pkgconf_error_handler_func_t pkgconf_client_get_warn_handler(const pkgconf_client_t *client); +PKGCONF_API void pkgconf_client_set_warn_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t warn_handler, void *warn_handler_data); +PKGCONF_API pkgconf_error_handler_func_t pkgconf_client_get_error_handler(const pkgconf_client_t *client); +PKGCONF_API void pkgconf_client_set_error_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data); +PKGCONF_API pkgconf_error_handler_func_t pkgconf_client_get_trace_handler(const pkgconf_client_t *client); +PKGCONF_API void pkgconf_client_set_trace_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t trace_handler, void *trace_handler_data); + +#define PKGCONF_IS_MODULE_SEPARATOR(c) ((c) == ',' || isspace ((unsigned int)(c))) +#define PKGCONF_IS_OPERATOR_CHAR(c) ((c) == '<' || (c) == '>' || (c) == '!' || (c) == '=') + +#define PKGCONF_PKG_PKGF_NONE 0x0000 +#define PKGCONF_PKG_PKGF_SEARCH_PRIVATE 0x0001 +#define PKGCONF_PKG_PKGF_ENV_ONLY 0x0002 +#define PKGCONF_PKG_PKGF_NO_UNINSTALLED 0x0004 +#define PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL 0x0008 +#define PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS 0x0010 +#define PKGCONF_PKG_PKGF_SKIP_CONFLICTS 0x0020 +#define PKGCONF_PKG_PKGF_NO_CACHE 0x0040 +#define PKGCONF_PKG_PKGF_SKIP_ERRORS 0x0080 +#define PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE 0x0100 +#define PKGCONF_PKG_PKGF_SKIP_PROVIDES 0x0200 +#define PKGCONF_PKG_PKGF_REDEFINE_PREFIX 0x0400 +#define PKGCONF_PKG_PKGF_DONT_RELOCATE_PATHS 0x0800 +#define PKGCONF_PKG_PKGF_SIMPLIFY_ERRORS 0x1000 + +#define PKGCONF_PKG_ERRF_OK 0x0 +#define PKGCONF_PKG_ERRF_PACKAGE_NOT_FOUND 0x1 +#define PKGCONF_PKG_ERRF_PACKAGE_VER_MISMATCH 0x2 +#define PKGCONF_PKG_ERRF_PACKAGE_CONFLICT 0x4 +#define PKGCONF_PKG_ERRF_DEPGRAPH_BREAK 0x8 + +/* pkg.c */ +#if defined(__GNUC__) || defined(__INTEL_COMPILER) +#define PRINTFLIKE(fmtarg, firstvararg) \ + __attribute__((__format__ (__printf__, fmtarg, firstvararg))) +#define DEPRECATED \ + __attribute__((deprecated)) +#else +#define PRINTFLIKE(fmtarg, firstvararg) +#define DEPRECATED +#endif /* defined(__INTEL_COMPILER) || defined(__GNUC__) */ + +PKGCONF_API bool pkgconf_error(const pkgconf_client_t *client, const char *format, ...) PRINTFLIKE(2, 3); +PKGCONF_API bool pkgconf_warn(const pkgconf_client_t *client, const char *format, ...) PRINTFLIKE(2, 3); +PKGCONF_API bool pkgconf_trace(const pkgconf_client_t *client, const char *filename, size_t lineno, const char *funcname, const char *format, ...) PRINTFLIKE(5, 6); +PKGCONF_API bool pkgconf_default_error_handler(const char *msg, const pkgconf_client_t *client, const void *data); + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) +#define PKGCONF_TRACE(client, ...) do { \ + pkgconf_trace(client, __FILE__, __LINE__, __PRETTY_FUNCTION__, __VA_ARGS__); \ + } while (0); +#else +#define PKGCONF_TRACE(client, ...) do { \ + pkgconf_trace(client, __FILE__, __LINE__, __func__, __VA_ARGS__); \ + } while (0); +#endif + +PKGCONF_API pkgconf_pkg_t *pkgconf_pkg_ref(const pkgconf_client_t *client, pkgconf_pkg_t *pkg); +PKGCONF_API void pkgconf_pkg_unref(pkgconf_client_t *client, pkgconf_pkg_t *pkg); +PKGCONF_API void pkgconf_pkg_free(pkgconf_client_t *client, pkgconf_pkg_t *pkg); +PKGCONF_API pkgconf_pkg_t *pkgconf_pkg_find(pkgconf_client_t *client, const char *name); +PKGCONF_API unsigned int pkgconf_pkg_traverse(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_pkg_traverse_func_t func, void *data, int maxdepth); +PKGCONF_API unsigned int pkgconf_pkg_verify_graph(pkgconf_client_t *client, pkgconf_pkg_t *root, int depth); +PKGCONF_API pkgconf_pkg_t *pkgconf_pkg_verify_dependency(pkgconf_client_t *client, pkgconf_dependency_t *pkgdep, unsigned int *eflags); +PKGCONF_API const char *pkgconf_pkg_get_comparator(const pkgconf_dependency_t *pkgdep); +PKGCONF_API unsigned int pkgconf_pkg_cflags(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_list_t *list, int maxdepth); +PKGCONF_API unsigned int pkgconf_pkg_libs(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_list_t *list, int maxdepth); +PKGCONF_API pkgconf_pkg_comparator_t pkgconf_pkg_comparator_lookup_by_name(const char *name); +PKGCONF_API pkgconf_pkg_t *pkgconf_builtin_pkg_get(const char *name); + +PKGCONF_API int pkgconf_compare_version(const char *a, const char *b); +PKGCONF_API pkgconf_pkg_t *pkgconf_scan_all(pkgconf_client_t *client, void *ptr, pkgconf_pkg_iteration_func_t func); +PKGCONF_API void pkgconf_pkg_dir_list_build(pkgconf_client_t *client); + +/* parse.c */ +PKGCONF_API pkgconf_pkg_t *pkgconf_pkg_new_from_file(pkgconf_client_t *client, const char *path, FILE *f); +PKGCONF_API void pkgconf_dependency_parse_str(const pkgconf_client_t *client, pkgconf_list_t *deplist_head, const char *depends); +PKGCONF_API void pkgconf_dependency_parse(const pkgconf_client_t *client, pkgconf_pkg_t *pkg, pkgconf_list_t *deplist_head, const char *depends); +PKGCONF_API void pkgconf_dependency_append(pkgconf_list_t *list, pkgconf_dependency_t *tail); +PKGCONF_API void pkgconf_dependency_free(pkgconf_list_t *list); +PKGCONF_API pkgconf_dependency_t *pkgconf_dependency_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *package, const char *version, pkgconf_pkg_comparator_t compare); + +/* argvsplit.c */ +PKGCONF_API int pkgconf_argv_split(const char *src, int *argc, char ***argv); +PKGCONF_API void pkgconf_argv_free(char **argv); + +/* fragment.c */ +typedef bool (*pkgconf_fragment_filter_func_t)(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data); +PKGCONF_API bool pkgconf_fragment_parse(const pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_list_t *vars, const char *value); +PKGCONF_API void pkgconf_fragment_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *string); +PKGCONF_API void pkgconf_fragment_copy(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_fragment_t *base, bool is_private); +PKGCONF_API void pkgconf_fragment_delete(pkgconf_list_t *list, pkgconf_fragment_t *node); +PKGCONF_API void pkgconf_fragment_free(pkgconf_list_t *list); +PKGCONF_API void pkgconf_fragment_filter(const pkgconf_client_t *client, pkgconf_list_t *dest, pkgconf_list_t *src, pkgconf_fragment_filter_func_t filter_func, void *data); +PKGCONF_API size_t pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape); +PKGCONF_API void pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t len, bool escape); +PKGCONF_API char *pkgconf_fragment_render(const pkgconf_list_t *list, bool escape); +PKGCONF_API bool pkgconf_fragment_has_system_dir(const pkgconf_client_t *client, const pkgconf_fragment_t *frag); + +/* fileio.c */ +PKGCONF_API char *pkgconf_fgetline(char *line, size_t size, FILE *stream); + +/* tuple.c */ +PKGCONF_API pkgconf_tuple_t *pkgconf_tuple_add(const pkgconf_client_t *client, pkgconf_list_t *parent, const char *key, const char *value, bool parse); +PKGCONF_API char *pkgconf_tuple_find(const pkgconf_client_t *client, pkgconf_list_t *list, const char *key); +PKGCONF_API char *pkgconf_tuple_parse(const pkgconf_client_t *client, pkgconf_list_t *list, const char *value); +PKGCONF_API void pkgconf_tuple_free(pkgconf_list_t *list); +PKGCONF_API void pkgconf_tuple_free_entry(pkgconf_tuple_t *tuple, pkgconf_list_t *list); +PKGCONF_API void pkgconf_tuple_add_global(pkgconf_client_t *client, const char *key, const char *value); +PKGCONF_API char *pkgconf_tuple_find_global(const pkgconf_client_t *client, const char *key); +PKGCONF_API void pkgconf_tuple_free_global(pkgconf_client_t *client); +PKGCONF_API void pkgconf_tuple_define_global(pkgconf_client_t *client, const char *kv); + +/* queue.c */ +PKGCONF_API void pkgconf_queue_push(pkgconf_list_t *list, const char *package); +PKGCONF_API bool pkgconf_queue_compile(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list); +PKGCONF_API void pkgconf_queue_free(pkgconf_list_t *list); +PKGCONF_API bool pkgconf_queue_apply(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queue_apply_func_t func, int maxdepth, void *data); +PKGCONF_API bool pkgconf_queue_validate(pkgconf_client_t *client, pkgconf_list_t *list, int maxdepth); + +/* cache.c */ +PKGCONF_API pkgconf_pkg_t *pkgconf_cache_lookup(const pkgconf_client_t *client, const char *id); +PKGCONF_API void pkgconf_cache_add(pkgconf_client_t *client, pkgconf_pkg_t *pkg); +PKGCONF_API void pkgconf_cache_remove(pkgconf_client_t *client, pkgconf_pkg_t *pkg); +PKGCONF_API void pkgconf_cache_free(pkgconf_client_t *client); + +/* audit.c */ +PKGCONF_API void pkgconf_audit_set_log(pkgconf_client_t *client, FILE *auditf); +PKGCONF_API void pkgconf_audit_log(pkgconf_client_t *client, const char *format, ...) PRINTFLIKE(2, 3); +PKGCONF_API void pkgconf_audit_log_dependency(pkgconf_client_t *client, const pkgconf_pkg_t *dep, const pkgconf_dependency_t *depnode); + +/* path.c */ +PKGCONF_API void pkgconf_path_add(const char *text, pkgconf_list_t *dirlist, bool filter); +PKGCONF_API size_t pkgconf_path_split(const char *text, pkgconf_list_t *dirlist, bool filter); +PKGCONF_API size_t pkgconf_path_build_from_environ(const char *envvarname, const char *fallback, pkgconf_list_t *dirlist, bool filter); +PKGCONF_API bool pkgconf_path_match_list(const char *path, const pkgconf_list_t *dirlist); +PKGCONF_API void pkgconf_path_free(pkgconf_list_t *dirlist); +PKGCONF_API bool pkgconf_path_relocate(char *buf, size_t buflen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libpkgconf/pkg.c b/libpkgconf/pkg.c index ce3921b..3e3268a 100644 --- a/libpkgconf/pkg.c +++ b/libpkgconf/pkg.c @@ -181,7 +181,7 @@ static const pkgconf_pkg_parser_keyword_pair_t pkgconf_pkg_parser_keyword_funcs[ {"LIBS.private", pkgconf_pkg_parser_fragment_func, offsetof(pkgconf_pkg_t, libs_private)}, {"Name", pkgconf_pkg_parser_tuple_func, offsetof(pkgconf_pkg_t, realname)}, {"Provides", pkgconf_pkg_parser_dependency_func, offsetof(pkgconf_pkg_t, provides)}, - {"Requires", pkgconf_pkg_parser_dependency_func, offsetof(pkgconf_pkg_t, requires)}, + {"Requires", pkgconf_pkg_parser_dependency_func, offsetof(pkgconf_pkg_t, requires_)}, {"Requires.private", pkgconf_pkg_parser_dependency_func, offsetof(pkgconf_pkg_t, requires_private)}, {"Version", pkgconf_pkg_parser_tuple_func, offsetof(pkgconf_pkg_t, version)}, }; @@ -423,7 +423,7 @@ pkgconf_pkg_free(pkgconf_client_t *client, pkgconf_pkg_t *pkg) pkgconf_cache_remove(client, pkg); - pkgconf_dependency_free(&pkg->requires); + pkgconf_dependency_free(&pkg->requires_); pkgconf_dependency_free(&pkg->requires_private); pkgconf_dependency_free(&pkg->conflicts); pkgconf_dependency_free(&pkg->provides); @@ -1408,7 +1408,7 @@ pkgconf_pkg_walk_conflicts_list(pkgconf_client_t *client, if (*parentnode->package == '\0') continue; - PKGCONF_FOREACH_LIST_ENTRY(root->requires.head, childnode) + PKGCONF_FOREACH_LIST_ENTRY(root->requires_.head, childnode) { pkgconf_pkg_t *pkgdep; pkgconf_dependency_t *depnode = childnode->data; @@ -1488,7 +1488,7 @@ pkgconf_pkg_traverse(pkgconf_client_t *client, } PKGCONF_TRACE(client, "%s: walking requires list", root->id); - eflags = pkgconf_pkg_walk_list(client, root, &root->requires, func, data, maxdepth); + eflags = pkgconf_pkg_walk_list(client, root, &root->requires_, func, data, maxdepth); if (eflags != PKGCONF_PKG_ERRF_OK) return eflags; diff --git a/libpkgconf/queue.c b/libpkgconf/queue.c index 73507fa..fb6eefd 100644 --- a/libpkgconf/queue.c +++ b/libpkgconf/queue.c @@ -77,10 +77,10 @@ pkgconf_queue_compile(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_li pkgconf_queue_t *pkgq; pkgq = iter->data; - pkgconf_dependency_parse(client, world, &world->requires, pkgq->package); + pkgconf_dependency_parse(client, world, &world->requires_, pkgq->package); } - return (world->requires.head != NULL); + return (world->requires_.head != NULL); } /* diff --git a/libpkgconf/queue.c.orig b/libpkgconf/queue.c.orig new file mode 100644 index 0000000..73507fa --- /dev/null +++ b/libpkgconf/queue.c.orig @@ -0,0 +1,195 @@ +/* + * queue.c + * compilation of a list of packages into a world dependency set + * + * Copyright (c) 2012 pkgconf authors (see AUTHORS). + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#include <libpkgconf/stdinc.h> +#include <libpkgconf/libpkgconf.h> + +/* + * !doc + * + * libpkgconf `queue` module + * ========================= + * + * The `queue` module provides an interface that allows easily building a dependency graph from an + * arbitrary set of dependencies. It also provides support for doing "preflight" checks on the entire + * dependency graph prior to working with it. + * + * Using the `queue` module functions is the recommended way of working with dependency graphs. + */ + +typedef struct { + pkgconf_node_t iter; + char *package; +} pkgconf_queue_t; + +/* + * !doc + * + * .. c:function:: void pkgconf_queue_push(pkgconf_list_t *list, const char *package) + * + * Pushes a requested dependency onto the dependency resolver's queue. + * + * :param pkgconf_list_t* list: the dependency resolution queue to add the package request to. + * :param char* package: the dependency atom requested + * :return: nothing + */ +void +pkgconf_queue_push(pkgconf_list_t *list, const char *package) +{ + pkgconf_queue_t *pkgq = calloc(sizeof(pkgconf_queue_t), 1); + + pkgq->package = strdup(package); + pkgconf_node_insert_tail(&pkgq->iter, pkgq, list); +} + +/* + * !doc + * + * .. c:function:: bool pkgconf_queue_compile(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list) + * + * Compile a dependency resolution queue into a dependency resolution problem if possible, otherwise report an error. + * + * :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution. + * :param pkgconf_pkg_t* world: The designated root of the dependency graph. + * :param pkgconf_list_t* list: The list of dependency requests to consider. + * :return: true if the built dependency resolution problem is consistent, else false + * :rtype: bool + */ +bool +pkgconf_queue_compile(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list) +{ + pkgconf_node_t *iter; + + PKGCONF_FOREACH_LIST_ENTRY(list->head, iter) + { + pkgconf_queue_t *pkgq; + + pkgq = iter->data; + pkgconf_dependency_parse(client, world, &world->requires, pkgq->package); + } + + return (world->requires.head != NULL); +} + +/* + * !doc + * + * .. c:function:: void pkgconf_queue_free(pkgconf_list_t *list) + * + * Release any memory related to a dependency resolution queue. + * + * :param pkgconf_list_t* list: The dependency resolution queue to release. + * :return: nothing + */ +void +pkgconf_queue_free(pkgconf_list_t *list) +{ + pkgconf_node_t *node, *tnode; + + PKGCONF_FOREACH_LIST_ENTRY_SAFE(list->head, tnode, node) + { + pkgconf_queue_t *pkgq = node->data; + + free(pkgq->package); + free(pkgq); + } +} + +static inline unsigned int +pkgconf_queue_verify(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list, int maxdepth) +{ + if (!pkgconf_queue_compile(client, world, list)) + return PKGCONF_PKG_ERRF_DEPGRAPH_BREAK; + + return pkgconf_pkg_verify_graph(client, world, maxdepth); +} + +/* + * !doc + * + * .. c:function:: void pkgconf_queue_apply(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queue_apply_func_t func, int maxdepth, void *data) + * + * Attempt to compile a dependency resolution queue into a dependency resolution problem, then attempt to solve the problem and + * feed the solution to a callback function if a complete dependency graph is found. + * + * :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution. + * :param pkgconf_list_t* list: The list of dependency requests to consider. + * :param pkgconf_queue_apply_func_t func: The callback function to call if a solution is found by the dependency resolver. + * :param int maxdepth: The maximum allowed depth for the dependency resolver. A depth of -1 means unlimited. + * :param void* data: An opaque pointer which is passed to the callback function. + * :returns: true if the dependency resolver found a solution, otherwise false. + * :rtype: bool + */ +bool +pkgconf_queue_apply(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queue_apply_func_t func, int maxdepth, void *data) +{ + pkgconf_pkg_t world = { + .id = "virtual:world", + .realname = "virtual world package", + .flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL, + }; + + /* if maxdepth is one, then we will not traverse deeper than our virtual package. */ + if (!maxdepth) + maxdepth = -1; + + if (pkgconf_queue_verify(client, &world, list, maxdepth) != PKGCONF_PKG_ERRF_OK) + return false; + + if (!func(client, &world, data, maxdepth)) + { + pkgconf_pkg_free(client, &world); + return false; + } + + pkgconf_pkg_free(client, &world); + + return true; +} + +/* + * !doc + * + * .. c:function:: void pkgconf_queue_validate(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queue_apply_func_t func, int maxdepth, void *data) + * + * Attempt to compile a dependency resolution queue into a dependency resolution problem, then attempt to solve the problem. + * + * :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution. + * :param pkgconf_list_t* list: The list of dependency requests to consider. + * :param int maxdepth: The maximum allowed depth for the dependency resolver. A depth of -1 means unlimited. + * :returns: true if the dependency resolver found a solution, otherwise false. + * :rtype: bool + */ +bool +pkgconf_queue_validate(pkgconf_client_t *client, pkgconf_list_t *list, int maxdepth) +{ + bool retval = true; + pkgconf_pkg_t world = { + .id = "virtual:world", + .realname = "virtual world package", + .flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL, + }; + + /* if maxdepth is one, then we will not traverse deeper than our virtual package. */ + if (!maxdepth) + maxdepth = -1; + + if (pkgconf_queue_verify(client, &world, list, maxdepth) != PKGCONF_PKG_ERRF_OK) + retval = false; + + pkgconf_pkg_free(client, &world); + + return retval; +} |