aboutsummaryrefslogtreecommitdiff
path: root/libpkgconf/dependency.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpkgconf/dependency.c')
-rw-r--r--libpkgconf/dependency.c102
1 files changed, 59 insertions, 43 deletions
diff --git a/libpkgconf/dependency.c b/libpkgconf/dependency.c
index 9b64809a4114..ce5237f2c154 100644
--- a/libpkgconf/dependency.c
+++ b/libpkgconf/dependency.c
@@ -2,6 +2,8 @@
* dependency.c
* dependency parsing and management
*
+ * SPDX-License-Identifier: pkgconf
+ *
* Copyright (c) 2011, 2012, 2013 pkgconf authors (see AUTHORS).
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -37,19 +39,16 @@ typedef enum {
#define DEBUG_PARSE 0
-static const char *
-dependency_to_str(const pkgconf_dependency_t *dep, char *buf, size_t buflen)
+static inline const char *
+dependency_to_buf(const pkgconf_dependency_t *dep, pkgconf_buffer_t *buf)
{
- pkgconf_strlcpy(buf, dep->package, buflen);
+ pkgconf_buffer_reset(buf);
+ pkgconf_buffer_append(buf, dep->package);
+
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);
- }
+ pkgconf_buffer_append_fmt(buf, " %s %s", pkgconf_pkg_get_comparator(dep), dep->version);
- return buf;
+ return pkgconf_buffer_str(buf);
}
/* find a colliding dependency that is coloured differently */
@@ -75,29 +74,33 @@ find_colliding_dependency(const pkgconf_dependency_t *dep, const pkgconf_list_t
static inline pkgconf_dependency_t *
add_or_replace_dependency_node(pkgconf_client_t *client, pkgconf_dependency_t *dep, pkgconf_list_t *list)
{
- char depbuf[PKGCONF_ITEM_SIZE];
+ pkgconf_buffer_t depbuf = PKGCONF_BUFFER_INITIALIZER;
pkgconf_dependency_t *dep2 = find_colliding_dependency(dep, list);
+ const char *depstr = dependency_to_buf(dep, &depbuf);
/* there is already a node in the graph which describes this dependency */
if (dep2 != NULL)
{
- char depbuf2[PKGCONF_ITEM_SIZE];
+ pkgconf_buffer_t depbuf2 = PKGCONF_BUFFER_INITIALIZER;
+ const char *depstr2 = dependency_to_buf(dep2, &depbuf2);
PKGCONF_TRACE(client, "dependency collision: [%s/%x] -- [%s/%x]",
- dependency_to_str(dep, depbuf, sizeof depbuf), dep->flags,
- dependency_to_str(dep2, depbuf2, sizeof depbuf2), dep2->flags);
+ depstr, dep->flags, depstr2, dep2->flags);
/* prefer the uncoloured node, either dep or dep2 */
if (dep->flags && dep2->flags == 0)
{
- PKGCONF_TRACE(client, "dropping dependency [%s]@%p because of collision", depbuf, dep);
+ PKGCONF_TRACE(client, "dropping dependency [%s]@%p because of collision", depstr, dep);
+ pkgconf_buffer_finalize(&depbuf);
+ pkgconf_buffer_finalize(&depbuf2);
pkgconf_dependency_unref(dep->owner, dep);
+
return NULL;
}
else if (dep2->flags && dep->flags == 0)
{
- PKGCONF_TRACE(client, "dropping dependency [%s]@%p because of collision", depbuf2, dep2);
+ PKGCONF_TRACE(client, "dropping dependency [%s]@%p because of collision", depstr2, dep2);
pkgconf_node_delete(&dep2->iter, list);
pkgconf_dependency_unref(dep2->owner, dep2);
@@ -110,11 +113,15 @@ add_or_replace_dependency_node(pkgconf_client_t *client, pkgconf_dependency_t *d
* fragment deduplication will handle the excessive fragments.
*/
PKGCONF_TRACE(client, "keeping both dependencies (harmless)");
+
+ pkgconf_buffer_finalize(&depbuf2);
}
- PKGCONF_TRACE(client, "added dependency [%s] to list @%p; flags=%x", dependency_to_str(dep, depbuf, sizeof depbuf), list, dep->flags);
+ PKGCONF_TRACE(client, "added dependency [%s] to list @%p; flags=%x", depstr, list, dep->flags);
pkgconf_node_insert_tail(&dep->iter, pkgconf_dependency_ref(dep->owner, dep), list);
+ pkgconf_buffer_finalize(&depbuf);
+
/* This dependency is intentionally unowned.
*
* Internally we have no use for the returned type, and usually just
@@ -135,6 +142,11 @@ pkgconf_dependency_addraw(pkgconf_client_t *client, pkgconf_list_t *list, const
return NULL;
dep->package = pkgconf_strndup(package, package_sz);
+ if (dep->package == NULL)
+ {
+ pkgconf_dependency_free_one(dep);
+ return NULL;
+ }
if (version_sz != 0)
dep->version = pkgconf_strndup(version, version_sz);
@@ -169,6 +181,8 @@ pkgconf_dependency_add(pkgconf_client_t *client, pkgconf_list_t *list, const cha
pkgconf_dependency_t *dep;
dep = pkgconf_dependency_addraw(client, list, package, strlen(package), version,
version != NULL ? strlen(version) : 0, compare, flags);
+ if (dep == NULL)
+ return NULL;
return pkgconf_dependency_ref(dep->owner, dep);
}
@@ -211,6 +225,9 @@ pkgconf_dependency_free_one(pkgconf_dependency_t *dep)
if (dep->version != NULL)
free(dep->version);
+ if (dep->why != NULL)
+ free(dep->why);
+
free(dep);
}
@@ -306,30 +323,25 @@ pkgconf_dependency_parse_str(pkgconf_client_t *client, pkgconf_list_t *deplist_h
{
parse_state_t state = OUTSIDE_MODULE;
pkgconf_pkg_comparator_t compare = PKGCONF_CMP_ANY;
- char cmpname[PKGCONF_ITEM_SIZE];
- size_t package_sz = 0, version_sz = 0, buf_sz = 0;
- char *buf;
+ pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
+ pkgconf_buffer_t cmpname = PKGCONF_BUFFER_INITIALIZER;
+ size_t package_sz = 0, version_sz = 0;
char *start = NULL;
char *ptr = NULL;
char *vstart = NULL;
char *package = NULL, *version = NULL;
- char *cnameptr = cmpname;
- char *cnameend = cmpname + PKGCONF_ITEM_SIZE - 1;
+ char *opstart = NULL;
- if (!*depends)
+ if (depends == NULL || *depends == '\0')
return;
- memset(cmpname, '\0', sizeof cmpname);
-
- buf_sz = strlen(depends) * 2;
- buf = calloc(1, buf_sz);
- if (buf == NULL)
- return;
+ if (!pkgconf_buffer_append(&buf, depends))
+ goto out;
- pkgconf_strlcpy(buf, depends, buf_sz);
- pkgconf_strlcat(buf, " ", buf_sz);
+ if (!pkgconf_buffer_append(&buf, " "))
+ goto out;
- start = ptr = buf;
+ start = ptr = buf.base;
while (*ptr)
{
@@ -391,23 +403,20 @@ pkgconf_dependency_parse_str(pkgconf_client_t *client, pkgconf_list_t *deplist_h
case BEFORE_OPERATOR:
if (PKGCONF_IS_OPERATOR_CHAR(*ptr))
{
+ opstart = ptr;
state = INSIDE_OPERATOR;
- if (cnameptr < cnameend)
- *cnameptr++ = *ptr;
}
break;
case INSIDE_OPERATOR:
if (PKGCONF_IS_OPERATOR_CHAR(*ptr))
- {
- if (cnameptr < cnameend)
- *cnameptr++ = *ptr;
break;
- }
+ pkgconf_buffer_reset(&cmpname);
+ pkgconf_buffer_append_slice(&cmpname, opstart, ptr - opstart);
+ compare = pkgconf_pkg_comparator_lookup_by_name(pkgconf_buffer_str(&cmpname));
state = AFTER_OPERATOR;
- compare = pkgconf_pkg_comparator_lookup_by_name(cmpname);
// fallthrough
case AFTER_OPERATOR:
@@ -428,9 +437,9 @@ pkgconf_dependency_parse_str(pkgconf_client_t *client, pkgconf_list_t *deplist_h
pkgconf_dependency_addraw(client, deplist_head, package, package_sz, version, version_sz, compare, flags);
compare = PKGCONF_CMP_ANY;
- cnameptr = cmpname;
- memset(cmpname, 0, sizeof cmpname);
package_sz = 0;
+ opstart = NULL;
+ pkgconf_buffer_reset(&cmpname);
}
if (state == OUTSIDE_MODULE)
@@ -441,7 +450,9 @@ pkgconf_dependency_parse_str(pkgconf_client_t *client, pkgconf_list_t *deplist_h
ptr++;
}
- free(buf);
+out:
+ pkgconf_buffer_finalize(&cmpname);
+ pkgconf_buffer_finalize(&buf);
}
/*
@@ -463,7 +474,7 @@ pkgconf_dependency_parse_str(pkgconf_client_t *client, pkgconf_list_t *deplist_h
void
pkgconf_dependency_parse(pkgconf_client_t *client, pkgconf_pkg_t *pkg, pkgconf_list_t *deplist, const char *depends, unsigned int flags)
{
- char *kvdepends = pkgconf_tuple_parse(client, &pkg->vars, depends, pkg->flags);
+ char *kvdepends = pkgconf_bytecode_eval_str(client, &pkg->vars, depends, NULL);
pkgconf_dependency_parse_str(client, deplist, kvdepends, flags);
free(kvdepends);
@@ -490,6 +501,11 @@ pkgconf_dependency_copy(pkgconf_client_t *client, const pkgconf_dependency_t *de
return NULL;
new_dep->package = strdup(dep->package);
+ if (new_dep->package == NULL)
+ {
+ pkgconf_dependency_free_one(new_dep);
+ return NULL;
+ }
if (dep->version != NULL)
new_dep->version = strdup(dep->version);