* Add #include <langinfo.h> to cmdline/apt-get.cc. Thi...
[ntk/apt.git] / apt-pkg / deb / debversion.cc
CommitLineData
b2e465d6
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
7b464090 3// $Id: debversion.cc,v 1.7 2003/07/18 14:13:59 mdz Exp $
b2e465d6
AL
4/* ######################################################################
5
6 Debian Version - Versioning system for Debian
7
8 This implements the standard Debian versioning system.
9
10 ##################################################################### */
11 /*}}}*/
12// Include Files /*{{{*/
13#define APT_COMPATIBILITY 986
14#ifdef __GNUG__
15#pragma implementation "apt-pkg/debversion.h"
16#endif
17
18#include <apt-pkg/debversion.h>
19#include <apt-pkg/pkgcache.h>
20
21#include <stdlib.h>
233b185f 22#include <ctype.h>
b2e465d6
AL
23 /*}}}*/
24
25debVersioningSystem debVS;
26
27// debVS::debVersioningSystem - Constructor /*{{{*/
28// ---------------------------------------------------------------------
29/* */
30debVersioningSystem::debVersioningSystem()
31{
32 Label = "Standard .deb";
33}
34 /*}}}*/
1e8167a6 35
b2e465d6
AL
36// debVS::CmpFragment - Compare versions /*{{{*/
37// ---------------------------------------------------------------------
09e712b1
AL
38/* This compares a fragment of the version. This is a slightly adapted
39 version of what dpkg uses. */
40#define order(x) ((x) == '~' ? -1 \
41 : isdigit((x)) ? 0 \
42 : !(x) ? 0 \
43 : isalpha((x)) ? (x) \
44 : (x) + 256)
45int debVersioningSystem::CmpFragment(const char *A,const char *AEnd,
b2e465d6
AL
46 const char *B,const char *BEnd)
47{
48 if (A >= AEnd && B >= BEnd)
49 return 0;
50 if (A >= AEnd)
51 return -1;
52 if (B >= BEnd)
53 return 1;
09e712b1 54
b2e465d6 55 /* Iterate over the whole string
09e712b1 56 What this does is to spilt the whole string into groups of
b2e465d6
AL
57 numeric and non numeric portions. For instance:
58 a67bhgs89
59 Has 4 portions 'a', '67', 'bhgs', '89'. A more normal:
60 2.7.2-linux-1
61 Has '2', '.', '7', '.' ,'-linux-','1' */
62 const char *lhs = A;
63 const char *rhs = B;
64 while (lhs != AEnd && rhs != BEnd)
65 {
1e8167a6 66 int first_diff = 0;
09e712b1 67
7b464090
AL
68 while (lhs != AEnd && rhs != BEnd &&
69 (!isdigit(*lhs) || !isdigit(*rhs)))
09e712b1
AL
70 {
71 int vc = order(*lhs);
72 int rc = order(*rhs);
73 if (vc != rc)
74 return vc - rc;
1e8167a6 75 lhs++; rhs++;
b2e465d6 76 }
b2e465d6 77
09e712b1
AL
78 while (*lhs == '0')
79 lhs++;
80 while (*rhs == '0')
81 rhs++;
82 while (isdigit(*lhs) && isdigit(*rhs))
83 {
84 if (!first_diff)
85 first_diff = *lhs - *rhs;
86 lhs++;
87 rhs++;
1e8167a6 88 }
09e712b1
AL
89
90 if (isdigit(*lhs))
91 return 1;
92 if (isdigit(*rhs))
93 return -1;
94 if (first_diff)
95 return first_diff;
b2e465d6
AL
96 }
97
98 // The strings must be equal
99 if (lhs == AEnd && rhs == BEnd)
100 return 0;
101
102 // lhs is shorter
103 if (lhs == AEnd)
104 return -1;
105
106 // rhs is shorter
107 if (rhs == BEnd)
108 return 1;
09e712b1 109
b2e465d6
AL
110 // Shouldnt happen
111 return 1;
112}
113 /*}}}*/
114// debVS::CmpVersion - Comparison for versions /*{{{*/
115// ---------------------------------------------------------------------
116/* This fragments the version into E:V-R triples and compares each
117 portion separately. */
118int debVersioningSystem::DoCmpVersion(const char *A,const char *AEnd,
119 const char *B,const char *BEnd)
120{
121 // Strip off the epoch and compare it
122 const char *lhs = A;
123 const char *rhs = B;
124 for (;lhs != AEnd && *lhs != ':'; lhs++);
125 for (;rhs != BEnd && *rhs != ':'; rhs++);
126 if (lhs == AEnd)
127 lhs = A;
128 if (rhs == BEnd)
129 rhs = B;
130
131 // Compare the epoch
132 int Res = CmpFragment(A,lhs,B,rhs);
133 if (Res != 0)
134 return Res;
135
136 // Skip the :
137 if (lhs != A)
138 lhs++;
139 if (rhs != B)
140 rhs++;
141
142 // Find the last -
143 const char *dlhs = AEnd-1;
144 const char *drhs = BEnd-1;
145 for (;dlhs > lhs && *dlhs != '-'; dlhs--);
146 for (;drhs > rhs && *drhs != '-'; drhs--);
147
148 if (dlhs == lhs)
149 dlhs = AEnd;
150 if (drhs == rhs)
151 drhs = BEnd;
152
153 // Compare the main version
154 Res = CmpFragment(lhs,dlhs,rhs,drhs);
155 if (Res != 0)
156 return Res;
157
158 // Skip the -
159 if (dlhs != lhs)
160 dlhs++;
161 if (drhs != rhs)
162 drhs++;
163
164 return CmpFragment(dlhs,AEnd,drhs,BEnd);
165}
166 /*}}}*/
167// debVS::CheckDep - Check a single dependency /*{{{*/
168// ---------------------------------------------------------------------
169/* This simply preforms the version comparison and switch based on
170 operator. If DepVer is 0 then we are comparing against a provides
171 with no version. */
172bool debVersioningSystem::CheckDep(const char *PkgVer,
173 int Op,const char *DepVer)
174{
175 if (DepVer == 0 || DepVer[0] == 0)
176 return true;
177 if (PkgVer == 0 || PkgVer[0] == 0)
178 return false;
179
180 // Perform the actual comparision.
181 int Res = CmpVersion(PkgVer,DepVer);
182 switch (Op & 0x0F)
183 {
184 case pkgCache::Dep::LessEq:
185 if (Res <= 0)
186 return true;
187 break;
188
189 case pkgCache::Dep::GreaterEq:
190 if (Res >= 0)
191 return true;
192 break;
193
194 case pkgCache::Dep::Less:
195 if (Res < 0)
196 return true;
197 break;
198
199 case pkgCache::Dep::Greater:
200 if (Res > 0)
201 return true;
202 break;
203
204 case pkgCache::Dep::Equals:
205 if (Res == 0)
206 return true;
207 break;
208
209 case pkgCache::Dep::NotEquals:
210 if (Res != 0)
211 return true;
212 break;
213 }
214
215 return false;
216}
217 /*}}}*/
218// debVS::UpstreamVersion - Return the upstream version string /*{{{*/
219// ---------------------------------------------------------------------
220/* This strips all the debian specific information from the version number */
221string debVersioningSystem::UpstreamVersion(const char *Ver)
222{
223 // Strip off the bit before the first colon
224 const char *I = Ver;
225 for (; *I != 0 && *I != ':'; I++);
226 if (*I == ':')
227 Ver = I + 1;
228
229 // Chop off the trailing -
230 I = Ver;
231 unsigned Last = strlen(Ver);
232 for (; *I != 0; I++)
233 if (*I == '-')
234 Last = I - Ver;
235
236 return string(Ver,Last);
237}
238 /*}}}*/