On May 7, 2009, at 12:15 PM, devzero2000 wrote:
> On Thu, May 7, 2009 at 3:12 PM, Mark Hatle
> <mark.hatle@windriver.com> wrote:
> > While I don't have an answer for you, my concern with any change to
> > rpmvercmp is around compatibility.. bugs become features....
> >
> > What I've never seen well documented is the actual algorithm that
> rpmvercmp
> > uses for it's comparison (in a human readable form). I attempted
> to write
> > one once and I can dig it up if it will help... but I'm not even
> 100% sure
> > it's really correct.
> >
>
> Look here, for an example description
>
> https://fedorahosted.org/pyrpm/browser/doc/pyrpm-devel.txt
>
That describes the behavior, but not the algorithm
What @rpm5.org uses for what is traditionally called "rpmvercmp"
is in rpmdb/rpmevr.c in a function called rpmEVRcmp().
The code was rewritten for clarity a couple of years back.
Whether the rpmEVRcmp() code is "official", I will not say. YMMV,
caveat emptor.
Meanwhile this is the rpmEVRcmp() code that has now been used
@rpm5.org without
problem for several years.
int rpmEVRcmp(const char * a, const char * b)
/*@*/
{
const char * ae = NULL, * be = NULL;
int rc = 0; /* assume equal */
assert(a != NULL);
assert(b != NULL);
/* Compare version strings segment by segment. */
for (; *a && *b && rc == 0; a = ae, b = be) {
/* Skip leading non-alpha, non-digit characters. */
while (*a && !(xisdigit((int)*a) || xisrpmalpha((int)*a))) a++;
while (*b && !(xisdigit((int)*b) || xisrpmalpha((int)*b))) b++;
/* Wildcard comparison? */
/* Note: limited to suffix-only wildcard matching at the
moment. */
if (a[0] == '*' && a[1] == '\0') {
be = strchr(b, '\0'); /* XXX be = b + strlen(b); */
} else
if (b[0] == '*' && b[1] == '\0') {
ae = strchr(a, '\0'); /* XXX ae = a + strlen(a); */
} else
/* Digit string comparison? */
if (xisdigit((int)*a) || xisdigit((int)*b)) {
/* Discard leading zeroes. */
while (a[0] == '0' && xisdigit((int)a[1])) a++;
while (b[0] == '0' && xisdigit((int)b[1])) b++;
/* Find end of digit strings. */
ae = a; while (xisdigit((int)*ae)) ae++;
be = b; while (xisdigit((int)*be)) be++;
/* Calculate digit comparison return code. */
if (a == ae || b == be)
rc = (int)(*a - *b) * _invert_digits_alphas_comparison;
else {
rc = (ae - a) - (be - b);
if (!rc)
rc = strncmp(a, b, (ae - a));
}
} else {
/* Find end of alpha strings. */
ae = a; while (xisrpmalpha((int)*ae)) ae++;
be = b; while (xisrpmalpha((int)*be)) be++;
/* Calculate alpha comparison return code. */
rc = strncmp(a, b, MAX((ae - a), (be - b)));
}
}
/* Longer string wins. */
if (!rc)
rc = (int)(*a - *b);
/* Force strict -1, 0, 1 return. */
rc = (rc > 0 ? 1
: rc < 0 ? -1
: 0);
return rc;
}
Received on Thu May 7 18:42:32 2009