2 * libdpkg - Debian packaging suite library routines
3 * vercmp.c - comparison of version numbers
5 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
7 * This is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version.
12 * This is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public
18 * License along with dpkg; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 struct versionrevision
{
33 const char *familiar_revision
;
37 static int verrevcmp(const char *val
, const char *ref
)
42 const char *vsep
, *rsep
;
47 vp
= val
; while (*vp
&& !isdigit(*vp
)) vp
++;
48 rp
= ref
; while (*rp
&& !isdigit(*rp
)) rp
++;
50 vc
= val
== vp
? 0 : *val
++;
51 rc
= ref
== rp
? 0 : *ref
++;
52 if (!rc
&& !vc
) break;
53 if (vc
&& !isalpha(vc
)) vc
+= 256; /* assumes ASCII character set */
54 if (rc
&& !isalpha(rc
)) rc
+= 256;
55 if (vc
!= rc
) return vc
- rc
;
59 vl
=0; if (isdigit(*vp
)) vl
= strtol(val
,(char**)&val
,10);
60 rl
=0; if (isdigit(*rp
)) rl
= strtol(ref
,(char**)&ref
,10);
61 if (vl
!= rl
) return vl
- rl
;
65 vsep
= strchr(".-", vc
);
66 rsep
= strchr(".-", rc
);
67 if (vsep
&& !rsep
) return -1;
68 if (!vsep
&& rsep
) return +1;
70 if (!*val
&& !*ref
) return 0;
76 int versioncompare(const struct versionrevision
*version
,
77 const struct versionrevision
*refversion
)
81 if (version
->epoch
> refversion
->epoch
) return 1;
82 if (version
->epoch
< refversion
->epoch
) return -1;
83 r
= verrevcmp(version
->version
,refversion
->version
); if (r
) return r
;
86 r
= verrevcmp(version
->revision
,refversion
->revision
); if (r
) return r
;
87 return verrevcmp(version
->familiar_revision
,refversion
->familiar_revision
);
91 int versionsatisfied3(const struct versionrevision
*it
,
92 const struct versionrevision
*ref
,
96 r
= versioncompare(it
,ref
);
97 if (strcmp(op
, "<=") == 0 || strcmp(op
, "<") == 0)
99 if (strcmp(op
, ">=") == 0 || strcmp(op
, ">") == 0)
101 if (strcmp(op
, "<<") == 0)
103 if (strcmp(op
, ">>") == 0)
105 if (strcmp(op
, "=") == 0)
107 fprintf(stderr
, "unknown operator: %s", op
);
112 const char *parseversion(struct versionrevision
*rversion
, const char *string
)
114 char *hyphen
, *colon
, *eepochcolon
;
117 if (!*string
) return _("version string is empty");
119 colon
= strchr(string
,':');
121 epoch
= strtoul(string
,&eepochcolon
,10);
122 if (colon
!= eepochcolon
) return _("epoch in version is not number");
123 if (!*++colon
) return _("nothing after colon in version number");
125 rversion
->epoch
= epoch
;
131 rversion
->revision
= "";
132 rversion
->familiar_revision
= "";
135 rversion
->version
= malloc(strlen(string
)+1);
136 strcpy(rversion
->version
, string
);
139 fprintf(stderr
,"Parsed version: %lu, %s\n",
147 int main(int argc
, char *argv
[])
150 struct versionrevision ver
, ref
;
153 fprintf(stderr
, "usage: %s: version op refversion\n", argv
[0]);
157 err
= parseversion(&ver
, argv
[1]);
159 fprintf(stderr
, "Invalid version `%s': %s\n", argv
[1], err
);
163 err
= parseversion(&ref
, argv
[3]);
165 fprintf(stderr
, "Invalid version `%s': %s\n", argv
[3], err
);
169 return ! versionsatisfied3(&ver
, &ref
, argv
[2]);