aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libpkgconf/argvsplit.c7
-rw-r--r--libpkgconf/fragment.c6
-rw-r--r--libpkgconf/fragment.c.orig658
-rw-r--r--tests/api/testscript12
4 files changed, 8 insertions, 675 deletions
diff --git a/libpkgconf/argvsplit.c b/libpkgconf/argvsplit.c
index 4553154..02ce1a3 100644
--- a/libpkgconf/argvsplit.c
+++ b/libpkgconf/argvsplit.c
@@ -88,12 +88,7 @@ pkgconf_argv_split(const char *src, int *argc, char ***argv)
*dst_iter++ = *src_iter;
}
else
- {
- if (*src_iter == '\\')
- *dst_iter++ = '\\';
-
*dst_iter++ = *src_iter;
- }
escaped = false;
}
@@ -101,7 +96,7 @@ pkgconf_argv_split(const char *src, int *argc, char ***argv)
{
if (*src_iter == quote)
quote = 0;
- else if (*src_iter == '\\')
+ else if (*src_iter == '\\' && quote != '\'')
escaped = true;
else
*dst_iter++ = *src_iter;
diff --git a/libpkgconf/fragment.c b/libpkgconf/fragment.c
index 78a3463..1ea91ee 100644
--- a/libpkgconf/fragment.c
+++ b/libpkgconf/fragment.c
@@ -405,7 +405,7 @@ fragment_should_quote(const pkgconf_fragment_t *frag)
(*src > 'Z' && *src < '^') ||
(*src == '`') ||
(*src > 'z' && *src < '~') ||
- (*src > '~')) && *src != '\\')
+ (*src > '~')))
return true;
}
@@ -535,10 +535,6 @@ pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen
(void) escape;
ops = ops != NULL ? ops : &default_render_ops;
-
- /*
- * The function must not return a value (issue #162 is reported).
- */
ops->render_buf(list, buf, buflen, true);
}
diff --git a/libpkgconf/fragment.c.orig b/libpkgconf/fragment.c.orig
deleted file mode 100644
index feb12f9..0000000
--- a/libpkgconf/fragment.c.orig
+++ /dev/null
@@ -1,658 +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 <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)
- {
- 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_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 bool
-fragment_should_quote(const pkgconf_fragment_t *frag)
-{
- const char *src;
-
- if (frag->data == NULL)
- return false;
-
- for (src = frag->data; *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 > '~')) && *src != '\\')
- return true;
- }
-
- return false;
-}
-
-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)
- {
- len += strlen(frag->data);
-
- if (fragment_should_quote(frag))
- len += 2;
- }
-
- 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);
- bool should_quote = fragment_should_quote(frag);
-
- if (pkgconf_fragment_len(frag) > buf_remaining)
- break;
-
- if (should_quote)
- *bptr++ = '\'';
-
- if (frag->type)
- {
- *bptr++ = '-';
- *bptr++ = frag->type;
- }
-
- if (frag->data)
- bptr += pkgconf_strlcpy(bptr, frag->data, buf_remaining);
-
- if (should_quote)
- *bptr++ = '\'';
-
- *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;
- return 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;
-}
diff --git a/tests/api/testscript b/tests/api/testscript
index 01f883b..6522c44 100644
--- a/tests/api/testscript
+++ b/tests/api/testscript
@@ -55,14 +55,14 @@
: cflags
:
$* --cflags $f >>EOO
- I C:Program FilesFoo
+ I C:\Program Files\Foo
EOO
: libs
:
$* --libs $f >>EOO
- L C:Program FilesFoo
- l C:Program FilesFoofoo
+ L C:\Program Files\Foo
+ l C:\Program Files\Foo\foo
EOO
: vars
@@ -91,14 +91,14 @@
: cflags
:
$* --cflags $f >>EOO
- I C:\\Program Files\\Foo
+ I C:\Program Files\Foo
EOO
: libs
:
$* --libs $f >>EOO
- L C:\\Program Files\\Foo
- l C:\\Program Files\\Foo\\foo
+ L C:\Program Files\Foo
+ l C:\Program Files\Foo\foo
EOO
: vars