diff --git a/Makefile b/Makefile index 588f738..29db07c 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ PROG = pkgconf${PROG_SUFFIX} -SRCS = main.c parse.c pkg.c bsdstubs.c getopt_long.c fragment.c argvsplit.c fileio.c tuple.c +SRCS = main.c parse.c pkg.c bsdstubs.c getopt_long.c fragment.c argvsplit.c fileio.c tuple.c dependency.c include buildsys.mk diff --git a/dependency.c b/dependency.c new file mode 100644 index 0000000..ecd066a --- /dev/null +++ b/dependency.c @@ -0,0 +1,296 @@ +/* + * dependency.c + * dependency parsing and management + * + * Copyright (c) 2011, 2012 William Pitcock . + * + * 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "pkg.h" +#include "bsdstubs.h" + +/* + * pkg_dependency_parse(pkg, depends) + * + * Add requirements to a .pc file. + * Commas are counted as whitespace, as to allow: + * @SUBSTVAR@, zlib + * getting substituted to: + * , zlib. + */ +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 inline pkg_dependency_t * +pkg_dependency_add(pkg_dependency_t *head, const char *package, const char *version, pkg_comparator_t compare) +{ + pkg_dependency_t *dep; + + dep = calloc(sizeof(pkg_dependency_t), 1); + dep->package = strdup(package); + + if (version != NULL) + dep->version = strdup(version); + + dep->compare = compare; + + dep->prev = head; + if (dep->prev != NULL) + dep->prev->next = dep; + +#if DEBUG_PARSE + fprintf(stderr, "--> %s %d %s\n", dep->package, dep->compare, dep->version); +#endif + + return dep; +} + +pkg_dependency_t * +pkg_dependency_append(pkg_dependency_t *head, pkg_dependency_t *tail) +{ + pkg_dependency_t *node; + + if (head == NULL) + return tail; + + /* skip to end of list */ + foreach_list_entry(head, node) + { + if (node->next == NULL) + break; + } + + node->next = tail; + tail->prev = node; + + return head; +} + +void +pkg_dependency_free(pkg_dependency_t *head) +{ + pkg_dependency_t *node, *next; + + foreach_list_entry_safe(head, next, node) + { + if (node->package != NULL) + free(node->package); + + if (node->version != NULL) + free(node->version); + + free(node); + } +} + +pkg_dependency_t * +pkg_dependency_parse(pkg_t *pkg, const char *depends) +{ + parse_state_t state = OUTSIDE_MODULE; + pkg_dependency_t *deplist = NULL; + pkg_dependency_t *deplist_head = NULL; + pkg_comparator_t compare = PKG_ANY; + char buf[BUFSIZ]; + char *kvdepends = pkg_tuple_parse(pkg->vars, depends); + char *start = buf; + char *ptr = buf; + char *vstart = NULL; + char *package = NULL, *version = NULL; + + strlcpy(buf, kvdepends, sizeof buf); + strlcat(buf, " ", sizeof buf); + free(kvdepends); + + while (*ptr) + { + switch (state) + { + case OUTSIDE_MODULE: + if (!PKG_MODULE_SEPARATOR(*ptr)) + state = INSIDE_MODULE_NAME; + + break; + + case INSIDE_MODULE_NAME: + if (isspace(*ptr)) + { + const char *sptr = ptr; + + while (*sptr && isspace(*sptr)) + sptr++; + + if (*sptr == '\0') + state = OUTSIDE_MODULE; + else if (PKG_MODULE_SEPARATOR(*sptr)) + state = OUTSIDE_MODULE; + else if (PKG_OPERATOR_CHAR(*sptr)) + state = BEFORE_OPERATOR; + else + state = OUTSIDE_MODULE; + } + else if (PKG_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 (PKG_MODULE_SEPARATOR(*iter)) + iter++; + + package = strndup(iter, ptr - iter); +#if DEBUG_PARSE + fprintf(stderr, "Found package: %s\n", package); +#endif + start = ptr; + } + + if (state == OUTSIDE_MODULE) + { + deplist = pkg_dependency_add(deplist, package, NULL, compare); + + if (deplist_head == NULL) + deplist_head = deplist; + + if (package != NULL) + { + free(package); + package = NULL; + } + + if (version != NULL) + { + free(version); + version = NULL; + } + + compare = PKG_ANY; + } + + break; + + case BEFORE_OPERATOR: + if (PKG_OPERATOR_CHAR(*ptr)) + { + switch(*ptr) + { + case '=': + compare = PKG_EQUAL; + break; + case '>': + compare = PKG_GREATER_THAN; + break; + case '<': + compare = PKG_LESS_THAN; + break; + case '!': + compare = PKG_NOT_EQUAL; + break; + default: + break; + } + + state = INSIDE_OPERATOR; + } + + break; + + case INSIDE_OPERATOR: + if (!PKG_OPERATOR_CHAR(*ptr)) + state = AFTER_OPERATOR; + else if (*ptr == '=') + { + switch(compare) + { + case PKG_LESS_THAN: + compare = PKG_LESS_THAN_EQUAL; + break; + case PKG_GREATER_THAN: + compare = PKG_GREATER_THAN_EQUAL; + break; + default: + break; + } + } + + break; + + case AFTER_OPERATOR: +#if DEBUG_PARSE + fprintf(stderr, "Found op: %d\n", compare); +#endif + + if (!isspace(*ptr)) + { + vstart = ptr; + state = INSIDE_VERSION; + } + break; + + case INSIDE_VERSION: + if (PKG_MODULE_SEPARATOR(*ptr) || *(ptr + 1) == '\0') + { + version = strndup(vstart, (ptr - vstart)); + state = OUTSIDE_MODULE; + +#if DEBUG_PARSE + fprintf(stderr, "Found version: %s\n", version); +#endif + deplist = pkg_dependency_add(deplist, package, version, compare); + + if (deplist_head == NULL) + deplist_head = deplist; + + if (package != NULL) + { + free(package); + package = NULL; + } + + if (version != NULL) + { + free(version); + version = NULL; + } + + compare = PKG_ANY; + } + + if (state == OUTSIDE_MODULE) + start = ptr; + break; + } + + ptr++; + } + + return deplist_head; +} diff --git a/parse.c b/parse.c index 0c3ee91..3418473 100644 --- a/parse.c +++ b/parse.c @@ -24,277 +24,6 @@ #include "pkg.h" #include "bsdstubs.h" -/* - * pkg_dependency_parse(pkg, depends) - * - * Add requirements to a .pc file. - * Commas are counted as whitespace, as to allow: - * @SUBSTVAR@, zlib - * getting substituted to: - * , zlib. - */ -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 pkg_dependency_t * -pkg_dependency_add(pkg_dependency_t *head, const char *package, const char *version, pkg_comparator_t compare) -{ - pkg_dependency_t *dep; - - dep = calloc(sizeof(pkg_dependency_t), 1); - dep->package = strdup(package); - - if (version != NULL) - dep->version = strdup(version); - - dep->compare = compare; - - dep->prev = head; - if (dep->prev != NULL) - dep->prev->next = dep; - -#if DEBUG_PARSE - fprintf(stderr, "--> %s %d %s\n", dep->package, dep->compare, dep->version); -#endif - - return dep; -} - -pkg_dependency_t * -pkg_dependency_append(pkg_dependency_t *head, pkg_dependency_t *tail) -{ - pkg_dependency_t *node; - - if (head == NULL) - return tail; - - /* skip to end of list */ - foreach_list_entry(head, node) - { - if (node->next == NULL) - break; - } - - node->next = tail; - tail->prev = node; - - return head; -} - -void -pkg_dependency_free(pkg_dependency_t *head) -{ - pkg_dependency_t *node, *next; - - foreach_list_entry_safe(head, next, node) - { - if (node->package != NULL) - free(node->package); - - if (node->version != NULL) - free(node->version); - - free(node); - } -} - -pkg_dependency_t * -pkg_dependency_parse(pkg_t *pkg, const char *depends) -{ - parse_state_t state = OUTSIDE_MODULE; - pkg_dependency_t *deplist = NULL; - pkg_dependency_t *deplist_head = NULL; - pkg_comparator_t compare = PKG_ANY; - char buf[BUFSIZ]; - char *kvdepends = pkg_tuple_parse(pkg->vars, depends); - char *start = buf; - char *ptr = buf; - char *vstart = NULL; - char *package = NULL, *version = NULL; - - strlcpy(buf, kvdepends, sizeof buf); - strlcat(buf, " ", sizeof buf); - free(kvdepends); - - while (*ptr) - { - switch (state) - { - case OUTSIDE_MODULE: - if (!PKG_MODULE_SEPARATOR(*ptr)) - state = INSIDE_MODULE_NAME; - - break; - - case INSIDE_MODULE_NAME: - if (isspace(*ptr)) - { - const char *sptr = ptr; - - while (*sptr && isspace(*sptr)) - sptr++; - - if (*sptr == '\0') - state = OUTSIDE_MODULE; - else if (PKG_MODULE_SEPARATOR(*sptr)) - state = OUTSIDE_MODULE; - else if (PKG_OPERATOR_CHAR(*sptr)) - state = BEFORE_OPERATOR; - else - state = OUTSIDE_MODULE; - } - else if (PKG_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 (PKG_MODULE_SEPARATOR(*iter)) - iter++; - - package = strndup(iter, ptr - iter); -#if DEBUG_PARSE - fprintf(stderr, "Found package: %s\n", package); -#endif - start = ptr; - } - - if (state == OUTSIDE_MODULE) - { - deplist = pkg_dependency_add(deplist, package, NULL, compare); - - if (deplist_head == NULL) - deplist_head = deplist; - - if (package != NULL) - { - free(package); - package = NULL; - } - - if (version != NULL) - { - free(version); - version = NULL; - } - - compare = PKG_ANY; - } - - break; - - case BEFORE_OPERATOR: - if (PKG_OPERATOR_CHAR(*ptr)) - { - switch(*ptr) - { - case '=': - compare = PKG_EQUAL; - break; - case '>': - compare = PKG_GREATER_THAN; - break; - case '<': - compare = PKG_LESS_THAN; - break; - case '!': - compare = PKG_NOT_EQUAL; - break; - default: - break; - } - - state = INSIDE_OPERATOR; - } - - break; - - case INSIDE_OPERATOR: - if (!PKG_OPERATOR_CHAR(*ptr)) - state = AFTER_OPERATOR; - else if (*ptr == '=') - { - switch(compare) - { - case PKG_LESS_THAN: - compare = PKG_LESS_THAN_EQUAL; - break; - case PKG_GREATER_THAN: - compare = PKG_GREATER_THAN_EQUAL; - break; - default: - break; - } - } - - break; - - case AFTER_OPERATOR: -#if DEBUG_PARSE - fprintf(stderr, "Found op: %d\n", compare); -#endif - - if (!isspace(*ptr)) - { - vstart = ptr; - state = INSIDE_VERSION; - } - break; - - case INSIDE_VERSION: - if (PKG_MODULE_SEPARATOR(*ptr) || *(ptr + 1) == '\0') - { - version = strndup(vstart, (ptr - vstart)); - state = OUTSIDE_MODULE; - -#if DEBUG_PARSE - fprintf(stderr, "Found version: %s\n", version); -#endif - deplist = pkg_dependency_add(deplist, package, version, compare); - - if (deplist_head == NULL) - deplist_head = deplist; - - if (package != NULL) - { - free(package); - package = NULL; - } - - if (version != NULL) - { - free(version); - version = NULL; - } - - compare = PKG_ANY; - } - - if (state == OUTSIDE_MODULE) - start = ptr; - break; - } - - ptr++; - } - - return deplist_head; -} - /* * parse_file(filename) *