[PATCH 1/5] Split rpmvercmp code into separate file

Dan Nicholson dbn.lists at gmail.com
Sat Apr 20 09:41:54 PDT 2013


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.
---
 Makefile.am |   2 +
 pkg.c       | 104 +---------------------------------------------------
 rpmvercmp.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 rpmvercmp.h |  19 ++++++++++
 4 files changed, 142 insertions(+), 103 deletions(-)
 create mode 100644 rpmvercmp.c
 create mode 100644 rpmvercmp.h

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);
-- 
1.8.1.4



More information about the pkg-config mailing list