From 298fa0ef5ba39445f960ab056c0d102ae8af91c5 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 17 Oct 2017 08:58:13 +0300 Subject: Merge with latest original package version (master branch) --- libpkgconf/dependency.c.orig | 309 --------------------- libpkgconf/fragment.c | 10 - libpkgconf/fragment.c.orig | 647 ------------------------------------------- libpkgconf/path.c | 17 +- libpkgconf/path.c.orig | 327 ---------------------- libpkgconf/pkg.c.orig | 20 +- libpkgconf/stdinc.h | 25 -- libpkgconf/stdinc.h.orig | 59 ---- libpkgconf/tuple.c.orig | 349 ----------------------- 9 files changed, 19 insertions(+), 1744 deletions(-) delete mode 100644 libpkgconf/dependency.c.orig delete mode 100644 libpkgconf/fragment.c.orig delete mode 100644 libpkgconf/path.c.orig delete mode 100644 libpkgconf/stdinc.h.orig delete mode 100644 libpkgconf/tuple.c.orig diff --git a/libpkgconf/dependency.c.orig b/libpkgconf/dependency.c.orig deleted file mode 100644 index 3078102..0000000 --- a/libpkgconf/dependency.c.orig +++ /dev/null @@ -1,309 +0,0 @@ -/* - * dependency.c - * dependency parsing and management - * - * 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 -#include - -/* - * !doc - * - * libpkgconf `dependency` module - * ============================== - * - * The `dependency` module provides support for building `dependency lists` (the basic component of the overall `dependency graph`) and - * `dependency nodes` which store dependency information. - */ - -typedef enum { - OUTSIDE_MODULE = 0, - INSIDE_MODULE_NAME = 1, - BEFORE_OPERATOR = 2, - INSIDE_OPERATOR = 3, - AFTER_OPERATOR = 4, - INSIDE_VERSION = 5 -} parse_state_t; - -#define DEBUG_PARSE 0 - -static const char * -dependency_to_str(const pkgconf_dependency_t *dep, char *buf, size_t buflen) -{ - pkgconf_strlcpy(buf, dep->package, buflen); - if (dep->version != NULL) - { - pkgconf_strlcat(buf, " ", buflen); - pkgconf_strlcat(buf, pkgconf_pkg_get_comparator(dep), buflen); - pkgconf_strlcat(buf, " ", buflen); - pkgconf_strlcat(buf, dep->version, buflen); - } - - return buf; -} - -static inline pkgconf_dependency_t * -pkgconf_dependency_addraw(const pkgconf_client_t *client, pkgconf_list_t *list, const char *package, size_t package_sz, const char *version, size_t version_sz, pkgconf_pkg_comparator_t compare) -{ - pkgconf_dependency_t *dep; - char depbuf[PKGCONF_BUFSIZE]; - - dep = calloc(sizeof(pkgconf_dependency_t), 1); - dep->package = pkgconf_strndup(package, package_sz); - - if (version_sz != 0) - dep->version = pkgconf_strndup(version, version_sz); - - dep->compare = compare; - - PKGCONF_TRACE(client, "added dependency [%s] to list @%p", dependency_to_str(dep, depbuf, sizeof depbuf), list); - pkgconf_node_insert_tail(&dep->iter, dep, list); - - return dep; -} - -/* - * !doc - * - * .. c:function:: pkgconf_dependency_t *pkgconf_dependency_add(pkgconf_list_t *list, const char *package, const char *version, pkgconf_pkg_comparator_t compare) - * - * Adds a parsed dependency to a dependency list as a dependency node. - * - * :param pkgconf_client_t* client: The client object that owns the package this dependency list belongs to. - * :param pkgconf_list_t* list: The dependency list to add a dependency node to. - * :param char* package: The package `atom` to set on the dependency node. - * :param char* version: The package `version` to set on the dependency node. - * :param pkgconf_pkg_comparator_t compare: The comparison operator to set on the dependency node. - * :return: A dependency node. - * :rtype: pkgconf_dependency_t * - */ -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) -{ - if (version != NULL) - return pkgconf_dependency_addraw(client, list, package, strlen(package), version, strlen(version), compare); - - return pkgconf_dependency_addraw(client, list, package, strlen(package), NULL, 0, compare); -} - -/* - * !doc - * - * .. c:function:: void pkgconf_dependency_append(pkgconf_list_t *list, pkgconf_dependency_t *tail) - * - * Adds a dependency node to a pre-existing dependency list. - * - * :param pkgconf_list_t* list: The dependency list to add a dependency node to. - * :param pkgconf_dependency_t* tail: The dependency node to add to the tail of the dependency list. - * :return: nothing - */ -void -pkgconf_dependency_append(pkgconf_list_t *list, pkgconf_dependency_t *tail) -{ - pkgconf_node_insert_tail(&tail->iter, tail, list); -} - -/* - * !doc - * - * .. c:function:: void pkgconf_dependency_free(pkgconf_list_t *list) - * - * Release a dependency list and it's child dependency nodes. - * - * :param pkgconf_list_t* list: The dependency list to release. - * :return: nothing - */ -void -pkgconf_dependency_free(pkgconf_list_t *list) -{ - pkgconf_node_t *node, *next; - - PKGCONF_FOREACH_LIST_ENTRY_SAFE(list->head, next, node) - { - pkgconf_dependency_t *dep = node->data; - - if (dep->package != NULL) - free(dep->package); - - if (dep->version != NULL) - free(dep->version); - - free(dep); - } -} - -/* - * !doc - * - * .. c:function:: void pkgconf_dependency_parse_str(pkgconf_list_t *deplist_head, const char *depends) - * - * Parse a dependency declaration into a dependency list. - * Commas are counted as whitespace to allow for constructs such as ``@SUBSTVAR@, zlib`` being processed - * into ``, zlib``. - * - * :param pkgconf_client_t* client: The client object that owns the package this dependency list belongs to. - * :param pkgconf_list_t* deplist_head: The dependency list to populate with dependency nodes. - * :param char* depends: The dependency data to parse. - * :return: nothing - */ -void -pkgconf_dependency_parse_str(const pkgconf_client_t *client, pkgconf_list_t *deplist_head, const char *depends) -{ - parse_state_t state = OUTSIDE_MODULE; - pkgconf_pkg_comparator_t compare = PKGCONF_CMP_ANY; - char cmpname[PKGCONF_BUFSIZE]; - char buf[PKGCONF_BUFSIZE]; - size_t package_sz = 0, version_sz = 0; - char *start = buf; - char *ptr = buf; - char *vstart = NULL; - char *package = NULL, *version = NULL; - char *cnameptr = cmpname; - - memset(cmpname, '\0', sizeof cmpname); - - pkgconf_strlcpy(buf, depends, sizeof buf); - pkgconf_strlcat(buf, " ", sizeof buf); - - while (*ptr) - { - switch (state) - { - case OUTSIDE_MODULE: - if (!PKGCONF_IS_MODULE_SEPARATOR(*ptr)) - state = INSIDE_MODULE_NAME; - - break; - - case INSIDE_MODULE_NAME: - if (isspace((unsigned int)*ptr)) - { - const char *sptr = ptr; - - while (*sptr && isspace((unsigned int)*sptr)) - sptr++; - - if (*sptr == '\0') - state = OUTSIDE_MODULE; - else if (PKGCONF_IS_MODULE_SEPARATOR(*sptr)) - state = OUTSIDE_MODULE; - else if (PKGCONF_IS_OPERATOR_CHAR(*sptr)) - state = BEFORE_OPERATOR; - else - state = OUTSIDE_MODULE; - } - else if (PKGCONF_IS_MODULE_SEPARATOR(*ptr)) - state = OUTSIDE_MODULE; - else if (*(ptr + 1) == '\0') - { - ptr++; - state = OUTSIDE_MODULE; - } - - if (state != INSIDE_MODULE_NAME && start != ptr) - { - char *iter = start; - - while (PKGCONF_IS_MODULE_SEPARATOR(*iter)) - iter++; - - package = iter; - package_sz = ptr - iter; - start = ptr; - } - - if (state == OUTSIDE_MODULE) - { - pkgconf_dependency_addraw(client, deplist_head, package, package_sz, NULL, 0, compare); - - compare = PKGCONF_CMP_ANY; - package_sz = 0; - } - - break; - - case BEFORE_OPERATOR: - if (PKGCONF_IS_OPERATOR_CHAR(*ptr)) - { - state = INSIDE_OPERATOR; - *cnameptr++ = *ptr; - } - - break; - - case INSIDE_OPERATOR: - if (!PKGCONF_IS_OPERATOR_CHAR(*ptr)) - { - state = AFTER_OPERATOR; - compare = pkgconf_pkg_comparator_lookup_by_name(cmpname); - } - else - *cnameptr++ = *ptr; - - break; - - case AFTER_OPERATOR: - if (!isspace((unsigned int)*ptr)) - { - vstart = ptr; - state = INSIDE_VERSION; - } - break; - - case INSIDE_VERSION: - if (PKGCONF_IS_MODULE_SEPARATOR(*ptr) || *(ptr + 1) == '\0') - { - version = vstart; - version_sz = ptr - vstart; - state = OUTSIDE_MODULE; - - pkgconf_dependency_addraw(client, deplist_head, package, package_sz, version, version_sz, compare); - - compare = PKGCONF_CMP_ANY; - cnameptr = cmpname; - memset(cmpname, 0, sizeof cmpname); - package_sz = 0; - } - - if (state == OUTSIDE_MODULE) - start = ptr; - break; - } - - ptr++; - } -} - -/* - * !doc - * - * .. c:function:: void pkgconf_dependency_parse(const pkgconf_client_t *client, pkgconf_pkg_t *pkg, pkgconf_list_t *deplist, const char *depends) - * - * Preprocess dependency data and then process that dependency declaration into a dependency list. - * Commas are counted as whitespace to allow for constructs such as ``@SUBSTVAR@, zlib`` being processed - * into ``, zlib``. - * - * :param pkgconf_client_t* client: The client object that owns the package this dependency list belongs to. - * :param pkgconf_pkg_t* pkg: The package object that owns this dependency list. - * :param pkgconf_list_t* deplist: The dependency list to populate with dependency nodes. - * :param char* depends: The dependency data to parse. - * :return: nothing - */ -void -pkgconf_dependency_parse(const pkgconf_client_t *client, pkgconf_pkg_t *pkg, pkgconf_list_t *deplist, const char *depends) -{ - char *kvdepends = pkgconf_tuple_parse(client, &pkg->vars, depends); - - pkgconf_dependency_parse_str(client, deplist, kvdepends); - free(kvdepends); -} diff --git a/libpkgconf/fragment.c b/libpkgconf/fragment.c index 7646f31..7576db7 100644 --- a/libpkgconf/fragment.c +++ b/libpkgconf/fragment.c @@ -71,22 +71,12 @@ pkgconf_fragment_is_unmergeable(const char *string) static inline bool pkgconf_fragment_should_munge(const char *string, const char *sysroot_dir) { - static const struct pkgconf_fragment_check check_fragments[] = { - {"-isystem", 8}, - {"-idirafter", 10}, - {"-include", 8}, - }; - if (*string != '/') return false; if (sysroot_dir != NULL && strncmp(sysroot_dir, string, strlen(sysroot_dir))) 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; - return false; } diff --git a/libpkgconf/fragment.c.orig b/libpkgconf/fragment.c.orig deleted file mode 100644 index 9e73515..0000000 --- a/libpkgconf/fragment.c.orig +++ /dev/null @@ -1,647 +0,0 @@ -/* - * 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 -#include - -/* - * !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) -{ - static const struct pkgconf_fragment_check check_fragments[] = { - {"-isystem", 8}, - {"-idirafter", 10}, - {"-include", 8}, - }; - - if (*string != '/') - return false; - - if (sysroot_dir != NULL && strncmp(sysroot_dir, string, strlen(sysroot_dir))) - 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; - - 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_BUFSIZE]; - 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_BUFSIZE]; - - if (list->tail != NULL && list->tail->data != NULL) - { - 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; - - /* 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->data = strdup(base->data); - - pkgconf_node_insert_tail(&frag->iter, frag, list); -} - -/* - * !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_escape(const char *src) -{ - ssize_t outlen = strlen(src) + 10; - char *out = calloc(outlen, 1); - char *dst = out; - - while (*src) - { - if (((*src < ' ') || - (*src > ' ' && *src < '$') || - (*src > '$' && *src < '(') || - (*src > ')' && *src < '+') || - (*src > ':' && *src < '=') || - (*src > '=' && *src < '@') || - (*src > 'Z' && *src < '^') || - (*src == '`') || - (*src > 'z' && *src < '~') || - (*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, bool escape) -{ - size_t len = 1; - - if (frag->type) - len += 2; - - if (frag->data != NULL) - { - if (!escape) - len += strlen(frag->data); - else - { - char *tmp = fragment_escape(frag->data); - len += strlen(tmp); - free(tmp); - } - } - - return len; -} - -/* - * !doc - * - * .. c:function:: size_t pkgconf_fragment_render_len(const pkgconf_list_t *list) - * - * 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. - * :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) -{ - 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, escape); - } - - return out; -} - -/* - * !doc - * - * .. c:function:: void pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen) - * - * 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. - * :return: nothing - */ -void -pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool 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); - - if (pkgconf_fragment_len(frag, escape) > buf_remaining) - break; - - if (frag->type) - { - *bptr++ = '-'; - *bptr++ = frag->type; - } - - if (frag->data) - { - if (!escape) - bptr += pkgconf_strlcpy(bptr, frag->data, buf_remaining); - else - { - char *tmp = fragment_escape(frag->data); - bptr += pkgconf_strlcpy(bptr, tmp, buf_remaining); - free(tmp); - } - } - - *bptr++ = ' '; - } - - *bptr = '\0'; -} - -/* - * !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. - * :return: An allocated string containing the rendered `fragment list`. - * :rtype: char * - */ -char * -pkgconf_fragment_render(const pkgconf_list_t *list, bool escape) -{ - size_t buflen = pkgconf_fragment_render_len(list, escape); - char *buf = calloc(1, buflen); - - pkgconf_fragment_render_buf(list, buf, buflen, escape); - - 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; -} diff --git a/libpkgconf/path.c b/libpkgconf/path.c index 36855fe..2f4cfbb 100644 --- a/libpkgconf/path.c +++ b/libpkgconf/path.c @@ -80,33 +80,36 @@ pkgconf_path_add(const char *text, pkgconf_list_t *dirlist, bool filter) pkgconf_path_t *node; char path[PKGCONF_ITEM_SIZE]; + pkgconf_strlcpy(path, text, sizeof path); + pkgconf_path_relocate(path, sizeof path); + #ifdef PKGCONF_CACHE_INODES struct stat st; if (filter) { - if (lstat(text, &st) == -1) + if (lstat(path, &st) == -1) return; if (S_ISLNK(st.st_mode)) { char linkdest[PKGCONF_ITEM_SIZE]; - ssize_t len = readlink(text, linkdest, sizeof(linkdest)); + ssize_t len; + + memset(linkdest, '\0', sizeof linkdest); + len = readlink(path, linkdest, sizeof linkdest); if (len != -1 && (size_t)len < sizeof(linkdest) && stat(linkdest, &st) == -1) return; } - if (path_list_contains_entry(text, dirlist, &st)) + if (path_list_contains_entry(path, dirlist, &st)) return; } #else - if (filter && path_list_contains_entry(text, dirlist)) + if (filter && path_list_contains_entry(path, dirlist)) return; #endif - pkgconf_strlcpy(path, text, sizeof path); - pkgconf_path_relocate(path, sizeof path); - node = calloc(sizeof(pkgconf_path_t), 1); node->path = strdup(path); diff --git a/libpkgconf/path.c.orig b/libpkgconf/path.c.orig deleted file mode 100644 index 5b7aa1c..0000000 --- a/libpkgconf/path.c.orig +++ /dev/null @@ -1,327 +0,0 @@ -/* - * path.c - * filesystem path management - * - * Copyright (c) 2016 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 -#include -#include - -#if defined(HAVE_CYGWIN_CONV_PATH) && defined(__MSYS__) -# include -#endif - -#if defined(HAVE_SYS_STAT_H) && ! defined(_WIN32) -# include -# define PKGCONF_CACHE_INODES -#endif - -static bool -#ifdef PKGCONF_CACHE_INODES -path_list_contains_entry(const char *text, pkgconf_list_t *dirlist, struct stat *st) -#else -path_list_contains_entry(const char *text, pkgconf_list_t *dirlist) -#endif -{ - pkgconf_node_t *n; - - PKGCONF_FOREACH_LIST_ENTRY(dirlist->head, n) - { - pkgconf_path_t *pn = n->data; - -#ifdef PKGCONF_CACHE_INODES - if (pn->handle_device == (void *)(intptr_t)st->st_dev && pn->handle_path == (void *)(intptr_t)st->st_ino) - return true; -#endif - - if (!strcmp(text, pn->path)) - return true; - } - - return false; -} - -/* - * !doc - * - * libpkgconf `path` module - * ======================== - * - * The `path` module provides functions for manipulating lists of paths in a cross-platform manner. Notably, - * it is used by the `pkgconf client` to parse the ``PKG_CONFIG_PATH``, ``PKG_CONFIG_LIBDIR`` and related environment - * variables. - */ - -/* - * !doc - * - * .. c:function:: void pkgconf_path_add(const char *text, pkgconf_list_t *dirlist) - * - * Adds a path node to a path list. If the path is already in the list, do nothing. - * - * :param char* text: The path text to add as a path node. - * :param pkgconf_list_t* dirlist: The path list to add the path node to. - * :param bool filter: Whether to perform duplicate filtering. - * :return: nothing - */ -void -pkgconf_path_add(const char *text, pkgconf_list_t *dirlist, bool filter) -{ - pkgconf_path_t *node; - char path[PKGCONF_BUFSIZE]; - -#ifdef PKGCONF_CACHE_INODES - struct stat st; - - if (filter) - { - if (lstat(text, &st) == -1) - return; - if (S_ISLNK(st.st_mode)) - { - char linkdest[PKGCONF_BUFSIZE]; - ssize_t len = readlink(text, linkdest, sizeof(linkdest)); - - if (len != -1 && (size_t)len < sizeof(linkdest) && - stat(linkdest, &st) == -1) - return; - } - if (path_list_contains_entry(text, dirlist, &st)) - return; - } -#else - if (filter && path_list_contains_entry(text, dirlist)) - return; -#endif - - pkgconf_strlcpy(path, text, sizeof path); - pkgconf_path_relocate(path, sizeof path); - - node = calloc(sizeof(pkgconf_path_t), 1); - node->path = strdup(path); - -#ifdef PKGCONF_CACHE_INODES - if (filter) { - node->handle_path = (void *)(intptr_t) st.st_ino; - node->handle_device = (void *)(intptr_t) st.st_dev; - } -#endif - - pkgconf_node_insert_tail(&node->lnode, node, dirlist); -} - -/* - * !doc - * - * .. c:function:: size_t pkgconf_path_split(const char *text, pkgconf_list_t *dirlist) - * - * Splits a given text input and inserts paths into a path list. - * - * :param char* text: The path text to split and add as path nodes. - * :param pkgconf_list_t* dirlist: The path list to have the path nodes added to. - * :param bool filter: Whether to perform duplicate filtering. - * :return: number of path nodes added to the path list - * :rtype: size_t - */ -size_t -pkgconf_path_split(const char *text, pkgconf_list_t *dirlist, bool filter) -{ - size_t count = 0; - char *workbuf, *p, *iter; - - if (text == NULL) - return 0; - - iter = workbuf = strdup(text); - while ((p = strtok(iter, PKG_CONFIG_PATH_SEP_S)) != NULL) - { - pkgconf_path_add(p, dirlist, filter); - - count++, iter = NULL; - } - free(workbuf); - - return count; -} - -/* - * !doc - * - * .. c:function:: size_t pkgconf_path_build_from_environ(const char *envvarname, const char *fallback, pkgconf_list_t *dirlist) - * - * Adds the paths specified in an environment variable to a path list. If the environment variable is not set, - * an optional default set of paths is added. - * - * :param char* envvarname: The environment variable to look up. - * :param char* fallback: The fallback paths to use if the environment variable is not set. - * :param pkgconf_list_t* dirlist: The path list to add the path nodes to. - * :param bool filter: Whether to perform duplicate filtering. - * :return: number of path nodes added to the path list - * :rtype: size_t - */ -size_t -pkgconf_path_build_from_environ(const char *envvarname, const char *fallback, pkgconf_list_t *dirlist, bool filter) -{ - const char *data; - - data = getenv(envvarname); - if (data != NULL) - return pkgconf_path_split(data, dirlist, filter); - - if (fallback != NULL) - return pkgconf_path_split(fallback, dirlist, filter); - - /* no fallback and no environment variable, thusly no nodes added */ - return 0; -} - -/* - * !doc - * - * .. c:function:: bool pkgconf_path_match_list(const char *path, const pkgconf_list_t *dirlist) - * - * Checks whether a path has a matching prefix in a path list. - * - * :param char* path: The path to check against a path list. - * :param pkgconf_list_t* dirlist: The path list to check the path against. - * :return: true if the path list has a matching prefix, otherwise false - * :rtype: bool - */ -bool -pkgconf_path_match_list(const char *path, const pkgconf_list_t *dirlist) -{ - pkgconf_node_t *n = NULL; - char relocated[PKGCONF_BUFSIZE]; - const char *cpath = path; - - pkgconf_strlcpy(relocated, path, sizeof relocated); - if (pkgconf_path_relocate(relocated, sizeof relocated)) - cpath = relocated; - - PKGCONF_FOREACH_LIST_ENTRY(dirlist->head, n) - { - pkgconf_path_t *pnode = n->data; - - if (!strcmp(pnode->path, cpath)) - return true; - } - - return false; -} - -/* - * !doc - * - * .. c:function:: void pkgconf_path_free(pkgconf_list_t *dirlist) - * - * Releases any path nodes attached to the given path list. - * - * :param pkgconf_list_t* dirlist: The path list to clean up. - * :return: nothing - */ -void -pkgconf_path_free(pkgconf_list_t *dirlist) -{ - pkgconf_node_t *n, *tn; - - PKGCONF_FOREACH_LIST_ENTRY_SAFE(dirlist->head, tn, n) - { - pkgconf_path_t *pnode = n->data; - - free(pnode->path); - free(pnode); - } -} - -static char * -normpath(const char *path) -{ - if (!path) - return NULL; - - char *copy = strdup(path); - if (NULL == copy) - return NULL; - char *ptr = copy; - - for (int ii = 0; copy[ii]; ii++) - { - *ptr++ = path[ii]; - if ('/' == path[ii]) - { - ii++; - while ('/' == path[ii]) - ii++; - ii--; - } - } - *ptr = '\0'; - - return copy; -} - -/* - * !doc - * - * .. c:function:: bool pkgconf_path_relocate(char *buf, size_t buflen) - * - * Relocates a path, possibly calling normpath() or cygwin_conv_path() on it. - * - * :param char* buf: The path to relocate. - * :param size_t buflen: The buffer length the path is contained in. - * :return: true on success, false on error - * :rtype: bool - */ -bool -pkgconf_path_relocate(char *buf, size_t buflen) -{ -#if defined(HAVE_CYGWIN_CONV_PATH) && defined(__MSYS__) - ssize_t size; - char *tmpbuf, *ti; - - size = cygwin_conv_path(CCP_POSIX_TO_WIN_A, buf, NULL, 0); - if (size < 0 || (size_t) size > buflen) - return false; - - tmpbuf = malloc(size); - if (cygwin_conv_path(CCP_POSIX_TO_WIN_A, buf, tmpbuf, size)) - return false; - - pkgconf_strlcpy(buf, tmpbuf, buflen); - free(tmpbuf); - - /* rewrite any backslash arguments for best compatibility */ - for (ti = buf; *ti != '\0'; ti++) - { - if (*ti == '\\') - *ti = '/'; - } -#else - char *tmpbuf; - - if ((tmpbuf = normpath(buf)) != NULL) - { - size_t tmpbuflen = strlen(tmpbuf); - if (tmpbuflen > buflen) - { - free(tmpbuf); - return false; - } - - pkgconf_strlcpy(buf, tmpbuf, buflen); - free(tmpbuf); - } -#endif - - return true; -} diff --git a/libpkgconf/pkg.c.orig b/libpkgconf/pkg.c.orig index a35a756..ea970b8 100644 --- a/libpkgconf/pkg.c.orig +++ b/libpkgconf/pkg.c.orig @@ -35,8 +35,7 @@ # define strcasecmp _stricmp #endif -#define PKG_CONFIG_EXT ".pc" -#define PKG_CONFIG_PATH_SZ (65535) +#define PKG_CONFIG_EXT ".pc" static inline bool str_has_suffix(const char *str, const char *suffix) @@ -287,8 +286,7 @@ pkgconf_pkg_new_from_file(pkgconf_client_t *client, const char *filename, FILE * { pkgconf_pkg_t *pkg; char readbuf[PKGCONF_BUFSIZE]; - char pathbuf[PKGCONF_BUFSIZE]; - char prefixbuf[PKGCONF_BUFSIZE]; + char pathbuf[PKGCONF_ITEM_SIZE]; char *idptr; size_t lineno = 0; @@ -374,7 +372,7 @@ pkgconf_pkg_new_from_file(pkgconf_client_t *client, const char *filename, FILE * pkgconf_tuple_add(client, &pkg->vars, key, value, true); else { - const char *relvalue = determine_prefix(pkg, prefixbuf, sizeof prefixbuf); + const char *relvalue = determine_prefix(pkg, pathbuf, sizeof pathbuf); if (relvalue != NULL) { pkgconf_tuple_add(client, &pkg->vars, "orig_prefix", value, true); @@ -509,8 +507,8 @@ pkgconf_pkg_try_specific_path(pkgconf_client_t *client, const char *path, const { pkgconf_pkg_t *pkg = NULL; FILE *f; - char locbuf[PKG_CONFIG_PATH_SZ]; - char uninst_locbuf[PKG_CONFIG_PATH_SZ]; + char locbuf[PKGCONF_ITEM_SIZE]; + char uninst_locbuf[PKGCONF_ITEM_SIZE]; PKGCONF_TRACE(client, "trying path: %s for %s", path, name); @@ -547,7 +545,7 @@ pkgconf_pkg_scan_dir(pkgconf_client_t *client, const char *path, void *data, pkg for (dirent = readdir(dir); dirent != NULL; dirent = readdir(dir)) { - char filebuf[PKGCONF_BUFSIZE]; + char filebuf[PKGCONF_ITEM_SIZE]; pkgconf_pkg_t *pkg; FILE *f; @@ -634,7 +632,7 @@ pkgconf_pkg_find_in_registry_key(pkgconf_client_t *client, HKEY hkey, const char while (RegEnumValue(key, i++, buf, &bufsize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { - char pathbuf[PKG_CONFIG_PATH_SZ]; + char pathbuf[PKGCONF_ITEM_SIZE]; DWORD type; DWORD pathbuflen = sizeof pathbuf; @@ -669,7 +667,7 @@ pkgconf_pkg_find_in_registry_key(pkgconf_client_t *client, HKEY hkey, const char pkgconf_pkg_t * pkgconf_pkg_find(pkgconf_client_t *client, const char *name) { - char pathbuf[PKGCONF_BUFSIZE]; + char pathbuf[PKGCONF_ITEM_SIZE]; pkgconf_pkg_t *pkg = NULL; pkgconf_node_t *n; FILE *f; @@ -749,7 +747,7 @@ int pkgconf_compare_version(const char *a, const char *b) { char oldch1, oldch2; - char buf1[PKGCONF_BUFSIZE], buf2[PKGCONF_BUFSIZE]; + char buf1[PKGCONF_ITEM_SIZE], buf2[PKGCONF_ITEM_SIZE]; char *str1, *str2; char *one, *two; int ret; diff --git a/libpkgconf/stdinc.h b/libpkgconf/stdinc.h index 418a06a..3b90853 100644 --- a/libpkgconf/stdinc.h +++ b/libpkgconf/stdinc.h @@ -26,31 +26,6 @@ #include #include -/* - * The original libpkgconf package uses PKGCONF_BUFSIZE size for all - * stack-allocated buffers, imposing high requirements for the thread stack - * size. This make it unusable on MacOS (as of 10.12) for non-main threads that - * are created with the default 512KB stack size. In particular that make it - * impossible to use libpkgconf API in threads created with C++11 std::thread - * class, that doesn't allow stack size customization. - * - * As an example, using pkgconf_pkg_find() for quite a simple .pc file consumes - * at least 460KB. The measurement was made as a difference between addresses - * of 2 stack-allocated variables: one was defined right before the function - * call, another right after the buffer definition in pkgconf_tuple_parse() - * function. - * - * To relax the stack size requirements we will minimize the usage of - * PKGCONF_BUFSIZE, inventing the smaller PKGCONF_ITEM_SIZE, and using it - * wherever it is possible instead. The PKGCONF_ITEM_SIZE is selected in such a - * way that a buffer of this size can accommodate the file system path, the - * value fragment, the variable name or the package dependency specification. - * The latest implies it also fits for the package key or the package version. - * This optimization decreased the stack usage for the described use case to - * 140KB. - * - * Issue #149 is reported. - */ #ifdef _WIN32 # define WIN32_LEAN_AND_MEAN # include diff --git a/libpkgconf/stdinc.h.orig b/libpkgconf/stdinc.h.orig deleted file mode 100644 index d0a43ad..0000000 --- a/libpkgconf/stdinc.h.orig +++ /dev/null @@ -1,59 +0,0 @@ -/* - * stdinc.h - * pull in standard headers (including portability hacks) - * - * Copyright (c) 2012 pkgconf authors (see AUTHORS). - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * This software is provided 'as is' and without any warranty, express or - * implied. In no event shall the authors be liable for any damages arising - * from the use of this software. - */ - -#ifndef __STDINC_H -#define __STDINC_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN -# include -# include -# define PATH_DEV_NULL "nul" -# ifdef _WIN64 -# define SIZE_FMT_SPECIFIER "%I64u" -# else -# define SIZE_FMT_SPECIFIER "%u" -# endif -# ifndef ssize_t -# ifndef __MINGW32__ -# include -# else -# include -# endif -# define ssize_t SSIZE_T -# endif -# ifndef __MINGW32__ -# include "win-dirent.h" -# else -# include -# endif -#else -# define PATH_DEV_NULL "/dev/null" -# define SIZE_FMT_SPECIFIER "%zu" -# include -# include -#endif - -#endif diff --git a/libpkgconf/tuple.c.orig b/libpkgconf/tuple.c.orig deleted file mode 100644 index 0b22b9a..0000000 --- a/libpkgconf/tuple.c.orig +++ /dev/null @@ -1,349 +0,0 @@ -/* - * tuple.c - * management of key->value tuples - * - * Copyright (c) 2011, 2012 pkgconf authors (see AUTHORS). - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * This software is provided 'as is' and without any warranty, express or - * implied. In no event shall the authors be liable for any damages arising - * from the use of this software. - */ - -#include -#include - -/* - * !doc - * - * libpkgconf `tuple` module - * ========================= - * - * The `tuple` module provides key-value mappings backed by a linked list. The key-value - * mapping is mainly used for variable substitution when parsing .pc files. - * - * There are two sets of mappings: a ``pkgconf_pkg_t`` specific mapping, and a `global` mapping. - * The `tuple` module provides convenience wrappers for managing the `global` mapping, which is - * attached to a given client object. - */ - -/* - * !doc - * - * .. c:function:: void pkgconf_tuple_add_global(pkgconf_client_t *client, const char *key, const char *value) - * - * Defines a global variable, replacing the previous declaration if one was set. - * - * :param pkgconf_client_t* client: The pkgconf client object to modify. - * :param char* key: The key for the mapping (variable name). - * :param char* value: The value for the mapped entry. - * :return: nothing - */ -void -pkgconf_tuple_add_global(pkgconf_client_t *client, const char *key, const char *value) -{ - pkgconf_tuple_add(client, &client->global_vars, key, value, false); -} - -/* - * !doc - * - * .. c:function:: void pkgconf_tuple_find_global(const pkgconf_client_t *client, const char *key) - * - * Looks up a global variable. - * - * :param pkgconf_client_t* client: The pkgconf client object to access. - * :param char* key: The key or variable name to look up. - * :return: the contents of the variable or ``NULL`` - * :rtype: char * - */ -char * -pkgconf_tuple_find_global(const pkgconf_client_t *client, const char *key) -{ - pkgconf_node_t *node; - - PKGCONF_FOREACH_LIST_ENTRY(client->global_vars.head, node) - { - pkgconf_tuple_t *tuple = node->data; - - if (!strcmp(tuple->key, key)) - return tuple->value; - } - - return NULL; -} - -/* - * !doc - * - * .. c:function:: void pkgconf_tuple_free_global(pkgconf_client_t *client) - * - * Delete all global variables associated with a pkgconf client object. - * - * :param pkgconf_client_t* client: The pkgconf client object to modify. - * :return: nothing - */ -void -pkgconf_tuple_free_global(pkgconf_client_t *client) -{ - pkgconf_tuple_free(&client->global_vars); -} - -/* - * !doc - * - * .. c:function:: void pkgconf_tuple_define_global(pkgconf_client_t *client, const char *kv) - * - * Parse and define a global variable. - * - * :param pkgconf_client_t* client: The pkgconf client object to modify. - * :param char* kv: The variable in the form of ``key=value``. - * :return: nothing - */ -void -pkgconf_tuple_define_global(pkgconf_client_t *client, const char *kv) -{ - char *workbuf = strdup(kv); - char *value; - - value = strchr(workbuf, '='); - if (value == NULL) - goto out; - - *value++ = '\0'; - pkgconf_tuple_add_global(client, workbuf, value); -out: - free(workbuf); -} - -static void -pkgconf_tuple_find_delete(pkgconf_list_t *list, const char *key) -{ - pkgconf_node_t *node, *next; - - PKGCONF_FOREACH_LIST_ENTRY_SAFE(list->head, next, node) - { - pkgconf_tuple_t *tuple = node->data; - - if (!strcmp(tuple->key, key)) - { - pkgconf_tuple_free_entry(tuple, list); - return; - } - } -} - -/* - * !doc - * - * .. c:function:: pkgconf_tuple_t *pkgconf_tuple_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *key, const char *value, bool parse) - * - * Optionally parse and then define a variable. - * - * :param pkgconf_client_t* client: The pkgconf client object to access. - * :param pkgconf_list_t* list: The variable list to add the new variable to. - * :param char* key: The name of the variable being added. - * :param char* value: The value of the variable being added. - * :param bool parse: Whether or not to parse the value for variable substitution. - * :return: a variable object - * :rtype: pkgconf_tuple_t * - */ -pkgconf_tuple_t * -pkgconf_tuple_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *key, const char *value, bool parse) -{ - pkgconf_tuple_t *tuple = calloc(sizeof(pkgconf_tuple_t), 1); - - pkgconf_tuple_find_delete(list, key); - - tuple->key = strdup(key); - if (parse) - tuple->value = pkgconf_tuple_parse(client, list, value); - else - tuple->value = strdup(value); - - pkgconf_node_insert(&tuple->iter, tuple, list); - - return tuple; -} - -/* - * !doc - * - * .. c:function:: char *pkgconf_tuple_find(const pkgconf_client_t *client, pkgconf_list_t *list, const char *key) - * - * Look up a variable in a variable list. - * - * :param pkgconf_client_t* client: The pkgconf client object to access. - * :param pkgconf_list_t* list: The variable list to search. - * :param char* key: The variable name to search for. - * :return: the value of the variable or ``NULL`` - * :rtype: char * - */ -char * -pkgconf_tuple_find(const pkgconf_client_t *client, pkgconf_list_t *list, const char *key) -{ - pkgconf_node_t *node; - char *res; - - if ((res = pkgconf_tuple_find_global(client, key)) != NULL) - return res; - - PKGCONF_FOREACH_LIST_ENTRY(list->head, node) - { - pkgconf_tuple_t *tuple = node->data; - - if (!strcmp(tuple->key, key)) - return tuple->value; - } - - return NULL; -} - -/* - * !doc - * - * .. c:function:: char *pkgconf_tuple_parse(const pkgconf_client_t *client, pkgconf_list_t *vars, const char *value) - * - * Parse an expression for variable substitution. - * - * :param pkgconf_client_t* client: The pkgconf client object to access. - * :param pkgconf_list_t* list: The variable list to search for variables (along side the global variable list). - * :param char* value: The ``key=value`` string to parse. - * :return: the variable data with any variables substituted - * :rtype: char * - */ -char * -pkgconf_tuple_parse(const pkgconf_client_t *client, pkgconf_list_t *vars, const char *value) -{ - char buf[PKGCONF_BUFSIZE]; - const char *ptr; - char *bptr = buf; - - if (*value == '/' && client->sysroot_dir != NULL && strncmp(value, client->sysroot_dir, strlen(client->sysroot_dir))) - bptr += pkgconf_strlcpy(buf, client->sysroot_dir, sizeof buf); - - for (ptr = value; *ptr != '\0' && bptr - buf < PKGCONF_BUFSIZE; ptr++) - { - if (*ptr != '$' || (*ptr == '$' && *(ptr + 1) != '{')) - *bptr++ = *ptr; - else if (*(ptr + 1) == '{') - { - char varname[PKGCONF_BUFSIZE]; - char *vptr = varname; - const char *pptr; - char *kv, *parsekv; - - *vptr = '\0'; - - for (pptr = ptr + 2; *pptr != '\0'; pptr++) - { - if (*pptr != '}') - *vptr++ = *pptr; - else - { - *vptr = '\0'; - break; - } - } - - ptr += (pptr - ptr); - kv = pkgconf_tuple_find_global(client, varname); - if (kv != NULL) - { - strncpy(bptr, kv, PKGCONF_BUFSIZE - (bptr - buf)); - bptr += strlen(kv); - } - else - { - kv = pkgconf_tuple_find(client, vars, varname); - - if (kv != NULL) - { - parsekv = pkgconf_tuple_parse(client, vars, kv); - - strncpy(bptr, parsekv, PKGCONF_BUFSIZE - (bptr - buf)); - bptr += strlen(parsekv); - - free(parsekv); - } - } - } - } - - *bptr = '\0'; - - /* - * Sigh. Somebody actually attempted to use freedesktop.org pkg-config's broken sysroot support, - * which was written by somebody who did not understand how sysroots are supposed to work. This - * results in an incorrect path being built as the sysroot will be prepended twice, once explicitly, - * and once by variable expansion (the pkgconf approach). We could simply make ${pc_sysrootdir} blank, - * but sometimes it is necessary to know the explicit sysroot path for other reasons, so we can't really - * do that. - * - * As a result, we check to see if ${pc_sysrootdir} is prepended as a duplicate, and if so, remove the - * prepend. This allows us to handle both our approach and the broken freedesktop.org implementation's - * approach. Because a path can be shorter than ${pc_sysrootdir}, we do some checks first to ensure it's - * safe to skip ahead in the string to scan for our sysroot dir. - * - * Finally, we call pkgconf_path_relocate() to clean the path of spurious elements. - */ - if (*buf == '/' && - client->sysroot_dir != NULL && - strcmp(client->sysroot_dir, "/") != 0 && - strlen(buf) > strlen(client->sysroot_dir) && - strstr(buf + strlen(client->sysroot_dir), client->sysroot_dir) != NULL) - { - char cleanpath[PKGCONF_BUFSIZE]; - - pkgconf_strlcpy(cleanpath, buf + strlen(client->sysroot_dir), sizeof cleanpath); - pkgconf_path_relocate(cleanpath, sizeof cleanpath); - - return strdup(cleanpath); - } - - return strdup(buf); -} - -/* - * !doc - * - * .. c:function:: void pkgconf_tuple_free_entry(pkgconf_tuple_t *tuple, pkgconf_list_t *list) - * - * Deletes a variable object, removing it from any variable lists and releasing any memory associated - * with it. - * - * :param pkgconf_tuple_t* tuple: The variable object to release. - * :param pkgconf_list_t* list: The variable list the variable object is attached to. - * :return: nothing - */ -void -pkgconf_tuple_free_entry(pkgconf_tuple_t *tuple, pkgconf_list_t *list) -{ - pkgconf_node_delete(&tuple->iter, list); - - free(tuple->key); - free(tuple->value); - free(tuple); -} - -/* - * !doc - * - * .. c:function:: void pkgconf_tuple_free(pkgconf_list_t *list) - * - * Deletes a variable list and any variables attached to it. - * - * :param pkgconf_list_t* list: The variable list to delete. - * :return: nothing - */ -void -pkgconf_tuple_free(pkgconf_list_t *list) -{ - pkgconf_node_t *node, *next; - - PKGCONF_FOREACH_LIST_ENTRY_SAFE(list->head, next, node) - pkgconf_tuple_free_entry(node->data, list); -} -- cgit v1.1