satsolver  0.17.2
evr.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007-2009, Novell Inc.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7 
8 /*
9  * evr.c
10  *
11  * version compare
12  */
13 
14 #include <stdio.h>
15 #include <string.h>
16 #include "evr.h"
17 #include "pool.h"
18 
19 
20 
21 #if defined(DEBIAN_SEMANTICS) || defined(MULTI_SEMANTICS)
22 
23 #ifdef MULTI_SEMANTICS
24 # define sat_vercmp sat_vercmp_deb
25 #endif
26 
27 /* debian type version compare */
28 int
29 sat_vercmp(const char *s1, const char *q1, const char *s2, const char *q2)
30 {
31  int r, c1, c2;
32  while (1)
33  {
34  c1 = s1 < q1 ? *(const unsigned char *)s1++ : 0;
35  c2 = s2 < q2 ? *(const unsigned char *)s2++ : 0;
36  if ((c1 >= '0' && c1 <= '9') && (c2 >= '0' && c2 <= '9'))
37  {
38  while (c1 == '0')
39  c1 = s1 < q1 ? *(const unsigned char *)s1++ : 0;
40  while (c2 == '0')
41  c2 = s2 < q2 ? *(const unsigned char *)s2++ : 0;
42  r = 0;
43  while ((c1 >= '0' && c1 <= '9') && (c2 >= '0' && c2 <= '9'))
44  {
45  if (!r)
46  r = c1 - c2;
47  c1 = s1 < q1 ? *(const unsigned char *)s1++ : 0;
48  c2 = s2 < q2 ? *(const unsigned char *)s2++ : 0;
49  }
50  if (c1 >= '0' && c1 <= '9')
51  return 1;
52  if (c2 >= '0' && c2 <= '9')
53  return -1;
54  if (r)
55  return r < 0 ? -1 : 1;
56  }
57  c1 = c1 == '~' ? -1 : !c1 || (c1 >= '0' && c1 <= '9') || (c1 >= 'A' && c1 <= 'Z') || (c1 >= 'a' && c1 <= 'z') ? c1 : c1 + 256;
58  c2 = c2 == '~' ? -1 : !c2 || (c2 >= '0' && c2 <= '9') || (c2 >= 'A' && c2 <= 'Z') || (c2 >= 'a' && c2 <= 'z') ? c2 : c2 + 256;
59  r = c1 - c2;
60  if (r)
61  return r < 0 ? -1 : 1;
62  if (!c1)
63  return 0;
64  }
65 }
66 
67 #ifdef MULTI_SEMANTICS
68 # undef sat_vercmp
69 #endif
70 
71 #endif
72 
73 #if !defined(DEBIAN_SEMANTICS) || defined(MULTI_SEMANTICS)
74 
75 /* rpm type version compare */
76 /* note: the code assumes that *q1 and *q2 are not alphanumeric! */
77 
78 int
79 sat_vercmp(const char *s1, const char *q1, const char *s2, const char *q2)
80 {
81  int r = 0;
82  const char *e1, *e2;
83 
84  while (s1 < q1 && s2 < q2)
85  {
86  while (s1 < q1 && !(*s1 >= '0' && *s1 <= '9') &&
87  !(*s1 >= 'a' && *s1 <= 'z') && !(*s1 >= 'A' && *s1 <= 'Z'))
88  s1++;
89  while (s2 < q2 && !(*s2 >= '0' && *s2 <= '9') &&
90  !(*s2 >= 'a' && *s2 <= 'z') && !(*s2 >= 'A' && *s2 <= 'Z'))
91  s2++;
92  if ((*s1 >= '0' && *s1 <= '9') || (*s2 >= '0' && *s2 <= '9'))
93  {
94  while (*s1 == '0' && s1[1] >= '0' && s1[1] <= '9')
95  s1++;
96  while (*s2 == '0' && s2[1] >= '0' && s2[1] <= '9')
97  s2++;
98  for (e1 = s1; *e1 >= '0' && *e1 <= '9'; )
99  e1++;
100  for (e2 = s2; *e2 >= '0' && *e2 <= '9'; )
101  e2++;
102  r = (e1 - s1) - (e2 - s2);
103  if (!r)
104  r = strncmp(s1, s2, e1 - s1);
105  if (r)
106  return r > 0 ? 1 : -1;
107  }
108  else
109  {
110  for (e1 = s1; (*e1 >= 'a' && *e1 <= 'z') || (*e1 >= 'A' && *e1 <= 'Z'); )
111  e1++;
112  for (e2 = s2; (*e2 >= 'a' && *e2 <= 'z') || (*e2 >= 'A' && *e2 <= 'Z'); )
113  e2++;
114  r = (e1 - s1) - (e2 - s2);
115  if (r > 0)
116  {
117  r = strncmp(s1, s2, e2 - s2);
118  return r >= 0 ? 1 : -1;
119  }
120  if (r < 0)
121  {
122  r = strncmp(s1, s2, e1 - s1);
123  return r <= 0 ? -1 : 1;
124  }
125  r = strncmp(s1, s2, e1 - s1);
126  if (r)
127  return r > 0 ? 1 : -1;
128  }
129  s1 = e1;
130  s2 = e2;
131  }
132  return s1 < q1 ? 1 : s2 < q2 ? -1 : 0;
133 }
134 
135 #endif
136 
137 #if defined(MULTI_SEMANTICS)
138 # define sat_vercmp (*(pool->disttype == DISTTYPE_DEB ? &sat_vercmp_deb : &sat_ver##cmp))
139 #endif
140 
141 /* edition (e:v-r) compare */
142 int
143 pool_evrcmp_str(const Pool *pool, const char *evr1, const char *evr2, int mode)
144 {
145  int r;
146  const char *s1, *s2;
147  const char *r1, *r2;
148 
149  if (evr1 == evr2)
150  return 0;
151 
152 #if 0
153  POOL_DEBUG(DEBUG_EVRCMP, "evrcmp %s %s mode=%d\n", evr1, evr2, mode);
154 #endif
155  for (s1 = evr1; *s1 >= '0' && *s1 <= '9'; s1++)
156  ;
157  for (s2 = evr2; *s2 >= '0' && *s2 <= '9'; s2++)
158  ;
159  if (mode == EVRCMP_MATCH && (*evr1 == ':' || *evr2 == ':'))
160  {
161  /* empty epoch, skip epoch check */
162  if (*s1 == ':')
163  evr1 = s1 + 1;
164  if (*s2 == ':')
165  evr2 = s2 + 1;
166  s1 = evr1;
167  s2 = evr2;
168  }
169  if (s1 == evr1 || *s1 != ':')
170  s1 = 0;
171  if (s2 == evr2 || *s2 != ':')
172  s2 = 0;
173  if (s1 && s2)
174  {
175  r = sat_vercmp(evr1, s1, evr2, s2);
176  if (r)
177  return r;
178  evr1 = s1 + 1;
179  evr2 = s2 + 1;
180  }
181  else if (s1)
182  {
183  if (!pool->promoteepoch)
184  {
185  while (*evr1 == '0')
186  evr1++;
187  if (*evr1 != ':')
188  return 1;
189  }
190  evr1 = s1 + 1;
191  }
192  else if (s2)
193  {
194  while (*evr2 == '0')
195  evr2++;
196  if (*evr2 != ':')
197  return -1;
198  evr2 = s2 + 1;
199  }
200  for (s1 = evr1, r1 = 0; *s1; s1++)
201  if (*s1 == '-')
202  r1 = s1;
203  for (s2 = evr2, r2 = 0; *s2; s2++)
204  if (*s2 == '-')
205  r2 = s2;
206 
207  r = 0;
208  if (mode != EVRCMP_MATCH || (evr1 != (r1 ? r1 : s1) && evr2 != (r2 ? r2 : s2)))
209  r = sat_vercmp(evr1, r1 ? r1 : s1, evr2, r2 ? r2 : s2);
210  if (r)
211  return r;
212 
213  if (mode == EVRCMP_COMPARE)
214  {
215  if (!r1 && r2)
216  return -1;
217  if (r1 && !r2)
218  return 1;
219  }
220  if (mode == EVRCMP_COMPARE_EVONLY)
221  return 0;
222  if (r1 && r2)
223  {
224  if (s1 != ++r1 && s2 != ++r2)
225  r = sat_vercmp(r1, s1, r2, s2);
226  }
227  return r;
228 }
229 
230 int
231 pool_evrcmp(const Pool *pool, Id evr1id, Id evr2id, int mode)
232 {
233  const char *evr1, *evr2;
234  if (evr1id == evr2id)
235  return 0;
236  evr1 = id2str(pool, evr1id);
237  evr2 = id2str(pool, evr2id);
238  return evrcmp_str(pool, evr1, evr2, mode);
239 }
240 
241 int
242 pool_evrmatch(const Pool *pool, Id evrid, const char *epoch, const char *version, const char *release)
243 {
244  const char *evr1;
245  const char *s1;
246  const char *r1;
247  int r;
248 
249  evr1 = id2str(pool, evrid);
250  for (s1 = evr1; *s1 >= '0' && *s1 <= '9'; s1++)
251  ;
252  if (s1 != evr1 && *s1 == ':')
253  {
254  if (epoch)
255  {
256  r = sat_vercmp(evr1, s1, epoch, epoch + strlen(epoch));
257  if (r)
258  return r;
259  }
260  evr1 = s1 + 1;
261  }
262  else if (epoch)
263  {
264  while (*epoch == '0')
265  epoch++;
266  if (*epoch)
267  return -1;
268  }
269  for (s1 = evr1, r1 = 0; *s1; s1++)
270  if (*s1 == '-')
271  r1 = s1;
272  if (version)
273  {
274  r = sat_vercmp(evr1, r1 ? r1 : s1, version, version + strlen(version));
275  if (r)
276  return r;
277  }
278  if (release)
279  {
280  if (!r1)
281  return -1;
282  r = sat_vercmp(r1 + 1, s1, release, release + strlen(release));
283  if (r)
284  return r;
285  }
286  return 0;
287 }
288