From 429162ba11e58758e5e4ac4f03239891fc3e189c Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 12 Dec 2017 16:04:02 +0300 Subject: Merge with latest upstream package version (master branch) --- libpkgconf/fragment.c | 171 +++++++++++++++++++++++++++++--------------------- 1 file changed, 98 insertions(+), 73 deletions(-) (limited to 'libpkgconf/fragment.c') diff --git a/libpkgconf/fragment.c b/libpkgconf/fragment.c index 7576db7..78a3463 100644 --- a/libpkgconf/fragment.c +++ b/libpkgconf/fragment.c @@ -173,6 +173,7 @@ pkgconf_fragment_add(const pkgconf_client_t *client, pkgconf_list_t *list, const free(parent->data); parent->data = newdata; + parent->merged = true; /* use a copy operation to force a dedup */ pkgconf_node_delete(&parent->iter, list); @@ -350,7 +351,9 @@ pkgconf_fragment_copy(const pkgconf_client_t *client, pkgconf_list_t *list, cons frag = calloc(sizeof(pkgconf_fragment_t), 1); frag->type = base->type; - frag->data = strdup(base->data); + frag->merged = base->merged; + if (base->data != NULL) + frag->data = strdup(base->data); pkgconf_node_insert_tail(&frag->iter, frag, list); } @@ -383,17 +386,18 @@ pkgconf_fragment_filter(const pkgconf_client_t *client, pkgconf_list_t *dest, pk } } -static inline char * -fragment_escape(const char *src) +static inline bool +fragment_should_quote(const pkgconf_fragment_t *frag) { - ssize_t outlen = strlen(src) + 10; - char *out = calloc(outlen, 1); - char *dst = out; + const char *src; - while (*src) + if (frag->data == NULL) + return false; + + for (src = frag->data; *src; src++) { if (((*src < ' ') || - (*src > ' ' && *src < '$') || + (*src >= (' ' + (frag->merged ? 1 : 0)) && *src < '$') || (*src > '$' && *src < '(') || (*src > ')' && *src < '+') || (*src > ':' && *src < '=') || @@ -402,23 +406,14 @@ fragment_escape(const char *src) (*src == '`') || (*src > 'z' && *src < '~') || (*src > '~')) && *src != '\\') - *dst++ = '\\'; - - *dst++ = *src++; - - if ((ptrdiff_t)(dst - out) + 2 > outlen) - { - outlen *= 2; - out = realloc(out, outlen); - } + return true; } - *dst = 0; - return out; + return false; } static inline size_t -pkgconf_fragment_len(const pkgconf_fragment_t *frag, bool escape) +pkgconf_fragment_len(const pkgconf_fragment_t *frag) { size_t len = 1; @@ -427,62 +422,37 @@ pkgconf_fragment_len(const pkgconf_fragment_t *frag, bool escape) if (frag->data != NULL) { - if (!escape) - len += strlen(frag->data); - else - { - char *tmp = fragment_escape(frag->data); - len += strlen(tmp); - free(tmp); - } + len += strlen(frag->data); + + if (fragment_should_quote(frag)) + len += 2; } 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) +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, escape); + out += pkgconf_fragment_len(frag); } 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) +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; @@ -492,10 +462,14 @@ pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen { 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, escape) > buf_remaining) + if (pkgconf_fragment_len(frag) > buf_remaining) break; + if (should_quote) + *bptr++ = '\''; + if (frag->type) { *bptr++ = '-'; @@ -503,16 +477,10 @@ pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen } 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 += pkgconf_strlcpy(bptr, frag->data, buf_remaining); + + if (should_quote) + *bptr++ = '\''; *bptr++ = ' '; } @@ -520,6 +488,60 @@ pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen *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; + + /* + * The function must not return a value (issue #162 is reported). + */ + ops->render_buf(list, buf, buflen, true); +} + /* * !doc * @@ -528,17 +550,20 @@ pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen * 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. + * :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) +pkgconf_fragment_render(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops) { - size_t buflen = pkgconf_fragment_render_len(list, escape); + (void) escape; + + size_t buflen = pkgconf_fragment_render_len(list, true, ops); char *buf = calloc(1, buflen); - pkgconf_fragment_render_buf(list, buf, buflen, escape); + pkgconf_fragment_render_buf(list, buf, buflen, true, ops); return buf; } -- cgit v1.1