2 * \file lib/rpmvercmp.c
11 /* compare alpha and numeric segments of two versions */
12 /* return 1: a is newer than b */
13 /* 0: a and b are the same version */
14 /* -1: b is newer than a */
15 int rpmvercmp(const char * a, const char * b)
23 /* easy comparison to see if versions are identical */
24 if (!strcmp(a, b)) return 0;
26 str1 = alloca(strlen(a) + 1);
27 str2 = alloca(strlen(b) + 1);
35 /* loop through each version segment of str1 and str2 and compare them */
38 while (*one && *two) {
39 while (*one && !xisalnum(*one)) one++;
40 while (*two && !xisalnum(*two)) two++;
45 /* grab first completely alpha or completely numeric segment */
46 /* leave one and two pointing to the start of the alpha or numeric */
47 /* segment and walk str1 and str2 to end of segment */
48 if (xisdigit(*str1)) {
49 while (*str1 && xisdigit(*str1)) str1++;
50 while (*str2 && xisdigit(*str2)) str2++;
53 while (*str1 && xisalpha(*str1)) str1++;
54 while (*str2 && xisalpha(*str2)) str2++;
58 /* save character at the end of the alpha or numeric segment */
59 /* so that they can be restored after the comparison */
67 /* take care of the case where the two version segments are */
68 /* different types: one numeric, the other alpha (i.e. empty) */
69 if (one == str1) return -1; /* arbitrary */
70 /* XXX See patch #60884 (and details) from bugzilla #50977. */
71 if (two == str2) return (isnum ? 1 : -1);
74 /* this used to be done by converting the digit segments */
75 /* to ints using atoi() - it's changed because long */
76 /* digit segments can overflow an int - this should fix that. */
78 /* throw away any leading zeros - it's a number, right? */
79 while (*one == '0') one++;
80 while (*two == '0') two++;
82 /* whichever number has more digits wins */
83 if (strlen(one) > strlen(two)) return 1;
84 if (strlen(two) > strlen(one)) return -1;
87 /* strcmp will return which one is greater - even if the two */
88 /* segments are alpha or if they are numeric. don't return */
89 /* if they are equal because there might be more segments to */
91 rc = strcmp(one, two);
94 /* restore character that was replaced by null above */
105 /* this catches the case where all numeric and alpha segments have */
106 /* compared identically but the segment sepparating characters were */
109 if ((!*one) && (!*two)) return 0;
111 /* whichever version still has characters left over wins */
112 if (!*one) return -1; else return 1;