diff options
author | Dan Nicholson <dbn.lists@gmail.com> | 2012-10-10 05:30:09 -0700 |
---|---|---|
committer | Dan Nicholson <dbn.lists@gmail.com> | 2013-05-17 05:36:12 -0700 |
commit | 4623b5e85a55b82aa73b184213459ba3c9971ba7 (patch) | |
tree | e901b8ef55e05a9836fe4ca803f8d4404f1ae4eb | |
parent | 32427bf2c648fd7425bc1e63636f5aa7456cd050 (diff) | |
download | pkg-config-4623b5e85a55b82aa73b184213459ba3c9971ba7.tar.gz |
Split rpmvercmp code into separate file
The rpmvercmp code is taken directly from upstream. Moving it to a
separate file allows it to be diffed and synced easily with the upstream
version. It also becomes really easy to switch to the actual rpmlib
version if that's ever desired.
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | pkg.c | 104 | ||||
-rw-r--r-- | rpmvercmp.c | 120 | ||||
-rw-r--r-- | rpmvercmp.h | 19 |
4 files changed, 142 insertions, 103 deletions
diff --git a/Makefile.am b/Makefile.am index 41e48e8..f64e2cd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -34,6 +34,8 @@ pkg_config_SOURCES= \ pkg.c \ parse.h \ parse.c \ + rpmvercmp.c \ + rpmvercmp.h \ main.c if HOST_TOOL @@ -24,6 +24,7 @@ #include "pkg.h" #include "parse.h" +#include "rpmvercmp.h" #ifdef HAVE_MALLOC_H # include <malloc.h> @@ -1067,109 +1068,6 @@ packages_get_var (GList *pkgs, return retval; } - - -/* Stolen verbatim from rpm/lib/misc.c - RPM is Copyright (c) 1998 by Red Hat Software, Inc., - and may be distributed under the terms of the GPL and LGPL. -*/ -/* compare alpha and numeric segments of two versions */ -/* return 1: a is newer than b */ -/* 0: a and b are the same version */ -/* -1: b is newer than a */ -static int rpmvercmp(const char * a, const char * b) { - char oldch1, oldch2; - char * str1, * str2; - char * one, * two; - int rc; - int isnum; - - /* easy comparison to see if versions are identical */ - if (!strcmp(a, b)) return 0; - - str1 = g_alloca(strlen(a) + 1); - str2 = g_alloca(strlen(b) + 1); - - strcpy(str1, a); - strcpy(str2, b); - - one = str1; - two = str2; - - /* loop through each version segment of str1 and str2 and compare them */ - while (*one && *two) { - while (*one && !isalnum((guchar)*one)) one++; - while (*two && !isalnum((guchar)*two)) two++; - - /* If we ran to the end of either, we are finished with the loop */ - if (!(*one && *two)) break; - - str1 = one; - str2 = two; - - /* grab first completely alpha or completely numeric segment */ - /* leave one and two pointing to the start of the alpha or numeric */ - /* segment and walk str1 and str2 to end of segment */ - if (isdigit((guchar)*str1)) { - while (*str1 && isdigit((guchar)*str1)) str1++; - while (*str2 && isdigit((guchar)*str2)) str2++; - isnum = 1; - } else { - while (*str1 && isalpha((guchar)*str1)) str1++; - while (*str2 && isalpha((guchar)*str2)) str2++; - isnum = 0; - } - - /* save character at the end of the alpha or numeric segment */ - /* so that they can be restored after the comparison */ - oldch1 = *str1; - *str1 = '\0'; - oldch2 = *str2; - *str2 = '\0'; - - /* take care of the case where the two version segments are */ - /* different types: one numeric and one alpha */ - if (one == str1) return -1; /* arbitrary */ - /* XXX See patch #60884 (and details) from bugzilla #50977. */ - if (two == str2) return (isnum ? 1 : -1); - - if (isnum) { - /* this used to be done by converting the digit segments */ - /* to ints using atoi() - it's changed because long */ - /* digit segments can overflow an int - this should fix that. */ - - /* throw away any leading zeros - it's a number, right? */ - while (*one == '0') one++; - while (*two == '0') two++; - - /* whichever number has more digits wins */ - if (strlen(one) > strlen(two)) return 1; - if (strlen(two) > strlen(one)) return -1; - } - - /* strcmp will return which one is greater - even if the two */ - /* segments are alpha or if they are numeric. don't return */ - /* if they are equal because there might be more segments to */ - /* compare */ - rc = strcmp(one, two); - if (rc) return rc; - - /* restore character that was replaced by null above */ - *str1 = oldch1; - one = str1; - *str2 = oldch2; - two = str2; - } - - /* this catches the case where all numeric and alpha segments have */ - /* compared identically but the segment sepparating characters were */ - /* different */ - if ((!*one) && (!*two)) return 0; - - /* whichever version still has characters left over wins */ - if (!*one) return -1; else return 1; -} - int compare_versions (const char * a, const char *b) { diff --git a/rpmvercmp.c b/rpmvercmp.c new file mode 100644 index 0000000..3b2e8d6 --- /dev/null +++ b/rpmvercmp.c @@ -0,0 +1,120 @@ +/* + * This code is taken from the RPM package manager. + * + * RPM is Copyright (c) 1998 by Red Hat Software, Inc., + * and may be distributed under the terms of the GPL and LGPL. + * See http://rpm.org/gitweb?p=rpm.git;a=blob_plain;f=COPYING;hb=HEAD + * + * The code should follow upstream as closely as possible. + * See http://rpm.org/gitweb?p=rpm.git;a=blob_plain;f=lib/rpmvercmp.c;hb=HEAD + * + * Currently the only difference as a policy is that upstream uses C99 + * features and pkg-config does not require a C99 compiler yet. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "rpmvercmp.h" + +#include <glib.h> +#include <string.h> +#include <ctype.h> + +/* compare alpha and numeric segments of two versions */ +/* return 1: a is newer than b */ +/* 0: a and b are the same version */ +/* -1: b is newer than a */ +int rpmvercmp(const char * a, const char * b) { + char oldch1, oldch2; + char * str1, * str2; + char * one, * two; + int rc; + int isnum; + + /* easy comparison to see if versions are identical */ + if (!strcmp(a, b)) return 0; + + str1 = g_alloca(strlen(a) + 1); + str2 = g_alloca(strlen(b) + 1); + + strcpy(str1, a); + strcpy(str2, b); + + one = str1; + two = str2; + + /* loop through each version segment of str1 and str2 and compare them */ + while (*one && *two) { + while (*one && !isalnum((guchar)*one)) one++; + while (*two && !isalnum((guchar)*two)) two++; + + /* If we ran to the end of either, we are finished with the loop */ + if (!(*one && *two)) break; + + str1 = one; + str2 = two; + + /* grab first completely alpha or completely numeric segment */ + /* leave one and two pointing to the start of the alpha or numeric */ + /* segment and walk str1 and str2 to end of segment */ + if (isdigit((guchar)*str1)) { + while (*str1 && isdigit((guchar)*str1)) str1++; + while (*str2 && isdigit((guchar)*str2)) str2++; + isnum = 1; + } else { + while (*str1 && isalpha((guchar)*str1)) str1++; + while (*str2 && isalpha((guchar)*str2)) str2++; + isnum = 0; + } + + /* save character at the end of the alpha or numeric segment */ + /* so that they can be restored after the comparison */ + oldch1 = *str1; + *str1 = '\0'; + oldch2 = *str2; + *str2 = '\0'; + + /* take care of the case where the two version segments are */ + /* different types: one numeric and one alpha */ + if (one == str1) return -1; /* arbitrary */ + /* XXX See patch #60884 (and details) from bugzilla #50977. */ + if (two == str2) return (isnum ? 1 : -1); + + if (isnum) { + /* this used to be done by converting the digit segments */ + /* to ints using atoi() - it's changed because long */ + /* digit segments can overflow an int - this should fix that. */ + + /* throw away any leading zeros - it's a number, right? */ + while (*one == '0') one++; + while (*two == '0') two++; + + /* whichever number has more digits wins */ + if (strlen(one) > strlen(two)) return 1; + if (strlen(two) > strlen(one)) return -1; + } + + /* strcmp will return which one is greater - even if the two */ + /* segments are alpha or if they are numeric. don't return */ + /* if they are equal because there might be more segments to */ + /* compare */ + rc = strcmp(one, two); + if (rc) return rc; + + /* restore character that was replaced by null above */ + *str1 = oldch1; + one = str1; + *str2 = oldch2; + two = str2; + } + + /* this catches the case where all numeric and alpha segments have */ + /* compared identically but the segment sepparating characters were */ + /* different */ + if ((!*one) && (!*two)) return 0; + + /* whichever version still has characters left over wins */ + if (!*one) return -1; else return 1; +} diff --git a/rpmvercmp.h b/rpmvercmp.h new file mode 100644 index 0000000..c08c1bc --- /dev/null +++ b/rpmvercmp.h @@ -0,0 +1,19 @@ +/* + * This code is taken from the RPM package manager. + * + * RPM is Copyright (c) 1998 by Red Hat Software, Inc., + * and may be distributed under the terms of the GPL and LGPL. + * See http://rpm.org/gitweb?p=rpm.git;a=blob_plain;f=COPYING;hb=HEAD + * + * The code should follow upstream as closely as possible. + * See http://rpm.org/gitweb?p=rpm.git;a=blob_plain;f=lib/rpmlib.h;hb=HEAD + */ + +/* + * Segmented string compare for version or release strings. + * + * @param a 1st string + * @param b 2nd string + * @return +1 if a is "newer", 0 if equal, -1 if b is "newer" + */ +int rpmvercmp(const char * a, const char * b); |