#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static void parseEVR(char *evr, const char **ep, const char **vp,
const char **rp)
{
const char *epoch;
const char *version;
const char *release;
char *s, *se;
s = evr;
while (*s && isdigit(*s)) s++;
se = strrchr(s, '-');
if(*s == ':') {
epoch = evr;
*s++ = '\0';
version = s;
if(*epoch == '\0') {
epoch = "0";
}
} else {
epoch = "0";
version = evr;
}
if(se) {
*se++ = '\0';
release = se;
} else {
release = NULL;
}
if(ep) *ep = epoch;
if(vp) *vp = version;
if(rp) *rp = release;
}
static int rpmvercmp(const char *a, const char *b)
{
char oldch1, oldch2;
char *str1, *str2;
char *ptr1, *ptr2;
char *one, *two;
int rc;
int isnum;
int ret = 0;
if(strcmp(a, b) == 0) return 0;
str1 = strdup(a);
str2 = strdup(b);
one = ptr1 = str1;
two = ptr2 = str2;
while (*one && *two) {
while (*one && !isalnum((int)*one)) one++;
while (*two && !isalnum((int)*two)) two++;
if (!(*one && *two)) break;
if ((one - ptr1) != (two - ptr2)) {
ret = (one - ptr1) < (two - ptr2) ? -1 : 1;
goto cleanup;
}
ptr1 = one;
ptr2 = two;
if (isdigit((int)*ptr1)) {
while (*ptr1 && isdigit((int)*ptr1)) ptr1++;
while (*ptr2 && isdigit((int)*ptr2)) ptr2++;
isnum = 1;
} else {
while (*ptr1 && isalpha((int)*ptr1)) ptr1++;
while (*ptr2 && isalpha((int)*ptr2)) ptr2++;
isnum = 0;
}
oldch1 = *ptr1;
*ptr1 = '\0';
oldch2 = *ptr2;
*ptr2 = '\0';
if (one == ptr1) {
ret = -1;
goto cleanup;
}
if (two == ptr2) {
ret = isnum ? 1 : -1;
goto cleanup;
}
if (isnum) {
while (*one == '0') one++;
while (*two == '0') two++;
if (strlen(one) > strlen(two)) {
ret = 1;
goto cleanup;
}
if (strlen(two) > strlen(one)) {
ret = -1;
goto cleanup;
}
}
rc = strcmp(one, two);
if (rc) {
ret = rc < 1 ? -1 : 1;
goto cleanup;
}
*ptr1 = oldch1;
one = ptr1;
*ptr2 = oldch2;
two = ptr2;
}
if ((!*one) && (!*two)) {
ret = 0;
goto cleanup;
}
if ( (!*one && !isalpha((int)*two))
|| isalpha((int)*one) ) {
ret = -1;
} else {
ret = 1;
}
cleanup:
free(str1);
free(str2);
return ret;
}
int alpm_pkg_vercmp(const char *a, const char *b)
{
char *full1, *full2;
const char *epoch1, *ver1, *rel1;
const char *epoch2, *ver2, *rel2;
int ret;
if(!a && !b) {
return 0;
} else if(!a) {
return -1;
} else if(!b) {
return 1;
}
if(strcmp(a, b) == 0) {
return 0;
}
full1 = strdup(a);
full2 = strdup(b);
parseEVR(full1, &epoch1, &ver1, &rel1);
parseEVR(full2, &epoch2, &ver2, &rel2);
ret = rpmvercmp(epoch1, epoch2);
if(ret == 0) {
ret = rpmvercmp(ver1, ver2);
if(ret == 0 && rel1 && rel2) {
ret = rpmvercmp(rel1, rel2);
}
}
free(full1);
free(full2);
return ret;
}
int main(const int argc, const char *const argv[]) {
if (argc != 3) {
fputs("error: wrong number of arguments\n", stderr);
return EXIT_FAILURE;
}
const char *const v1 = argv[1];
const char *const v2 = argv[2];
const int res = alpm_pkg_vercmp(v1, v2);
if (res > 0) {
puts("Greater");
} else if (res < 0) {
puts("Less");
} else {
puts("Equal");
}
return EXIT_SUCCESS;
}