summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--pkg.c104
-rw-r--r--rpmvercmp.c120
-rw-r--r--rpmvercmp.h19
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
diff --git a/pkg.c b/pkg.c
index a56149b..e78c12d 100644
--- a/pkg.c
+++ b/pkg.c
@@ -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);