summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2020-06-30 11:42:25 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2020-06-30 14:52:03 +0300
commit044ded722887357e4c9fff845e87c6db7e08f736 (patch)
treee7e5836b673b0589adae15ee2c1ea0b564416648
parenta881eefe7a5fe884e5b958bb2b861e58e90a044b (diff)
Upgrade to 1.7.31.7.3
-rw-r--r--.gitattributes2
-rw-r--r--libpkgconf/README-DEV15
-rw-r--r--libpkgconf/build/bootstrap.build7
-rw-r--r--libpkgconf/dont-merge-fragments.patch26
-rw-r--r--libpkgconf/fix-demunging-windows-paths.patch13
l---------[-rw-r--r--]libpkgconf/libpkgconf/fragment.c698
l---------libpkgconf/libpkgconf/fragment.c.orig1
l---------[-rw-r--r--]libpkgconf/libpkgconf/libpkgconf.h389
l---------libpkgconf/libpkgconf/libpkgconf.h.orig1
-rw-r--r--[l---------]libpkgconf/libpkgconf/pkg.c1677
l---------libpkgconf/libpkgconf/pkg.c.orig1
-rw-r--r--libpkgconf/manifest2
m---------upstream0
13 files changed, 1704 insertions, 1128 deletions
diff --git a/.gitattributes b/.gitattributes
index 9fce1b0..1631641 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -10,7 +10,7 @@
#*.bat text eol=crlf
# Use `eol=lf` for files that should have the LF line ending both in the
-# working tree (even on Windows) in the repository.
+# working tree (even on Windows) and in the repository.
#
#*.sh text eol=lf
diff --git a/libpkgconf/README-DEV b/libpkgconf/README-DEV
index 37a1317..3d7618e 100644
--- a/libpkgconf/README-DEV
+++ b/libpkgconf/README-DEV
@@ -30,17 +30,14 @@ $ cat libpkgconf/config.h.in |
$ diff defined-macros used-macros
-We also extend the upstream package functionality allowing to prevent merging
-of "special" fragments, such as `-framework <name>`, into a single fragment.
+We also fix the bug in demunging windows paths (issue #17 is reported):
-$ mv libpkgconf.h libpkgconf.h.orig
-$ cp libpkgconf.h.orig libpkgconf.h
+$ mv pkg.c pkg.c.orig
+$ cp pkg.c.orig pkg.c
-$ mv fragment.c fragment.c.orig
-$ cp fragment.c.orig fragment.c
-
-$ git apply dont-merge-fragments.patch
+$ cd ..
+$ git apply fix-demunging-windows-paths.patch
Note that the patch is produces by the following command:
-$ git diff >dont-merge-fragments.patch
+$ git diff >fix-demunging-windows-paths.patch
diff --git a/libpkgconf/build/bootstrap.build b/libpkgconf/build/bootstrap.build
index 6599b62..aedf2a6 100644
--- a/libpkgconf/build/bootstrap.build
+++ b/libpkgconf/build/bootstrap.build
@@ -15,15 +15,16 @@ using dist
# 2 to 3 (libpkgconf.so.2.0.0 -> libpkgconf.so.3.0.0). This probably means
# that the first two release version components constitute a major version,
# and the release number increments each time this version changes. So we just
-# need to watch their Makefile.am for any changes.
+# need to watch their Makefile.am for any changes of the libpkgconf_la_LDFLAGS
+# variable value.
#
# See also: http://kaniini.dereferenced.org/2015/07/20/pkgconf-0-9-12-and-future.html
#
# Note that the upstream project didn't increment the release number (3) for
# the 1.5 library version despite the ABI-breaking changes (issue #15 is
-# reported).
+# reported), so we increment it ourselves.
#
-if ($version.major == 1 && $version.minor == 6)
+if ($version.major == 1 && $version.minor == 7)
release_num = 4
else
fail "increment the release number?"
diff --git a/libpkgconf/dont-merge-fragments.patch b/libpkgconf/dont-merge-fragments.patch
deleted file mode 100644
index d8e5eae..0000000
--- a/libpkgconf/dont-merge-fragments.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-diff --git a/libpkgconf/libpkgconf/fragment.c b/libpkgconf/libpkgconf/fragment.c
-index b431694..37830c8 100644
---- a/libpkgconf/libpkgconf/fragment.c
-+++ b/libpkgconf/libpkgconf/fragment.c
-@@ -150,7 +150,8 @@ pkgconf_fragment_add(const pkgconf_client_t *client, pkgconf_list_t *list, const
- {
- char mungebuf[PKGCONF_ITEM_SIZE];
-
-- if (list->tail != NULL && list->tail->data != NULL)
-+ if (list->tail != NULL && list->tail->data != NULL &&
-+ !(client->flags & PKGCONF_PKG_PKGF_DONT_MERGE_SPECIAL_FRAGMENTS))
- {
- pkgconf_fragment_t *parent = list->tail->data;
-
-diff --git a/libpkgconf/libpkgconf/libpkgconf.h b/libpkgconf/libpkgconf/libpkgconf.h
-index 44a9e7f..6f4c8b5 100644
---- a/libpkgconf/libpkgconf/libpkgconf.h
-+++ b/libpkgconf/libpkgconf/libpkgconf.h
-@@ -247,6 +247,7 @@ PKGCONF_API pkgconf_cross_personality_t *pkgconf_cross_personality_find(const ch
- #define PKGCONF_PKG_PKGF_DONT_RELOCATE_PATHS 0x0800
- #define PKGCONF_PKG_PKGF_SIMPLIFY_ERRORS 0x1000
- #define PKGCONF_PKG_PKGF_DONT_FILTER_INTERNAL_CFLAGS 0x2000
-+#define PKGCONF_PKG_PKGF_DONT_MERGE_SPECIAL_FRAGMENTS 0x4000
-
- #define PKGCONF_PKG_DEPF_INTERNAL 0x1
-
diff --git a/libpkgconf/fix-demunging-windows-paths.patch b/libpkgconf/fix-demunging-windows-paths.patch
new file mode 100644
index 0000000..c9f11f6
--- /dev/null
+++ b/libpkgconf/fix-demunging-windows-paths.patch
@@ -0,0 +1,13 @@
+diff --git a/libpkgconf/libpkgconf/pkg.c b/libpkgconf/libpkgconf/pkg.c
+index 214f544..ba4fb5f 100644
+--- a/libpkgconf/libpkgconf/pkg.c
++++ b/libpkgconf/libpkgconf/pkg.c
+@@ -391,7 +391,7 @@ pkgconf_pkg_new_from_file(pkgconf_client_t *client, const char *filename, FILE *
+ */
+ char *mungeptr;
+ if ((mungeptr = strrchr(idptr, '/')) != NULL)
+- idptr = mungeptr++;
++ idptr = ++mungeptr;
+ #endif
+
+ pkg->id = strdup(idptr);
diff --git a/libpkgconf/libpkgconf/fragment.c b/libpkgconf/libpkgconf/fragment.c
index 37830c8..ccec352 100644..120000
--- a/libpkgconf/libpkgconf/fragment.c
+++ b/libpkgconf/libpkgconf/fragment.c
@@ -1,697 +1 @@
-/*
- * fragment.c
- * Management of fragment lists.
- *
- * Copyright (c) 2012, 2013, 2014 pkgconf authors (see AUTHORS).
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * This software is provided 'as is' and without any warranty, express or
- * implied. In no event shall the authors be liable for any damages arising
- * from the use of this software.
- */
-
-#include <libpkgconf/stdinc.h>
-#include <libpkgconf/libpkgconf.h>
-
-/*
- * !doc
- *
- * libpkgconf `fragment` module
- * ============================
- *
- * The `fragment` module provides low-level management and rendering of fragment lists. A
- * `fragment list` contains various `fragments` of text (such as ``-I /usr/include``) in a matter
- * which is composable, mergeable and reorderable.
- */
-
-struct pkgconf_fragment_check {
- char *token;
- size_t len;
-};
-
-static inline bool
-pkgconf_fragment_is_unmergeable(const char *string)
-{
- static const struct pkgconf_fragment_check check_fragments[] = {
- {"-framework", 10},
- {"-isystem", 8},
- {"-idirafter", 10},
- {"-pthread", 8},
- {"-Wa,", 4},
- {"-Wl,", 4},
- {"-Wp,", 4},
- {"-trigraphs", 10},
- {"-pedantic", 9},
- {"-ansi", 5},
- {"-std=", 5},
- {"-stdlib=", 8},
- {"-include", 8},
- {"-nostdinc", 9},
- {"-nostdlibinc", 12},
- {"-nobuiltininc", 13},
- };
-
- if (*string != '-')
- return true;
-
- for (size_t i = 0; i < PKGCONF_ARRAY_SIZE(check_fragments); i++)
- if (!strncmp(string, check_fragments[i].token, check_fragments[i].len))
- return true;
-
- /* only one pair of {-flag, arg} may be merged together */
- if (strchr(string, ' ') != NULL)
- return false;
-
- return false;
-}
-
-static inline bool
-pkgconf_fragment_should_munge(const char *string, const char *sysroot_dir)
-{
- if (*string != '/')
- return false;
-
- if (sysroot_dir != NULL && strncmp(sysroot_dir, string, strlen(sysroot_dir)))
- return true;
-
- return false;
-}
-
-static inline bool
-pkgconf_fragment_is_special(const char *string)
-{
- if (*string != '-')
- return true;
-
- if (!strncmp(string, "-lib:", 5))
- return true;
-
- return pkgconf_fragment_is_unmergeable(string);
-}
-
-static inline void
-pkgconf_fragment_munge(const pkgconf_client_t *client, char *buf, size_t buflen, const char *source, const char *sysroot_dir)
-{
- *buf = '\0';
-
- if (sysroot_dir == NULL)
- sysroot_dir = pkgconf_tuple_find_global(client, "pc_sysrootdir");
-
- if (sysroot_dir != NULL && pkgconf_fragment_should_munge(source, sysroot_dir))
- pkgconf_strlcat(buf, sysroot_dir, buflen);
-
- pkgconf_strlcat(buf, source, buflen);
-
- if (*buf == '/' && !(client->flags & PKGCONF_PKG_PKGF_DONT_RELOCATE_PATHS))
- pkgconf_path_relocate(buf, buflen);
-}
-
-static inline char *
-pkgconf_fragment_copy_munged(const pkgconf_client_t *client, const char *source)
-{
- char mungebuf[PKGCONF_ITEM_SIZE];
- pkgconf_fragment_munge(client, mungebuf, sizeof mungebuf, source, client->sysroot_dir);
- return strdup(mungebuf);
-}
-
-/*
- * !doc
- *
- * .. c:function:: void pkgconf_fragment_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *string)
- *
- * Adds a `fragment` of text to a `fragment list`, possibly modifying the fragment if a sysroot is set.
- *
- * :param pkgconf_client_t* client: The pkgconf client being accessed.
- * :param pkgconf_list_t* list: The fragment list.
- * :param char* string: The string of text to add as a fragment to the fragment list.
- * :return: nothing
- */
-void
-pkgconf_fragment_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *string)
-{
- pkgconf_fragment_t *frag;
-
- if (*string == '\0')
- return;
-
- if (!pkgconf_fragment_is_special(string))
- {
- frag = calloc(sizeof(pkgconf_fragment_t), 1);
-
- frag->type = *(string + 1);
- frag->data = pkgconf_fragment_copy_munged(client, string + 2);
-
- PKGCONF_TRACE(client, "added fragment {%c, '%s'} to list @%p", frag->type, frag->data, list);
- }
- else
- {
- char mungebuf[PKGCONF_ITEM_SIZE];
-
- if (list->tail != NULL && list->tail->data != NULL &&
- !(client->flags & PKGCONF_PKG_PKGF_DONT_MERGE_SPECIAL_FRAGMENTS))
- {
- pkgconf_fragment_t *parent = list->tail->data;
-
- /* only attempt to merge 'special' fragments together */
- if (!parent->type && pkgconf_fragment_is_unmergeable(parent->data))
- {
- size_t len;
- char *newdata;
-
- pkgconf_fragment_munge(client, mungebuf, sizeof mungebuf, string, NULL);
-
- len = strlen(parent->data) + strlen(mungebuf) + 2;
- newdata = malloc(len);
-
- pkgconf_strlcpy(newdata, parent->data, len);
- pkgconf_strlcat(newdata, " ", len);
- pkgconf_strlcat(newdata, mungebuf, len);
-
- PKGCONF_TRACE(client, "merging '%s' to '%s' to form fragment {'%s'} in list @%p", mungebuf, parent->data, newdata, list);
-
- free(parent->data);
- parent->data = newdata;
- parent->merged = true;
-
- /* use a copy operation to force a dedup */
- pkgconf_node_delete(&parent->iter, list);
- pkgconf_fragment_copy(client, list, parent, false);
-
- /* the fragment list now (maybe) has the copied node, so free the original */
- free(parent->data);
- free(parent);
-
- return;
- }
- }
-
- frag = calloc(sizeof(pkgconf_fragment_t), 1);
-
- frag->type = 0;
- frag->data = strdup(string);
-
- PKGCONF_TRACE(client, "created special fragment {'%s'} in list @%p", frag->data, list);
- }
-
- pkgconf_node_insert_tail(&frag->iter, frag, list);
-}
-
-static inline pkgconf_fragment_t *
-pkgconf_fragment_lookup(pkgconf_list_t *list, const pkgconf_fragment_t *base)
-{
- pkgconf_node_t *node;
-
- PKGCONF_FOREACH_LIST_ENTRY_REVERSE(list->tail, node)
- {
- pkgconf_fragment_t *frag = node->data;
-
- if (base->type != frag->type)
- continue;
-
- if (!strcmp(base->data, frag->data))
- return frag;
- }
-
- return NULL;
-}
-
-static inline bool
-pkgconf_fragment_can_merge_back(const pkgconf_fragment_t *base, unsigned int flags, bool is_private)
-{
- (void) flags;
-
- if (base->type == 'l')
- {
- if (is_private)
- return false;
-
- return true;
- }
-
- if (base->type == 'F')
- return false;
- if (base->type == 'L')
- return false;
- if (base->type == 'I')
- return false;
-
- return true;
-}
-
-static inline bool
-pkgconf_fragment_can_merge(const pkgconf_fragment_t *base, unsigned int flags, bool is_private)
-{
- (void) flags;
-
- if (is_private)
- return false;
-
- return pkgconf_fragment_is_unmergeable(base->data);
-}
-
-static inline pkgconf_fragment_t *
-pkgconf_fragment_exists(pkgconf_list_t *list, const pkgconf_fragment_t *base, unsigned int flags, bool is_private)
-{
- if (!pkgconf_fragment_can_merge_back(base, flags, is_private))
- return NULL;
-
- if (!pkgconf_fragment_can_merge(base, flags, is_private))
- return NULL;
-
- return pkgconf_fragment_lookup(list, base);
-}
-
-static inline bool
-pkgconf_fragment_should_merge(const pkgconf_fragment_t *base)
-{
- const pkgconf_fragment_t *parent;
-
- /* if we are the first fragment, that means the next fragment is the same, so it's always safe. */
- if (base->iter.prev == NULL)
- return true;
-
- /* this really shouldn't ever happen, but handle it */
- parent = base->iter.prev->data;
- if (parent == NULL)
- return true;
-
- switch (parent->type)
- {
- case 'l':
- case 'L':
- case 'I':
- return true;
- default:
- return !base->type || parent->type == base->type;
- }
-}
-
-/*
- * !doc
- *
- * .. c:function:: bool pkgconf_fragment_has_system_dir(const pkgconf_client_t *client, const pkgconf_fragment_t *frag)
- *
- * Checks if a `fragment` contains a `system path`. System paths are detected at compile time and optionally overridden by
- * the ``PKG_CONFIG_SYSTEM_INCLUDE_PATH`` and ``PKG_CONFIG_SYSTEM_LIBRARY_PATH`` environment variables.
- *
- * :param pkgconf_client_t* client: The pkgconf client object the fragment belongs to.
- * :param pkgconf_fragment_t* frag: The fragment being checked.
- * :return: true if the fragment contains a system path, else false
- * :rtype: bool
- */
-bool
-pkgconf_fragment_has_system_dir(const pkgconf_client_t *client, const pkgconf_fragment_t *frag)
-{
- const pkgconf_list_t *check_paths = NULL;
-
- switch (frag->type)
- {
- case 'L':
- check_paths = &client->filter_libdirs;
- break;
- case 'I':
- check_paths = &client->filter_includedirs;
- break;
- default:
- return false;
- }
-
- return pkgconf_path_match_list(frag->data, check_paths);
-}
-
-/*
- * !doc
- *
- * .. c:function:: void pkgconf_fragment_copy(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_fragment_t *base, bool is_private)
- *
- * Copies a `fragment` to another `fragment list`, possibly removing a previous copy of the `fragment`
- * in a process known as `mergeback`.
- *
- * :param pkgconf_client_t* client: The pkgconf client being accessed.
- * :param pkgconf_list_t* list: The list the fragment is being added to.
- * :param pkgconf_fragment_t* base: The fragment being copied.
- * :param bool is_private: Whether the fragment list is a `private` fragment list (static linking).
- * :return: nothing
- */
-void
-pkgconf_fragment_copy(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_fragment_t *base, bool is_private)
-{
- pkgconf_fragment_t *frag;
-
- if ((frag = pkgconf_fragment_exists(list, base, client->flags, is_private)) != NULL)
- {
- if (pkgconf_fragment_should_merge(frag))
- pkgconf_fragment_delete(list, frag);
- }
- else if (!is_private && !pkgconf_fragment_can_merge_back(base, client->flags, is_private) && (pkgconf_fragment_lookup(list, base) != NULL))
- return;
-
- frag = calloc(sizeof(pkgconf_fragment_t), 1);
-
- frag->type = base->type;
- frag->merged = base->merged;
- if (base->data != NULL)
- frag->data = strdup(base->data);
-
- pkgconf_node_insert_tail(&frag->iter, frag, list);
-}
-
-/*
- * !doc
- *
- * .. c:function:: void pkgconf_fragment_copy_list(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_list_t *base)
- *
- * Copies a `fragment list` to another `fragment list`, possibly removing a previous copy of the fragments
- * in a process known as `mergeback`.
- *
- * :param pkgconf_client_t* client: The pkgconf client being accessed.
- * :param pkgconf_list_t* list: The list the fragments are being added to.
- * :param pkgconf_list_t* base: The list the fragments are being copied from.
- * :return: nothing
- */
-void
-pkgconf_fragment_copy_list(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_list_t *base)
-{
- pkgconf_node_t *node;
-
- PKGCONF_FOREACH_LIST_ENTRY(base->head, node)
- {
- pkgconf_fragment_t *frag = node->data;
-
- pkgconf_fragment_copy(client, list, frag, true);
- }
-}
-
-/*
- * !doc
- *
- * .. c:function:: void pkgconf_fragment_filter(const pkgconf_client_t *client, pkgconf_list_t *dest, pkgconf_list_t *src, pkgconf_fragment_filter_func_t filter_func)
- *
- * Copies a `fragment list` to another `fragment list` which match a user-specified filtering function.
- *
- * :param pkgconf_client_t* client: The pkgconf client being accessed.
- * :param pkgconf_list_t* dest: The destination list.
- * :param pkgconf_list_t* src: The source list.
- * :param pkgconf_fragment_filter_func_t filter_func: The filter function to use.
- * :param void* data: Optional data to pass to the filter function.
- * :return: nothing
- */
-void
-pkgconf_fragment_filter(const pkgconf_client_t *client, pkgconf_list_t *dest, pkgconf_list_t *src, pkgconf_fragment_filter_func_t filter_func, void *data)
-{
- pkgconf_node_t *node;
-
- PKGCONF_FOREACH_LIST_ENTRY(src->head, node)
- {
- pkgconf_fragment_t *frag = node->data;
-
- if (filter_func(client, frag, data))
- pkgconf_fragment_copy(client, dest, frag, true);
- }
-}
-
-static inline char *
-fragment_quote(const pkgconf_fragment_t *frag)
-{
- const char *src = frag->data;
- ssize_t outlen = strlen(src) + 10;
- char *out, *dst;
-
- if (frag->data == NULL)
- return NULL;
-
- out = dst = calloc(outlen, 1);
-
- for (; *src; src++)
- {
- if (((*src < ' ') ||
- (*src >= (' ' + (frag->merged ? 1 : 0)) && *src < '$') ||
- (*src > '$' && *src < '(') ||
- (*src > ')' && *src < '+') ||
- (*src > ':' && *src < '=') ||
- (*src > '=' && *src < '@') ||
- (*src > 'Z' && *src < '^') ||
- (*src == '`') ||
- (*src > 'z' && *src < '~') ||
- (*src > '~')))
- *dst++ = '\\';
-
- *dst++ = *src;
-
- if ((ptrdiff_t)(dst - out) + 2 > outlen)
- {
- outlen *= 2;
- out = realloc(out, outlen);
- }
- }
-
- *dst = 0;
- return out;
-}
-
-static inline size_t
-pkgconf_fragment_len(const pkgconf_fragment_t *frag)
-{
- size_t len = 1;
-
- if (frag->type)
- len += 2;
-
- if (frag->data != NULL)
- {
- char *quoted = fragment_quote(frag);
- len += strlen(quoted);
- free(quoted);
- }
-
- return len;
-}
-
-static size_t
-fragment_render_len(const pkgconf_list_t *list, bool escape)
-{
- (void) escape;
-
- size_t out = 1; /* trailing nul */
- pkgconf_node_t *node;
-
- PKGCONF_FOREACH_LIST_ENTRY(list->head, node)
- {
- const pkgconf_fragment_t *frag = node->data;
- out += pkgconf_fragment_len(frag);
- }
-
- return out;
-}
-
-static void
-fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape)
-{
- (void) escape;
-
- pkgconf_node_t *node;
- char *bptr = buf;
-
- memset(buf, 0, buflen);
-
- PKGCONF_FOREACH_LIST_ENTRY(list->head, node)
- {
- const pkgconf_fragment_t *frag = node->data;
- size_t buf_remaining = buflen - (bptr - buf);
- char *quoted = fragment_quote(frag);
-
- if (strlen(quoted) > buf_remaining)
- {
- free(quoted);
- break;
- }
-
- if (frag->type)
- {
- *bptr++ = '-';
- *bptr++ = frag->type;
- }
-
- if (quoted != NULL)
- {
- bptr += pkgconf_strlcpy(bptr, quoted, buf_remaining);
- free(quoted);
- }
-
- *bptr++ = ' ';
- }
-
- *bptr = '\0';
-}
-
-static const pkgconf_fragment_render_ops_t default_render_ops = {
- .render_len = fragment_render_len,
- .render_buf = fragment_render_buf
-};
-
-/*
- * !doc
- *
- * .. c:function:: size_t pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops)
- *
- * Calculates the required memory to store a `fragment list` when rendered as a string.
- *
- * :param pkgconf_list_t* list: The `fragment list` being rendered.
- * :param bool escape: Whether or not to escape special shell characters (deprecated).
- * :param pkgconf_fragment_render_ops_t* ops: An optional ops structure to use for custom renderers, else ``NULL``.
- * :return: the amount of bytes required to represent the `fragment list` when rendered
- * :rtype: size_t
- */
-size_t
-pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops)
-{
- (void) escape;
-
- ops = ops != NULL ? ops : &default_render_ops;
- return ops->render_len(list, true);
-}
-
-/*
- * !doc
- *
- * .. c:function:: void pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape, const pkgconf_fragment_render_ops_t *ops)
- *
- * Renders a `fragment list` into a buffer.
- *
- * :param pkgconf_list_t* list: The `fragment list` being rendered.
- * :param char* buf: The buffer to render the fragment list into.
- * :param size_t buflen: The length of the buffer.
- * :param bool escape: Whether or not to escape special shell characters (deprecated).
- * :param pkgconf_fragment_render_ops_t* ops: An optional ops structure to use for custom renderers, else ``NULL``.
- * :return: nothing
- */
-void
-pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape, const pkgconf_fragment_render_ops_t *ops)
-{
- (void) escape;
-
- ops = ops != NULL ? ops : &default_render_ops;
- ops->render_buf(list, buf, buflen, true);
-}
-
-/*
- * !doc
- *
- * .. c:function:: char *pkgconf_fragment_render(const pkgconf_list_t *list)
- *
- * Allocate memory and render a `fragment list` into it.
- *
- * :param pkgconf_list_t* list: The `fragment list` being rendered.
- * :param bool escape: Whether or not to escape special shell characters (deprecated).
- * :param pkgconf_fragment_render_ops_t* ops: An optional ops structure to use for custom renderers, else ``NULL``.
- * :return: An allocated string containing the rendered `fragment list`.
- * :rtype: char *
- */
-char *
-pkgconf_fragment_render(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops)
-{
- (void) escape;
-
- size_t buflen = pkgconf_fragment_render_len(list, true, ops);
- char *buf = calloc(1, buflen);
-
- pkgconf_fragment_render_buf(list, buf, buflen, true, ops);
-
- return buf;
-}
-
-/*
- * !doc
- *
- * .. c:function:: void pkgconf_fragment_delete(pkgconf_list_t *list, pkgconf_fragment_t *node)
- *
- * Delete a `fragment node` from a `fragment list`.
- *
- * :param pkgconf_list_t* list: The `fragment list` to delete from.
- * :param pkgconf_fragment_t* node: The `fragment node` to delete.
- * :return: nothing
- */
-void
-pkgconf_fragment_delete(pkgconf_list_t *list, pkgconf_fragment_t *node)
-{
- pkgconf_node_delete(&node->iter, list);
-
- free(node->data);
- free(node);
-}
-
-/*
- * !doc
- *
- * .. c:function:: void pkgconf_fragment_free(pkgconf_list_t *list)
- *
- * Delete an entire `fragment list`.
- *
- * :param pkgconf_list_t* list: The `fragment list` to delete.
- * :return: nothing
- */
-void
-pkgconf_fragment_free(pkgconf_list_t *list)
-{
- pkgconf_node_t *node, *next;
-
- PKGCONF_FOREACH_LIST_ENTRY_SAFE(list->head, next, node)
- {
- pkgconf_fragment_t *frag = node->data;
-
- free(frag->data);
- free(frag);
- }
-}
-
-/*
- * !doc
- *
- * .. c:function:: bool pkgconf_fragment_parse(const pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_list_t *vars, const char *value)
- *
- * Parse a string into a `fragment list`.
- *
- * :param pkgconf_client_t* client: The pkgconf client being accessed.
- * :param pkgconf_list_t* list: The `fragment list` to add the fragment entries to.
- * :param pkgconf_list_t* vars: A list of variables to use for variable substitution.
- * :param char* value: The string to parse into fragments.
- * :return: true on success, false on parse error
- */
-bool
-pkgconf_fragment_parse(const pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_list_t *vars, const char *value)
-{
- int i, ret, argc;
- char **argv;
- char *repstr = pkgconf_tuple_parse(client, vars, value);
-
- PKGCONF_TRACE(client, "post-subst: [%s] -> [%s]", value, repstr);
-
- ret = pkgconf_argv_split(repstr, &argc, &argv);
- if (ret < 0)
- {
- PKGCONF_TRACE(client, "unable to parse fragment string [%s]", repstr);
- free(repstr);
- return false;
- }
-
- for (i = 0; i < argc; i++)
- {
- if (argv[i] == NULL)
- {
- PKGCONF_TRACE(client, "parsed fragment string is inconsistent: argc = %d while argv[%d] == NULL", argc, i);
- pkgconf_argv_free(argv);
- free(repstr);
- return false;
- }
-
- pkgconf_fragment_add(client, list, argv[i]);
- }
-
- pkgconf_argv_free(argv);
- free(repstr);
-
- return true;
-}
+../../upstream/libpkgconf/fragment.c \ No newline at end of file
diff --git a/libpkgconf/libpkgconf/fragment.c.orig b/libpkgconf/libpkgconf/fragment.c.orig
deleted file mode 120000
index ccec352..0000000
--- a/libpkgconf/libpkgconf/fragment.c.orig
+++ /dev/null
@@ -1 +0,0 @@
-../../upstream/libpkgconf/fragment.c \ No newline at end of file
diff --git a/libpkgconf/libpkgconf/libpkgconf.h b/libpkgconf/libpkgconf/libpkgconf.h
index 6f4c8b5..b885e88 100644..120000
--- a/libpkgconf/libpkgconf/libpkgconf.h
+++ b/libpkgconf/libpkgconf/libpkgconf.h
@@ -1,388 +1 @@
-/*
- * libpkgconf.h
- * Global include file for everything in libpkgconf.
- *
- * Copyright (c) 2011, 2015 pkgconf authors (see AUTHORS).
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * This software is provided 'as is' and without any warranty, express or
- * implied. In no event shall the authors be liable for any damages arising
- * from the use of this software.
- */
-
-#ifndef LIBPKGCONF__LIBPKGCONF_H
-#define LIBPKGCONF__LIBPKGCONF_H
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdbool.h>
-#include <libpkgconf/libpkgconf-api.h>
-#include <libpkgconf/iter.h>
-#include <libpkgconf/bsdstubs.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* pkg-config uses ';' on win32 as ':' is part of path */
-#ifdef _WIN32
-#define PKG_CONFIG_PATH_SEP_S ";"
-#else
-#define PKG_CONFIG_PATH_SEP_S ":"
-#endif
-
-#ifdef _WIN32
-#define PKG_DIR_SEP_S '\\'
-#else
-#define PKG_DIR_SEP_S '/'
-#endif
-
-#ifdef _WIN32
-#define realpath(N,R) _fullpath((R),(N),_MAX_PATH)
-#endif
-
-#define PKGCONF_BUFSIZE (65535)
-
-typedef enum {
- PKGCONF_CMP_NOT_EQUAL,
- PKGCONF_CMP_ANY,
- PKGCONF_CMP_LESS_THAN,
- PKGCONF_CMP_LESS_THAN_EQUAL,
- PKGCONF_CMP_EQUAL,
- PKGCONF_CMP_GREATER_THAN,
- PKGCONF_CMP_GREATER_THAN_EQUAL
-} pkgconf_pkg_comparator_t;
-
-#define PKGCONF_CMP_COUNT 7
-
-typedef struct pkgconf_pkg_ pkgconf_pkg_t;
-typedef struct pkgconf_dependency_ pkgconf_dependency_t;
-typedef struct pkgconf_tuple_ pkgconf_tuple_t;
-typedef struct pkgconf_fragment_ pkgconf_fragment_t;
-typedef struct pkgconf_path_ pkgconf_path_t;
-typedef struct pkgconf_client_ pkgconf_client_t;
-typedef struct pkgconf_cross_personality_ pkgconf_cross_personality_t;
-
-#define PKGCONF_ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
-
-#define PKGCONF_FOREACH_LIST_ENTRY(head, value) \
- for ((value) = (head); (value) != NULL; (value) = (value)->next)
-
-#define PKGCONF_FOREACH_LIST_ENTRY_SAFE(head, nextiter, value) \
- for ((value) = (head), (nextiter) = (head) != NULL ? (head)->next : NULL; (value) != NULL; (value) = (nextiter), (nextiter) = (nextiter) != NULL ? (nextiter)->next : NULL)
-
-#define PKGCONF_FOREACH_LIST_ENTRY_REVERSE(tail, value) \
- for ((value) = (tail); (value) != NULL; (value) = (value)->prev)
-
-#define LIBPKGCONF_VERSION 10603
-#define LIBPKGCONF_VERSION_STR "1.6.3"
-
-struct pkgconf_fragment_ {
- pkgconf_node_t iter;
-
- char type;
- char *data;
-
- bool merged;
-};
-
-struct pkgconf_dependency_ {
- pkgconf_node_t iter;
-
- char *package;
- pkgconf_pkg_comparator_t compare;
- char *version;
- pkgconf_pkg_t *parent;
- pkgconf_pkg_t *match;
-
- unsigned int flags;
-};
-
-struct pkgconf_tuple_ {
- pkgconf_node_t iter;
-
- char *key;
- char *value;
-};
-
-struct pkgconf_path_ {
- pkgconf_node_t lnode;
-
- char *path;
- void *handle_path;
- void *handle_device;
-};
-
-#define PKGCONF_PKG_PROPF_NONE 0x00
-#define PKGCONF_PKG_PROPF_STATIC 0x01
-#define PKGCONF_PKG_PROPF_CACHED 0x02
-#define PKGCONF_PKG_PROPF_SEEN 0x04
-#define PKGCONF_PKG_PROPF_UNINSTALLED 0x08
-#define PKGCONF_PKG_PROPF_VIRTUAL 0x10
-
-struct pkgconf_pkg_ {
- pkgconf_node_t cache_iter;
-
- int refcount;
- char *id;
- char *filename;
- char *realname;
- char *version;
- char *description;
- char *url;
- char *pc_filedir;
-
- pkgconf_list_t libs;
- pkgconf_list_t libs_private;
- pkgconf_list_t cflags;
- pkgconf_list_t cflags_private;
-
- pkgconf_list_t required; /* this used to be requires but that is now a reserved keyword */
- pkgconf_list_t requires_private;
- pkgconf_list_t conflicts;
- pkgconf_list_t provides;
-
- pkgconf_list_t vars;
-
- unsigned int flags;
-
- pkgconf_client_t *owner;
-
- /* these resources are owned by the package and do not need special management,
- * under no circumstance attempt to allocate or free objects belonging to these pointers
- */
- pkgconf_tuple_t *orig_prefix;
- pkgconf_tuple_t *prefix;
-};
-
-typedef bool (*pkgconf_pkg_iteration_func_t)(const pkgconf_pkg_t *pkg, void *data);
-typedef void (*pkgconf_pkg_traverse_func_t)(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data);
-typedef bool (*pkgconf_queue_apply_func_t)(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth);
-typedef bool (*pkgconf_error_handler_func_t)(const char *msg, const pkgconf_client_t *client, const void *data);
-
-struct pkgconf_client_ {
- pkgconf_list_t dir_list;
- pkgconf_list_t pkg_cache;
-
- pkgconf_list_t filter_libdirs;
- pkgconf_list_t filter_includedirs;
-
- pkgconf_list_t global_vars;
-
- void *error_handler_data;
- void *warn_handler_data;
- void *trace_handler_data;
-
- pkgconf_error_handler_func_t error_handler;
- pkgconf_error_handler_func_t warn_handler;
- pkgconf_error_handler_func_t trace_handler;
-
- FILE *auditf;
-
- char *sysroot_dir;
- char *buildroot_dir;
-
- unsigned int flags;
-
- char *prefix_varname;
-
- bool already_sent_notice;
-};
-
-struct pkgconf_cross_personality_ {
- const char *name;
-
- pkgconf_list_t dir_list;
-
- pkgconf_list_t filter_libdirs;
- pkgconf_list_t filter_includedirs;
-
- char *sysroot_dir;
-};
-
-/* client.c */
-PKGCONF_API void pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality);
-PKGCONF_API pkgconf_client_t * pkgconf_client_new(pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality);
-PKGCONF_API void pkgconf_client_deinit(pkgconf_client_t *client);
-PKGCONF_API void pkgconf_client_free(pkgconf_client_t *client);
-PKGCONF_API const char *pkgconf_client_get_sysroot_dir(const pkgconf_client_t *client);
-PKGCONF_API void pkgconf_client_set_sysroot_dir(pkgconf_client_t *client, const char *sysroot_dir);
-PKGCONF_API const char *pkgconf_client_get_buildroot_dir(const pkgconf_client_t *client);
-PKGCONF_API void pkgconf_client_set_buildroot_dir(pkgconf_client_t *client, const char *buildroot_dir);
-PKGCONF_API unsigned int pkgconf_client_get_flags(const pkgconf_client_t *client);
-PKGCONF_API void pkgconf_client_set_flags(pkgconf_client_t *client, unsigned int flags);
-PKGCONF_API const char *pkgconf_client_get_prefix_varname(const pkgconf_client_t *client);
-PKGCONF_API void pkgconf_client_set_prefix_varname(pkgconf_client_t *client, const char *prefix_varname);
-PKGCONF_API pkgconf_error_handler_func_t pkgconf_client_get_warn_handler(const pkgconf_client_t *client);
-PKGCONF_API void pkgconf_client_set_warn_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t warn_handler, void *warn_handler_data);
-PKGCONF_API pkgconf_error_handler_func_t pkgconf_client_get_error_handler(const pkgconf_client_t *client);
-PKGCONF_API void pkgconf_client_set_error_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data);
-PKGCONF_API pkgconf_error_handler_func_t pkgconf_client_get_trace_handler(const pkgconf_client_t *client);
-PKGCONF_API void pkgconf_client_set_trace_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t trace_handler, void *trace_handler_data);
-PKGCONF_API void pkgconf_client_dir_list_build(pkgconf_client_t *client, const pkgconf_cross_personality_t *personality);
-
-/* personality.c */
-PKGCONF_API pkgconf_cross_personality_t *pkgconf_cross_personality_default(void);
-PKGCONF_API pkgconf_cross_personality_t *pkgconf_cross_personality_find(const char *triplet);
-
-#define PKGCONF_IS_MODULE_SEPARATOR(c) ((c) == ',' || isspace ((unsigned int)(c)))
-#define PKGCONF_IS_OPERATOR_CHAR(c) ((c) == '<' || (c) == '>' || (c) == '!' || (c) == '=')
-
-#define PKGCONF_PKG_PKGF_NONE 0x0000
-#define PKGCONF_PKG_PKGF_SEARCH_PRIVATE 0x0001
-#define PKGCONF_PKG_PKGF_ENV_ONLY 0x0002
-#define PKGCONF_PKG_PKGF_NO_UNINSTALLED 0x0004
-#define PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL 0x0008
-#define PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS 0x0010
-#define PKGCONF_PKG_PKGF_SKIP_CONFLICTS 0x0020
-#define PKGCONF_PKG_PKGF_NO_CACHE 0x0040
-#define PKGCONF_PKG_PKGF_SKIP_ERRORS 0x0080
-#define PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE 0x0100
-#define PKGCONF_PKG_PKGF_SKIP_PROVIDES 0x0200
-#define PKGCONF_PKG_PKGF_REDEFINE_PREFIX 0x0400
-#define PKGCONF_PKG_PKGF_DONT_RELOCATE_PATHS 0x0800
-#define PKGCONF_PKG_PKGF_SIMPLIFY_ERRORS 0x1000
-#define PKGCONF_PKG_PKGF_DONT_FILTER_INTERNAL_CFLAGS 0x2000
-#define PKGCONF_PKG_PKGF_DONT_MERGE_SPECIAL_FRAGMENTS 0x4000
-
-#define PKGCONF_PKG_DEPF_INTERNAL 0x1
-
-#define PKGCONF_PKG_ERRF_OK 0x0
-#define PKGCONF_PKG_ERRF_PACKAGE_NOT_FOUND 0x1
-#define PKGCONF_PKG_ERRF_PACKAGE_VER_MISMATCH 0x2
-#define PKGCONF_PKG_ERRF_PACKAGE_CONFLICT 0x4
-#define PKGCONF_PKG_ERRF_DEPGRAPH_BREAK 0x8
-
-#if defined(__GNUC__) || defined(__INTEL_COMPILER)
-#define PRINTFLIKE(fmtarg, firstvararg) \
- __attribute__((__format__ (__printf__, fmtarg, firstvararg)))
-#define DEPRECATED \
- __attribute__((deprecated))
-#else
-#define PRINTFLIKE(fmtarg, firstvararg)
-#define DEPRECATED
-#endif /* defined(__INTEL_COMPILER) || defined(__GNUC__) */
-
-/* parser.c */
-typedef void (*pkgconf_parser_operand_func_t)(void *data, const size_t lineno, const char *key, const char *value);
-typedef void (*pkgconf_parser_warn_func_t)(void *data, const char *fmt, ...);
-
-PKGCONF_API void pkgconf_parser_parse(FILE *f, void *data, const pkgconf_parser_operand_func_t *ops, const pkgconf_parser_warn_func_t warnfunc, const char *filename);
-
-/* pkg.c */
-PKGCONF_API bool pkgconf_error(const pkgconf_client_t *client, const char *format, ...) PRINTFLIKE(2, 3);
-PKGCONF_API bool pkgconf_warn(const pkgconf_client_t *client, const char *format, ...) PRINTFLIKE(2, 3);
-PKGCONF_API bool pkgconf_trace(const pkgconf_client_t *client, const char *filename, size_t lineno, const char *funcname, const char *format, ...) PRINTFLIKE(5, 6);
-PKGCONF_API bool pkgconf_default_error_handler(const char *msg, const pkgconf_client_t *client, const void *data);
-
-#ifndef PKGCONF_LITE
-#if defined(__GNUC__) || defined(__INTEL_COMPILER)
-#define PKGCONF_TRACE(client, ...) do { \
- pkgconf_trace(client, __FILE__, __LINE__, __PRETTY_FUNCTION__, __VA_ARGS__); \
- } while (0);
-#else
-#define PKGCONF_TRACE(client, ...) do { \
- pkgconf_trace(client, __FILE__, __LINE__, __func__, __VA_ARGS__); \
- } while (0);
-#endif
-#else
-#define PKGCONF_TRACE(client, ...)
-#endif
-
-PKGCONF_API pkgconf_pkg_t *pkgconf_pkg_ref(pkgconf_client_t *client, pkgconf_pkg_t *pkg);
-PKGCONF_API void pkgconf_pkg_unref(pkgconf_client_t *client, pkgconf_pkg_t *pkg);
-PKGCONF_API void pkgconf_pkg_free(pkgconf_client_t *client, pkgconf_pkg_t *pkg);
-PKGCONF_API pkgconf_pkg_t *pkgconf_pkg_find(pkgconf_client_t *client, const char *name);
-PKGCONF_API unsigned int pkgconf_pkg_traverse(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_pkg_traverse_func_t func, void *data, int maxdepth, unsigned int skip_flags);
-PKGCONF_API unsigned int pkgconf_pkg_verify_graph(pkgconf_client_t *client, pkgconf_pkg_t *root, int depth);
-PKGCONF_API pkgconf_pkg_t *pkgconf_pkg_verify_dependency(pkgconf_client_t *client, pkgconf_dependency_t *pkgdep, unsigned int *eflags);
-PKGCONF_API const char *pkgconf_pkg_get_comparator(const pkgconf_dependency_t *pkgdep);
-PKGCONF_API unsigned int pkgconf_pkg_cflags(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_list_t *list, int maxdepth);
-PKGCONF_API unsigned int pkgconf_pkg_libs(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_list_t *list, int maxdepth);
-PKGCONF_API pkgconf_pkg_comparator_t pkgconf_pkg_comparator_lookup_by_name(const char *name);
-PKGCONF_API pkgconf_pkg_t *pkgconf_builtin_pkg_get(const char *name);
-
-PKGCONF_API int pkgconf_compare_version(const char *a, const char *b);
-PKGCONF_API pkgconf_pkg_t *pkgconf_scan_all(pkgconf_client_t *client, void *ptr, pkgconf_pkg_iteration_func_t func);
-
-/* parse.c */
-PKGCONF_API pkgconf_pkg_t *pkgconf_pkg_new_from_file(pkgconf_client_t *client, const char *path, FILE *f);
-PKGCONF_API void pkgconf_dependency_parse_str(const pkgconf_client_t *client, pkgconf_list_t *deplist_head, const char *depends, unsigned int flags);
-PKGCONF_API void pkgconf_dependency_parse(const pkgconf_client_t *client, pkgconf_pkg_t *pkg, pkgconf_list_t *deplist_head, const char *depends, unsigned int flags);
-PKGCONF_API void pkgconf_dependency_append(pkgconf_list_t *list, pkgconf_dependency_t *tail);
-PKGCONF_API void pkgconf_dependency_free(pkgconf_list_t *list);
-PKGCONF_API pkgconf_dependency_t *pkgconf_dependency_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *package, const char *version, pkgconf_pkg_comparator_t compare, unsigned int flags);
-
-/* argvsplit.c */
-PKGCONF_API int pkgconf_argv_split(const char *src, int *argc, char ***argv);
-PKGCONF_API void pkgconf_argv_free(char **argv);
-
-/* fragment.c */
-typedef struct pkgconf_fragment_render_ops_ {
- size_t (*render_len)(const pkgconf_list_t *list, bool escape);
- void (*render_buf)(const pkgconf_list_t *list, char *buf, size_t len, bool escape);
-} pkgconf_fragment_render_ops_t;
-
-typedef bool (*pkgconf_fragment_filter_func_t)(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data);
-PKGCONF_API bool pkgconf_fragment_parse(const pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_list_t *vars, const char *value);
-PKGCONF_API void pkgconf_fragment_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *string);
-PKGCONF_API void pkgconf_fragment_copy(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_fragment_t *base, bool is_private);
-PKGCONF_API void pkgconf_fragment_copy_list(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_list_t *base);
-PKGCONF_API void pkgconf_fragment_delete(pkgconf_list_t *list, pkgconf_fragment_t *node);
-PKGCONF_API void pkgconf_fragment_free(pkgconf_list_t *list);
-PKGCONF_API void pkgconf_fragment_filter(const pkgconf_client_t *client, pkgconf_list_t *dest, pkgconf_list_t *src, pkgconf_fragment_filter_func_t filter_func, void *data);
-PKGCONF_API size_t pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops);
-PKGCONF_API void pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t len, bool escape, const pkgconf_fragment_render_ops_t *ops);
-PKGCONF_API char *pkgconf_fragment_render(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops);
-PKGCONF_API bool pkgconf_fragment_has_system_dir(const pkgconf_client_t *client, const pkgconf_fragment_t *frag);
-
-/* fileio.c */
-PKGCONF_API char *pkgconf_fgetline(char *line, size_t size, FILE *stream);
-
-/* tuple.c */
-PKGCONF_API pkgconf_tuple_t *pkgconf_tuple_add(const pkgconf_client_t *client, pkgconf_list_t *parent, const char *key, const char *value, bool parse);
-PKGCONF_API char *pkgconf_tuple_find(const pkgconf_client_t *client, pkgconf_list_t *list, const char *key);
-PKGCONF_API char *pkgconf_tuple_parse(const pkgconf_client_t *client, pkgconf_list_t *list, const char *value);
-PKGCONF_API void pkgconf_tuple_free(pkgconf_list_t *list);
-PKGCONF_API void pkgconf_tuple_free_entry(pkgconf_tuple_t *tuple, pkgconf_list_t *list);
-PKGCONF_API void pkgconf_tuple_add_global(pkgconf_client_t *client, const char *key, const char *value);
-PKGCONF_API char *pkgconf_tuple_find_global(const pkgconf_client_t *client, const char *key);
-PKGCONF_API void pkgconf_tuple_free_global(pkgconf_client_t *client);
-PKGCONF_API void pkgconf_tuple_define_global(pkgconf_client_t *client, const char *kv);
-
-/* queue.c */
-PKGCONF_API void pkgconf_queue_push(pkgconf_list_t *list, const char *package);
-PKGCONF_API bool pkgconf_queue_compile(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list);
-PKGCONF_API void pkgconf_queue_free(pkgconf_list_t *list);
-PKGCONF_API bool pkgconf_queue_apply(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queue_apply_func_t func, int maxdepth, void *data);
-PKGCONF_API bool pkgconf_queue_validate(pkgconf_client_t *client, pkgconf_list_t *list, int maxdepth);
-
-/* cache.c */
-PKGCONF_API pkgconf_pkg_t *pkgconf_cache_lookup(pkgconf_client_t *client, const char *id);
-PKGCONF_API void pkgconf_cache_add(pkgconf_client_t *client, pkgconf_pkg_t *pkg);
-PKGCONF_API void pkgconf_cache_remove(pkgconf_client_t *client, pkgconf_pkg_t *pkg);
-PKGCONF_API void pkgconf_cache_free(pkgconf_client_t *client);
-
-/* audit.c */
-PKGCONF_API void pkgconf_audit_set_log(pkgconf_client_t *client, FILE *auditf);
-PKGCONF_API void pkgconf_audit_log(pkgconf_client_t *client, const char *format, ...) PRINTFLIKE(2, 3);
-PKGCONF_API void pkgconf_audit_log_dependency(pkgconf_client_t *client, const pkgconf_pkg_t *dep, const pkgconf_dependency_t *depnode);
-
-/* path.c */
-PKGCONF_API void pkgconf_path_add(const char *text, pkgconf_list_t *dirlist, bool filter);
-PKGCONF_API size_t pkgconf_path_split(const char *text, pkgconf_list_t *dirlist, bool filter);
-PKGCONF_API size_t pkgconf_path_build_from_environ(const char *envvarname, const char *fallback, pkgconf_list_t *dirlist, bool filter);
-PKGCONF_API bool pkgconf_path_match_list(const char *path, const pkgconf_list_t *dirlist);
-PKGCONF_API void pkgconf_path_free(pkgconf_list_t *dirlist);
-PKGCONF_API bool pkgconf_path_relocate(char *buf, size_t buflen);
-PKGCONF_API void pkgconf_path_copy_list(pkgconf_list_t *dst, const pkgconf_list_t *src);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+../../upstream/libpkgconf/libpkgconf.h \ No newline at end of file
diff --git a/libpkgconf/libpkgconf/libpkgconf.h.orig b/libpkgconf/libpkgconf/libpkgconf.h.orig
deleted file mode 120000
index b885e88..0000000
--- a/libpkgconf/libpkgconf/libpkgconf.h.orig
+++ /dev/null
@@ -1 +0,0 @@
-../../upstream/libpkgconf/libpkgconf.h \ No newline at end of file
diff --git a/libpkgconf/libpkgconf/pkg.c b/libpkgconf/libpkgconf/pkg.c
index ea9e3fd..ba4fb5f 120000..100644
--- a/libpkgconf/libpkgconf/pkg.c
+++ b/libpkgconf/libpkgconf/pkg.c
@@ -1 +1,1676 @@
-../../upstream/libpkgconf/pkg.c \ No newline at end of file
+/*
+ * pkg.c
+ * higher-level dependency graph compilation, management and manipulation
+ *
+ * Copyright (c) 2011, 2012, 2013 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 <libpkgconf/stdinc.h>
+#include <libpkgconf/libpkgconf.h>
+
+/*
+ * !doc
+ *
+ * libpkgconf `pkg` module
+ * =======================
+ *
+ * The `pkg` module provides dependency resolution services and the overall `.pc` file parsing
+ * routines.
+ */
+
+#ifdef _WIN32
+# define PKG_CONFIG_REG_KEY "Software\\pkgconfig\\PKG_CONFIG_PATH"
+# undef PKG_DEFAULT_PATH
+# define PKG_DEFAULT_PATH "../lib/pkgconfig;../share/pkgconfig"
+# define strncasecmp _strnicmp
+# define strcasecmp _stricmp
+#endif
+
+#define PKG_CONFIG_EXT ".pc"
+
+static inline bool
+str_has_suffix(const char *str, const char *suffix)
+{
+ size_t str_len = strlen(str);
+ size_t suf_len = strlen(suffix);
+
+ if (str_len < suf_len)
+ return false;
+
+ return !strncasecmp(str + str_len - suf_len, suffix, suf_len);
+}
+
+static char *
+pkg_get_parent_dir(pkgconf_pkg_t *pkg)
+{
+ char buf[PKGCONF_ITEM_SIZE], *pathbuf;
+
+ pkgconf_strlcpy(buf, pkg->filename, sizeof buf);
+ pathbuf = strrchr(buf, PKG_DIR_SEP_S);
+ if (pathbuf == NULL)
+ pathbuf = strrchr(buf, '/');
+ if (pathbuf != NULL)
+ pathbuf[0] = '\0';
+
+ return strdup(buf);
+}
+
+typedef void (*pkgconf_pkg_parser_keyword_func_t)(const pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const size_t lineno, const ptrdiff_t offset, const char *value);
+typedef struct {
+ const char *keyword;
+ const pkgconf_pkg_parser_keyword_func_t func;
+ const ptrdiff_t offset;
+} pkgconf_pkg_parser_keyword_pair_t;
+
+static int pkgconf_pkg_parser_keyword_pair_cmp(const void *key, const void *ptr)
+{
+ const pkgconf_pkg_parser_keyword_pair_t *pair = ptr;
+ return strcasecmp(key, pair->keyword);
+}
+
+static void
+pkgconf_pkg_parser_tuple_func(const pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const size_t lineno, const ptrdiff_t offset, const char *value)
+{
+ (void) keyword;
+ (void) lineno;
+
+ char **dest = (char **)((char *) pkg + offset);
+ *dest = pkgconf_tuple_parse(client, &pkg->vars, value);
+}
+
+static void
+pkgconf_pkg_parser_version_func(const pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const size_t lineno, const ptrdiff_t offset, const char *value)
+{
+ (void) keyword;
+ (void) lineno;
+ char *p, *i;
+ size_t len;
+ char **dest = (char **)((char *) pkg + offset);
+
+ /* cut at any detected whitespace */
+ p = pkgconf_tuple_parse(client, &pkg->vars, value);
+
+ len = strcspn(p, " \t");
+ if (len)
+ {
+ i = p + (ptrdiff_t) len;
+ *i = '\0';
+
+ pkgconf_warn(client, "%s:" SIZE_FMT_SPECIFIER ": warning: malformed version field with whitespace, trimming to [%s]\n", pkg->filename,
+ lineno, p);
+ }
+
+ *dest = p;
+}
+
+static void
+pkgconf_pkg_parser_fragment_func(const pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const size_t lineno, const ptrdiff_t offset, const char *value)
+{
+ pkgconf_list_t *dest = (pkgconf_list_t *)((char *) pkg + offset);
+ bool ret = pkgconf_fragment_parse(client, dest, &pkg->vars, value);
+
+ if (!ret)
+ {
+ pkgconf_warn(client, "%s:" SIZE_FMT_SPECIFIER ": warning: unable to parse field '%s' into an argument vector, value [%s]\n", pkg->filename,
+ lineno, keyword, value);
+ }
+}
+
+static void
+pkgconf_pkg_parser_dependency_func(const pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const size_t lineno, const ptrdiff_t offset, const char *value)
+{
+ (void) keyword;
+ (void) lineno;
+
+ pkgconf_list_t *dest = (pkgconf_list_t *)((char *) pkg + offset);
+ pkgconf_dependency_parse(client, pkg, dest, value, 0);
+}
+
+/* a variant of pkgconf_pkg_parser_dependency_func which colors the dependency node as an "internal" dependency. */
+static void
+pkgconf_pkg_parser_internal_dependency_func(const pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const size_t lineno, const ptrdiff_t offset, const char *value)
+{
+ (void) keyword;
+ (void) lineno;
+
+ pkgconf_list_t *dest = (pkgconf_list_t *)((char *) pkg + offset);
+ pkgconf_dependency_parse(client, pkg, dest, value, PKGCONF_PKG_DEPF_INTERNAL);
+}
+
+/* keep this in alphabetical order */
+static const pkgconf_pkg_parser_keyword_pair_t pkgconf_pkg_parser_keyword_funcs[] = {
+ {"CFLAGS", pkgconf_pkg_parser_fragment_func, offsetof(pkgconf_pkg_t, cflags)},
+ {"CFLAGS.private", pkgconf_pkg_parser_fragment_func, offsetof(pkgconf_pkg_t, cflags_private)},
+ {"Conflicts", pkgconf_pkg_parser_dependency_func, offsetof(pkgconf_pkg_t, conflicts)},
+ {"Description", pkgconf_pkg_parser_tuple_func, offsetof(pkgconf_pkg_t, description)},
+ {"LIBS", pkgconf_pkg_parser_fragment_func, offsetof(pkgconf_pkg_t, libs)},
+ {"LIBS.private", pkgconf_pkg_parser_fragment_func, offsetof(pkgconf_pkg_t, libs_private)},
+ {"Name", pkgconf_pkg_parser_tuple_func, offsetof(pkgconf_pkg_t, realname)},
+ {"Provides", pkgconf_pkg_parser_dependency_func, offsetof(pkgconf_pkg_t, provides)},
+ {"Requires", pkgconf_pkg_parser_dependency_func, offsetof(pkgconf_pkg_t, required)},
+ {"Requires.internal", pkgconf_pkg_parser_internal_dependency_func, offsetof(pkgconf_pkg_t, requires_private)},
+ {"Requires.private", pkgconf_pkg_parser_dependency_func, offsetof(pkgconf_pkg_t, requires_private)},
+ {"Version", pkgconf_pkg_parser_version_func, offsetof(pkgconf_pkg_t, version)},
+};
+
+static void
+pkgconf_pkg_parser_keyword_set(void *opaque, const size_t lineno, const char *keyword, const char *value)
+{
+ pkgconf_pkg_t *pkg = opaque;
+
+ const pkgconf_pkg_parser_keyword_pair_t *pair = bsearch(keyword,
+ pkgconf_pkg_parser_keyword_funcs, PKGCONF_ARRAY_SIZE(pkgconf_pkg_parser_keyword_funcs),
+ sizeof(pkgconf_pkg_parser_keyword_pair_t), pkgconf_pkg_parser_keyword_pair_cmp);
+
+ if (pair == NULL || pair->func == NULL)
+ return;
+
+ pair->func(pkg->owner, pkg, keyword, lineno, pair->offset, value);
+}
+
+static const char *
+determine_prefix(const pkgconf_pkg_t *pkg, char *buf, size_t buflen)
+{
+ char *pathiter;
+
+ pkgconf_strlcpy(buf, pkg->filename, buflen);
+ pkgconf_path_relocate(buf, buflen);
+
+ pathiter = strrchr(buf, PKG_DIR_SEP_S);
+ if (pathiter == NULL)
+ pathiter = strrchr(buf, '/');
+ if (pathiter != NULL)
+ pathiter[0] = '\0';
+
+ pathiter = strrchr(buf, PKG_DIR_SEP_S);
+ if (pathiter == NULL)
+ pathiter = strrchr(buf, '/');
+ if (pathiter == NULL)
+ return NULL;
+
+ /* parent dir is not pkgconfig, can't relocate then */
+ if (strcmp(pathiter + 1, "pkgconfig"))
+ return NULL;
+
+ /* okay, work backwards and do it again. */
+ pathiter[0] = '\0';
+ pathiter = strrchr(buf, PKG_DIR_SEP_S);
+ if (pathiter == NULL)
+ pathiter = strrchr(buf, '/');
+ if (pathiter == NULL)
+ return NULL;
+
+ pathiter[0] = '\0';
+
+ return buf;
+}
+
+static void
+remove_additional_separators(char *buf)
+{
+ char *p = buf;
+
+ while (*p) {
+ if (*p == '/') {
+ char *q;
+
+ q = ++p;
+ while (*q && *q == '/')
+ q++;
+
+ if (p != q)
+ memmove (p, q, strlen (q) + 1);
+ } else {
+ p++;
+ }
+ }
+}
+
+static void
+canonicalize_path(char *buf)
+{
+#ifdef _WIN32
+ char *p = buf;
+
+ while (*p) {
+ if (*p == '\\')
+ *p = '/';
+ p++;
+ }
+#endif
+
+ remove_additional_separators(buf);
+}
+
+static bool
+is_path_prefix_equal(const char *path1, const char *path2, size_t path2_len)
+{
+#ifdef _WIN32
+ return !_strnicmp(path1, path2, path2_len);
+#else
+ return !strncmp(path1, path2, path2_len);
+#endif
+}
+
+static void
+pkgconf_pkg_parser_value_set(void *opaque, const size_t lineno, const char *keyword, const char *value)
+{
+ char canonicalized_value[PKGCONF_ITEM_SIZE];
+ pkgconf_pkg_t *pkg = opaque;
+
+ (void) lineno;
+
+ pkgconf_strlcpy(canonicalized_value, value, sizeof canonicalized_value);
+ canonicalize_path(canonicalized_value);
+
+ /* Some pc files will use absolute paths for all of their directories
+ * which is broken when redefining the prefix. We try to outsmart the
+ * file and rewrite any directory that starts with the same prefix.
+ */
+ if (pkg->owner->flags & PKGCONF_PKG_PKGF_REDEFINE_PREFIX && pkg->orig_prefix
+ && is_path_prefix_equal(canonicalized_value, pkg->orig_prefix->value, strlen(pkg->orig_prefix->value)))
+ {
+ char newvalue[PKGCONF_ITEM_SIZE];
+
+ pkgconf_strlcpy(newvalue, pkg->prefix->value, sizeof newvalue);
+ pkgconf_strlcat(newvalue, canonicalized_value + strlen(pkg->orig_prefix->value), sizeof newvalue);
+ pkgconf_tuple_add(pkg->owner, &pkg->vars, keyword, newvalue, false);
+ }
+ else if (strcmp(keyword, pkg->owner->prefix_varname) || !(pkg->owner->flags & PKGCONF_PKG_PKGF_REDEFINE_PREFIX))
+ pkgconf_tuple_add(pkg->owner, &pkg->vars, keyword, value, true);
+ else
+ {
+ char pathbuf[PKGCONF_ITEM_SIZE];
+ const char *relvalue = determine_prefix(pkg, pathbuf, sizeof pathbuf);
+
+ if (relvalue != NULL)
+ {
+ pkg->orig_prefix = pkgconf_tuple_add(pkg->owner, &pkg->vars, "orig_prefix", canonicalized_value, true);
+ pkg->prefix = pkgconf_tuple_add(pkg->owner, &pkg->vars, keyword, relvalue, false);
+ }
+ else
+ pkgconf_tuple_add(pkg->owner, &pkg->vars, keyword, value, true);
+ }
+}
+
+typedef struct {
+ const char *field;
+ const ptrdiff_t offset;
+} pkgconf_pkg_validity_check_t;
+
+static const pkgconf_pkg_validity_check_t pkgconf_pkg_validations[] = {
+ {"Name", offsetof(pkgconf_pkg_t, realname)},
+ {"Description", offsetof(pkgconf_pkg_t, description)},
+ {"Version", offsetof(pkgconf_pkg_t, version)},
+};
+
+static const pkgconf_parser_operand_func_t pkg_parser_funcs[256] = {
+ [':'] = pkgconf_pkg_parser_keyword_set,
+ ['='] = pkgconf_pkg_parser_value_set
+};
+
+static void pkg_warn_func(pkgconf_pkg_t *pkg, const char *fmt, ...) PRINTFLIKE(2, 3);
+
+static void
+pkg_warn_func(pkgconf_pkg_t *pkg, const char *fmt, ...)
+{
+ char buf[PKGCONF_ITEM_SIZE];
+ va_list va;
+
+ va_start(va, fmt);
+ vsnprintf(buf, sizeof buf, fmt, va);
+ va_end(va);
+
+ pkgconf_warn(pkg->owner, "%s", buf);
+}
+
+static bool
+pkgconf_pkg_validate(const pkgconf_client_t *client, const pkgconf_pkg_t *pkg)
+{
+ size_t i;
+ bool valid = true;
+
+ for (i = 0; i < PKGCONF_ARRAY_SIZE(pkgconf_pkg_validations); i++)
+ {
+ char **p = (char **)((char *) pkg + pkgconf_pkg_validations[i].offset);
+
+ if (*p != NULL)
+ continue;
+
+ pkgconf_warn(client, "%s: warning: file does not declare a `%s' field\n", pkg->filename, pkgconf_pkg_validations[i].field);
+ valid = false;
+ }
+
+ return valid;
+}
+
+/*
+ * !doc
+ *
+ * .. c:function:: pkgconf_pkg_t *pkgconf_pkg_new_from_file(const pkgconf_client_t *client, const char *filename, FILE *f)
+ *
+ * Parse a .pc file into a pkgconf_pkg_t object structure.
+ *
+ * :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
+ * :param char* filename: The filename of the package file (including full path).
+ * :param FILE* f: The file object to read from.
+ * :returns: A ``pkgconf_pkg_t`` object which contains the package data.
+ * :rtype: pkgconf_pkg_t *
+ */
+pkgconf_pkg_t *
+pkgconf_pkg_new_from_file(pkgconf_client_t *client, const char *filename, FILE *f)
+{
+ pkgconf_pkg_t *pkg;
+ char *idptr;
+
+ pkg = calloc(sizeof(pkgconf_pkg_t), 1);
+ pkg->owner = client;
+ pkg->filename = strdup(filename);
+ pkg->pc_filedir = pkg_get_parent_dir(pkg);
+ pkgconf_tuple_add(client, &pkg->vars, "pcfiledir", pkg->pc_filedir, true);
+
+ /* make module id */
+ if ((idptr = strrchr(pkg->filename, PKG_DIR_SEP_S)) != NULL)
+ idptr++;
+ else
+ idptr = pkg->filename;
+
+#ifdef _WIN32
+ /* On Windows, both \ and / are allowed in paths, so we have to chop both.
+ * strrchr() took us to the last \ in that case, so we just have to see if
+ * it is followed by a /. If so, lop it off.
+ */
+ char *mungeptr;
+ if ((mungeptr = strrchr(idptr, '/')) != NULL)
+ idptr = ++mungeptr;
+#endif
+
+ pkg->id = strdup(idptr);
+ idptr = strrchr(pkg->id, '.');
+ if (idptr)
+ *idptr = '\0';
+
+ pkgconf_parser_parse(f, pkg, pkg_parser_funcs, (pkgconf_parser_warn_func_t) pkg_warn_func, pkg->filename);
+
+ if (!pkgconf_pkg_validate(client, pkg))
+ {
+ pkgconf_warn(client, "%s: warning: skipping invalid file\n", pkg->filename);
+ pkgconf_pkg_free(client, pkg);
+ return NULL;
+ }
+
+ pkgconf_dependency_add(client, &pkg->provides, pkg->id, pkg->version, PKGCONF_CMP_EQUAL, 0);
+
+ return pkgconf_pkg_ref(client, pkg);
+}
+
+/*
+ * !doc
+ *
+ * .. c:function:: void pkgconf_pkg_free(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
+ *
+ * Releases all releases for a given ``pkgconf_pkg_t`` object.
+ *
+ * :param pkgconf_client_t* client: The client which owns the ``pkgconf_pkg_t`` object, `pkg`.
+ * :param pkgconf_pkg_t* pkg: The package to free.
+ * :return: nothing
+ */
+void
+pkgconf_pkg_free(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
+{
+ if (pkg == NULL)
+ return;
+
+ if (pkg->flags & PKGCONF_PKG_PROPF_STATIC && !(pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL))
+ return;
+
+ pkgconf_cache_remove(client, pkg);
+
+ pkgconf_dependency_free(&pkg->required);
+ pkgconf_dependency_free(&pkg->requires_private);
+ pkgconf_dependency_free(&pkg->conflicts);
+ pkgconf_dependency_free(&pkg->provides);
+
+ pkgconf_fragment_free(&pkg->cflags);
+ pkgconf_fragment_free(&pkg->cflags_private);
+ pkgconf_fragment_free(&pkg->libs);
+ pkgconf_fragment_free(&pkg->libs_private);
+
+ pkgconf_tuple_free(&pkg->vars);
+
+ if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL)
+ return;
+
+ if (pkg->id != NULL)
+ free(pkg->id);
+
+ if (pkg->filename != NULL)
+ free(pkg->filename);
+
+ if (pkg->realname != NULL)
+ free(pkg->realname);
+
+ if (pkg->version != NULL)
+ free(pkg->version);
+
+ if (pkg->description != NULL)
+ free(pkg->description);
+
+ if (pkg->url != NULL)
+ free(pkg->url);
+
+ if (pkg->pc_filedir != NULL)
+ free(pkg->pc_filedir);
+
+ free(pkg);
+}
+
+/*
+ * !doc
+ *
+ * .. c:function:: pkgconf_pkg_t *pkgconf_pkg_ref(const pkgconf_client_t *client, pkgconf_pkg_t *pkg)
+ *
+ * Adds an additional reference to the package object.
+ *
+ * :param pkgconf_client_t* client: The pkgconf client object which owns the package being referenced.
+ * :param pkgconf_pkg_t* pkg: The package object being referenced.
+ * :return: The package itself with an incremented reference count.
+ * :rtype: pkgconf_pkg_t *
+ */
+pkgconf_pkg_t *
+pkgconf_pkg_ref(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
+{
+ if (pkg->owner != NULL && pkg->owner != client)
+ PKGCONF_TRACE(client, "WTF: client %p refers to package %p owned by other client %p", client, pkg, pkg->owner);
+
+ pkg->refcount++;
+ PKGCONF_TRACE(client, "refcount@%p: %d", pkg, pkg->refcount);
+
+ return pkg;
+}
+
+/*
+ * !doc
+ *
+ * .. c:function:: void pkgconf_pkg_unref(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
+ *
+ * Releases a reference on the package object. If the reference count is 0, then also free the package.
+ *
+ * :param pkgconf_client_t* client: The pkgconf client object which owns the package being dereferenced.
+ * :param pkgconf_pkg_t* pkg: The package object being dereferenced.
+ * :return: nothing
+ */
+void
+pkgconf_pkg_unref(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
+{
+ if (pkg->owner != NULL && pkg->owner != client)
+ PKGCONF_TRACE(client, "WTF: client %p unrefs package %p owned by other client %p", client, pkg, pkg->owner);
+
+ pkg->refcount--;
+ PKGCONF_TRACE(pkg->owner, "refcount@%p: %d", pkg, pkg->refcount);
+
+ if (pkg->refcount <= 0)
+ pkgconf_pkg_free(pkg->owner, pkg);
+}
+
+static inline pkgconf_pkg_t *
+pkgconf_pkg_try_specific_path(pkgconf_client_t *client, const char *path, const char *name)
+{
+ pkgconf_pkg_t *pkg = NULL;
+ FILE *f;
+ char locbuf[PKGCONF_ITEM_SIZE];
+ char uninst_locbuf[PKGCONF_ITEM_SIZE];
+
+ PKGCONF_TRACE(client, "trying path: %s for %s", path, name);
+
+ snprintf(locbuf, sizeof locbuf, "%s%c%s" PKG_CONFIG_EXT, path, PKG_DIR_SEP_S, name);
+ snprintf(uninst_locbuf, sizeof uninst_locbuf, "%s%c%s-uninstalled" PKG_CONFIG_EXT, path, PKG_DIR_SEP_S, name);
+
+ if (!(client->flags & PKGCONF_PKG_PKGF_NO_UNINSTALLED) && (f = fopen(uninst_locbuf, "r")) != NULL)
+ {
+ PKGCONF_TRACE(client, "found (uninstalled): %s", uninst_locbuf);
+ pkg = pkgconf_pkg_new_from_file(client, uninst_locbuf, f);
+ pkg->flags |= PKGCONF_PKG_PROPF_UNINSTALLED;
+ }
+ else if ((f = fopen(locbuf, "r")) != NULL)
+ {
+ PKGCONF_TRACE(client, "found: %s", locbuf);
+ pkg = pkgconf_pkg_new_from_file(client, locbuf, f);
+ }
+
+ return pkg;
+}
+
+static pkgconf_pkg_t *
+pkgconf_pkg_scan_dir(pkgconf_client_t *client, const char *path, void *data, pkgconf_pkg_iteration_func_t func)
+{
+ DIR *dir;
+ struct dirent *dirent;
+ pkgconf_pkg_t *outpkg = NULL;
+
+ dir = opendir(path);
+ if (dir == NULL)
+ return NULL;
+
+ PKGCONF_TRACE(client, "scanning dir [%s]", path);
+
+ for (dirent = readdir(dir); dirent != NULL; dirent = readdir(dir))
+ {
+ char filebuf[PKGCONF_ITEM_SIZE];
+ pkgconf_pkg_t *pkg;
+ FILE *f;
+
+ pkgconf_strlcpy(filebuf, path, sizeof filebuf);
+ pkgconf_strlcat(filebuf, "/", sizeof filebuf);
+ pkgconf_strlcat(filebuf, dirent->d_name, sizeof filebuf);
+
+ if (!str_has_suffix(filebuf, PKG_CONFIG_EXT))
+ continue;
+
+ PKGCONF_TRACE(client, "trying file [%s]", filebuf);
+
+ f = fopen(filebuf, "r");
+ if (f == NULL)
+ continue;
+
+ pkg = pkgconf_pkg_new_from_file(client, filebuf, f);
+ if (pkg != NULL)
+ {
+ if (func(pkg, data))
+ {
+ outpkg = pkg;
+ goto out;
+ }
+
+ pkgconf_pkg_unref(client, pkg);
+ }
+ }
+
+out:
+ closedir(dir);
+ return outpkg;
+}
+
+/*
+ * !doc
+ *
+ * .. c:function:: pkgconf_pkg_t *pkgconf_scan_all(pkgconf_client_t *client, void *data, pkgconf_pkg_iteration_func_t func)
+ *
+ * Iterates over all packages found in the `package directory list`, running ``func`` on them. If ``func`` returns true,
+ * then stop iteration and return the last iterated package.
+ *
+ * :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
+ * :param void* data: An opaque pointer to data to provide the iteration function with.
+ * :param pkgconf_pkg_iteration_func_t func: A function which is called for each package to determine if the package matches,
+ * always return ``false`` to iterate over all packages.
+ * :return: A package object reference if one is found by the scan function, else ``NULL``.
+ * :rtype: pkgconf_pkg_t *
+ */
+pkgconf_pkg_t *
+pkgconf_scan_all(pkgconf_client_t *client, void *data, pkgconf_pkg_iteration_func_t func)
+{
+ pkgconf_node_t *n;
+ pkgconf_pkg_t *pkg;
+
+ PKGCONF_FOREACH_LIST_ENTRY(client->dir_list.head, n)
+ {
+ pkgconf_path_t *pnode = n->data;
+
+ PKGCONF_TRACE(client, "scanning directory: %s", pnode->path);
+
+ if ((pkg = pkgconf_pkg_scan_dir(client, pnode->path, data, func)) != NULL)
+ return pkg;
+ }
+
+ return NULL;
+}
+
+#ifdef _WIN32
+static pkgconf_pkg_t *
+pkgconf_pkg_find_in_registry_key(pkgconf_client_t *client, HKEY hkey, const char *name)
+{
+ pkgconf_pkg_t *pkg = NULL;
+
+ HKEY key;
+ int i = 0;
+
+ char buf[16384]; /* per registry limits */
+ DWORD bufsize = sizeof buf;
+ if (RegOpenKeyEx(hkey, PKG_CONFIG_REG_KEY,
+ 0, KEY_READ, &key) != ERROR_SUCCESS)
+ return NULL;
+
+ while (RegEnumValue(key, i++, buf, &bufsize, NULL, NULL, NULL, NULL)
+ == ERROR_SUCCESS)
+ {
+ char pathbuf[PKGCONF_ITEM_SIZE];
+ DWORD type;
+ DWORD pathbuflen = sizeof pathbuf;
+
+ if (RegQueryValueEx(key, buf, NULL, &type, (LPBYTE) pathbuf, &pathbuflen)
+ == ERROR_SUCCESS && type == REG_SZ)
+ {
+ pkg = pkgconf_pkg_try_specific_path(client, pathbuf, name);
+ if (pkg != NULL)
+ break;
+ }
+
+ bufsize = sizeof buf;
+ }
+
+ RegCloseKey(key);
+ return pkg;
+}
+#endif
+
+/*
+ * !doc
+ *
+ * .. c:function:: pkgconf_pkg_t *pkgconf_pkg_find(pkgconf_client_t *client, const char *name)
+ *
+ * Search for a package.
+ *
+ * :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
+ * :param char* name: The name of the package `atom` to use for searching.
+ * :return: A package object reference if the package was found, else ``NULL``.
+ * :rtype: pkgconf_pkg_t *
+ */
+pkgconf_pkg_t *
+pkgconf_pkg_find(pkgconf_client_t *client, const char *name)
+{
+ pkgconf_pkg_t *pkg = NULL;
+ pkgconf_node_t *n;
+ FILE *f;
+
+ PKGCONF_TRACE(client, "looking for: %s", name);
+
+ /* name might actually be a filename. */
+ if (str_has_suffix(name, PKG_CONFIG_EXT))
+ {
+ if ((f = fopen(name, "r")) != NULL)
+ {
+ pkgconf_pkg_t *pkg;
+
+ PKGCONF_TRACE(client, "%s is a file", name);
+
+ pkg = pkgconf_pkg_new_from_file(client, name, f);
+ if (pkg != NULL)
+ {
+ pkgconf_path_add(pkg->pc_filedir, &client->dir_list, true);
+ return pkg;
+ }
+ }
+ }
+
+ /* check builtins */
+ if ((pkg = pkgconf_builtin_pkg_get(name)) != NULL)
+ {
+ PKGCONF_TRACE(client, "%s is a builtin", name);
+ return pkg;
+ }
+
+ /* check cache */
+ if (!(client->flags & PKGCONF_PKG_PKGF_NO_CACHE))
+ {
+ if ((pkg = pkgconf_cache_lookup(client, name)) != NULL)
+ {
+ PKGCONF_TRACE(client, "%s is cached", name);
+ return pkg;
+ }
+ }
+
+ PKGCONF_FOREACH_LIST_ENTRY(client->dir_list.head, n)
+ {
+ pkgconf_path_t *pnode = n->data;
+
+ pkg = pkgconf_pkg_try_specific_path(client, pnode->path, name);
+ if (pkg != NULL)
+ goto out;
+ }
+
+#ifdef _WIN32
+ /* support getting PKG_CONFIG_PATH from registry */
+ pkg = pkgconf_pkg_find_in_registry_key(client, HKEY_CURRENT_USER, name);
+ if (!pkg)
+ pkg = pkgconf_pkg_find_in_registry_key(client, HKEY_LOCAL_MACHINE, name);
+#endif
+
+out:
+ pkgconf_cache_add(client, pkg);
+
+ return pkg;
+}
+
+/*
+ * !doc
+ *
+ * .. c:function:: int pkgconf_compare_version(const char *a, const char *b)
+ *
+ * Compare versions using RPM version comparison rules as described in the LSB.
+ *
+ * :param char* a: The first version to compare in the pair.
+ * :param char* b: The second version to compare in the pair.
+ * :return: -1 if the first version is greater, 0 if both versions are equal, 1 if the second version is greater.
+ * :rtype: int
+ */
+int
+pkgconf_compare_version(const char *a, const char *b)
+{
+ char oldch1, oldch2;
+ char buf1[PKGCONF_ITEM_SIZE], buf2[PKGCONF_ITEM_SIZE];
+ char *str1, *str2;
+ char *one, *two;
+ int ret;
+ bool isnum;
+
+ /* optimization: if version matches then it's the same version. */
+ if (a == NULL)
+ return 1;
+
+ if (b == NULL)
+ return -1;
+
+ if (!strcasecmp(a, b))
+ return 0;
+
+ pkgconf_strlcpy(buf1, a, sizeof buf1);
+ pkgconf_strlcpy(buf2, b, sizeof buf2);
+
+ one = str1 = buf1;
+ two = str2 = buf2;
+
+ while (*one || *two)
+ {
+ while (*one && !isalnum((unsigned int)*one) && *one != '~')
+ one++;
+ while (*two && !isalnum((unsigned int)*two) && *two != '~')
+ two++;
+
+ if (*one == '~' || *two == '~')
+ {
+ if (*one != '~')
+ return -1;
+ if (*two != '~')
+ return 1;
+
+ one++;
+ two++;
+ continue;
+ }
+
+ if (!(*one && *two))
+ break;
+
+ str1 = one;
+ str2 = two;
+
+ if (isdigit((unsigned int)*str1))
+ {
+ while (*str1 && isdigit((unsigned int)*str1))
+ str1++;
+
+ while (*str2 && isdigit((unsigned int)*str2))
+ str2++;
+
+ isnum = true;
+ }
+ else
+ {
+ while (*str1 && isalpha((unsigned int)*str1))
+ str1++;
+
+ while (*str2 && isalpha((unsigned int)*str2))
+ str2++;
+
+ isnum = false;
+ }
+
+ oldch1 = *str1;
+ oldch2 = *str2;
+
+ *str1 = '\0';
+ *str2 = '\0';
+
+ if (one == str1)
+ return -1;
+
+ if (two == str2)
+ return (isnum ? 1 : -1);
+
+ if (isnum)
+ {
+ int onelen, twolen;
+
+ while (*one == '0')
+ one++;
+
+ while (*two == '0')
+ two++;
+
+ onelen = strlen(one);
+ twolen = strlen(two);
+
+ if (onelen > twolen)
+ return 1;
+ else if (twolen > onelen)
+ return -1;
+ }
+
+ ret = strcmp(one, two);
+ if (ret != 0)
+ return ret < 0 ? -1 : 1;
+
+ *str1 = oldch1;
+ *str2 = oldch2;
+
+ one = str1;
+ two = str2;
+ }
+
+ if ((!*one) && (!*two))
+ return 0;
+
+ if (!*one)
+ return -1;
+
+ return 1;
+}
+
+static pkgconf_pkg_t pkg_config_virtual = {
+ .id = "pkg-config",
+ .realname = "pkg-config",
+ .description = "virtual package defining pkg-config API version supported",
+ .url = PACKAGE_BUGREPORT,
+ .version = PACKAGE_VERSION,
+ .flags = PKGCONF_PKG_PROPF_STATIC,
+ .vars = {
+ .head = &(pkgconf_node_t){
+ .next = &(pkgconf_node_t){
+ .next = &(pkgconf_node_t){
+ .data = &(pkgconf_tuple_t){
+ .key = "pc_system_libdirs",
+ .value = SYSTEM_LIBDIR,
+ }
+ },
+ .data = &(pkgconf_tuple_t){
+ .key = "pc_system_includedirs",
+ .value = SYSTEM_INCLUDEDIR,
+ }
+ },
+ .data = &(pkgconf_tuple_t){
+ .key = "pc_path",
+ .value = PKG_DEFAULT_PATH,
+ },
+ },
+ .tail = NULL,
+ }
+};
+
+static pkgconf_pkg_t pkgconf_virtual = {
+ .id = "pkgconf",
+ .realname = "pkgconf",
+ .description = "virtual package defining pkgconf API version supported",
+ .url = PACKAGE_BUGREPORT,
+ .version = PACKAGE_VERSION,
+ .flags = PKGCONF_PKG_PROPF_STATIC,
+ .vars = {
+ .head = &(pkgconf_node_t){
+ .next = &(pkgconf_node_t){
+ .next = &(pkgconf_node_t){
+ .data = &(pkgconf_tuple_t){
+ .key = "pc_system_libdirs",
+ .value = SYSTEM_LIBDIR,
+ }
+ },
+ .data = &(pkgconf_tuple_t){
+ .key = "pc_system_includedirs",
+ .value = SYSTEM_INCLUDEDIR,
+ }
+ },
+ .data = &(pkgconf_tuple_t){
+ .key = "pc_path",
+ .value = PKG_DEFAULT_PATH,
+ },
+ },
+ .tail = NULL,
+ },
+};
+
+typedef struct {
+ const char *name;
+ pkgconf_pkg_t *pkg;
+} pkgconf_builtin_pkg_pair_t;
+
+/* keep these in alphabetical order */
+static const pkgconf_builtin_pkg_pair_t pkgconf_builtin_pkg_pair_set[] = {
+ {"pkg-config", &pkg_config_virtual},
+ {"pkgconf", &pkgconf_virtual},
+};
+
+static int pkgconf_builtin_pkg_pair_cmp(const void *key, const void *ptr)
+{
+ const pkgconf_builtin_pkg_pair_t *pair = ptr;
+ return strcasecmp(key, pair->name);
+}
+
+/*
+ * !doc
+ *
+ * .. c:function:: pkgconf_pkg_t *pkgconf_builtin_pkg_get(const char *name)
+ *
+ * Looks up a built-in package. The package should not be freed or dereferenced.
+ *
+ * :param char* name: An atom corresponding to a built-in package to search for.
+ * :return: the built-in package if present, else ``NULL``.
+ * :rtype: pkgconf_pkg_t *
+ */
+pkgconf_pkg_t *
+pkgconf_builtin_pkg_get(const char *name)
+{
+ const pkgconf_builtin_pkg_pair_t *pair = bsearch(name, pkgconf_builtin_pkg_pair_set,
+ PKGCONF_ARRAY_SIZE(pkgconf_builtin_pkg_pair_set), sizeof(pkgconf_builtin_pkg_pair_t),
+ pkgconf_builtin_pkg_pair_cmp);
+
+ return (pair != NULL) ? pair->pkg : NULL;
+}
+
+typedef bool (*pkgconf_vercmp_res_func_t)(const char *a, const char *b);
+
+typedef struct {
+ const char *name;
+ pkgconf_pkg_comparator_t compare;
+} pkgconf_pkg_comparator_pair_t;
+
+static const pkgconf_pkg_comparator_pair_t pkgconf_pkg_comparator_names[] = {
+ {"!=", PKGCONF_CMP_NOT_EQUAL},
+ {"(any)", PKGCONF_CMP_ANY},
+ {"<", PKGCONF_CMP_LESS_THAN},
+ {"<=", PKGCONF_CMP_LESS_THAN_EQUAL},
+ {"=", PKGCONF_CMP_EQUAL},
+ {">", PKGCONF_CMP_GREATER_THAN},
+ {">=", PKGCONF_CMP_GREATER_THAN_EQUAL},
+};
+
+static int pkgconf_pkg_comparator_pair_namecmp(const void *key, const void *ptr)
+{
+ const pkgconf_pkg_comparator_pair_t *pair = ptr;
+ return strcmp(key, pair->name);
+}
+
+static bool pkgconf_pkg_comparator_lt(const char *a, const char *b)
+{
+ return (pkgconf_compare_version(a, b) < 0);
+}
+
+static bool pkgconf_pkg_comparator_gt(const char *a, const char *b)
+{
+ return (pkgconf_compare_version(a, b) > 0);
+}
+
+static bool pkgconf_pkg_comparator_lte(const char *a, const char *b)
+{
+ return (pkgconf_compare_version(a, b) <= 0);
+}
+
+static bool pkgconf_pkg_comparator_gte(const char *a, const char *b)
+{
+ return (pkgconf_compare_version(a, b) >= 0);
+}
+
+static bool pkgconf_pkg_comparator_eq(const char *a, const char *b)
+{
+ return (pkgconf_compare_version(a, b) == 0);
+}
+
+static bool pkgconf_pkg_comparator_ne(const char *a, const char *b)
+{
+ return (pkgconf_compare_version(a, b) != 0);
+}
+
+static bool pkgconf_pkg_comparator_any(const char *a, const char *b)
+{
+ (void) a;
+ (void) b;
+
+ return true;
+}
+
+static bool pkgconf_pkg_comparator_none(const char *a, const char *b)
+{
+ (void) a;
+ (void) b;
+
+ return false;
+}
+
+static const pkgconf_vercmp_res_func_t pkgconf_pkg_comparator_impls[] = {
+ [PKGCONF_CMP_ANY] = pkgconf_pkg_comparator_any,
+ [PKGCONF_CMP_LESS_THAN] = pkgconf_pkg_comparator_lt,
+ [PKGCONF_CMP_GREATER_THAN] = pkgconf_pkg_comparator_gt,
+ [PKGCONF_CMP_LESS_THAN_EQUAL] = pkgconf_pkg_comparator_lte,
+ [PKGCONF_CMP_GREATER_THAN_EQUAL] = pkgconf_pkg_comparator_gte,
+ [PKGCONF_CMP_EQUAL] = pkgconf_pkg_comparator_eq,
+ [PKGCONF_CMP_NOT_EQUAL] = pkgconf_pkg_comparator_ne,
+};
+
+/*
+ * !doc
+ *
+ * .. c:function:: const char *pkgconf_pkg_get_comparator(const pkgconf_dependency_t *pkgdep)
+ *
+ * Returns the comparator used in a depgraph dependency node as a string.
+ *
+ * :param pkgconf_dependency_t* pkgdep: The depgraph dependency node to return the comparator for.
+ * :return: A string matching the comparator or ``"???"``.
+ * :rtype: char *
+ */
+const char *
+pkgconf_pkg_get_comparator(const pkgconf_dependency_t *pkgdep)
+{
+ if (pkgdep->compare >= PKGCONF_ARRAY_SIZE(pkgconf_pkg_comparator_names))
+ return "???";
+
+ return pkgconf_pkg_comparator_names[pkgdep->compare].name;
+}
+
+/*
+ * !doc
+ *
+ * .. c:function:: pkgconf_pkg_comparator_t pkgconf_pkg_comparator_lookup_by_name(const char *name)
+ *
+ * Look up the appropriate comparator bytecode in the comparator set (defined
+ * in ``pkg.c``, see ``pkgconf_pkg_comparator_names`` and ``pkgconf_pkg_comparator_impls``).
+ *
+ * :param char* name: The comparator to look up by `name`.
+ * :return: The comparator bytecode if found, else ``PKGCONF_CMP_ANY``.
+ * :rtype: pkgconf_pkg_comparator_t
+ */
+pkgconf_pkg_comparator_t
+pkgconf_pkg_comparator_lookup_by_name(const char *name)
+{
+ const pkgconf_pkg_comparator_pair_t *p = bsearch(name, pkgconf_pkg_comparator_names,
+ PKGCONF_ARRAY_SIZE(pkgconf_pkg_comparator_names), sizeof(pkgconf_pkg_comparator_pair_t),
+ pkgconf_pkg_comparator_pair_namecmp);
+
+ return (p != NULL) ? p->compare : PKGCONF_CMP_ANY;
+}
+
+typedef struct {
+ pkgconf_dependency_t *pkgdep;
+} pkgconf_pkg_scan_providers_ctx_t;
+
+typedef struct {
+ const pkgconf_vercmp_res_func_t rulecmp[PKGCONF_CMP_COUNT];
+ const pkgconf_vercmp_res_func_t depcmp[PKGCONF_CMP_COUNT];
+} pkgconf_pkg_provides_vermatch_rule_t;
+
+static const pkgconf_pkg_provides_vermatch_rule_t pkgconf_pkg_provides_vermatch_rules[] = {
+ [PKGCONF_CMP_ANY] = {
+ .rulecmp = {
+ [PKGCONF_CMP_ANY] = pkgconf_pkg_comparator_none,
+ },
+ .depcmp = {
+ [PKGCONF_CMP_ANY] = pkgconf_pkg_comparator_none,
+ },
+ },
+ [PKGCONF_CMP_LESS_THAN] = {
+ .rulecmp = {
+ [PKGCONF_CMP_ANY] = pkgconf_pkg_comparator_none,
+ [PKGCONF_CMP_LESS_THAN] = pkgconf_pkg_comparator_lt,
+ [PKGCONF_CMP_GREATER_THAN] = pkgconf_pkg_comparator_gt,
+ [PKGCONF_CMP_LESS_THAN_EQUAL] = pkgconf_pkg_comparator_lte,
+ [PKGCONF_CMP_GREATER_THAN_EQUAL] = pkgconf_pkg_comparator_gte,
+ },
+ .depcmp = {
+ [PKGCONF_CMP_GREATER_THAN] = pkgconf_pkg_comparator_lt,
+ [PKGCONF_CMP_GREATER_THAN_EQUAL] = pkgconf_pkg_comparator_lt,
+ [PKGCONF_CMP_EQUAL] = pkgconf_pkg_comparator_lt,
+ [PKGCONF_CMP_NOT_EQUAL] = pkgconf_pkg_comparator_gte,
+ },
+ },
+ [PKGCONF_CMP_GREATER_THAN] = {
+ .rulecmp = {
+ [PKGCONF_CMP_ANY] = pkgconf_pkg_comparator_none,
+ [PKGCONF_CMP_LESS_THAN] = pkgconf_pkg_comparator_lt,
+ [PKGCONF_CMP_GREATER_THAN] = pkgconf_pkg_comparator_gt,
+ [PKGCONF_CMP_LESS_THAN_EQUAL] = pkgconf_pkg_comparator_lte,
+ [PKGCONF_CMP_GREATER_THAN_EQUAL] = pkgconf_pkg_comparator_gte,
+ },
+ .depcmp = {
+ [PKGCONF_CMP_LESS_THAN] = pkgconf_pkg_comparator_gt,
+ [PKGCONF_CMP_LESS_THAN_EQUAL] = pkgconf_pkg_comparator_gt,
+ [PKGCONF_CMP_EQUAL] = pkgconf_pkg_comparator_gt,
+ [PKGCONF_CMP_NOT_EQUAL] = pkgconf_pkg_comparator_lte,
+ },
+ },
+ [PKGCONF_CMP_LESS_THAN_EQUAL] = {
+ .rulecmp = {
+ [PKGCONF_CMP_ANY] = pkgconf_pkg_comparator_none,
+ [PKGCONF_CMP_LESS_THAN] = pkgconf_pkg_comparator_lt,
+ [PKGCONF_CMP_GREATER_THAN] = pkgconf_pkg_comparator_gt,
+ [PKGCONF_CMP_LESS_THAN_EQUAL] = pkgconf_pkg_comparator_lte,
+ [PKGCONF_CMP_GREATER_THAN_EQUAL] = pkgconf_pkg_comparator_gte,
+ },
+ .depcmp = {
+ [PKGCONF_CMP_GREATER_THAN] = pkgconf_pkg_comparator_lte,
+ [PKGCONF_CMP_GREATER_THAN_EQUAL] = pkgconf_pkg_comparator_lte,
+ [PKGCONF_CMP_EQUAL] = pkgconf_pkg_comparator_lte,
+ [PKGCONF_CMP_NOT_EQUAL] = pkgconf_pkg_comparator_gt,
+ },
+ },
+ [PKGCONF_CMP_GREATER_THAN_EQUAL] = {
+ .rulecmp = {
+ [PKGCONF_CMP_ANY] = pkgconf_pkg_comparator_none,
+ [PKGCONF_CMP_LESS_THAN] = pkgconf_pkg_comparator_lt,
+ [PKGCONF_CMP_GREATER_THAN] = pkgconf_pkg_comparator_gt,
+ [PKGCONF_CMP_LESS_THAN_EQUAL] = pkgconf_pkg_comparator_lte,
+ [PKGCONF_CMP_GREATER_THAN_EQUAL] = pkgconf_pkg_comparator_gte,
+ },
+ .depcmp = {
+ [PKGCONF_CMP_LESS_THAN] = pkgconf_pkg_comparator_gte,
+ [PKGCONF_CMP_LESS_THAN_EQUAL] = pkgconf_pkg_comparator_gte,
+ [PKGCONF_CMP_EQUAL] = pkgconf_pkg_comparator_gte,
+ [PKGCONF_CMP_NOT_EQUAL] = pkgconf_pkg_comparator_lt,
+ },
+ },
+ [PKGCONF_CMP_EQUAL] = {
+ .rulecmp = {
+ [PKGCONF_CMP_ANY] = pkgconf_pkg_comparator_none,
+ [PKGCONF_CMP_LESS_THAN] = pkgconf_pkg_comparator_lt,
+ [PKGCONF_CMP_GREATER_THAN] = pkgconf_pkg_comparator_gt,
+ [PKGCONF_CMP_LESS_THAN_EQUAL] = pkgconf_pkg_comparator_lte,
+ [PKGCONF_CMP_GREATER_THAN_EQUAL] = pkgconf_pkg_comparator_gte,
+ [PKGCONF_CMP_EQUAL] = pkgconf_pkg_comparator_eq,
+ [PKGCONF_CMP_NOT_EQUAL] = pkgconf_pkg_comparator_ne
+ },
+ .depcmp = {
+ [PKGCONF_CMP_ANY] = pkgconf_pkg_comparator_none,
+ },
+ },
+ [PKGCONF_CMP_NOT_EQUAL] = {
+ .rulecmp = {
+ [PKGCONF_CMP_ANY] = pkgconf_pkg_comparator_none,
+ [PKGCONF_CMP_LESS_THAN] = pkgconf_pkg_comparator_gte,
+ [PKGCONF_CMP_GREATER_THAN] = pkgconf_pkg_comparator_lte,
+ [PKGCONF_CMP_LESS_THAN_EQUAL] = pkgconf_pkg_comparator_gt,
+ [PKGCONF_CMP_GREATER_THAN_EQUAL] = pkgconf_pkg_comparator_lt,
+ [PKGCONF_CMP_EQUAL] = pkgconf_pkg_comparator_ne,
+ [PKGCONF_CMP_NOT_EQUAL] = pkgconf_pkg_comparator_eq
+ },
+ .depcmp = {
+ [PKGCONF_CMP_ANY] = pkgconf_pkg_comparator_none,
+ },
+ },
+};
+
+/*
+ * pkgconf_pkg_scan_provides_vercmp(pkgdep, provider)
+ *
+ * compare a provides node against the requested dependency node.
+ *
+ * XXX: maybe handle PKGCONF_CMP_ANY in a versioned comparison
+ */
+static bool
+pkgconf_pkg_scan_provides_vercmp(const pkgconf_dependency_t *pkgdep, const pkgconf_dependency_t *provider)
+{
+ const pkgconf_pkg_provides_vermatch_rule_t *rule = &pkgconf_pkg_provides_vermatch_rules[pkgdep->compare];
+
+ if (rule->depcmp[provider->compare] != NULL &&
+ !rule->depcmp[provider->compare](provider->version, pkgdep->version))
+ return false;
+
+ if (rule->rulecmp[provider->compare] != NULL &&
+ !rule->rulecmp[provider->compare](pkgdep->version, provider->version))
+ return false;
+
+ return true;
+}
+
+/*
+ * pkgconf_pkg_scan_provides_entry(pkg, ctx)
+ *
+ * attempt to match a single package's Provides rules against the requested dependency node.
+ */
+static bool
+pkgconf_pkg_scan_provides_entry(const pkgconf_pkg_t *pkg, const pkgconf_pkg_scan_providers_ctx_t *ctx)
+{
+ const pkgconf_dependency_t *pkgdep = ctx->pkgdep;
+ pkgconf_node_t *node;
+
+ PKGCONF_FOREACH_LIST_ENTRY(pkg->provides.head, node)
+ {
+ const pkgconf_dependency_t *provider = node->data;
+ if (!strcmp(provider->package, pkgdep->package))
+ return pkgconf_pkg_scan_provides_vercmp(pkgdep, provider);
+ }
+
+ return false;
+}
+
+/*
+ * pkgconf_pkg_scan_providers(client, pkgdep, eflags)
+ *
+ * scan all available packages to see if a Provides rule matches the pkgdep.
+ */
+static pkgconf_pkg_t *
+pkgconf_pkg_scan_providers(pkgconf_client_t *client, pkgconf_dependency_t *pkgdep, unsigned int *eflags)
+{
+ pkgconf_pkg_t *pkg;
+ pkgconf_pkg_scan_providers_ctx_t ctx = {
+ .pkgdep = pkgdep,
+ };
+
+ pkg = pkgconf_scan_all(client, &ctx, (pkgconf_pkg_iteration_func_t) pkgconf_pkg_scan_provides_entry);
+ if (pkg != NULL)
+ {
+ pkgdep->match = pkgconf_pkg_ref(client, pkg);
+ return pkg;
+ }
+
+ if (eflags != NULL)
+ *eflags |= PKGCONF_PKG_ERRF_PACKAGE_NOT_FOUND;
+
+ return NULL;
+}
+
+/*
+ * !doc
+ *
+ * .. c:function:: pkgconf_pkg_t *pkgconf_pkg_verify_dependency(pkgconf_client_t *client, pkgconf_dependency_t *pkgdep, unsigned int *eflags)
+ *
+ * Verify a pkgconf_dependency_t node in the depgraph. If the dependency is solvable,
+ * return the appropriate ``pkgconf_pkg_t`` object, else ``NULL``.
+ *
+ * :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
+ * :param pkgconf_dependency_t* pkgdep: The dependency graph node to solve.
+ * :param uint* eflags: An optional pointer that, if set, will be populated with an error code from the resolver.
+ * :return: On success, the appropriate ``pkgconf_pkg_t`` object to solve the dependency, else ``NULL``.
+ * :rtype: pkgconf_pkg_t *
+ */
+pkgconf_pkg_t *
+pkgconf_pkg_verify_dependency(pkgconf_client_t *client, pkgconf_dependency_t *pkgdep, unsigned int *eflags)
+{
+ pkgconf_pkg_t *pkg = NULL;
+
+ if (eflags != NULL)
+ *eflags = PKGCONF_PKG_ERRF_OK;
+
+ PKGCONF_TRACE(client, "trying to verify dependency: %s", pkgdep->package);
+
+ if (pkgdep->match != NULL)
+ {
+ PKGCONF_TRACE(client, "cached dependency: %s -> %s@%p", pkgdep->package, pkgdep->match->id, pkgdep->match);
+ return pkgconf_pkg_ref(client, pkgdep->match);
+ }
+
+ pkg = pkgconf_pkg_find(client, pkgdep->package);
+ if (pkg == NULL)
+ {
+ if (client->flags & PKGCONF_PKG_PKGF_SKIP_PROVIDES)
+ {
+ if (eflags != NULL)
+ *eflags |= PKGCONF_PKG_ERRF_PACKAGE_NOT_FOUND;
+
+ return NULL;
+ }
+
+ return pkgconf_pkg_scan_providers(client, pkgdep, eflags);
+ }
+
+ if (pkg->id == NULL)
+ pkg->id = strdup(pkgdep->package);
+
+ if (pkgconf_pkg_comparator_impls[pkgdep->compare](pkg->version, pkgdep->version) != true)
+ {
+ if (eflags != NULL)
+ *eflags |= PKGCONF_PKG_ERRF_PACKAGE_VER_MISMATCH;
+ }
+ else
+ pkgdep->match = pkgconf_pkg_ref(client, pkg);
+
+ return pkg;
+}
+
+/*
+ * !doc
+ *
+ * .. c:function:: unsigned int pkgconf_pkg_verify_graph(pkgconf_client_t *client, pkgconf_pkg_t *root, int depth)
+ *
+ * Verify the graph dependency nodes are satisfiable by walking the tree using
+ * ``pkgconf_pkg_traverse()``.
+ *
+ * :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
+ * :param pkgconf_pkg_t* root: The root entry in the package dependency graph which should contain the top-level dependencies to resolve.
+ * :param int depth: The maximum allowed depth for dependency resolution.
+ * :return: On success, ``PKGCONF_PKG_ERRF_OK`` (0), else an error code.
+ * :rtype: unsigned int
+ */
+unsigned int
+pkgconf_pkg_verify_graph(pkgconf_client_t *client, pkgconf_pkg_t *root, int depth)
+{
+ return pkgconf_pkg_traverse(client, root, NULL, NULL, depth, 0);
+}
+
+static unsigned int
+pkgconf_pkg_report_graph_error(pkgconf_client_t *client, pkgconf_pkg_t *parent, pkgconf_pkg_t *pkg, pkgconf_dependency_t *node, unsigned int eflags)
+{
+ if (eflags & PKGCONF_PKG_ERRF_PACKAGE_NOT_FOUND)
+ {
+ if (!(client->flags & PKGCONF_PKG_PKGF_SIMPLIFY_ERRORS) & !client->already_sent_notice)
+ {
+ pkgconf_error(client, "Package %s was not found in the pkg-config search path.\n", node->package);
+ pkgconf_error(client, "Perhaps you should add the directory containing `%s.pc'\n", node->package);
+ pkgconf_error(client, "to the PKG_CONFIG_PATH environment variable\n");
+ client->already_sent_notice = true;
+ }
+
+ pkgconf_error(client, "Package '%s', required by '%s', not found\n", node->package, parent->id);
+ pkgconf_audit_log(client, "%s NOT-FOUND\n", node->package);
+ }
+ else if (eflags & PKGCONF_PKG_ERRF_PACKAGE_VER_MISMATCH)
+ {
+ pkgconf_error(client, "Package dependency requirement '%s %s %s' could not be satisfied.\n",
+ node->package, pkgconf_pkg_get_comparator(node), node->version);
+
+ if (pkg != NULL)
+ pkgconf_error(client, "Package '%s' has version '%s', required version is '%s %s'\n",
+ node->package, pkg->version, pkgconf_pkg_get_comparator(node), node->version);
+ }
+
+ if (pkg != NULL)
+ pkgconf_pkg_unref(client, pkg);
+
+ return eflags;
+}
+
+static inline unsigned int
+pkgconf_pkg_walk_list(pkgconf_client_t *client,
+ pkgconf_pkg_t *parent,
+ pkgconf_list_t *deplist,
+ pkgconf_pkg_traverse_func_t func,
+ void *data,
+ int depth,
+ unsigned int skip_flags)
+{
+ unsigned int eflags = PKGCONF_PKG_ERRF_OK;
+ pkgconf_node_t *node;
+
+ PKGCONF_FOREACH_LIST_ENTRY(deplist->head, node)
+ {
+ unsigned int eflags_local = PKGCONF_PKG_ERRF_OK;
+ pkgconf_dependency_t *depnode = node->data;
+ pkgconf_pkg_t *pkgdep;
+
+ if (*depnode->package == '\0')
+ continue;
+
+ pkgdep = pkgconf_pkg_verify_dependency(client, depnode, &eflags_local);
+
+ eflags |= eflags_local;
+ if (eflags_local != PKGCONF_PKG_ERRF_OK && !(client->flags & PKGCONF_PKG_PKGF_SKIP_ERRORS))
+ {
+ pkgconf_pkg_report_graph_error(client, parent, pkgdep, depnode, eflags_local);
+ continue;
+ }
+ if (pkgdep == NULL)
+ continue;
+
+ if (pkgdep->flags & PKGCONF_PKG_PROPF_SEEN)
+ {
+ pkgconf_pkg_unref(client, pkgdep);
+ continue;
+ }
+
+ if (skip_flags && (depnode->flags & skip_flags) == skip_flags)
+ {
+ pkgconf_pkg_unref(client, pkgdep);
+ continue;
+ }
+
+ pkgconf_audit_log_dependency(client, pkgdep, depnode);
+
+ pkgdep->flags |= PKGCONF_PKG_PROPF_SEEN;
+ eflags |= pkgconf_pkg_traverse(client, pkgdep, func, data, depth - 1, skip_flags);
+ pkgdep->flags &= ~PKGCONF_PKG_PROPF_SEEN;
+ pkgconf_pkg_unref(client, pkgdep);
+ }
+
+ return eflags;
+}
+
+static inline unsigned int
+pkgconf_pkg_walk_conflicts_list(pkgconf_client_t *client,
+ pkgconf_pkg_t *root, pkgconf_list_t *deplist)
+{
+ unsigned int eflags;
+ pkgconf_node_t *node, *childnode;
+
+ PKGCONF_FOREACH_LIST_ENTRY(deplist->head, node)
+ {
+ pkgconf_dependency_t *parentnode = node->data;
+
+ if (*parentnode->package == '\0')
+ continue;
+
+ PKGCONF_FOREACH_LIST_ENTRY(root->required.head, childnode)
+ {
+ pkgconf_pkg_t *pkgdep;
+ pkgconf_dependency_t *depnode = childnode->data;
+
+ if (*depnode->package == '\0' || strcmp(depnode->package, parentnode->package))
+ continue;
+
+ pkgdep = pkgconf_pkg_verify_dependency(client, parentnode, &eflags);
+ if (eflags == PKGCONF_PKG_ERRF_OK)
+ {
+ pkgconf_error(client, "Version '%s' of '%s' conflicts with '%s' due to satisfying conflict rule '%s %s%s%s'.\n",
+ pkgdep->version, pkgdep->realname, root->realname, parentnode->package, pkgconf_pkg_get_comparator(parentnode),
+ parentnode->version != NULL ? " " : "", parentnode->version != NULL ? parentnode->version : "");
+
+ if (!(client->flags & PKGCONF_PKG_PKGF_SIMPLIFY_ERRORS))
+ {
+ pkgconf_error(client, "It may be possible to ignore this conflict and continue, try the\n");
+ pkgconf_error(client, "PKG_CONFIG_IGNORE_CONFLICTS environment variable.\n");
+ }
+
+ pkgconf_pkg_unref(client, pkgdep);
+
+ return PKGCONF_PKG_ERRF_PACKAGE_CONFLICT;
+ }
+
+ pkgconf_pkg_unref(client, pkgdep);
+ }
+ }
+
+ return PKGCONF_PKG_ERRF_OK;
+}
+
+/*
+ * !doc
+ *
+ * .. c:function:: unsigned int pkgconf_pkg_traverse(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_pkg_traverse_func_t func, void *data, int maxdepth, unsigned int skip_flags)
+ *
+ * Walk and resolve the dependency graph up to `maxdepth` levels.
+ *
+ * :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
+ * :param pkgconf_pkg_t* root: The root of the dependency graph.
+ * :param pkgconf_pkg_traverse_func_t func: A traversal function to call for each resolved node in the dependency graph.
+ * :param void* data: An opaque pointer to data to be passed to the traversal function.
+ * :param int maxdepth: The maximum depth to walk the dependency graph for. -1 means infinite recursion.
+ * :param uint skip_flags: Skip over dependency nodes containing the specified flags. A setting of 0 skips no dependency nodes.
+ * :return: ``PKGCONF_PKG_ERRF_OK`` on success, else an error code.
+ * :rtype: unsigned int
+ */
+unsigned int
+pkgconf_pkg_traverse(pkgconf_client_t *client,
+ pkgconf_pkg_t *root,
+ pkgconf_pkg_traverse_func_t func,
+ void *data,
+ int maxdepth,
+ unsigned int skip_flags)
+{
+ unsigned int eflags = PKGCONF_PKG_ERRF_OK;
+
+ if (maxdepth == 0)
+ return eflags;
+
+ PKGCONF_TRACE(client, "%s: level %d", root->id, maxdepth);
+
+ if ((root->flags & PKGCONF_PKG_PROPF_VIRTUAL) != PKGCONF_PKG_PROPF_VIRTUAL || (client->flags & PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL) != PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL)
+ {
+ if (func != NULL)
+ func(client, root, data);
+ }
+
+ if (!(client->flags & PKGCONF_PKG_PKGF_SKIP_CONFLICTS))
+ {
+ eflags = pkgconf_pkg_walk_conflicts_list(client, root, &root->conflicts);
+ if (eflags != PKGCONF_PKG_ERRF_OK)
+ return eflags;
+ }
+
+ PKGCONF_TRACE(client, "%s: walking requires list", root->id);
+ eflags = pkgconf_pkg_walk_list(client, root, &root->required, func, data, maxdepth, skip_flags);
+ if (eflags != PKGCONF_PKG_ERRF_OK)
+ return eflags;
+
+ if (client->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE)
+ {
+ PKGCONF_TRACE(client, "%s: walking requires.private list", root->id);
+
+ /* XXX: ugly */
+ client->flags |= PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE;
+ eflags = pkgconf_pkg_walk_list(client, root, &root->requires_private, func, data, maxdepth, skip_flags);
+ client->flags &= ~PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE;
+
+ if (eflags != PKGCONF_PKG_ERRF_OK)
+ return eflags;
+ }
+
+ return eflags;
+}
+
+static void
+pkgconf_pkg_cflags_collect(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data)
+{
+ pkgconf_list_t *list = data;
+ pkgconf_node_t *node;
+
+ PKGCONF_FOREACH_LIST_ENTRY(pkg->cflags.head, node)
+ {
+ pkgconf_fragment_t *frag = node->data;
+ pkgconf_fragment_copy(client, list, frag, false);
+ }
+}
+
+static void
+pkgconf_pkg_cflags_private_collect(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data)
+{
+ pkgconf_list_t *list = data;
+ pkgconf_node_t *node;
+
+ PKGCONF_FOREACH_LIST_ENTRY(pkg->cflags_private.head, node)
+ {
+ pkgconf_fragment_t *frag = node->data;
+ pkgconf_fragment_copy(client, list, frag, true);
+ }
+}
+
+/*
+ * !doc
+ *
+ * .. c:function:: int pkgconf_pkg_cflags(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_list_t *list, int maxdepth)
+ *
+ * Walks a dependency graph and extracts relevant ``CFLAGS`` fragments.
+ *
+ * :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
+ * :param pkgconf_pkg_t* root: The root of the dependency graph.
+ * :param pkgconf_list_t* list: The fragment list to add the extracted ``CFLAGS`` fragments to.
+ * :param int maxdepth: The maximum allowed depth for dependency resolution. -1 means infinite recursion.
+ * :return: ``PKGCONF_PKG_ERRF_OK`` if successful, otherwise an error code.
+ * :rtype: unsigned int
+ */
+unsigned int
+pkgconf_pkg_cflags(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_list_t *list, int maxdepth)
+{
+ unsigned int eflag;
+ unsigned int skip_flags = (client->flags & PKGCONF_PKG_PKGF_DONT_FILTER_INTERNAL_CFLAGS) == 0 ? PKGCONF_PKG_DEPF_INTERNAL : 0;
+ pkgconf_list_t frags = PKGCONF_LIST_INITIALIZER;
+
+ eflag = pkgconf_pkg_traverse(client, root, pkgconf_pkg_cflags_collect, &frags, maxdepth, skip_flags);
+
+ if (eflag == PKGCONF_PKG_ERRF_OK && client->flags & PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS)
+ eflag = pkgconf_pkg_traverse(client, root, pkgconf_pkg_cflags_private_collect, &frags, maxdepth, skip_flags);
+
+ if (eflag != PKGCONF_PKG_ERRF_OK)
+ {
+ pkgconf_fragment_free(&frags);
+ return eflag;
+ }
+
+ pkgconf_fragment_copy_list(client, list, &frags);
+ pkgconf_fragment_free(&frags);
+
+ return eflag;
+}
+
+static void
+pkgconf_pkg_libs_collect(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data)
+{
+ pkgconf_list_t *list = data;
+ pkgconf_node_t *node;
+
+ PKGCONF_FOREACH_LIST_ENTRY(pkg->libs.head, node)
+ {
+ pkgconf_fragment_t *frag = node->data;
+ pkgconf_fragment_copy(client, list, frag, (client->flags & PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE) != 0);
+ }
+
+ if (client->flags & PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS)
+ {
+ PKGCONF_FOREACH_LIST_ENTRY(pkg->libs_private.head, node)
+ {
+ pkgconf_fragment_t *frag = node->data;
+ pkgconf_fragment_copy(client, list, frag, true);
+ }
+ }
+}
+
+/*
+ * !doc
+ *
+ * .. c:function:: int pkgconf_pkg_libs(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_list_t *list, int maxdepth)
+ *
+ * Walks a dependency graph and extracts relevant ``LIBS`` fragments.
+ *
+ * :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
+ * :param pkgconf_pkg_t* root: The root of the dependency graph.
+ * :param pkgconf_list_t* list: The fragment list to add the extracted ``LIBS`` fragments to.
+ * :param int maxdepth: The maximum allowed depth for dependency resolution. -1 means infinite recursion.
+ * :return: ``PKGCONF_PKG_ERRF_OK`` if successful, otherwise an error code.
+ * :rtype: unsigned int
+ */
+unsigned int
+pkgconf_pkg_libs(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_list_t *list, int maxdepth)
+{
+ unsigned int eflag;
+
+ eflag = pkgconf_pkg_traverse(client, root, pkgconf_pkg_libs_collect, list, maxdepth, 0);
+
+ if (eflag != PKGCONF_PKG_ERRF_OK)
+ {
+ pkgconf_fragment_free(list);
+ return eflag;
+ }
+
+ return eflag;
+}
diff --git a/libpkgconf/libpkgconf/pkg.c.orig b/libpkgconf/libpkgconf/pkg.c.orig
new file mode 120000
index 0000000..ea9e3fd
--- /dev/null
+++ b/libpkgconf/libpkgconf/pkg.c.orig
@@ -0,0 +1 @@
+../../upstream/libpkgconf/pkg.c \ No newline at end of file
diff --git a/libpkgconf/manifest b/libpkgconf/manifest
index 6099c0f..d40c3fe 100644
--- a/libpkgconf/manifest
+++ b/libpkgconf/manifest
@@ -1,6 +1,6 @@
: 1
name: libpkgconf
-version: 1.6.3+3
+version: 1.7.3-a.0.z
project: pkgconf
summary: C library for retriving pkg-config compiler and linker flags
license: ISC, MIT ; ISC for the most of original files.
diff --git a/upstream b/upstream
-Subproject c862e030cf83447f679e4f49876f5298f0fc969
+Subproject aca0674837cb6df1b29faddb8afe6b2f39733f6