From 8459b05bbfdb31d057bc152c582d7394f631e282 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 23 Dec 2025 16:36:05 -0800 Subject: [PATCH] cli: refactor main for testing purposes Signed-off-by: Ariadne Conill --- Makefile.am | 2 + Makefile.lite | 3 +- cli/core.c | 1448 +++++++++++++++++++++++++++++++++++ cli/core.h | 101 +++ cli/main.c | 1767 ++++--------------------------------------- cli/renderer-msvc.c | 4 +- cli/renderer-msvc.h | 2 +- meson.build | 1 + 8 files changed, 1706 insertions(+), 1622 deletions(-) create mode 100644 cli/core.c create mode 100644 cli/core.h diff --git a/Makefile.am b/Makefile.am index 3f4fccf..fac30d4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -205,10 +205,12 @@ dist_man_MANS = \ pkgconf_LDADD = libpkgconf.la pkgconf_SOURCES = \ cli/main.c \ + cli/core.c \ cli/getopt_long.c \ cli/renderer-msvc.c pkgconf_CPPFLAGS = -I$(top_srcdir)/libpkgconf -I$(top_srcdir)/cli noinst_HEADERS = \ + cli/core.h \ cli/getopt_long.h \ cli/renderer-msvc.h \ cli/spdxtool/core.h \ diff --git a/Makefile.lite b/Makefile.lite index 8192170..f2ae323 100644 --- a/Makefile.lite +++ b/Makefile.lite @@ -30,7 +30,8 @@ SRCS = \ libpkgconf/queue.c \ libpkgconf/tuple.c \ cli/getopt_long.c \ - cli/main.c + cli/main.c \ + cli/core.c OBJS = ${SRCS:.c=.o} CFLAGS = ${STATIC} -DPKGCONF_LITE -I. -Ilibpkgconf -Icli -DSYSTEM_LIBDIR=\"${SYSTEM_LIBDIR}\" -DSYSTEM_INCLUDEDIR=\"${SYSTEM_INCLUDEDIR}\" -DPKG_DEFAULT_PATH=\"${PKG_DEFAULT_PATH}\" STATIC = diff --git a/cli/core.c b/cli/core.c new file mode 100644 index 0000000..8a47fd8 --- /dev/null +++ b/cli/core.c @@ -0,0 +1,1448 @@ +/* + * core.c + * core, printer functions + * + * Copyright (c) 2011-2025 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/config.h" +#include +#include +#include "core.h" +#include "getopt_long.h" +#ifndef PKGCONF_LITE +#include "renderer-msvc.h" +#endif + +static bool +print_list_entry(const pkgconf_pkg_t *entry, void *data) +{ + const pkgconf_node_t *n; + pkgconf_client_t *client = data; + + if (entry->flags & PKGCONF_PKG_PROPF_UNINSTALLED) + return false; + + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, + "%-30s %s - %s\n", entry->id, entry->realname, entry->description); + + PKGCONF_FOREACH_LIST_ENTRY(entry->provides.head, n) + { + const pkgconf_dependency_t *dep = n->data; + + if (!strcmp(dep->package, entry->id)) + continue; + + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, + "%-30s %s - %s (provided by %s)\n", dep->package, entry->realname, entry->description, entry->id); + } + + return false; +} + +static bool +print_package_entry(const pkgconf_pkg_t *entry, void *data) +{ + const pkgconf_node_t *n; + pkgconf_client_t *client = data; + + if (entry->flags & PKGCONF_PKG_PROPF_UNINSTALLED) + return false; + + pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, entry->id); + + PKGCONF_FOREACH_LIST_ENTRY(entry->provides.head, n) + { + const pkgconf_dependency_t *dep = n->data; + + if (!strcmp(dep->package, entry->id)) + continue; + + pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, dep->package); + } + + return false; +} + +static bool +filter_cflags(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data) +{ + int got_flags = 0; + pkgconf_cli_state_t *state = client->client_data; + (void) data; + + if (!(state->want_flags & PKG_KEEP_SYSTEM_CFLAGS) && pkgconf_fragment_has_system_dir(client, frag)) + return false; + + if (state->want_fragment_filter != NULL && (strchr(state->want_fragment_filter, frag->type) == NULL || !frag->type)) + return false; + + if (frag->type == 'I') + got_flags = PKG_CFLAGS_ONLY_I; + else + got_flags = PKG_CFLAGS_ONLY_OTHER; + + return (state->want_flags & got_flags) != 0; +} + +static bool +filter_libs(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data) +{ + int got_flags = 0; + pkgconf_cli_state_t *state = client->client_data; + (void) data; + + if (!(state->want_flags & PKG_KEEP_SYSTEM_LIBS) && pkgconf_fragment_has_system_dir(client, frag)) + return false; + + if (state->want_fragment_filter != NULL && (strchr(state->want_fragment_filter, frag->type) == NULL || !frag->type)) + return false; + + switch (frag->type) + { + case 'L': got_flags = PKG_LIBS_ONLY_LDPATH; break; + case 'l': got_flags = PKG_LIBS_ONLY_LIBNAME; break; + default: got_flags = PKG_LIBS_ONLY_OTHER; break; + } + + return (state->want_flags & got_flags) != 0; +} + +static void +print_variables(pkgconf_output_t *output, pkgconf_pkg_t *pkg) +{ + pkgconf_node_t *node; + + PKGCONF_FOREACH_LIST_ENTRY(pkg->vars.head, node) + { + pkgconf_tuple_t *tuple = node->data; + + pkgconf_output_puts(output, PKGCONF_OUTPUT_STDOUT, tuple->key); + } +} + +static void +print_dependency_list(pkgconf_output_t *output, pkgconf_list_t *list) +{ + pkgconf_node_t *node; + + PKGCONF_FOREACH_LIST_ENTRY(list->head, node) + { + pkgconf_dependency_t *dep = node->data; + + pkgconf_output_fmt(output, PKGCONF_OUTPUT_STDOUT, "%s", dep->package); + + if (dep->version != NULL) + pkgconf_output_fmt(output, PKGCONF_OUTPUT_STDOUT, " %s %s", + pkgconf_pkg_get_comparator(dep), dep->version); + + pkgconf_output_fmt(output, PKGCONF_OUTPUT_STDOUT, "\n"); + } +} + +static bool +apply_provides(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) +{ + pkgconf_node_t *iter; + (void) unused; + (void) maxdepth; + + PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) + { + pkgconf_dependency_t *dep = iter->data; + pkgconf_pkg_t *pkg = dep->match; + + print_dependency_list(client->output, &pkg->provides); + } + + return true; +} + +#ifndef PKGCONF_LITE +static void +print_digraph_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) +{ + pkgconf_node_t *node; + pkgconf_pkg_t **last_seen = data; + + if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL) + return; + + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "\"%s\" [fontname=Sans fontsize=8", pkg->id); + + if (pkg->flags & PKGCONF_PKG_PROPF_VISITED_PRIVATE) + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, " fontcolor=gray color=gray"); + + pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, "]"); + + if (last_seen != NULL) + { + if (*last_seen != NULL) + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, + "\"%s\" -> \"%s\" [fontname=Sans fontsize=8 color=red]\n", (*last_seen)->id, pkg->id); + + *last_seen = pkg; + } + + PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, node) + { + pkgconf_dependency_t *dep = node->data; + const char *dep_id = (dep->match != NULL) ? dep->match->id : dep->package; + + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "\"%s\" -> \"%s\" [fontname=Sans fontsize=8", + pkg->id, dep_id); + + if (dep->flags & PKGCONF_PKG_DEPF_PRIVATE) + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, " color=gray"); + + pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, "]"); + } + + PKGCONF_FOREACH_LIST_ENTRY(pkg->requires_private.head, node) + { + pkgconf_dependency_t *dep = node->data; + const char *dep_id = (dep->match != NULL) ? dep->match->id : dep->package; + + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, + "\"%s\" -> \"%s\" [fontname=Sans fontsize=8 color=gray]\n", pkg->id, dep_id); + } +} + +static bool +apply_digraph(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) +{ + int eflag; + pkgconf_list_t *list = data; + pkgconf_pkg_t *last_seen = NULL; + pkgconf_node_t *iter; + + pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, + "digraph deptree {\n" + "edge [color=blue len=7.5 fontname=Sans fontsize=8]\n" + "node [fontname=Sans fontsize=8]\n" + "\"user:request\" [fontname=Sans fontsize=8]"); + + PKGCONF_FOREACH_LIST_ENTRY(list->head, iter) + { + pkgconf_queue_t *pkgq = iter->data; + pkgconf_pkg_t *pkg = pkgconf_pkg_find(client, pkgq->package); + + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, + "\"user:request\" -> \"%s\" [fontname=Sans fontsize=8]\n", + pkg == NULL ? pkgq->package : pkg->id); + + if (pkg != NULL) + pkgconf_pkg_unref(client, pkg); + } + + eflag = pkgconf_pkg_traverse(client, world, print_digraph_node, &last_seen, maxdepth, 0); + + if (eflag != PKGCONF_PKG_ERRF_OK) + return false; + + pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, "}"); + return true; +} + +static void +print_solution_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *unused) +{ + (void) unused; + + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "%s (%"PRIu64")%s\n", + pkg->id, pkg->identifier, (pkg->flags & PKGCONF_PKG_PROPF_VISITED_PRIVATE) == PKGCONF_PKG_PROPF_VISITED_PRIVATE ? " [private]" : ""); +} + +static bool +apply_print_solution(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) +{ + int eflag; + + eflag = pkgconf_pkg_traverse(client, world, print_solution_node, unused, maxdepth, 0); + + return eflag == PKGCONF_PKG_ERRF_OK; +} +#endif + +static bool +apply_modversion(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) +{ + pkgconf_cli_state_t *state = client->client_data; + pkgconf_node_t *queue_iter; + pkgconf_list_t *pkgq = data; + (void) maxdepth; + + PKGCONF_FOREACH_LIST_ENTRY(pkgq->head, queue_iter) + { + pkgconf_node_t *world_iter; + pkgconf_queue_t *queue_node = queue_iter->data; + + PKGCONF_FOREACH_LIST_ENTRY(world->required.head, world_iter) + { + pkgconf_dependency_t *dep = world_iter->data; + pkgconf_pkg_t *pkg = dep->match; + + const size_t name_len = strlen(pkg->why); + if (name_len > strlen(queue_node->package) || + strncmp(pkg->why, queue_node->package, name_len) || + (queue_node->package[name_len] != 0 && + !isspace((unsigned char)queue_node->package[name_len]) && + !PKGCONF_IS_OPERATOR_CHAR(queue_node->package[name_len]))) + continue; + + if (pkg->version != NULL) { + if (state->verbosity) + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "%s: ", pkg->id); + + pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, pkg->version); + } + + break; + } + } + + return true; +} + +static bool +apply_variables(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) +{ + pkgconf_node_t *iter; + (void) unused; + (void) maxdepth; + + PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) + { + pkgconf_dependency_t *dep = iter->data; + pkgconf_pkg_t *pkg = dep->match; + + print_variables(client->output, pkg); + } + + return true; +} + +static bool +apply_path(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) +{ + pkgconf_node_t *iter; + (void) unused; + (void) maxdepth; + + PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) + { + pkgconf_dependency_t *dep = iter->data; + pkgconf_pkg_t *pkg = dep->match; + + /* a module entry with no filename is either virtual, static (builtin) or synthesized. */ + if (pkg->filename != NULL) + pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, pkg->filename); + } + + return true; +} + +static bool +apply_variable(pkgconf_client_t *client, pkgconf_pkg_t *world, void *variable, int maxdepth) +{ + pkgconf_node_t *iter; + (void) maxdepth; + + PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) + { + pkgconf_dependency_t *dep = iter->data; + pkgconf_pkg_t *pkg = dep->match; + const char *var; + + var = pkgconf_tuple_find(client, &pkg->vars, variable); + + if (var != NULL) + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, + "%s%s", iter->prev != NULL ? " " : "", var); + } + + pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, ""); + + return true; +} + +static bool +apply_env_var(const char *prefix, pkgconf_client_t *client, pkgconf_pkg_t *world, int maxdepth, + unsigned int (*collect_fn)(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list, int maxdepth), + bool (*filter_fn)(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data), + void (*postprocess_fn)(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *fragment_list)) +{ + pkgconf_cli_state_t *state = client->client_data; + pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER; + pkgconf_list_t filtered_list = PKGCONF_LIST_INITIALIZER; + pkgconf_buffer_t render_buf = PKGCONF_BUFFER_INITIALIZER; + unsigned int eflag; + + eflag = collect_fn(client, world, &unfiltered_list, maxdepth); + if (eflag != PKGCONF_PKG_ERRF_OK) + return false; + + pkgconf_fragment_filter(client, &filtered_list, &unfiltered_list, filter_fn, NULL); + + if (postprocess_fn != NULL) + postprocess_fn(client, world, &filtered_list); + + if (filtered_list.head == NULL) + goto out; + + pkgconf_fragment_render_buf(&filtered_list, &render_buf, true, state->want_render_ops, (state->want_flags & PKG_NEWLINES) ? '\n' : ' '); + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "%s='%s'\n", + prefix, pkgconf_buffer_str_or_empty(&render_buf)); + pkgconf_buffer_finalize(&render_buf); + +out: + pkgconf_fragment_free(&unfiltered_list); + pkgconf_fragment_free(&filtered_list); + + return true; +} + +static void +maybe_add_module_definitions(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *fragment_list) +{ + pkgconf_node_t *world_iter; + pkgconf_cli_state_t *state = client->client_data; + + if ((state->want_flags & PKG_EXISTS_CFLAGS) != PKG_EXISTS_CFLAGS) + return; + + PKGCONF_FOREACH_LIST_ENTRY(world->required.head, world_iter) + { + pkgconf_dependency_t *dep = world_iter->data; + char havebuf[PKGCONF_ITEM_SIZE]; + char *p; + + if ((dep->flags & PKGCONF_PKG_DEPF_QUERY) != PKGCONF_PKG_DEPF_QUERY) + continue; + + if (dep->match == NULL) + continue; + + snprintf(havebuf, sizeof havebuf, "HAVE_%s", dep->match->id); + + for (p = havebuf; *p; p++) + { + switch (*p) + { + case ' ': + case '-': + *p = '_'; + break; + + default: + *p = toupper((unsigned char) *p); + } + } + + pkgconf_fragment_insert(client, fragment_list, 'D', havebuf, false); + } +} + +static void +apply_env_variables(pkgconf_client_t *client, pkgconf_pkg_t *world, const char *env_prefix) +{ + pkgconf_node_t *world_iter; + pkgconf_cli_state_t *state = client->client_data; + + PKGCONF_FOREACH_LIST_ENTRY(world->required.head, world_iter) + { + pkgconf_dependency_t *dep = world_iter->data; + pkgconf_pkg_t *pkg = dep->match; + pkgconf_node_t *tuple_iter; + + if ((dep->flags & PKGCONF_PKG_DEPF_QUERY) != PKGCONF_PKG_DEPF_QUERY) + continue; + + if (dep->match == NULL) + continue; + + PKGCONF_FOREACH_LIST_ENTRY(pkg->vars.head, tuple_iter) + { + pkgconf_tuple_t *tuple = tuple_iter->data; + char havebuf[PKGCONF_ITEM_SIZE]; + char *p; + + if (state->want_variable != NULL && strcmp(state->want_variable, tuple->key)) + continue; + + snprintf(havebuf, sizeof havebuf, "%s_%s", env_prefix, tuple->key); + + for (p = havebuf; *p; p++) + { + switch (*p) + { + case ' ': + case '-': + *p = '_'; + break; + + default: + *p = toupper((unsigned char) *p); + } + } + + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, + "%s='%s'\n", havebuf, tuple->value); + } + } +} + +static bool +apply_env(pkgconf_client_t *client, pkgconf_pkg_t *world, void *env_prefix_p, int maxdepth) +{ + pkgconf_cli_state_t *state = client->client_data; + const char *want_env_prefix = env_prefix_p, *it; + char workbuf[PKGCONF_ITEM_SIZE]; + + for (it = want_env_prefix; *it != '\0'; it++) + if (!isalpha((unsigned char)*it) && + !isdigit((unsigned char)*it)) + return false; + + snprintf(workbuf, sizeof workbuf, "%s_CFLAGS", want_env_prefix); + if (!apply_env_var(workbuf, client, world, maxdepth, pkgconf_pkg_cflags, filter_cflags, maybe_add_module_definitions)) + return false; + + snprintf(workbuf, sizeof workbuf, "%s_LIBS", want_env_prefix); + if (!apply_env_var(workbuf, client, world, maxdepth, pkgconf_pkg_libs, filter_libs, NULL)) + return false; + + if ((state->want_flags & PKG_VARIABLES) == PKG_VARIABLES || state->want_variable != NULL) + apply_env_variables(client, world, want_env_prefix); + + return true; +} + +static bool +apply_cflags(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *target_list, int maxdepth) +{ + pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER; + pkgconf_list_t filtered_list = PKGCONF_LIST_INITIALIZER; + int eflag; + + eflag = pkgconf_pkg_cflags(client, world, &unfiltered_list, maxdepth); + if (eflag != PKGCONF_PKG_ERRF_OK) + return false; + + pkgconf_fragment_filter(client, &filtered_list, &unfiltered_list, filter_cflags, NULL); + maybe_add_module_definitions(client, world, &filtered_list); + + if (filtered_list.head == NULL) + goto out; + + pkgconf_fragment_copy_list(client, target_list, &filtered_list); + +out: + pkgconf_fragment_free(&unfiltered_list); + pkgconf_fragment_free(&filtered_list); + + return true; +} + +static bool +apply_libs(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *target_list, int maxdepth) +{ + pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER; + pkgconf_list_t filtered_list = PKGCONF_LIST_INITIALIZER; + int eflag; + + eflag = pkgconf_pkg_libs(client, world, &unfiltered_list, maxdepth); + if (eflag != PKGCONF_PKG_ERRF_OK) + return false; + + pkgconf_fragment_filter(client, &filtered_list, &unfiltered_list, filter_libs, NULL); + + if (filtered_list.head == NULL) + goto out; + + pkgconf_fragment_copy_list(client, target_list, &filtered_list); + +out: + pkgconf_fragment_free(&unfiltered_list); + pkgconf_fragment_free(&filtered_list); + + return true; +} + +static bool +apply_requires(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) +{ + pkgconf_node_t *iter; + (void) unused; + (void) maxdepth; + + PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) + { + pkgconf_dependency_t *dep = iter->data; + pkgconf_pkg_t *pkg = dep->match; + + print_dependency_list(client->output, &pkg->required); + } + + return true; +} + +static bool +apply_requires_private(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) +{ + pkgconf_node_t *iter; + (void) unused; + (void) maxdepth; + + PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) + { + pkgconf_dependency_t *dep = iter->data; + pkgconf_pkg_t *pkg = dep->match; + + print_dependency_list(client->output, &pkg->requires_private); + } + return true; +} + +static void +check_uninstalled(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) +{ + int *retval = data; + (void) client; + + if (pkg->flags & PKGCONF_PKG_PROPF_UNINSTALLED) + *retval = EXIT_SUCCESS; +} + +static bool +apply_uninstalled(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) +{ + int eflag; + + eflag = pkgconf_pkg_traverse(client, world, check_uninstalled, data, maxdepth, 0); + + if (eflag != PKGCONF_PKG_ERRF_OK) + return false; + + return true; +} + +#ifndef PKGCONF_LITE +static void +print_graph_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) +{ + pkgconf_node_t *n; + + (void) data; + + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "node '%s' {\n", pkg->id); + + if (pkg->version != NULL) + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, " version = '%s';\n", pkg->version); + + PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, n) + { + pkgconf_dependency_t *dep = n->data; + + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, " dependency '%s'", dep->package); + + if (dep->compare != PKGCONF_CMP_ANY) + { + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, + " {\n" + " comparator = '%s';\n" + " version = '%s';\n" + " };\n", + pkgconf_pkg_get_comparator(dep), dep->version); + } + else + pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, ";"); + } + + pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, "};"); +} + +static bool +apply_simulate(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) +{ + int eflag; + + eflag = pkgconf_pkg_traverse(client, world, print_graph_node, data, maxdepth, 0); + + if (eflag != PKGCONF_PKG_ERRF_OK) + return false; + + return true; +} +#endif + +static void +print_fragment_tree_branch(pkgconf_output_t *output, pkgconf_list_t *fragment_list, int indent) +{ + pkgconf_node_t *iter; + + PKGCONF_FOREACH_LIST_ENTRY(fragment_list->head, iter) + { + pkgconf_fragment_t *frag = iter->data; + + if (frag->type) + pkgconf_output_fmt(output, PKGCONF_OUTPUT_STDOUT, + "%*s'-%c%s' [type %c]\n", indent, "", frag->type, frag->data, frag->type); + else + pkgconf_output_fmt(output, PKGCONF_OUTPUT_STDOUT, + "%*s'%s' [untyped]\n", indent, "", frag->data); + + print_fragment_tree_branch(output, &frag->children, indent + 2); + } + + if (fragment_list->head != NULL) + pkgconf_output_puts(output, PKGCONF_OUTPUT_STDOUT, ""); +} + +static bool +apply_fragment_tree(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) +{ + pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER; + int eflag; + + (void) data; + + eflag = pkgconf_pkg_cflags(client, world, &unfiltered_list, maxdepth); + if (eflag != PKGCONF_PKG_ERRF_OK) + return false; + + eflag = pkgconf_pkg_libs(client, world, &unfiltered_list, maxdepth); + if (eflag != PKGCONF_PKG_ERRF_OK) + return false; + + print_fragment_tree_branch(client->output, &unfiltered_list, 0); + pkgconf_fragment_free(&unfiltered_list); + + return true; +} + +static void +print_license(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) +{ + (void) data; + + if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL) + return; + + /* NOASSERTION is the default when the license is unknown, per SPDX spec § 3.15 */ + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "%s: %s\n", + pkg->id, pkg->license != NULL ? pkg->license : "NOASSERTION"); +} + +static bool +apply_license(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) +{ + int eflag; + + eflag = pkgconf_pkg_traverse(client, world, print_license, data, maxdepth, 0); + + if (eflag != PKGCONF_PKG_ERRF_OK) + return false; + + return true; +} + +static void +print_license_file(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) +{ + (void) data; + + if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL) + return; + + /* If license file location is not available then just print empty */ + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "%s: %s\n", + pkg->id, pkg->license_file != NULL ? pkg->license_file : ""); +} + +static bool +apply_license_file(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) +{ + int eflag; + + eflag = pkgconf_pkg_traverse(client, world, print_license_file, data, maxdepth, 0); + + if (eflag != PKGCONF_PKG_ERRF_OK) + return false; + + return true; +} + +static void +print_source(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) +{ + (void) data; + + if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL) + return; + + /* If source is empty then empty string is printed otherwise URL */ + pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "%s: %s\n", + pkg->id, pkg->source != NULL ? pkg->source : ""); +} + +static bool +apply_source(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) +{ + int eflag; + + eflag = pkgconf_pkg_traverse(client, world, print_source, data, maxdepth, 0); + + if (eflag != PKGCONF_PKG_ERRF_OK) + return false; + + return true; +} + +void +path_list_to_buffer(const pkgconf_list_t *list, pkgconf_buffer_t *buffer, char delim) +{ + pkgconf_node_t *n; + + PKGCONF_FOREACH_LIST_ENTRY(list->head, n) + { + pkgconf_path_t *pn = n->data; + + if (n != list->head) + pkgconf_buffer_push_byte(buffer, delim); + + pkgconf_buffer_append(buffer, pn->path); + } +} + +static void +unveil_handler(const pkgconf_client_t *client, const char *path, const char *permissions) +{ + (void) client; + + if (pkgconf_unveil(path, permissions) == -1) + { + fprintf(stderr, "pkgconf: unveil failed: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } +} + +static bool +unveil_search_paths(pkgconf_client_t *client, const pkgconf_cross_personality_t *personality) +{ + pkgconf_node_t *n; + + if (pkgconf_unveil("/dev/null", "rwc") == -1) + return false; + + PKGCONF_FOREACH_LIST_ENTRY(client->dir_list.head, n) + { + pkgconf_path_t *pn = n->data; + + if (pkgconf_unveil(pn->path, "r") == -1 && errno != ENOENT) + return false; + } + + PKGCONF_FOREACH_LIST_ENTRY(personality->dir_list.head, n) + { + pkgconf_path_t *pn = n->data; + + if (pkgconf_unveil(pn->path, "r") == -1 && errno != ENOENT) + return false; + } + + pkgconf_client_set_unveil_handler(client, unveil_handler); + + return true; +} + +/* SAFETY: pkgconf_client_t takes ownership of these package objects */ +static void +register_builtins(pkgconf_client_t *client, pkgconf_cross_personality_t *personality) +{ + pkgconf_buffer_t pc_path_buf = PKGCONF_BUFFER_INITIALIZER; + path_list_to_buffer(&personality->dir_list, &pc_path_buf, ':'); + + pkgconf_buffer_t pc_system_libdirs_buf = PKGCONF_BUFFER_INITIALIZER; + path_list_to_buffer(&personality->filter_libdirs, &pc_system_libdirs_buf, ':'); + + pkgconf_buffer_t pc_system_includedirs_buf = PKGCONF_BUFFER_INITIALIZER; + path_list_to_buffer(&personality->filter_includedirs, &pc_system_includedirs_buf, ':'); + + pkgconf_pkg_t *pkg_config_virtual = calloc(1, sizeof(pkgconf_pkg_t)); + if (pkg_config_virtual == NULL) + { + goto error; + } + + pkg_config_virtual->owner = client; + pkg_config_virtual->id = strdup("pkg-config"); + pkg_config_virtual->realname = strdup("pkg-config"); + pkg_config_virtual->description = strdup("virtual package defining pkgconf API version supported"); + pkg_config_virtual->url = strdup(PACKAGE_BUGREPORT); + pkg_config_virtual->version = strdup(PACKAGE_VERSION); + + pkgconf_tuple_add(client, &pkg_config_virtual->vars, "pc_system_libdirs", pc_system_libdirs_buf.base, false, 0); + pkgconf_tuple_add(client, &pkg_config_virtual->vars, "pc_system_includedirs", pc_system_includedirs_buf.base, false, 0); + pkgconf_tuple_add(client, &pkg_config_virtual->vars, "pc_path", pc_path_buf.base, false, 0); + + if (!pkgconf_client_preload_one(client, pkg_config_virtual)) + { + goto error; + } + + pkgconf_pkg_t *pkgconf_virtual = calloc(1, sizeof(pkgconf_pkg_t)); + if (pkgconf_virtual == NULL) + { + goto error; + } + + pkgconf_virtual->owner = client; + pkgconf_virtual->id = strdup("pkgconf"); + pkgconf_virtual->realname = strdup("pkgconf"); + pkgconf_virtual->description = strdup("virtual package defining pkgconf API version supported"); + pkgconf_virtual->url = strdup(PACKAGE_BUGREPORT); + pkgconf_virtual->version = strdup(PACKAGE_VERSION); + + pkgconf_tuple_add(client, &pkgconf_virtual->vars, "pc_system_libdirs", pc_system_libdirs_buf.base, false, 0); + pkgconf_tuple_add(client, &pkgconf_virtual->vars, "pc_system_includedirs", pc_system_includedirs_buf.base, false, 0); + pkgconf_tuple_add(client, &pkgconf_virtual->vars, "pc_path", pc_path_buf.base, false, 0); + + if (!pkgconf_client_preload_one(client, pkgconf_virtual)) + { + goto error; + } + +error: + pkgconf_buffer_finalize(&pc_path_buf); + pkgconf_buffer_finalize(&pc_system_libdirs_buf); + pkgconf_buffer_finalize(&pc_system_includedirs_buf); +} + +int +pkgconf_cli_run(pkgconf_cli_state_t *state, int argc, char *argv[], int last_argc) +{ + (void) argc; + + int ret = EXIT_SUCCESS; + unsigned int want_client_flags = PKGCONF_PKG_PKGF_NONE; + char *builddir; + char *sysroot_dir; + pkgconf_list_t pkgq = PKGCONF_LIST_INITIALIZER; + pkgconf_pkg_t world = { + .id = "virtual:world", + .realname = "virtual world package", + .flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL, + }; + +#ifndef PKGCONF_LITE + if ((state->want_flags & PKG_MSVC_SYNTAX) == PKG_MSVC_SYNTAX) + state->want_render_ops = msvc_renderer_get(); +#endif + + if (getenv("PKG_CONFIG_FDO_SYSROOT_RULES")) + want_client_flags |= PKGCONF_PKG_PKGF_FDO_SYSROOT_RULES; + + if (getenv("PKG_CONFIG_PKGCONF1_SYSROOT_RULES")) + want_client_flags |= PKGCONF_PKG_PKGF_PKGCONF1_SYSROOT_RULES; + + if ((state->want_flags & PKG_SHORT_ERRORS) == PKG_SHORT_ERRORS) + want_client_flags |= PKGCONF_PKG_PKGF_SIMPLIFY_ERRORS; + + if ((state->want_flags & PKG_DONT_RELOCATE_PATHS) == PKG_DONT_RELOCATE_PATHS) + want_client_flags |= PKGCONF_PKG_PKGF_DONT_RELOCATE_PATHS; + + state->error_msgout = stderr; + if ((state->want_flags & PKG_ERRORS_ON_STDOUT) == PKG_ERRORS_ON_STDOUT) + state->error_msgout = stdout; + if ((state->want_flags & PKG_SILENCE_ERRORS) == PKG_SILENCE_ERRORS) { + state->error_msgout = fopen(PATH_DEV_NULL, "w"); + state->opened_error_msgout = true; + } + + if ((state->want_flags & PKG_IGNORE_CONFLICTS) == PKG_IGNORE_CONFLICTS || getenv("PKG_CONFIG_IGNORE_CONFLICTS") != NULL) + want_client_flags |= PKGCONF_PKG_PKGF_SKIP_CONFLICTS; + + if ((state->want_flags & PKG_STATIC) == PKG_STATIC || state->personality->want_default_static) + want_client_flags |= (PKGCONF_PKG_PKGF_SEARCH_PRIVATE | PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS); + + if ((state->want_flags & PKG_SHARED) == PKG_SHARED) + want_client_flags &= ~(PKGCONF_PKG_PKGF_SEARCH_PRIVATE | PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS); + + /* if --static and --pure are both specified, then disable merge-back. + * this allows for a --static which searches private modules, but has the same fragment behaviour as if + * --static were disabled. see for rationale. + */ + if ((state->want_flags & PKG_PURE) == PKG_PURE || getenv("PKG_CONFIG_PURE_DEPGRAPH") != NULL || state->personality->want_default_pure) + want_client_flags &= ~PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS; + + if ((state->want_flags & PKG_ENV_ONLY) == PKG_ENV_ONLY) + want_client_flags |= PKGCONF_PKG_PKGF_ENV_ONLY; + + if ((state->want_flags & PKG_NO_CACHE) == PKG_NO_CACHE) + want_client_flags |= PKGCONF_PKG_PKGF_NO_CACHE; + +/* On Windows we want to always redefine the prefix by default + * but allow that behavior to be manually disabled */ +#if !defined(_WIN32) && !defined(_WIN64) + if ((state->want_flags & PKG_DEFINE_PREFIX) == PKG_DEFINE_PREFIX || getenv("PKG_CONFIG_RELOCATE_PATHS") != NULL) +#endif + want_client_flags |= PKGCONF_PKG_PKGF_REDEFINE_PREFIX; + + if ((state->want_flags & PKG_NO_UNINSTALLED) == PKG_NO_UNINSTALLED || getenv("PKG_CONFIG_DISABLE_UNINSTALLED") != NULL) + want_client_flags |= PKGCONF_PKG_PKGF_NO_UNINSTALLED; + + if ((state->want_flags & PKG_NO_PROVIDES) == PKG_NO_PROVIDES) + want_client_flags |= PKGCONF_PKG_PKGF_SKIP_PROVIDES; + + if ((state->want_flags & PKG_DONT_DEFINE_PREFIX) == PKG_DONT_DEFINE_PREFIX || getenv("PKG_CONFIG_DONT_DEFINE_PREFIX") != NULL) + want_client_flags &= ~PKGCONF_PKG_PKGF_REDEFINE_PREFIX; + + if ((state->want_flags & PKG_INTERNAL_CFLAGS) == PKG_INTERNAL_CFLAGS) + want_client_flags |= PKGCONF_PKG_PKGF_DONT_FILTER_INTERNAL_CFLAGS; + + /* --static --libs, --exists require the full dependency graph to be solved */ + if ((state->want_flags & (PKG_STATIC|PKG_LIBS)) == (PKG_STATIC|PKG_LIBS) || (state->want_flags & PKG_EXISTS) == PKG_EXISTS) + want_client_flags |= PKGCONF_PKG_PKGF_REQUIRE_INTERNAL; + + /* if these selectors are used, it means that we are querying metadata. + * so signal to libpkgconf that we only want to walk the flattened dependency set. + */ + if ((state->want_flags & PKG_MODVERSION) == PKG_MODVERSION || + (state->want_flags & PKG_REQUIRES) == PKG_REQUIRES || + (state->want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE || + (state->want_flags & PKG_PROVIDES) == PKG_PROVIDES || + (state->want_flags & PKG_VARIABLES) == PKG_VARIABLES || + (state->want_flags & PKG_PATH) == PKG_PATH || + state->want_variable != NULL) + state->maximum_traverse_depth = 1; + + /* if we are asking for a variable, path or list of variables, this only makes sense + * for a single package. + */ + if ((state->want_flags & PKG_VARIABLES) == PKG_VARIABLES || + (state->want_flags & PKG_PATH) == PKG_PATH || + state->want_variable != NULL) + state->maximum_package_count = 1; + + if ((state->want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE || + (state->want_flags & PKG_CFLAGS)) + { + want_client_flags |= PKGCONF_PKG_PKGF_SEARCH_PRIVATE; + } + + if ((builddir = getenv("PKG_CONFIG_TOP_BUILD_DIR")) != NULL) + pkgconf_client_set_buildroot_dir(&state->pkg_client, builddir); + + if ((sysroot_dir = getenv("PKG_CONFIG_SYSROOT_DIR")) != NULL) + { + const char *destdir; + + pkgconf_client_set_sysroot_dir(&state->pkg_client, sysroot_dir); + + if ((destdir = getenv("DESTDIR")) != NULL) + { + if (!strcmp(destdir, sysroot_dir)) + want_client_flags |= PKGCONF_PKG_PKGF_FDO_SYSROOT_RULES; + } + } + + /* we have determined what features we want most likely. in some cases, we override later. */ + pkgconf_client_set_flags(&state->pkg_client, want_client_flags); + + /* at this point, want_client_flags should be set, so build the dir list */ + pkgconf_client_dir_list_build(&state->pkg_client, state->personality); + + /* unveil the entire search path now that we have loaded the personality data and built the dir list. */ + if (!unveil_search_paths(&state->pkg_client, state->personality)) + { + fprintf(stderr, "pkgconf: unveil failed: %s\n", strerror(errno)); + return EXIT_FAILURE; + } + + /* register built-in packages */ + register_builtins(&state->pkg_client, state->personality); + + /* preload any files in PKG_CONFIG_PRELOADED_FILES */ + pkgconf_client_preload_from_environ(&state->pkg_client, "PKG_CONFIG_PRELOADED_FILES"); + + if (state->required_pkgconfig_version != NULL) + { + if (pkgconf_compare_version(PACKAGE_VERSION, state->required_pkgconfig_version) >= 0) + ret = EXIT_SUCCESS; + else + ret = EXIT_FAILURE; + + goto out; + } + + if ((state->want_flags & PKG_LIST) == PKG_LIST) + { + pkgconf_scan_all(&state->pkg_client, &state->pkg_client, print_list_entry); + ret = EXIT_SUCCESS; + goto out; + } + + if ((state->want_flags & PKG_LIST_PACKAGE_NAMES) == PKG_LIST_PACKAGE_NAMES) + { + pkgconf_scan_all(&state->pkg_client, &state->pkg_client, print_package_entry); + ret = EXIT_SUCCESS; + goto out; + } + + if (state->required_module_version != NULL) + { + pkgconf_pkg_t *pkg = NULL; + pkgconf_node_t *node; + pkgconf_list_t deplist = PKGCONF_LIST_INITIALIZER; + + while (argv[last_argc]) + { + pkgconf_dependency_parse_str(&state->pkg_client, &deplist, argv[last_argc], 0); + last_argc++; + } + + PKGCONF_FOREACH_LIST_ENTRY(deplist.head, node) + { + pkgconf_dependency_t *pkgiter = node->data; + + pkg = pkgconf_pkg_find(&state->pkg_client, pkgiter->package); + if (pkg == NULL) + { + if (state->want_flags & PKG_PRINT_ERRORS) + pkgconf_error(&state->pkg_client, "Package '%s' was not found\n", pkgiter->package); + + ret = EXIT_FAILURE; + goto cleanup; + } + + if (pkgconf_compare_version(pkg->version, state->required_module_version) >= 0) + { + ret = EXIT_SUCCESS; + goto cleanup; + } + } + + ret = EXIT_FAILURE; +cleanup: + if (pkg != NULL) + pkgconf_pkg_unref(&state->pkg_client, pkg); + pkgconf_dependency_free(&deplist); + goto out; + } + else if (state->required_exact_module_version != NULL) + { + pkgconf_pkg_t *pkg = NULL; + pkgconf_node_t *node; + pkgconf_list_t deplist = PKGCONF_LIST_INITIALIZER; + + while (argv[pkg_optind]) + { + pkgconf_dependency_parse_str(&state->pkg_client, &deplist, argv[pkg_optind], 0); + pkg_optind++; + } + + PKGCONF_FOREACH_LIST_ENTRY(deplist.head, node) + { + pkgconf_dependency_t *pkgiter = node->data; + + pkg = pkgconf_pkg_find(&state->pkg_client, pkgiter->package); + if (pkg == NULL) + { + if (state->want_flags & PKG_PRINT_ERRORS) + pkgconf_error(&state->pkg_client, "Package '%s' was not found\n", pkgiter->package); + + ret = EXIT_FAILURE; + goto cleanup2; + } + + if (pkgconf_compare_version(pkg->version, state->required_exact_module_version) == 0) + { + ret = EXIT_SUCCESS; + goto cleanup2; + } + } + + ret = EXIT_FAILURE; +cleanup2: + if (pkg != NULL) + pkgconf_pkg_unref(&state->pkg_client, pkg); + pkgconf_dependency_free(&deplist); + goto out; + } + else if (state->required_max_module_version != NULL) + { + pkgconf_pkg_t *pkg = NULL; + pkgconf_node_t *node; + pkgconf_list_t deplist = PKGCONF_LIST_INITIALIZER; + + while (argv[pkg_optind]) + { + pkgconf_dependency_parse_str(&state->pkg_client, &deplist, argv[pkg_optind], 0); + pkg_optind++; + } + + PKGCONF_FOREACH_LIST_ENTRY(deplist.head, node) + { + pkgconf_dependency_t *pkgiter = node->data; + + pkg = pkgconf_pkg_find(&state->pkg_client, pkgiter->package); + if (pkg == NULL) + { + if (state->want_flags & PKG_PRINT_ERRORS) + pkgconf_error(&state->pkg_client, "Package '%s' was not found\n", pkgiter->package); + + ret = EXIT_FAILURE; + goto cleanup3; + } + + if (pkgconf_compare_version(pkg->version, state->required_max_module_version) <= 0) + { + ret = EXIT_SUCCESS; + goto cleanup3; + } + } + + ret = EXIT_FAILURE; +cleanup3: + if (pkg != NULL) + pkgconf_pkg_unref(&state->pkg_client, pkg); + pkgconf_dependency_free(&deplist); + goto out; + } + + while (1) + { + char *package = argv[pkg_optind]; + char *end; + + if (package == NULL) + break; + + /* check if there is a limit to the number of packages allowed to be included, if so and we have hit + * the limit, stop adding packages to the queue. + */ + if (state->maximum_package_count > 0 && pkgq.length >= state->maximum_package_count) + break; + + while (isspace((unsigned char)package[0])) + package++; + + /* skip empty packages */ + if (package[0] == '\0') { + pkg_optind++; + continue; + } + + end = package + strlen(package) - 1; + while(end > package && isspace((unsigned char)end[0])) end--; + end[1] = '\0'; + + if (argv[pkg_optind + 1] == NULL || !PKGCONF_IS_OPERATOR_CHAR(*(argv[pkg_optind + 1]))) + { + pkgconf_queue_push(&pkgq, package); + pkg_optind++; + } + else if (argv[pkg_optind + 2] == NULL) + { + char packagebuf[PKGCONF_BUFSIZE]; + + snprintf(packagebuf, sizeof packagebuf, "%s %s", package, argv[pkg_optind + 1]); + pkg_optind += 2; + + pkgconf_queue_push(&pkgq, packagebuf); + } + else + { + char packagebuf[PKGCONF_BUFSIZE]; + + snprintf(packagebuf, sizeof packagebuf, "%s %s %s", package, argv[pkg_optind + 1], argv[pkg_optind + 2]); + pkg_optind += 3; + + pkgconf_queue_push(&pkgq, packagebuf); + } + } + + if (pkgq.head == NULL) + { + fprintf(stderr, "Please specify at least one package name on the command line.\n"); + ret = EXIT_FAILURE; + goto out; + } + + ret = EXIT_SUCCESS; + + if (!pkgconf_queue_solve(&state->pkg_client, &pkgq, &world, state->maximum_traverse_depth)) + { + ret = EXIT_FAILURE; + goto out; + } + + /* we shouldn't need to unveil any more filesystem accesses from this point, so lock it down */ + if (pkgconf_unveil(NULL, NULL) == -1) + { + fprintf(stderr, "pkgconf: unveil lockdown failed: %s\n", strerror(errno)); + return EXIT_FAILURE; + } + +#ifndef PKGCONF_LITE + if ((state->want_flags & PKG_SIMULATE) == PKG_SIMULATE) + { + state->want_flags &= ~(PKG_CFLAGS|PKG_LIBS); + + pkgconf_client_set_flags(&state->pkg_client, want_client_flags | PKGCONF_PKG_PKGF_SKIP_ERRORS); + apply_simulate(&state->pkg_client, &world, NULL, -1); + } +#endif + + if ((state->want_flags & PKG_VALIDATE) == PKG_VALIDATE) + goto out; + + if ((state->want_flags & PKG_DUMP_LICENSE) == PKG_DUMP_LICENSE) + { + apply_license(&state->pkg_client, &world, &ret, 2); + goto out; + } + + if ((state->want_flags & PKG_DUMP_LICENSE_FILE) == PKG_DUMP_LICENSE_FILE) + { + apply_license_file(&state->pkg_client, &world, &ret, 2); + goto out; + } + + if ((state->want_flags & PKG_DUMP_SOURCE) == PKG_DUMP_SOURCE) + { + apply_source(&state->pkg_client, &world, &ret, 2); + goto out; + } + + + if ((state->want_flags & PKG_UNINSTALLED) == PKG_UNINSTALLED) + { + ret = EXIT_FAILURE; + apply_uninstalled(&state->pkg_client, &world, &ret, 2); + goto out; + } + + if (state->want_env_prefix != NULL) + { + apply_env(&state->pkg_client, &world, state->want_env_prefix, 2); + goto out; + } + + if ((state->want_flags & PKG_PROVIDES) == PKG_PROVIDES) + { + state->want_flags &= ~(PKG_CFLAGS|PKG_LIBS); + apply_provides(&state->pkg_client, &world, NULL, 2); + } + +#ifndef PKGCONF_LITE + if ((state->want_flags & PKG_DIGRAPH) == PKG_DIGRAPH) + { + state->want_flags &= ~(PKG_CFLAGS|PKG_LIBS); + apply_digraph(&state->pkg_client, &world, &pkgq, 2); + } + + if ((state->want_flags & PKG_SOLUTION) == PKG_SOLUTION) + { + state->want_flags &= ~(PKG_CFLAGS|PKG_LIBS); + apply_print_solution(&state->pkg_client, &world, NULL, 2); + } +#endif + + if ((state->want_flags & PKG_MODVERSION) == PKG_MODVERSION) + { + state->want_flags &= ~(PKG_CFLAGS|PKG_LIBS); + apply_modversion(&state->pkg_client, &world, &pkgq, 2); + } + + if ((state->want_flags & PKG_PATH) == PKG_PATH) + { + state->want_flags &= ~(PKG_CFLAGS|PKG_LIBS); + + pkgconf_client_set_flags(&state->pkg_client, want_client_flags | PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL); + apply_path(&state->pkg_client, &world, NULL, 2); + } + + if ((state->want_flags & PKG_VARIABLES) == PKG_VARIABLES) + { + state->want_flags &= ~(PKG_CFLAGS|PKG_LIBS); + apply_variables(&state->pkg_client, &world, NULL, 2); + } + + if (state->want_variable != NULL) + { + state->want_flags &= ~(PKG_CFLAGS|PKG_LIBS); + + pkgconf_client_set_flags(&state->pkg_client, want_client_flags | PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL); + apply_variable(&state->pkg_client, &world, state->want_variable, 2); + } + + if ((state->want_flags & PKG_REQUIRES) == PKG_REQUIRES) + { + state->want_flags &= ~(PKG_CFLAGS|PKG_LIBS); + apply_requires(&state->pkg_client, &world, NULL, 2); + } + + if ((state->want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE) + { + state->want_flags &= ~(PKG_CFLAGS|PKG_LIBS); + + apply_requires_private(&state->pkg_client, &world, NULL, 2); + } + + if ((state->want_flags & PKG_FRAGMENT_TREE)) + { + state->want_flags &= ~(PKG_CFLAGS|PKG_LIBS); + + apply_fragment_tree(&state->pkg_client, &world, NULL, 2); + } + + if ((state->want_flags & (PKG_CFLAGS|PKG_LIBS))) + { + pkgconf_list_t target_list = PKGCONF_LIST_INITIALIZER; + pkgconf_buffer_t render_buf = PKGCONF_BUFFER_INITIALIZER; + + if ((state->want_flags & PKG_CFLAGS)) + apply_cflags(&state->pkg_client, &world, &target_list, 2); + + if ((state->want_flags & PKG_LIBS) && !(state->want_flags & PKG_STATIC)) + pkgconf_client_set_flags(&state->pkg_client, state->pkg_client.flags & ~PKGCONF_PKG_PKGF_SEARCH_PRIVATE); + + if ((state->want_flags & PKG_LIBS)) + apply_libs(&state->pkg_client, &world, &target_list, 2); + + pkgconf_fragment_render_buf(&target_list, &render_buf, true, state->want_render_ops, (state->want_flags & PKG_NEWLINES) ? '\n' : ' '); + pkgconf_output_putbuf(state->pkg_client.output, PKGCONF_OUTPUT_STDOUT, &render_buf, true); + pkgconf_buffer_finalize(&render_buf); + + pkgconf_fragment_free(&target_list); + } + +out: + pkgconf_solution_free(&state->pkg_client, &world); + pkgconf_queue_free(&pkgq); + pkgconf_cli_state_reset(state); + + return ret; +} + +void +pkgconf_cli_state_reset(pkgconf_cli_state_t *state) +{ + pkgconf_cross_personality_deinit(state->personality); + pkgconf_client_deinit(&state->pkg_client); + + if (state->logfile_out != NULL) + fclose(state->logfile_out); + if (state->opened_error_msgout) + fclose(state->error_msgout); +} diff --git a/cli/core.h b/cli/core.h new file mode 100644 index 0000000..f5307fb --- /dev/null +++ b/cli/core.h @@ -0,0 +1,101 @@ +/* + * core.h + * core, printer functions + * + * Copyright (c) 2011-2025 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 __CLI_CORE_H +#define __CLI_CORE_H + +#define PKG_CFLAGS_ONLY_I (((uint64_t) 1) << 2) +#define PKG_CFLAGS_ONLY_OTHER (((uint64_t) 1) << 3) +#define PKG_CFLAGS (PKG_CFLAGS_ONLY_I|PKG_CFLAGS_ONLY_OTHER) +#define PKG_LIBS_ONLY_LDPATH (((uint64_t) 1) << 5) +#define PKG_LIBS_ONLY_LIBNAME (((uint64_t) 1) << 6) +#define PKG_LIBS_ONLY_OTHER (((uint64_t) 1) << 7) +#define PKG_LIBS (PKG_LIBS_ONLY_LDPATH|PKG_LIBS_ONLY_LIBNAME|PKG_LIBS_ONLY_OTHER) +#define PKG_MODVERSION (((uint64_t) 1) << 8) +#define PKG_REQUIRES (((uint64_t) 1) << 9) +#define PKG_REQUIRES_PRIVATE (((uint64_t) 1) << 10) +#define PKG_VARIABLES (((uint64_t) 1) << 11) +#define PKG_DIGRAPH (((uint64_t) 1) << 12) +#define PKG_KEEP_SYSTEM_CFLAGS (((uint64_t) 1) << 13) +#define PKG_KEEP_SYSTEM_LIBS (((uint64_t) 1) << 14) +#define PKG_VERSION (((uint64_t) 1) << 15) +#define PKG_ABOUT (((uint64_t) 1) << 16) +#define PKG_ENV_ONLY (((uint64_t) 1) << 17) +#define PKG_ERRORS_ON_STDOUT (((uint64_t) 1) << 18) +#define PKG_SILENCE_ERRORS (((uint64_t) 1) << 19) +#define PKG_IGNORE_CONFLICTS (((uint64_t) 1) << 20) +#define PKG_STATIC (((uint64_t) 1) << 21) +#define PKG_NO_UNINSTALLED (((uint64_t) 1) << 22) +#define PKG_UNINSTALLED (((uint64_t) 1) << 23) +#define PKG_LIST (((uint64_t) 1) << 24) +#define PKG_HELP (((uint64_t) 1) << 25) +#define PKG_PRINT_ERRORS (((uint64_t) 1) << 26) +#define PKG_SIMULATE (((uint64_t) 1) << 27) +#define PKG_NO_CACHE (((uint64_t) 1) << 28) +#define PKG_PROVIDES (((uint64_t) 1) << 29) +#define PKG_VALIDATE (((uint64_t) 1) << 30) +#define PKG_LIST_PACKAGE_NAMES (((uint64_t) 1) << 31) +#define PKG_NO_PROVIDES (((uint64_t) 1) << 32) +#define PKG_PURE (((uint64_t) 1) << 33) +#define PKG_PATH (((uint64_t) 1) << 34) +#define PKG_DEFINE_PREFIX (((uint64_t) 1) << 35) +#define PKG_DONT_DEFINE_PREFIX (((uint64_t) 1) << 36) +#define PKG_DONT_RELOCATE_PATHS (((uint64_t) 1) << 37) +#define PKG_DEBUG (((uint64_t) 1) << 38) +#define PKG_SHORT_ERRORS (((uint64_t) 1) << 39) +#define PKG_EXISTS (((uint64_t) 1) << 40) +#define PKG_MSVC_SYNTAX (((uint64_t) 1) << 41) +#define PKG_INTERNAL_CFLAGS (((uint64_t) 1) << 42) +#define PKG_DUMP_PERSONALITY (((uint64_t) 1) << 43) +#define PKG_SHARED (((uint64_t) 1) << 44) +#define PKG_DUMP_LICENSE (((uint64_t) 1) << 45) +#define PKG_SOLUTION (((uint64_t) 1) << 46) +#define PKG_EXISTS_CFLAGS (((uint64_t) 1) << 47) +#define PKG_FRAGMENT_TREE (((uint64_t) 1) << 48) +#define PKG_DUMP_SOURCE (((uint64_t) 1) << 49) +#define PKG_DUMP_LICENSE_FILE (((uint64_t) 1) << 50) +#define PKG_NEWLINES (((uint64_t) 1) << 51) + +typedef struct { + pkgconf_client_t pkg_client; + pkgconf_fragment_render_ops_t *want_render_ops; + + uint64_t want_flags; + int verbosity; + int maximum_traverse_depth; + size_t maximum_package_count; + + char *want_variable; + char *want_fragment_filter; + char *want_env_prefix; + + char *required_pkgconfig_version; + char *required_exact_module_version; + char *required_max_module_version; + char *required_module_version; + + FILE *error_msgout; + FILE *logfile_out; + + bool opened_error_msgout; + + pkgconf_cross_personality_t *personality; +} pkgconf_cli_state_t; + +extern void path_list_to_buffer(const pkgconf_list_t *list, pkgconf_buffer_t *buffer, char delim); +extern int pkgconf_cli_run(pkgconf_cli_state_t *state, int argc, char *argv[], int last_argc); +extern void pkgconf_cli_state_reset(pkgconf_cli_state_t *state); + +#endif diff --git a/cli/main.c b/cli/main.c index a1fb0d4..77c1c8a 100644 --- a/cli/main.c +++ b/cli/main.c @@ -1,9 +1,8 @@ /* * main.c - * main() routine, printer functions + * main() routine * - * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 - * pkgconf authors (see AUTHORS). + * Copyright (c) 2011-2025 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 @@ -18,865 +17,87 @@ #include #include #include "getopt_long.h" -#ifndef PKGCONF_LITE -#include "renderer-msvc.h" -#endif - -#define PKG_CFLAGS_ONLY_I (((uint64_t) 1) << 2) -#define PKG_CFLAGS_ONLY_OTHER (((uint64_t) 1) << 3) -#define PKG_CFLAGS (PKG_CFLAGS_ONLY_I|PKG_CFLAGS_ONLY_OTHER) -#define PKG_LIBS_ONLY_LDPATH (((uint64_t) 1) << 5) -#define PKG_LIBS_ONLY_LIBNAME (((uint64_t) 1) << 6) -#define PKG_LIBS_ONLY_OTHER (((uint64_t) 1) << 7) -#define PKG_LIBS (PKG_LIBS_ONLY_LDPATH|PKG_LIBS_ONLY_LIBNAME|PKG_LIBS_ONLY_OTHER) -#define PKG_MODVERSION (((uint64_t) 1) << 8) -#define PKG_REQUIRES (((uint64_t) 1) << 9) -#define PKG_REQUIRES_PRIVATE (((uint64_t) 1) << 10) -#define PKG_VARIABLES (((uint64_t) 1) << 11) -#define PKG_DIGRAPH (((uint64_t) 1) << 12) -#define PKG_KEEP_SYSTEM_CFLAGS (((uint64_t) 1) << 13) -#define PKG_KEEP_SYSTEM_LIBS (((uint64_t) 1) << 14) -#define PKG_VERSION (((uint64_t) 1) << 15) -#define PKG_ABOUT (((uint64_t) 1) << 16) -#define PKG_ENV_ONLY (((uint64_t) 1) << 17) -#define PKG_ERRORS_ON_STDOUT (((uint64_t) 1) << 18) -#define PKG_SILENCE_ERRORS (((uint64_t) 1) << 19) -#define PKG_IGNORE_CONFLICTS (((uint64_t) 1) << 20) -#define PKG_STATIC (((uint64_t) 1) << 21) -#define PKG_NO_UNINSTALLED (((uint64_t) 1) << 22) -#define PKG_UNINSTALLED (((uint64_t) 1) << 23) -#define PKG_LIST (((uint64_t) 1) << 24) -#define PKG_HELP (((uint64_t) 1) << 25) -#define PKG_PRINT_ERRORS (((uint64_t) 1) << 26) -#define PKG_SIMULATE (((uint64_t) 1) << 27) -#define PKG_NO_CACHE (((uint64_t) 1) << 28) -#define PKG_PROVIDES (((uint64_t) 1) << 29) -#define PKG_VALIDATE (((uint64_t) 1) << 30) -#define PKG_LIST_PACKAGE_NAMES (((uint64_t) 1) << 31) -#define PKG_NO_PROVIDES (((uint64_t) 1) << 32) -#define PKG_PURE (((uint64_t) 1) << 33) -#define PKG_PATH (((uint64_t) 1) << 34) -#define PKG_DEFINE_PREFIX (((uint64_t) 1) << 35) -#define PKG_DONT_DEFINE_PREFIX (((uint64_t) 1) << 36) -#define PKG_DONT_RELOCATE_PATHS (((uint64_t) 1) << 37) -#define PKG_DEBUG (((uint64_t) 1) << 38) -#define PKG_SHORT_ERRORS (((uint64_t) 1) << 39) -#define PKG_EXISTS (((uint64_t) 1) << 40) -#define PKG_MSVC_SYNTAX (((uint64_t) 1) << 41) -#define PKG_INTERNAL_CFLAGS (((uint64_t) 1) << 42) -#define PKG_DUMP_PERSONALITY (((uint64_t) 1) << 43) -#define PKG_SHARED (((uint64_t) 1) << 44) -#define PKG_DUMP_LICENSE (((uint64_t) 1) << 45) -#define PKG_SOLUTION (((uint64_t) 1) << 46) -#define PKG_EXISTS_CFLAGS (((uint64_t) 1) << 47) -#define PKG_FRAGMENT_TREE (((uint64_t) 1) << 48) -#define PKG_DUMP_SOURCE (((uint64_t) 1) << 49) -#define PKG_DUMP_LICENSE_FILE (((uint64_t) 1) << 50) -#define PKG_NEWLINES (((uint64_t) 1) << 51) - -static pkgconf_client_t pkg_client; -static const pkgconf_fragment_render_ops_t *want_render_ops = NULL; - -static uint64_t want_flags; -static int verbosity = 0; -static int maximum_traverse_depth = 2000; -static size_t maximum_package_count = 0; - -static char *want_variable = NULL; -static char *want_fragment_filter = NULL; - -static FILE *error_msgout = NULL; -static FILE *logfile_out = NULL; +#include "core.h" static bool error_handler(const char *msg, const pkgconf_client_t *client, void *data) { - (void) client; (void) data; - fprintf(error_msgout, "%s", msg); + pkgconf_cli_state_t *state = client->client_data; + + fprintf(state->error_msgout, "%s", msg); return true; } -static bool -print_list_entry(const pkgconf_pkg_t *entry, void *data) -{ - const pkgconf_node_t *n; - pkgconf_client_t *client = data; - - if (entry->flags & PKGCONF_PKG_PROPF_UNINSTALLED) - return false; - - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, - "%-30s %s - %s\n", entry->id, entry->realname, entry->description); - - PKGCONF_FOREACH_LIST_ENTRY(entry->provides.head, n) - { - const pkgconf_dependency_t *dep = n->data; - - if (!strcmp(dep->package, entry->id)) - continue; - - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, - "%-30s %s - %s (provided by %s)\n", dep->package, entry->realname, entry->description, entry->id); - } - - return false; -} - -static bool -print_package_entry(const pkgconf_pkg_t *entry, void *data) -{ - const pkgconf_node_t *n; - pkgconf_client_t *client = data; - - if (entry->flags & PKGCONF_PKG_PROPF_UNINSTALLED) - return false; - - pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, entry->id); - - PKGCONF_FOREACH_LIST_ENTRY(entry->provides.head, n) - { - const pkgconf_dependency_t *dep = n->data; - - if (!strcmp(dep->package, entry->id)) - continue; - - pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, dep->package); - } - - return false; -} - -static bool -filter_cflags(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data) -{ - int got_flags = 0; - (void) client; - (void) data; - - if (!(want_flags & PKG_KEEP_SYSTEM_CFLAGS) && pkgconf_fragment_has_system_dir(client, frag)) - return false; - - if (want_fragment_filter != NULL && (strchr(want_fragment_filter, frag->type) == NULL || !frag->type)) - return false; - - if (frag->type == 'I') - got_flags = PKG_CFLAGS_ONLY_I; - else - got_flags = PKG_CFLAGS_ONLY_OTHER; - - return (want_flags & got_flags) != 0; -} - -static bool -filter_libs(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data) -{ - int got_flags = 0; - (void) client; - (void) data; - - if (!(want_flags & PKG_KEEP_SYSTEM_LIBS) && pkgconf_fragment_has_system_dir(client, frag)) - return false; - - if (want_fragment_filter != NULL && (strchr(want_fragment_filter, frag->type) == NULL || !frag->type)) - return false; - - switch (frag->type) - { - case 'L': got_flags = PKG_LIBS_ONLY_LDPATH; break; - case 'l': got_flags = PKG_LIBS_ONLY_LIBNAME; break; - default: got_flags = PKG_LIBS_ONLY_OTHER; break; - } - - return (want_flags & got_flags) != 0; -} - static void -print_variables(pkgconf_output_t *output, pkgconf_pkg_t *pkg) +relocate_path(const char *path) { - pkgconf_node_t *node; + char buf[PKGCONF_BUFSIZE]; - PKGCONF_FOREACH_LIST_ENTRY(pkg->vars.head, node) - { - pkgconf_tuple_t *tuple = node->data; + pkgconf_strlcpy(buf, path, sizeof buf); + pkgconf_path_relocate(buf, sizeof buf); - pkgconf_output_puts(output, PKGCONF_OUTPUT_STDOUT, tuple->key); - } -} - -static void -print_dependency_list(pkgconf_output_t *output, pkgconf_list_t *list) -{ - pkgconf_node_t *node; - - PKGCONF_FOREACH_LIST_ENTRY(list->head, node) - { - pkgconf_dependency_t *dep = node->data; - - pkgconf_output_fmt(output, PKGCONF_OUTPUT_STDOUT, "%s", dep->package); - - if (dep->version != NULL) - pkgconf_output_fmt(output, PKGCONF_OUTPUT_STDOUT, " %s %s", - pkgconf_pkg_get_comparator(dep), dep->version); - - pkgconf_output_fmt(output, PKGCONF_OUTPUT_STDOUT, "\n"); - } -} - -static bool -apply_provides(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) -{ - pkgconf_node_t *iter; - (void) unused; - (void) maxdepth; - - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) - { - pkgconf_dependency_t *dep = iter->data; - pkgconf_pkg_t *pkg = dep->match; - - print_dependency_list(client->output, &pkg->provides); - } - - return true; + printf("%s\n", buf); } #ifndef PKGCONF_LITE static void -print_digraph_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) +dump_personality(const pkgconf_cross_personality_t *p) { - pkgconf_node_t *node; - pkgconf_pkg_t **last_seen = data; + pkgconf_buffer_t pc_path_buf = PKGCONF_BUFFER_INITIALIZER; + path_list_to_buffer(&p->dir_list, &pc_path_buf, ':'); - if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL) - return; + pkgconf_buffer_t pc_system_libdirs_buf = PKGCONF_BUFFER_INITIALIZER; + path_list_to_buffer(&p->filter_libdirs, &pc_system_libdirs_buf, ':'); - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "\"%s\" [fontname=Sans fontsize=8", pkg->id); + pkgconf_buffer_t pc_system_includedirs_buf = PKGCONF_BUFFER_INITIALIZER; + path_list_to_buffer(&p->filter_includedirs, &pc_system_includedirs_buf, ':'); - if (pkg->flags & PKGCONF_PKG_PROPF_VISITED_PRIVATE) - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, " fontcolor=gray color=gray"); + printf("Triplet: %s\n", p->name); - pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, "]"); + if (p->sysroot_dir) + printf("SysrootDir: %s\n", p->sysroot_dir); - if (last_seen != NULL) - { - if (*last_seen != NULL) - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, - "\"%s\" -> \"%s\" [fontname=Sans fontsize=8 color=red]\n", (*last_seen)->id, pkg->id); + printf("DefaultSearchPaths: %s\n", pc_path_buf.base); + printf("SystemIncludePaths: %s\n", pc_system_includedirs_buf.base); + printf("SystemLibraryPaths: %s\n", pc_system_libdirs_buf.base); - *last_seen = pkg; - } - - PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, node) - { - pkgconf_dependency_t *dep = node->data; - const char *dep_id = (dep->match != NULL) ? dep->match->id : dep->package; - - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "\"%s\" -> \"%s\" [fontname=Sans fontsize=8", - pkg->id, dep_id); - - if (dep->flags & PKGCONF_PKG_DEPF_PRIVATE) - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, " color=gray"); - - pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, "]"); - } - - PKGCONF_FOREACH_LIST_ENTRY(pkg->requires_private.head, node) - { - pkgconf_dependency_t *dep = node->data; - const char *dep_id = (dep->match != NULL) ? dep->match->id : dep->package; - - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, - "\"%s\" -> \"%s\" [fontname=Sans fontsize=8 color=gray]\n", pkg->id, dep_id); - } + pkgconf_buffer_finalize(&pc_path_buf); + pkgconf_buffer_finalize(&pc_system_libdirs_buf); + pkgconf_buffer_finalize(&pc_system_includedirs_buf); } -static bool -apply_digraph(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) +static pkgconf_cross_personality_t * +deduce_personality(char *argv[]) { - int eflag; - pkgconf_list_t *list = data; - pkgconf_pkg_t *last_seen = NULL; - pkgconf_node_t *iter; + const char *argv0 = argv[0]; + char *i, *prefix; + pkgconf_cross_personality_t *out; - pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, - "digraph deptree {\n" - "edge [color=blue len=7.5 fontname=Sans fontsize=8]\n" - "node [fontname=Sans fontsize=8]\n" - "\"user:request\" [fontname=Sans fontsize=8]"); + i = strrchr(argv0, '/'); + if (i != NULL) + argv0 = i + 1; - PKGCONF_FOREACH_LIST_ENTRY(list->head, iter) - { - pkgconf_queue_t *pkgq = iter->data; - pkgconf_pkg_t *pkg = pkgconf_pkg_find(client, pkgq->package); - - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, - "\"user:request\" -> \"%s\" [fontname=Sans fontsize=8]\n", - pkg == NULL ? pkgq->package : pkg->id); - - if (pkg != NULL) - pkgconf_pkg_unref(client, pkg); - } - - eflag = pkgconf_pkg_traverse(client, world, print_digraph_node, &last_seen, maxdepth, 0); - - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, "}"); - return true; -} - -static void -print_solution_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *unused) -{ - (void) unused; - - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "%s (%"PRIu64")%s\n", - pkg->id, pkg->identifier, (pkg->flags & PKGCONF_PKG_PROPF_VISITED_PRIVATE) == PKGCONF_PKG_PROPF_VISITED_PRIVATE ? " [private]" : ""); -} - -static bool -apply_print_solution(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) -{ - int eflag; - - eflag = pkgconf_pkg_traverse(client, world, print_solution_node, unused, maxdepth, 0); - - return eflag == PKGCONF_PKG_ERRF_OK; -} +#if defined(_WIN32) || defined(_WIN64) + i = strrchr(argv0, '\\'); + if (i != NULL) + argv0 = i + 1; #endif -static bool -apply_modversion(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) -{ - pkgconf_node_t *queue_iter; - pkgconf_list_t *pkgq = data; - (void) maxdepth; + i = strstr(argv0, "-pkg"); + if (i == NULL) + return pkgconf_cross_personality_default(); - PKGCONF_FOREACH_LIST_ENTRY(pkgq->head, queue_iter) - { - pkgconf_node_t *world_iter; - pkgconf_queue_t *queue_node = queue_iter->data; + prefix = pkgconf_strndup(argv0, i - argv0); + out = pkgconf_cross_personality_find(prefix); + free(prefix); + if (out == NULL) + return pkgconf_cross_personality_default(); - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, world_iter) - { - pkgconf_dependency_t *dep = world_iter->data; - pkgconf_pkg_t *pkg = dep->match; - - const size_t name_len = strlen(pkg->why); - if (name_len > strlen(queue_node->package) || - strncmp(pkg->why, queue_node->package, name_len) || - (queue_node->package[name_len] != 0 && - !isspace((unsigned char)queue_node->package[name_len]) && - !PKGCONF_IS_OPERATOR_CHAR(queue_node->package[name_len]))) - continue; - - if (pkg->version != NULL) { - if (verbosity) - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "%s: ", pkg->id); - - pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, pkg->version); - } - - break; - } - } - - return true; -} - -static bool -apply_variables(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) -{ - pkgconf_node_t *iter; - (void) unused; - (void) maxdepth; - - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) - { - pkgconf_dependency_t *dep = iter->data; - pkgconf_pkg_t *pkg = dep->match; - - print_variables(client->output, pkg); - } - - return true; -} - -static bool -apply_path(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) -{ - pkgconf_node_t *iter; - (void) unused; - (void) maxdepth; - - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) - { - pkgconf_dependency_t *dep = iter->data; - pkgconf_pkg_t *pkg = dep->match; - - /* a module entry with no filename is either virtual, static (builtin) or synthesized. */ - if (pkg->filename != NULL) - pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, pkg->filename); - } - - return true; -} - -static bool -apply_variable(pkgconf_client_t *client, pkgconf_pkg_t *world, void *variable, int maxdepth) -{ - pkgconf_node_t *iter; - (void) maxdepth; - - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) - { - pkgconf_dependency_t *dep = iter->data; - pkgconf_pkg_t *pkg = dep->match; - const char *var; - - var = pkgconf_tuple_find(client, &pkg->vars, variable); - - if (var != NULL) - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, - "%s%s", iter->prev != NULL ? " " : "", var); - } - - pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, ""); - - return true; -} - -static bool -apply_env_var(const char *prefix, pkgconf_client_t *client, pkgconf_pkg_t *world, int maxdepth, - unsigned int (*collect_fn)(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list, int maxdepth), - bool (*filter_fn)(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data), - void (*postprocess_fn)(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *fragment_list)) -{ - pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER; - pkgconf_list_t filtered_list = PKGCONF_LIST_INITIALIZER; - pkgconf_buffer_t render_buf = PKGCONF_BUFFER_INITIALIZER; - unsigned int eflag; - - eflag = collect_fn(client, world, &unfiltered_list, maxdepth); - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - pkgconf_fragment_filter(client, &filtered_list, &unfiltered_list, filter_fn, NULL); - - if (postprocess_fn != NULL) - postprocess_fn(client, world, &filtered_list); - - if (filtered_list.head == NULL) - goto out; - - pkgconf_fragment_render_buf(&filtered_list, &render_buf, true, want_render_ops, (want_flags & PKG_NEWLINES) ? '\n' : ' '); - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "%s='%s'\n", - prefix, pkgconf_buffer_str_or_empty(&render_buf)); - pkgconf_buffer_finalize(&render_buf); - -out: - pkgconf_fragment_free(&unfiltered_list); - pkgconf_fragment_free(&filtered_list); - - return true; -} - -static void -maybe_add_module_definitions(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *fragment_list) -{ - pkgconf_node_t *world_iter; - - if ((want_flags & PKG_EXISTS_CFLAGS) != PKG_EXISTS_CFLAGS) - return; - - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, world_iter) - { - pkgconf_dependency_t *dep = world_iter->data; - char havebuf[PKGCONF_ITEM_SIZE]; - char *p; - - if ((dep->flags & PKGCONF_PKG_DEPF_QUERY) != PKGCONF_PKG_DEPF_QUERY) - continue; - - if (dep->match == NULL) - continue; - - snprintf(havebuf, sizeof havebuf, "HAVE_%s", dep->match->id); - - for (p = havebuf; *p; p++) - { - switch (*p) - { - case ' ': - case '-': - *p = '_'; - break; - - default: - *p = toupper((unsigned char) *p); - } - } - - pkgconf_fragment_insert(client, fragment_list, 'D', havebuf, false); - } -} - -static void -apply_env_variables(pkgconf_client_t *client, pkgconf_pkg_t *world, const char *env_prefix) -{ - pkgconf_node_t *world_iter; - - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, world_iter) - { - pkgconf_dependency_t *dep = world_iter->data; - pkgconf_pkg_t *pkg = dep->match; - pkgconf_node_t *tuple_iter; - - if ((dep->flags & PKGCONF_PKG_DEPF_QUERY) != PKGCONF_PKG_DEPF_QUERY) - continue; - - if (dep->match == NULL) - continue; - - PKGCONF_FOREACH_LIST_ENTRY(pkg->vars.head, tuple_iter) - { - pkgconf_tuple_t *tuple = tuple_iter->data; - char havebuf[PKGCONF_ITEM_SIZE]; - char *p; - - if (want_variable != NULL && strcmp(want_variable, tuple->key)) - continue; - - snprintf(havebuf, sizeof havebuf, "%s_%s", env_prefix, tuple->key); - - for (p = havebuf; *p; p++) - { - switch (*p) - { - case ' ': - case '-': - *p = '_'; - break; - - default: - *p = toupper((unsigned char) *p); - } - } - - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, - "%s='%s'\n", havebuf, tuple->value); - } - } -} - -static bool -apply_env(pkgconf_client_t *client, pkgconf_pkg_t *world, void *env_prefix_p, int maxdepth) -{ - const char *want_env_prefix = env_prefix_p, *it; - char workbuf[PKGCONF_ITEM_SIZE]; - - for (it = want_env_prefix; *it != '\0'; it++) - if (!isalpha((unsigned char)*it) && - !isdigit((unsigned char)*it)) - return false; - - snprintf(workbuf, sizeof workbuf, "%s_CFLAGS", want_env_prefix); - if (!apply_env_var(workbuf, client, world, maxdepth, pkgconf_pkg_cflags, filter_cflags, maybe_add_module_definitions)) - return false; - - snprintf(workbuf, sizeof workbuf, "%s_LIBS", want_env_prefix); - if (!apply_env_var(workbuf, client, world, maxdepth, pkgconf_pkg_libs, filter_libs, NULL)) - return false; - - if ((want_flags & PKG_VARIABLES) == PKG_VARIABLES || want_variable != NULL) - apply_env_variables(client, world, want_env_prefix); - - return true; -} - -static bool -apply_cflags(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *target_list, int maxdepth) -{ - pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER; - pkgconf_list_t filtered_list = PKGCONF_LIST_INITIALIZER; - int eflag; - - eflag = pkgconf_pkg_cflags(client, world, &unfiltered_list, maxdepth); - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - pkgconf_fragment_filter(client, &filtered_list, &unfiltered_list, filter_cflags, NULL); - maybe_add_module_definitions(client, world, &filtered_list); - - if (filtered_list.head == NULL) - goto out; - - pkgconf_fragment_copy_list(client, target_list, &filtered_list); - -out: - pkgconf_fragment_free(&unfiltered_list); - pkgconf_fragment_free(&filtered_list); - - return true; -} - -static bool -apply_libs(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *target_list, int maxdepth) -{ - pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER; - pkgconf_list_t filtered_list = PKGCONF_LIST_INITIALIZER; - int eflag; - - eflag = pkgconf_pkg_libs(client, world, &unfiltered_list, maxdepth); - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - pkgconf_fragment_filter(client, &filtered_list, &unfiltered_list, filter_libs, NULL); - - if (filtered_list.head == NULL) - goto out; - - pkgconf_fragment_copy_list(client, target_list, &filtered_list); - -out: - pkgconf_fragment_free(&unfiltered_list); - pkgconf_fragment_free(&filtered_list); - - return true; -} - -static bool -apply_requires(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) -{ - pkgconf_node_t *iter; - (void) unused; - (void) maxdepth; - - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) - { - pkgconf_dependency_t *dep = iter->data; - pkgconf_pkg_t *pkg = dep->match; - - print_dependency_list(client->output, &pkg->required); - } - - return true; -} - -static bool -apply_requires_private(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) -{ - pkgconf_node_t *iter; - (void) unused; - (void) maxdepth; - - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) - { - pkgconf_dependency_t *dep = iter->data; - pkgconf_pkg_t *pkg = dep->match; - - print_dependency_list(client->output, &pkg->requires_private); - } - return true; -} - -static void -check_uninstalled(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) -{ - int *retval = data; - (void) client; - - if (pkg->flags & PKGCONF_PKG_PROPF_UNINSTALLED) - *retval = EXIT_SUCCESS; -} - -static bool -apply_uninstalled(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) -{ - int eflag; - - eflag = pkgconf_pkg_traverse(client, world, check_uninstalled, data, maxdepth, 0); - - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - return true; -} - -#ifndef PKGCONF_LITE -static void -print_graph_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) -{ - pkgconf_node_t *n; - - (void) data; - - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "node '%s' {\n", pkg->id); - - if (pkg->version != NULL) - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, " version = '%s';\n", pkg->version); - - PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, n) - { - pkgconf_dependency_t *dep = n->data; - - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, " dependency '%s'", dep->package); - - if (dep->compare != PKGCONF_CMP_ANY) - { - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, - " {\n" - " comparator = '%s';\n" - " version = '%s';\n" - " };\n", - pkgconf_pkg_get_comparator(dep), dep->version); - } - else - pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, ";"); - } - - pkgconf_output_puts(client->output, PKGCONF_OUTPUT_STDOUT, "};"); -} - -static bool -apply_simulate(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) -{ - int eflag; - - eflag = pkgconf_pkg_traverse(client, world, print_graph_node, data, maxdepth, 0); - - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - return true; + return out; } #endif -static void -print_fragment_tree_branch(pkgconf_output_t *output, pkgconf_list_t *fragment_list, int indent) -{ - pkgconf_node_t *iter; - - PKGCONF_FOREACH_LIST_ENTRY(fragment_list->head, iter) - { - pkgconf_fragment_t *frag = iter->data; - - if (frag->type) - pkgconf_output_fmt(output, PKGCONF_OUTPUT_STDOUT, - "%*s'-%c%s' [type %c]\n", indent, "", frag->type, frag->data, frag->type); - else - pkgconf_output_fmt(output, PKGCONF_OUTPUT_STDOUT, - "%*s'%s' [untyped]\n", indent, "", frag->data); - - print_fragment_tree_branch(output, &frag->children, indent + 2); - } - - if (fragment_list->head != NULL) - pkgconf_output_puts(output, PKGCONF_OUTPUT_STDOUT, ""); -} - -static bool -apply_fragment_tree(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) -{ - pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER; - int eflag; - - (void) data; - - eflag = pkgconf_pkg_cflags(client, world, &unfiltered_list, maxdepth); - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - eflag = pkgconf_pkg_libs(client, world, &unfiltered_list, maxdepth); - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - print_fragment_tree_branch(client->output, &unfiltered_list, 0); - pkgconf_fragment_free(&unfiltered_list); - - return true; -} - -static void -print_license(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) -{ - (void) data; - - if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL) - return; - - /* NOASSERTION is the default when the license is unknown, per SPDX spec § 3.15 */ - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "%s: %s\n", - pkg->id, pkg->license != NULL ? pkg->license : "NOASSERTION"); -} - -static bool -apply_license(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) -{ - int eflag; - - eflag = pkgconf_pkg_traverse(client, world, print_license, data, maxdepth, 0); - - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - return true; -} - -static void -print_license_file(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) -{ - (void) data; - - if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL) - return; - - /* If license file location is not available then just print empty */ - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "%s: %s\n", - pkg->id, pkg->license_file != NULL ? pkg->license_file : ""); -} - -static bool -apply_license_file(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) -{ - int eflag; - - eflag = pkgconf_pkg_traverse(client, world, print_license_file, data, maxdepth, 0); - - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - return true; -} - -static void -print_source(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) -{ - (void) data; - - if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL) - return; - - /* If source is empty then empty string is printed otherwise URL */ - pkgconf_output_fmt(client->output, PKGCONF_OUTPUT_STDOUT, "%s: %s\n", - pkg->id, pkg->source != NULL ? pkg->source : ""); -} - -static bool -apply_source(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) -{ - int eflag; - - eflag = pkgconf_pkg_traverse(client, world, print_source, data, maxdepth, 0); - - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - return true; -} - static void version(void) { @@ -998,218 +219,16 @@ usage(void) printf("\nreport bugs to <%s>.\n", PACKAGE_BUGREPORT); } -static void -relocate_path(const char *path) -{ - char buf[PKGCONF_BUFSIZE]; - - pkgconf_strlcpy(buf, path, sizeof buf); - pkgconf_path_relocate(buf, sizeof buf); - - printf("%s\n", buf); -} - -static void -path_list_to_buffer(const pkgconf_list_t *list, pkgconf_buffer_t *buffer, char delim) -{ - pkgconf_node_t *n; - - PKGCONF_FOREACH_LIST_ENTRY(list->head, n) - { - pkgconf_path_t *pn = n->data; - - if (n != list->head) - pkgconf_buffer_push_byte(buffer, delim); - - pkgconf_buffer_append(buffer, pn->path); - } -} - -#ifndef PKGCONF_LITE -static void -dump_personality(const pkgconf_cross_personality_t *p) -{ - pkgconf_buffer_t pc_path_buf = PKGCONF_BUFFER_INITIALIZER; - path_list_to_buffer(&p->dir_list, &pc_path_buf, ':'); - - pkgconf_buffer_t pc_system_libdirs_buf = PKGCONF_BUFFER_INITIALIZER; - path_list_to_buffer(&p->filter_libdirs, &pc_system_libdirs_buf, ':'); - - pkgconf_buffer_t pc_system_includedirs_buf = PKGCONF_BUFFER_INITIALIZER; - path_list_to_buffer(&p->filter_includedirs, &pc_system_includedirs_buf, ':'); - - printf("Triplet: %s\n", p->name); - - if (p->sysroot_dir) - printf("SysrootDir: %s\n", p->sysroot_dir); - - printf("DefaultSearchPaths: %s\n", pc_path_buf.base); - printf("SystemIncludePaths: %s\n", pc_system_includedirs_buf.base); - printf("SystemLibraryPaths: %s\n", pc_system_libdirs_buf.base); - - pkgconf_buffer_finalize(&pc_path_buf); - pkgconf_buffer_finalize(&pc_system_libdirs_buf); - pkgconf_buffer_finalize(&pc_system_includedirs_buf); -} - -static pkgconf_cross_personality_t * -deduce_personality(char *argv[]) -{ - const char *argv0 = argv[0]; - char *i, *prefix; - pkgconf_cross_personality_t *out; - - i = strrchr(argv0, '/'); - if (i != NULL) - argv0 = i + 1; - -#if defined(_WIN32) || defined(_WIN64) - i = strrchr(argv0, '\\'); - if (i != NULL) - argv0 = i + 1; -#endif - - i = strstr(argv0, "-pkg"); - if (i == NULL) - return pkgconf_cross_personality_default(); - - prefix = pkgconf_strndup(argv0, i - argv0); - out = pkgconf_cross_personality_find(prefix); - free(prefix); - if (out == NULL) - return pkgconf_cross_personality_default(); - - return out; -} -#endif - -static void -unveil_handler(const pkgconf_client_t *client, const char *path, const char *permissions) -{ - (void) client; - - if (pkgconf_unveil(path, permissions) == -1) - { - fprintf(stderr, "pkgconf: unveil failed: %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } -} - -static bool -unveil_search_paths(const pkgconf_client_t *client, const pkgconf_cross_personality_t *personality) -{ - pkgconf_node_t *n; - - if (pkgconf_unveil("/dev/null", "rwc") == -1) - return false; - - PKGCONF_FOREACH_LIST_ENTRY(client->dir_list.head, n) - { - pkgconf_path_t *pn = n->data; - - if (pkgconf_unveil(pn->path, "r") == -1 && errno != ENOENT) - return false; - } - - PKGCONF_FOREACH_LIST_ENTRY(personality->dir_list.head, n) - { - pkgconf_path_t *pn = n->data; - - if (pkgconf_unveil(pn->path, "r") == -1 && errno != ENOENT) - return false; - } - - pkgconf_client_set_unveil_handler(&pkg_client, unveil_handler); - - return true; -} - -/* SAFETY: pkgconf_client_t takes ownership of these package objects */ -static void -register_builtins(pkgconf_client_t *client, pkgconf_cross_personality_t *personality) -{ - pkgconf_buffer_t pc_path_buf = PKGCONF_BUFFER_INITIALIZER; - path_list_to_buffer(&personality->dir_list, &pc_path_buf, ':'); - - pkgconf_buffer_t pc_system_libdirs_buf = PKGCONF_BUFFER_INITIALIZER; - path_list_to_buffer(&personality->filter_libdirs, &pc_system_libdirs_buf, ':'); - - pkgconf_buffer_t pc_system_includedirs_buf = PKGCONF_BUFFER_INITIALIZER; - path_list_to_buffer(&personality->filter_includedirs, &pc_system_includedirs_buf, ':'); - - pkgconf_pkg_t *pkg_config_virtual = calloc(1, sizeof(pkgconf_pkg_t)); - if (pkg_config_virtual == NULL) - { - goto error; - } - - pkg_config_virtual->owner = client; - pkg_config_virtual->id = strdup("pkg-config"); - pkg_config_virtual->realname = strdup("pkg-config"); - pkg_config_virtual->description = strdup("virtual package defining pkgconf API version supported"); - pkg_config_virtual->url = strdup(PACKAGE_BUGREPORT); - pkg_config_virtual->version = strdup(PACKAGE_VERSION); - - pkgconf_tuple_add(client, &pkg_config_virtual->vars, "pc_system_libdirs", pc_system_libdirs_buf.base, false, 0); - pkgconf_tuple_add(client, &pkg_config_virtual->vars, "pc_system_includedirs", pc_system_includedirs_buf.base, false, 0); - pkgconf_tuple_add(client, &pkg_config_virtual->vars, "pc_path", pc_path_buf.base, false, 0); - - if (!pkgconf_client_preload_one(client, pkg_config_virtual)) - { - goto error; - } - - pkgconf_pkg_t *pkgconf_virtual = calloc(1, sizeof(pkgconf_pkg_t)); - if (pkgconf_virtual == NULL) - { - goto error; - } - - pkgconf_virtual->owner = client; - pkgconf_virtual->id = strdup("pkgconf"); - pkgconf_virtual->realname = strdup("pkgconf"); - pkgconf_virtual->description = strdup("virtual package defining pkgconf API version supported"); - pkgconf_virtual->url = strdup(PACKAGE_BUGREPORT); - pkgconf_virtual->version = strdup(PACKAGE_VERSION); - - pkgconf_tuple_add(client, &pkgconf_virtual->vars, "pc_system_libdirs", pc_system_libdirs_buf.base, false, 0); - pkgconf_tuple_add(client, &pkgconf_virtual->vars, "pc_system_includedirs", pc_system_includedirs_buf.base, false, 0); - pkgconf_tuple_add(client, &pkgconf_virtual->vars, "pc_path", pc_path_buf.base, false, 0); - - if (!pkgconf_client_preload_one(client, pkgconf_virtual)) - { - goto error; - } - -error: - pkgconf_buffer_finalize(&pc_path_buf); - pkgconf_buffer_finalize(&pc_system_libdirs_buf); - pkgconf_buffer_finalize(&pc_system_includedirs_buf); -} - int main(int argc, char *argv[]) { int ret; - pkgconf_list_t pkgq = PKGCONF_LIST_INITIALIZER; - pkgconf_list_t dir_list = PKGCONF_LIST_INITIALIZER; - char *builddir; - char *sysroot_dir; - char *env_traverse_depth; - char *required_pkgconfig_version = NULL; - char *required_exact_module_version = NULL; - char *required_max_module_version = NULL; - char *required_module_version = NULL; - char *logfile_arg = NULL; - char *want_env_prefix = NULL; - unsigned int want_client_flags = PKGCONF_PKG_PKGF_NONE; - pkgconf_cross_personality_t *personality = NULL; - bool opened_error_msgout = false; - pkgconf_pkg_t world = { - .id = "virtual:world", - .realname = "virtual world package", - .flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL, + pkgconf_cli_state_t state = { + .want_flags = 0, }; + pkgconf_list_t dir_list = PKGCONF_LIST_INITIALIZER; + char *env_traverse_depth; + char *logfile_arg = NULL; if (pkgconf_pledge("stdio rpath wpath cpath unveil", NULL) == -1) { @@ -1217,8 +236,6 @@ main(int argc, char *argv[]) return EXIT_FAILURE; } - want_flags = 0; - #ifdef _WIN32 /* When running regression tests in cygwin, and building native * executable, tests fail unless native executable outputs unix @@ -1230,88 +247,88 @@ main(int argc, char *argv[]) #endif struct pkg_option options[] = { - { "version", no_argument, &want_flags, PKG_VERSION|PKG_PRINT_ERRORS, }, - { "about", no_argument, &want_flags, PKG_ABOUT|PKG_PRINT_ERRORS, }, + { "version", no_argument, &state.want_flags, PKG_VERSION|PKG_PRINT_ERRORS, }, + { "about", no_argument, &state.want_flags, PKG_ABOUT|PKG_PRINT_ERRORS, }, { "atleast-version", required_argument, NULL, 2, }, { "atleast-pkgconfig-version", required_argument, NULL, 3, }, - { "libs", no_argument, &want_flags, PKG_LIBS|PKG_PRINT_ERRORS, }, - { "cflags", no_argument, &want_flags, PKG_CFLAGS|PKG_PRINT_ERRORS, }, - { "modversion", no_argument, &want_flags, PKG_MODVERSION|PKG_PRINT_ERRORS, }, + { "libs", no_argument, &state.want_flags, PKG_LIBS|PKG_PRINT_ERRORS, }, + { "cflags", no_argument, &state.want_flags, PKG_CFLAGS|PKG_PRINT_ERRORS, }, + { "modversion", no_argument, &state.want_flags, PKG_MODVERSION|PKG_PRINT_ERRORS, }, { "variable", required_argument, NULL, 7, }, - { "exists", no_argument, &want_flags, PKG_EXISTS, }, - { "print-errors", no_argument, &want_flags, PKG_PRINT_ERRORS, }, - { "short-errors", no_argument, &want_flags, PKG_SHORT_ERRORS, }, + { "exists", no_argument, &state.want_flags, PKG_EXISTS, }, + { "print-errors", no_argument, &state.want_flags, PKG_PRINT_ERRORS, }, + { "short-errors", no_argument, &state.want_flags, PKG_SHORT_ERRORS, }, { "maximum-traverse-depth", required_argument, NULL, 11, }, - { "static", no_argument, &want_flags, PKG_STATIC, }, - { "shared", no_argument, &want_flags, PKG_SHARED, }, - { "pure", no_argument, &want_flags, PKG_PURE, }, - { "print-requires", no_argument, &want_flags, PKG_REQUIRES, }, - { "print-variables", no_argument, &want_flags, PKG_VARIABLES|PKG_PRINT_ERRORS, }, + { "static", no_argument, &state.want_flags, PKG_STATIC, }, + { "shared", no_argument, &state.want_flags, PKG_SHARED, }, + { "pure", no_argument, &state.want_flags, PKG_PURE, }, + { "print-requires", no_argument, &state.want_flags, PKG_REQUIRES, }, + { "print-variables", no_argument, &state.want_flags, PKG_VARIABLES|PKG_PRINT_ERRORS, }, #ifndef PKGCONF_LITE - { "digraph", no_argument, &want_flags, PKG_DIGRAPH, }, - { "solution", no_argument, &want_flags, PKG_SOLUTION, }, + { "digraph", no_argument, &state.want_flags, PKG_DIGRAPH, }, + { "solution", no_argument, &state.want_flags, PKG_SOLUTION, }, #endif - { "help", no_argument, &want_flags, PKG_HELP, }, - { "env-only", no_argument, &want_flags, PKG_ENV_ONLY, }, - { "print-requires-private", no_argument, &want_flags, PKG_REQUIRES_PRIVATE, }, - { "cflags-only-I", no_argument, &want_flags, PKG_CFLAGS_ONLY_I|PKG_PRINT_ERRORS, }, - { "cflags-only-other", no_argument, &want_flags, PKG_CFLAGS_ONLY_OTHER|PKG_PRINT_ERRORS, }, - { "libs-only-L", no_argument, &want_flags, PKG_LIBS_ONLY_LDPATH|PKG_PRINT_ERRORS, }, - { "libs-only-l", no_argument, &want_flags, PKG_LIBS_ONLY_LIBNAME|PKG_PRINT_ERRORS, }, - { "libs-only-other", no_argument, &want_flags, PKG_LIBS_ONLY_OTHER|PKG_PRINT_ERRORS, }, - { "uninstalled", no_argument, &want_flags, PKG_UNINSTALLED, }, - { "no-uninstalled", no_argument, &want_flags, PKG_NO_UNINSTALLED, }, - { "keep-system-cflags", no_argument, &want_flags, PKG_KEEP_SYSTEM_CFLAGS, }, - { "keep-system-libs", no_argument, &want_flags, PKG_KEEP_SYSTEM_LIBS, }, + { "help", no_argument, &state.want_flags, PKG_HELP, }, + { "env-only", no_argument, &state.want_flags, PKG_ENV_ONLY, }, + { "print-requires-private", no_argument, &state.want_flags, PKG_REQUIRES_PRIVATE, }, + { "cflags-only-I", no_argument, &state.want_flags, PKG_CFLAGS_ONLY_I|PKG_PRINT_ERRORS, }, + { "cflags-only-other", no_argument, &state.want_flags, PKG_CFLAGS_ONLY_OTHER|PKG_PRINT_ERRORS, }, + { "libs-only-L", no_argument, &state.want_flags, PKG_LIBS_ONLY_LDPATH|PKG_PRINT_ERRORS, }, + { "libs-only-l", no_argument, &state.want_flags, PKG_LIBS_ONLY_LIBNAME|PKG_PRINT_ERRORS, }, + { "libs-only-other", no_argument, &state.want_flags, PKG_LIBS_ONLY_OTHER|PKG_PRINT_ERRORS, }, + { "uninstalled", no_argument, &state.want_flags, PKG_UNINSTALLED, }, + { "no-uninstalled", no_argument, &state.want_flags, PKG_NO_UNINSTALLED, }, + { "keep-system-cflags", no_argument, &state.want_flags, PKG_KEEP_SYSTEM_CFLAGS, }, + { "keep-system-libs", no_argument, &state.want_flags, PKG_KEEP_SYSTEM_LIBS, }, { "define-variable", required_argument, NULL, 27, }, { "exact-version", required_argument, NULL, 28, }, { "max-version", required_argument, NULL, 29, }, - { "ignore-conflicts", no_argument, &want_flags, PKG_IGNORE_CONFLICTS, }, - { "errors-to-stdout", no_argument, &want_flags, PKG_ERRORS_ON_STDOUT, }, - { "silence-errors", no_argument, &want_flags, PKG_SILENCE_ERRORS, }, - { "list-all", no_argument, &want_flags, PKG_LIST|PKG_PRINT_ERRORS, }, - { "list-package-names", no_argument, &want_flags, PKG_LIST_PACKAGE_NAMES|PKG_PRINT_ERRORS, }, + { "ignore-conflicts", no_argument, &state.want_flags, PKG_IGNORE_CONFLICTS, }, + { "errors-to-stdout", no_argument, &state.want_flags, PKG_ERRORS_ON_STDOUT, }, + { "silence-errors", no_argument, &state.want_flags, PKG_SILENCE_ERRORS, }, + { "list-all", no_argument, &state.want_flags, PKG_LIST|PKG_PRINT_ERRORS, }, + { "list-package-names", no_argument, &state.want_flags, PKG_LIST_PACKAGE_NAMES|PKG_PRINT_ERRORS, }, #ifndef PKGCONF_LITE - { "simulate", no_argument, &want_flags, PKG_SIMULATE, }, + { "simulate", no_argument, &state.want_flags, PKG_SIMULATE, }, #endif - { "no-cache", no_argument, &want_flags, PKG_NO_CACHE, }, - { "print-provides", no_argument, &want_flags, PKG_PROVIDES, }, - { "no-provides", no_argument, &want_flags, PKG_NO_PROVIDES, }, - { "debug", no_argument, &want_flags, PKG_DEBUG|PKG_PRINT_ERRORS, }, - { "validate", no_argument, &want_flags, PKG_VALIDATE|PKG_PRINT_ERRORS|PKG_ERRORS_ON_STDOUT }, + { "no-cache", no_argument, &state.want_flags, PKG_NO_CACHE, }, + { "print-provides", no_argument, &state.want_flags, PKG_PROVIDES, }, + { "no-provides", no_argument, &state.want_flags, PKG_NO_PROVIDES, }, + { "debug", no_argument, &state.want_flags, PKG_DEBUG|PKG_PRINT_ERRORS, }, + { "validate", no_argument, &state.want_flags, PKG_VALIDATE|PKG_PRINT_ERRORS|PKG_ERRORS_ON_STDOUT }, { "log-file", required_argument, NULL, 40 }, - { "path", no_argument, &want_flags, PKG_PATH }, + { "path", no_argument, &state.want_flags, PKG_PATH }, { "with-path", required_argument, NULL, 42 }, { "prefix-variable", required_argument, NULL, 43 }, - { "define-prefix", no_argument, &want_flags, PKG_DEFINE_PREFIX }, + { "define-prefix", no_argument, &state.want_flags, PKG_DEFINE_PREFIX }, { "relocate", required_argument, NULL, 45 }, - { "dont-define-prefix", no_argument, &want_flags, PKG_DONT_DEFINE_PREFIX }, - { "dont-relocate-paths", no_argument, &want_flags, PKG_DONT_RELOCATE_PATHS }, + { "dont-define-prefix", no_argument, &state.want_flags, PKG_DONT_DEFINE_PREFIX }, + { "dont-relocate-paths", no_argument, &state.want_flags, PKG_DONT_RELOCATE_PATHS }, { "env", required_argument, NULL, 48 }, #ifndef PKGCONF_LITE - { "msvc-syntax", no_argument, &want_flags, PKG_MSVC_SYNTAX }, + { "msvc-syntax", no_argument, &state.want_flags, PKG_MSVC_SYNTAX }, #endif { "fragment-filter", required_argument, NULL, 50 }, - { "internal-cflags", no_argument, &want_flags, PKG_INTERNAL_CFLAGS }, + { "internal-cflags", no_argument, &state.want_flags, PKG_INTERNAL_CFLAGS }, #ifndef PKGCONF_LITE - { "dump-personality", no_argument, &want_flags, PKG_DUMP_PERSONALITY }, + { "dump-personality", no_argument, &state.want_flags, PKG_DUMP_PERSONALITY }, { "personality", required_argument, NULL, 53 }, #endif - { "license", no_argument, &want_flags, PKG_DUMP_LICENSE }, - { "license-file", no_argument, &want_flags, PKG_DUMP_LICENSE_FILE }, + { "license", no_argument, &state.want_flags, PKG_DUMP_LICENSE }, + { "license-file", no_argument, &state.want_flags, PKG_DUMP_LICENSE_FILE }, { "verbose", no_argument, NULL, 55 }, - { "exists-cflags", no_argument, &want_flags, PKG_EXISTS_CFLAGS }, - { "fragment-tree", no_argument, &want_flags, PKG_FRAGMENT_TREE }, - { "source", no_argument, &want_flags, PKG_DUMP_SOURCE }, - { "newlines", no_argument, &want_flags, PKG_NEWLINES }, + { "exists-cflags", no_argument, &state.want_flags, PKG_EXISTS_CFLAGS }, + { "fragment-tree", no_argument, &state.want_flags, PKG_FRAGMENT_TREE }, + { "source", no_argument, &state.want_flags, PKG_DUMP_SOURCE }, + { "newlines", no_argument, &state.want_flags, PKG_NEWLINES }, { NULL, 0, NULL, 0 } }; #ifndef PKGCONF_LITE if (getenv("PKG_CONFIG_EARLY_TRACE")) { - error_msgout = stderr; - pkgconf_client_set_trace_handler(&pkg_client, error_handler, NULL); + state.error_msgout = stderr; + pkgconf_client_set_trace_handler(&state.pkg_client, error_handler, NULL); } #endif @@ -1320,25 +337,25 @@ main(int argc, char *argv[]) switch (ret) { case 2: - required_module_version = pkg_optarg; + state.required_module_version = pkg_optarg; break; case 3: - required_pkgconfig_version = pkg_optarg; + state.required_pkgconfig_version = pkg_optarg; break; case 7: - want_variable = pkg_optarg; + state.want_variable = pkg_optarg; break; case 11: - maximum_traverse_depth = atoi(pkg_optarg); + state.maximum_traverse_depth = atoi(pkg_optarg); break; case 27: - pkgconf_tuple_define_global(&pkg_client, pkg_optarg); + pkgconf_tuple_define_global(&state.pkg_client, pkg_optarg); break; case 28: - required_exact_module_version = pkg_optarg; + state.required_exact_module_version = pkg_optarg; break; case 29: - required_max_module_version = pkg_optarg; + state.required_max_module_version = pkg_optarg; break; case 40: logfile_arg = pkg_optarg; @@ -1347,24 +364,24 @@ main(int argc, char *argv[]) pkgconf_path_prepend(pkg_optarg, &dir_list, true); break; case 43: - pkgconf_client_set_prefix_varname(&pkg_client, pkg_optarg); + pkgconf_client_set_prefix_varname(&state.pkg_client, pkg_optarg); break; case 45: relocate_path(pkg_optarg); return EXIT_SUCCESS; case 48: - want_env_prefix = pkg_optarg; + state.want_env_prefix = pkg_optarg; break; case 50: - want_fragment_filter = pkg_optarg; + state.want_fragment_filter = pkg_optarg; break; #ifndef PKGCONF_LITE case 53: - personality = pkgconf_cross_personality_find(pkg_optarg); + state.personality = pkgconf_cross_personality_find(pkg_optarg); break; #endif case 55: - verbosity++; + state.verbosity++; break; case '?': case ':': @@ -1375,18 +392,18 @@ main(int argc, char *argv[]) } } - if (personality == NULL) { + if (state.personality == NULL) { #ifndef PKGCONF_LITE - personality = deduce_personality(argv); + state.personality = deduce_personality(argv); #else - personality = pkgconf_cross_personality_default(); + state.personality = pkgconf_cross_personality_default(); #endif } #ifndef PKGCONF_LITE - if ((want_flags & PKG_DUMP_PERSONALITY) == PKG_DUMP_PERSONALITY) + if ((state.want_flags & PKG_DUMP_PERSONALITY) == PKG_DUMP_PERSONALITY) { - dump_personality(personality); + dump_personality(state.personality); ret = EXIT_SUCCESS; goto out; @@ -1394,39 +411,39 @@ main(int argc, char *argv[]) #endif /* now, bring up the client. settings are preserved since the client is prealloced */ - pkgconf_client_init(&pkg_client, error_handler, NULL, personality); + pkgconf_client_init(&state.pkg_client, error_handler, &state, state.personality, &state); #ifndef PKGCONF_LITE - if ((want_flags & PKG_MSVC_SYNTAX) == PKG_MSVC_SYNTAX || getenv("PKG_CONFIG_MSVC_SYNTAX") != NULL) - want_render_ops = msvc_renderer_get(); + if (getenv("PKG_CONFIG_MSVC_SYNTAX") != NULL) + state.want_flags |= PKG_MSVC_SYNTAX; #endif if ((env_traverse_depth = getenv("PKG_CONFIG_MAXIMUM_TRAVERSE_DEPTH")) != NULL) - maximum_traverse_depth = atoi(env_traverse_depth); + state.maximum_traverse_depth = atoi(env_traverse_depth); - if ((want_flags & PKG_PRINT_ERRORS) != PKG_PRINT_ERRORS) - want_flags |= (PKG_SILENCE_ERRORS); + if ((state.want_flags & PKG_PRINT_ERRORS) != PKG_PRINT_ERRORS) + state.want_flags |= (PKG_SILENCE_ERRORS); - if ((want_flags & PKG_SILENCE_ERRORS) == PKG_SILENCE_ERRORS && !getenv("PKG_CONFIG_DEBUG_SPEW")) - want_flags |= (PKG_SILENCE_ERRORS); + if ((state.want_flags & PKG_SILENCE_ERRORS) == PKG_SILENCE_ERRORS && !getenv("PKG_CONFIG_DEBUG_SPEW")) + state.want_flags |= (PKG_SILENCE_ERRORS); else - want_flags &= ~(PKG_SILENCE_ERRORS); + state.want_flags &= ~(PKG_SILENCE_ERRORS); if (getenv("PKG_CONFIG_DONT_RELOCATE_PATHS")) - want_flags |= (PKG_DONT_RELOCATE_PATHS); + state.want_flags |= (PKG_DONT_RELOCATE_PATHS); - if ((want_flags & PKG_VALIDATE) == PKG_VALIDATE || (want_flags & PKG_DEBUG) == PKG_DEBUG) - pkgconf_client_set_warn_handler(&pkg_client, error_handler, NULL); + if ((state.want_flags & PKG_VALIDATE) == PKG_VALIDATE || (state.want_flags & PKG_DEBUG) == PKG_DEBUG) + pkgconf_client_set_warn_handler(&state.pkg_client, error_handler, NULL); #ifndef PKGCONF_LITE - if ((want_flags & PKG_DEBUG) == PKG_DEBUG) - pkgconf_client_set_trace_handler(&pkg_client, error_handler, NULL); + if ((state.want_flags & PKG_DEBUG) == PKG_DEBUG) + pkgconf_client_set_trace_handler(&state.pkg_client, error_handler, NULL); #endif - pkgconf_path_prepend_list(&pkg_client.dir_list, &dir_list); + pkgconf_path_prepend_list(&state.pkg_client.dir_list, &dir_list); pkgconf_path_free(&dir_list); - if ((want_flags & PKG_ABOUT) == PKG_ABOUT) + if ((state.want_flags & PKG_ABOUT) == PKG_ABOUT) { about(); @@ -1434,7 +451,7 @@ main(int argc, char *argv[]) goto out; } - if ((want_flags & PKG_VERSION) == PKG_VERSION) + if ((state.want_flags & PKG_VERSION) == PKG_VERSION) { version(); @@ -1442,7 +459,7 @@ main(int argc, char *argv[]) goto out; } - if ((want_flags & PKG_HELP) == PKG_HELP) + if ((state.want_flags & PKG_HELP) == PKG_HELP) { usage(); @@ -1450,162 +467,6 @@ main(int argc, char *argv[]) goto out; } - if (getenv("PKG_CONFIG_FDO_SYSROOT_RULES")) - want_client_flags |= PKGCONF_PKG_PKGF_FDO_SYSROOT_RULES; - - if (getenv("PKG_CONFIG_PKGCONF1_SYSROOT_RULES")) - want_client_flags |= PKGCONF_PKG_PKGF_PKGCONF1_SYSROOT_RULES; - - if ((want_flags & PKG_SHORT_ERRORS) == PKG_SHORT_ERRORS) - want_client_flags |= PKGCONF_PKG_PKGF_SIMPLIFY_ERRORS; - - if ((want_flags & PKG_DONT_RELOCATE_PATHS) == PKG_DONT_RELOCATE_PATHS) - want_client_flags |= PKGCONF_PKG_PKGF_DONT_RELOCATE_PATHS; - - error_msgout = stderr; - if ((want_flags & PKG_ERRORS_ON_STDOUT) == PKG_ERRORS_ON_STDOUT) - error_msgout = stdout; - if ((want_flags & PKG_SILENCE_ERRORS) == PKG_SILENCE_ERRORS) { - error_msgout = fopen(PATH_DEV_NULL, "w"); - opened_error_msgout = true; - } - - if ((want_flags & PKG_IGNORE_CONFLICTS) == PKG_IGNORE_CONFLICTS || getenv("PKG_CONFIG_IGNORE_CONFLICTS") != NULL) - want_client_flags |= PKGCONF_PKG_PKGF_SKIP_CONFLICTS; - - if ((want_flags & PKG_STATIC) == PKG_STATIC || personality->want_default_static) - want_client_flags |= (PKGCONF_PKG_PKGF_SEARCH_PRIVATE | PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS); - - if ((want_flags & PKG_SHARED) == PKG_SHARED) - want_client_flags &= ~(PKGCONF_PKG_PKGF_SEARCH_PRIVATE | PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS); - - /* if --static and --pure are both specified, then disable merge-back. - * this allows for a --static which searches private modules, but has the same fragment behaviour as if - * --static were disabled. see for rationale. - */ - if ((want_flags & PKG_PURE) == PKG_PURE || getenv("PKG_CONFIG_PURE_DEPGRAPH") != NULL || personality->want_default_pure) - want_client_flags &= ~PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS; - - if ((want_flags & PKG_ENV_ONLY) == PKG_ENV_ONLY) - want_client_flags |= PKGCONF_PKG_PKGF_ENV_ONLY; - - if ((want_flags & PKG_NO_CACHE) == PKG_NO_CACHE) - want_client_flags |= PKGCONF_PKG_PKGF_NO_CACHE; - -/* On Windows we want to always redefine the prefix by default - * but allow that behavior to be manually disabled */ -#if !defined(_WIN32) && !defined(_WIN64) - if ((want_flags & PKG_DEFINE_PREFIX) == PKG_DEFINE_PREFIX || getenv("PKG_CONFIG_RELOCATE_PATHS") != NULL) -#endif - want_client_flags |= PKGCONF_PKG_PKGF_REDEFINE_PREFIX; - - if ((want_flags & PKG_NO_UNINSTALLED) == PKG_NO_UNINSTALLED || getenv("PKG_CONFIG_DISABLE_UNINSTALLED") != NULL) - want_client_flags |= PKGCONF_PKG_PKGF_NO_UNINSTALLED; - - if ((want_flags & PKG_NO_PROVIDES) == PKG_NO_PROVIDES) - want_client_flags |= PKGCONF_PKG_PKGF_SKIP_PROVIDES; - - if ((want_flags & PKG_DONT_DEFINE_PREFIX) == PKG_DONT_DEFINE_PREFIX || getenv("PKG_CONFIG_DONT_DEFINE_PREFIX") != NULL) - want_client_flags &= ~PKGCONF_PKG_PKGF_REDEFINE_PREFIX; - - if ((want_flags & PKG_INTERNAL_CFLAGS) == PKG_INTERNAL_CFLAGS) - want_client_flags |= PKGCONF_PKG_PKGF_DONT_FILTER_INTERNAL_CFLAGS; - - /* --static --libs, --exists require the full dependency graph to be solved */ - if ((want_flags & (PKG_STATIC|PKG_LIBS)) == (PKG_STATIC|PKG_LIBS) || (want_flags & PKG_EXISTS) == PKG_EXISTS) - want_client_flags |= PKGCONF_PKG_PKGF_REQUIRE_INTERNAL; - - /* if these selectors are used, it means that we are querying metadata. - * so signal to libpkgconf that we only want to walk the flattened dependency set. - */ - if ((want_flags & PKG_MODVERSION) == PKG_MODVERSION || - (want_flags & PKG_REQUIRES) == PKG_REQUIRES || - (want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE || - (want_flags & PKG_PROVIDES) == PKG_PROVIDES || - (want_flags & PKG_VARIABLES) == PKG_VARIABLES || - (want_flags & PKG_PATH) == PKG_PATH || - want_variable != NULL) - maximum_traverse_depth = 1; - - /* if we are asking for a variable, path or list of variables, this only makes sense - * for a single package. - */ - if ((want_flags & PKG_VARIABLES) == PKG_VARIABLES || - (want_flags & PKG_PATH) == PKG_PATH || - want_variable != NULL) - maximum_package_count = 1; - - if (getenv("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS") != NULL) - want_flags |= PKG_KEEP_SYSTEM_CFLAGS; - - if (getenv("PKG_CONFIG_ALLOW_SYSTEM_LIBS") != NULL) - want_flags |= PKG_KEEP_SYSTEM_LIBS; - - if ((builddir = getenv("PKG_CONFIG_TOP_BUILD_DIR")) != NULL) - pkgconf_client_set_buildroot_dir(&pkg_client, builddir); - - if ((want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE || - (want_flags & PKG_CFLAGS)) - { - want_client_flags |= PKGCONF_PKG_PKGF_SEARCH_PRIVATE; - } - - if ((sysroot_dir = getenv("PKG_CONFIG_SYSROOT_DIR")) != NULL) - { - const char *destdir; - - pkgconf_client_set_sysroot_dir(&pkg_client, sysroot_dir); - - if ((destdir = getenv("DESTDIR")) != NULL) - { - if (!strcmp(destdir, sysroot_dir)) - want_client_flags |= PKGCONF_PKG_PKGF_FDO_SYSROOT_RULES; - } - } - - /* we have determined what features we want most likely. in some cases, we override later. */ - pkgconf_client_set_flags(&pkg_client, want_client_flags); - - /* at this point, want_client_flags should be set, so build the dir list */ - pkgconf_client_dir_list_build(&pkg_client, personality); - - /* unveil the entire search path now that we have loaded the personality data and built the dir list. */ - if (!unveil_search_paths(&pkg_client, personality)) - { - fprintf(stderr, "pkgconf: unveil failed: %s\n", strerror(errno)); - return EXIT_FAILURE; - } - - /* register built-in packages */ - register_builtins(&pkg_client, personality); - - /* preload any files in PKG_CONFIG_PRELOADED_FILES */ - pkgconf_client_preload_from_environ(&pkg_client, "PKG_CONFIG_PRELOADED_FILES"); - - if (required_pkgconfig_version != NULL) - { - if (pkgconf_compare_version(PACKAGE_VERSION, required_pkgconfig_version) >= 0) - ret = EXIT_SUCCESS; - else - ret = EXIT_FAILURE; - - goto out; - } - - if ((want_flags & PKG_LIST) == PKG_LIST) - { - pkgconf_scan_all(&pkg_client, &pkg_client, print_list_entry); - ret = EXIT_SUCCESS; - goto out; - } - - if ((want_flags & PKG_LIST_PACKAGE_NAMES) == PKG_LIST_PACKAGE_NAMES) - { - pkgconf_scan_all(&pkg_client, &pkg_client, print_package_entry); - ret = EXIT_SUCCESS; - goto out; - } - if (logfile_arg == NULL) logfile_arg = getenv("PKG_CONFIG_LOG"); @@ -1617,349 +478,19 @@ main(int argc, char *argv[]) return EXIT_FAILURE; } - logfile_out = fopen(logfile_arg, "a"); - pkgconf_audit_set_log(&pkg_client, logfile_out); + state.logfile_out = fopen(logfile_arg, "a"); + pkgconf_audit_set_log(&state.pkg_client, state.logfile_out); } - if (required_module_version != NULL) - { - pkgconf_pkg_t *pkg = NULL; - pkgconf_node_t *node; - pkgconf_list_t deplist = PKGCONF_LIST_INITIALIZER; + if (getenv("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS") != NULL) + state.want_flags |= PKG_KEEP_SYSTEM_CFLAGS; - while (argv[pkg_optind]) - { - pkgconf_dependency_parse_str(&pkg_client, &deplist, argv[pkg_optind], 0); - pkg_optind++; - } + if (getenv("PKG_CONFIG_ALLOW_SYSTEM_LIBS") != NULL) + state.want_flags |= PKG_KEEP_SYSTEM_LIBS; - PKGCONF_FOREACH_LIST_ENTRY(deplist.head, node) - { - pkgconf_dependency_t *pkgiter = node->data; - - pkg = pkgconf_pkg_find(&pkg_client, pkgiter->package); - if (pkg == NULL) - { - if (want_flags & PKG_PRINT_ERRORS) - pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package); - - ret = EXIT_FAILURE; - goto cleanup; - } - - if (pkgconf_compare_version(pkg->version, required_module_version) >= 0) - { - ret = EXIT_SUCCESS; - goto cleanup; - } - } - - ret = EXIT_FAILURE; -cleanup: - if (pkg != NULL) - pkgconf_pkg_unref(&pkg_client, pkg); - pkgconf_dependency_free(&deplist); - goto out; - } - else if (required_exact_module_version != NULL) - { - pkgconf_pkg_t *pkg = NULL; - pkgconf_node_t *node; - pkgconf_list_t deplist = PKGCONF_LIST_INITIALIZER; - - while (argv[pkg_optind]) - { - pkgconf_dependency_parse_str(&pkg_client, &deplist, argv[pkg_optind], 0); - pkg_optind++; - } - - PKGCONF_FOREACH_LIST_ENTRY(deplist.head, node) - { - pkgconf_dependency_t *pkgiter = node->data; - - pkg = pkgconf_pkg_find(&pkg_client, pkgiter->package); - if (pkg == NULL) - { - if (want_flags & PKG_PRINT_ERRORS) - pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package); - - ret = EXIT_FAILURE; - goto cleanup2; - } - - if (pkgconf_compare_version(pkg->version, required_exact_module_version) == 0) - { - ret = EXIT_SUCCESS; - goto cleanup2; - } - } - - ret = EXIT_FAILURE; -cleanup2: - if (pkg != NULL) - pkgconf_pkg_unref(&pkg_client, pkg); - pkgconf_dependency_free(&deplist); - goto out; - } - else if (required_max_module_version != NULL) - { - pkgconf_pkg_t *pkg = NULL; - pkgconf_node_t *node; - pkgconf_list_t deplist = PKGCONF_LIST_INITIALIZER; - - while (argv[pkg_optind]) - { - pkgconf_dependency_parse_str(&pkg_client, &deplist, argv[pkg_optind], 0); - pkg_optind++; - } - - PKGCONF_FOREACH_LIST_ENTRY(deplist.head, node) - { - pkgconf_dependency_t *pkgiter = node->data; - - pkg = pkgconf_pkg_find(&pkg_client, pkgiter->package); - if (pkg == NULL) - { - if (want_flags & PKG_PRINT_ERRORS) - pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package); - - ret = EXIT_FAILURE; - goto cleanup3; - } - - if (pkgconf_compare_version(pkg->version, required_max_module_version) <= 0) - { - ret = EXIT_SUCCESS; - goto cleanup3; - } - } - - ret = EXIT_FAILURE; -cleanup3: - if (pkg != NULL) - pkgconf_pkg_unref(&pkg_client, pkg); - pkgconf_dependency_free(&deplist); - goto out; - } - - while (1) - { - char *package = argv[pkg_optind]; - char *end; - - if (package == NULL) - break; - - /* check if there is a limit to the number of packages allowed to be included, if so and we have hit - * the limit, stop adding packages to the queue. - */ - if (maximum_package_count > 0 && pkgq.length >= maximum_package_count) - break; - - while (isspace((unsigned char)package[0])) - package++; - - /* skip empty packages */ - if (package[0] == '\0') { - pkg_optind++; - continue; - } - - end = package + strlen(package) - 1; - while(end > package && isspace((unsigned char)end[0])) end--; - end[1] = '\0'; - - if (argv[pkg_optind + 1] == NULL || !PKGCONF_IS_OPERATOR_CHAR(*(argv[pkg_optind + 1]))) - { - pkgconf_queue_push(&pkgq, package); - pkg_optind++; - } - else if (argv[pkg_optind + 2] == NULL) - { - char packagebuf[PKGCONF_BUFSIZE]; - - snprintf(packagebuf, sizeof packagebuf, "%s %s", package, argv[pkg_optind + 1]); - pkg_optind += 2; - - pkgconf_queue_push(&pkgq, packagebuf); - } - else - { - char packagebuf[PKGCONF_BUFSIZE]; - - snprintf(packagebuf, sizeof packagebuf, "%s %s %s", package, argv[pkg_optind + 1], argv[pkg_optind + 2]); - pkg_optind += 3; - - pkgconf_queue_push(&pkgq, packagebuf); - } - } - - if (pkgq.head == NULL) - { - fprintf(stderr, "Please specify at least one package name on the command line.\n"); - ret = EXIT_FAILURE; - goto out; - } - - ret = EXIT_SUCCESS; - - if (!pkgconf_queue_solve(&pkg_client, &pkgq, &world, maximum_traverse_depth)) - { - ret = EXIT_FAILURE; - goto out; - } - - /* we shouldn't need to unveil any more filesystem accesses from this point, so lock it down */ - if (pkgconf_unveil(NULL, NULL) == -1) - { - fprintf(stderr, "pkgconf: unveil lockdown failed: %s\n", strerror(errno)); - return EXIT_FAILURE; - } - -#ifndef PKGCONF_LITE - if ((want_flags & PKG_SIMULATE) == PKG_SIMULATE) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - - pkgconf_client_set_flags(&pkg_client, want_client_flags | PKGCONF_PKG_PKGF_SKIP_ERRORS); - apply_simulate(&pkg_client, &world, NULL, -1); - } -#endif - - if ((want_flags & PKG_VALIDATE) == PKG_VALIDATE) - goto out; - - if ((want_flags & PKG_DUMP_LICENSE) == PKG_DUMP_LICENSE) - { - apply_license(&pkg_client, &world, &ret, 2); - goto out; - } - - if ((want_flags & PKG_DUMP_LICENSE_FILE) == PKG_DUMP_LICENSE_FILE) - { - apply_license_file(&pkg_client, &world, &ret, 2); - goto out; - } - - if ((want_flags & PKG_DUMP_SOURCE) == PKG_DUMP_SOURCE) - { - apply_source(&pkg_client, &world, &ret, 2); - goto out; - } - - - if ((want_flags & PKG_UNINSTALLED) == PKG_UNINSTALLED) - { - ret = EXIT_FAILURE; - apply_uninstalled(&pkg_client, &world, &ret, 2); - goto out; - } - - if (want_env_prefix != NULL) - { - apply_env(&pkg_client, &world, want_env_prefix, 2); - goto out; - } - - if ((want_flags & PKG_PROVIDES) == PKG_PROVIDES) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - apply_provides(&pkg_client, &world, NULL, 2); - } - -#ifndef PKGCONF_LITE - if ((want_flags & PKG_DIGRAPH) == PKG_DIGRAPH) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - apply_digraph(&pkg_client, &world, &pkgq, 2); - } - - if ((want_flags & PKG_SOLUTION) == PKG_SOLUTION) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - apply_print_solution(&pkg_client, &world, NULL, 2); - } -#endif - - if ((want_flags & PKG_MODVERSION) == PKG_MODVERSION) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - apply_modversion(&pkg_client, &world, &pkgq, 2); - } - - if ((want_flags & PKG_PATH) == PKG_PATH) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - - pkgconf_client_set_flags(&pkg_client, want_client_flags | PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL); - apply_path(&pkg_client, &world, NULL, 2); - } - - if ((want_flags & PKG_VARIABLES) == PKG_VARIABLES) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - apply_variables(&pkg_client, &world, NULL, 2); - } - - if (want_variable) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - - pkgconf_client_set_flags(&pkg_client, want_client_flags | PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL); - apply_variable(&pkg_client, &world, want_variable, 2); - } - - if ((want_flags & PKG_REQUIRES) == PKG_REQUIRES) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - apply_requires(&pkg_client, &world, NULL, 2); - } - - if ((want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - - apply_requires_private(&pkg_client, &world, NULL, 2); - } - - if ((want_flags & PKG_FRAGMENT_TREE)) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - - apply_fragment_tree(&pkg_client, &world, NULL, 2); - } - - if ((want_flags & (PKG_CFLAGS|PKG_LIBS))) - { - pkgconf_list_t target_list = PKGCONF_LIST_INITIALIZER; - pkgconf_buffer_t render_buf = PKGCONF_BUFFER_INITIALIZER; - - if ((want_flags & PKG_CFLAGS)) - apply_cflags(&pkg_client, &world, &target_list, 2); - - if ((want_flags & PKG_LIBS) && !(want_flags & PKG_STATIC)) - pkgconf_client_set_flags(&pkg_client, pkg_client.flags & ~PKGCONF_PKG_PKGF_SEARCH_PRIVATE); - - if ((want_flags & PKG_LIBS)) - apply_libs(&pkg_client, &world, &target_list, 2); - - pkgconf_fragment_render_buf(&target_list, &render_buf, true, want_render_ops, (want_flags & PKG_NEWLINES) ? '\n' : ' '); - pkgconf_output_putbuf(pkg_client.output, PKGCONF_OUTPUT_STDOUT, &render_buf, true); - pkgconf_buffer_finalize(&render_buf); - - pkgconf_fragment_free(&target_list); - } + return pkgconf_cli_run(&state, argc, argv, pkg_optind); out: - pkgconf_solution_free(&pkg_client, &world); - pkgconf_queue_free(&pkgq); - pkgconf_cross_personality_deinit(personality); - pkgconf_client_deinit(&pkg_client); - - if (logfile_out != NULL) - fclose(logfile_out); - if (opened_error_msgout) - fclose(error_msgout); - + pkgconf_cli_state_reset(&state); return ret; } diff --git a/cli/renderer-msvc.c b/cli/renderer-msvc.c index 248c0a5..a96f7c0 100644 --- a/cli/renderer-msvc.c +++ b/cli/renderer-msvc.c @@ -142,12 +142,12 @@ msvc_renderer_render_buf(const pkgconf_list_t *list, pkgconf_buffer_t *buf, bool } } -static const pkgconf_fragment_render_ops_t msvc_renderer_ops = { +static pkgconf_fragment_render_ops_t msvc_renderer_ops = { .render_len = msvc_renderer_render_len, .render_buf = msvc_renderer_render_buf }; -const pkgconf_fragment_render_ops_t * +pkgconf_fragment_render_ops_t * msvc_renderer_get(void) { return &msvc_renderer_ops; diff --git a/cli/renderer-msvc.h b/cli/renderer-msvc.h index 2a095fd..3440cec 100644 --- a/cli/renderer-msvc.h +++ b/cli/renderer-msvc.h @@ -18,6 +18,6 @@ #include -const pkgconf_fragment_render_ops_t *msvc_renderer_get(void); +pkgconf_fragment_render_ops_t *msvc_renderer_get(void); #endif diff --git a/meson.build b/meson.build index e654f0a..694f4f5 100644 --- a/meson.build +++ b/meson.build @@ -133,6 +133,7 @@ cli_include = include_directories('cli') pkgconf_exe = executable('pkgconf', 'cli/main.c', + 'cli/core.c', 'cli/getopt_long.c', 'cli/renderer-msvc.c', link_with : libpkgconf,