]> pd.if.org Git - zpackage/blob - lib/vercmp.c
add libelf_soneed function
[zpackage] / lib / vercmp.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <ctype.h>
5
6 struct ver {
7         char str[1024]; /* string rep */
8         char *s; /* start component */
9         int cn; /* current component number */
10         char *next; /* start of potential next component */
11         char keep; /* character over-written with null byte */
12         int sep; /* number of characters in separator */
13         
14         int nv; /* numeric value */
15         int type; /* 0 null, 1 text, 2 numeric */
16         int release;
17         char *relstr;
18 };
19
20 static void init_ver(struct ver *v, const char *s) {
21         strncpy(v->str, s, 1023);
22         v->str[1023] = 0;
23         v->s = 0;
24         v->cn = 0;
25         v->next = v->str;
26         v->relstr = 0;
27         v->keep = 0;
28         v->sep = 0;
29
30         /* scan for trailing release */
31         int n;
32         n = strlen(v->str) - 1;
33         if (n > 0 && isdigit(v->str[n])) {
34                 while (isdigit(v->str[n])) {
35                         n--;
36                 }
37                 if (s[n] == '-') {
38                         v->relstr = v->str + n;
39                         v->release = atoi(v->str + n + 1);
40                         v->str[n] = 0;
41                 }
42         }
43
44 }
45
46 static int ver_cmp(struct ver *a, struct ver *b) {
47         if (a->type == 0 && b->type == 0) {
48                 return 0;
49         }
50         if (a->type != b->type) {
51                 return a->type < b->type ? -1 : 1;
52         }
53         if (a->type == 1) {
54                 int cmp;
55                 cmp = strcmp(a->s, b->s);
56                 if (cmp == 0) {
57                         return 0;
58                 }
59                 return cmp < 0 ? -1 : 1;
60         }
61         if (a->type == 2) {
62                 if (a->nv != b->nv)
63                 return a->nv < b->nv ? -1 : 1;
64         }
65         return 0;
66 }
67
68 static int next_comp(struct ver *v) {
69         char *s;
70
71         /* restore over-written character */
72         if (v->keep) {
73                 v->next[0] = v->keep;
74                 v->keep = 0;
75         }
76         s = v->next;
77
78         /* skip over anything that isn't alphanumeric */
79         v->sep = 0;
80         while (*s && !isalnum(*s)) {
81                 v->sep++;
82                 s++;
83         }
84         v->next = s;
85
86         /* zero return if at end of string */
87         if (!*s) {
88                 return 0;
89         }
90         if (isdigit(*s)) {
91                 v->type = 2;
92                 while (isdigit(*s)) s++;
93                 v->keep = *s;
94                 *s = 0;
95                 v->s = v->next;
96                 v->nv = atoi(v->s);
97         } else if (isalpha(*s)) {
98                 v->type = 1;
99                 while (isalpha(*s)) s++;
100                 v->keep = *s;
101                 *s = 0;
102                 v->s = v->next;
103         }
104         v->next = s;
105
106         return ++v->cn;
107 }
108
109 /*
110  * alphabetic less than numeric
111  */
112 int zpm_vercmp(const char *vsa, const char *vsb) {
113         struct ver a, b;
114         int an, bn;
115         int cmp;
116
117         init_ver(&a, vsa);
118         init_ver(&b, vsb);
119         do {
120                 an = next_comp(&a);
121                 bn = next_comp(&b);
122                 if (an != bn) {
123                         if (an == 0 && a.type == 2 && b.sep == 0 && b.type == 1) {
124                                 return 1;
125                         } else if (bn == 0 && b.type == 2 && a.sep == 0 && a.type == 1) {
126                                 return -1;
127                         }
128                         return an < bn ? -1 : 1;
129                 }
130                 cmp = ver_cmp(&a, &b);
131                 if (cmp != 0) {
132                         return cmp;
133                 }
134         } while (an && bn);
135
136         /* if we've gotten here, and both have releases, check those */
137         if (a.relstr && b.relstr && a.release != b.release) {
138                 return a.release < b.release ? -1 : 1;
139         }
140         
141         return 0;
142 }