/*
Copyright (C) 1988, 1991-2008 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#include
#include "system.h"
#include "vercmp.h"
#define xisalnum isalnum
#define xisdigit isdigit
#define xisalpha isalpha
/*
* match file suffix defined as RE (\.[A-Za-z][A-Za-z0-9]*)*$
*
* Return pointer to suffix begin or NULL if not found.
*/
const char* match_suffix(const char *str)
{
const char *match = NULL;
bool read_alpha = false;
while (*str)
{
if (read_alpha)
{
read_alpha = false;
if (!xisalpha(*str))
match = NULL;
}
else if ('.'==*str)
{
read_alpha = true;
if (!match)
match = str;
}
else if (!xisalnum(*str))
match = NULL;
str++;
}
return match;
}
int
filevercmp (const char *a, const char *b)
{
char oldch1, oldch2;
char * str1, * str2;
char * one, * two;
/* easy comparison to see if versions are identical */
if (!strcmp(a, b)) return 0;
one = alloca(strlen(a) + 1);
two = alloca(strlen(b) + 1);
strcpy(one, a);
strcpy(two, b);
/* cut file suffixes */
oldch1 = oldch2 = '\0';
if ((str1 = (char*)match_suffix(one))) {
oldch1 = *str1;
*str1 = '\0';
}
if ((str2 = (char*)match_suffix(two))) {
oldch2 = *str2;
*str2 = '\0';
}
if ((str1 || str2) && 0 == strcmp(one, two)) {
/* restore file suffixes */
if (str1)
*str1 = oldch1;
if (str2)
*str2 = oldch2;
}
return verrevcmp(one, two);
}
#define cisdigit isdigit
#define cisalpha isalpha
/* following code was taken from dpkg (vercmp.c) */
/* assume ascii; warning: evaluates x multiple times! */
#define order(x) ((x) == '~' ? -1 \
: cisdigit((x)) ? 0 \
: !(x) ? 0 \
: cisalpha((x)) ? (x) \
: (x) + 256)
int verrevcmp(const char *val, const char *ref) {
/*if (!val) val= "";
if (!ref) ref= "";*/
while (*val || *ref) {
int first_diff= 0;
while ( (*val && !cisdigit(*val)) || (*ref && !cisdigit(*ref)) ) {
int vc= order(*val), rc= order(*ref);
if (vc != rc) return vc - rc;
val++; ref++;
}
while ( *val == '0' ) val++;
while ( *ref == '0' ) ref++;
while (cisdigit(*val) && cisdigit(*ref)) {
if (!first_diff) first_diff= *val - *ref;
val++; ref++;
}
if (cisdigit(*val)) return 1;
if (cisdigit(*ref)) return -1;
if (first_diff) return first_diff;
}
return 0;
}