#include #include #include #include struct ver { char str[1024]; /* string rep */ char *s; /* start component */ int cn; /* current component number */ char *next; /* start of potential next component */ char keep; /* character over-written with null byte */ int sep; /* number of characters in separator */ int nv; /* numeric value */ int type; /* 0 null, 1 text, 2 numeric */ }; static void init_ver(struct ver *v, const char *s) { strncpy(v->str, s, 1023); v->str[1023] = 0; v->s = 0; v->cn = 0; v->next = v->str; v->keep = 0; v->sep = 0; } static int ver_cmp(struct ver *a, struct ver *b) { if (a->type == 0 && b->type == 0) { return 0; } if (a->type != b->type) { return a->type < b->type ? -1 : 1; } if (a->type == 1) { int cmp; if (a->s && ! b->s) return 1; if (b->s && ! a->s) return -1; if (!b->s && ! a->s) { return 0; } cmp = strcmp(a->s, b->s); if (cmp == 0) { return 0; } return cmp < 0 ? -1 : 1; } if (a->type == 2) { if (a->nv != b->nv) return a->nv < b->nv ? -1 : 1; } return 0; } static int next_comp(struct ver *v) { char *s; /* restore over-written character */ if (v->keep) { v->next[0] = v->keep; v->keep = 0; } s = v->next; /* skip over anything that isn't alphanumeric */ v->sep = 0; while (*s && !isalnum(*s)) { v->sep++; s++; } v->next = s; /* zero return if at end of string */ if (!*s) { return 0; } if (isdigit(*s)) { v->type = 2; while (isdigit(*s)) s++; v->keep = *s; *s = 0; v->s = v->next; v->nv = atoi(v->s); } else if (isalpha(*s)) { v->type = 1; while (isalpha(*s)) s++; v->keep = *s; *s = 0; v->s = v->next; } v->next = s; return ++v->cn; } /* * alphabetic less than numeric */ int zpm_vercmp(const char *vsa, const char *vsb) { struct ver a, b; int an, bn; int cmp; if (vsa && !vsb) { return 1; } if (vsb && !vsa) { return -1; } if (!vsa && !vsb) { return 0; } init_ver(&a, vsa); init_ver(&b, vsb); do { an = next_comp(&a); bn = next_comp(&b); if (an != bn) { if (an == 0 && a.type == 2 && b.sep == 0 && b.type == 1) { return 1; } else if (bn == 0 && b.type == 2 && a.sep == 0 && a.type == 1) { return -1; } return an < bn ? -1 : 1; } if (an == 0 && bn == 0) { return 0; } cmp = ver_cmp(&a, &b); if (cmp != 0) { return cmp; } } while (an && bn); return 0; }