aboutsummaryrefslogtreecommitdiff
path: root/src/version.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2011-05-08 15:13:59 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2011-05-08 15:13:59 +0300
commit79f6b2c923d1c2366b68a431756bde6e4a04ae86 (patch)
tree75087c12a3b763634bd5ea9ae616e6dd447b3f9d /src/version.c
parentced98e1b1e040bd0f50b2ebd146a22e74f5913c0 (diff)
downloadgrecs-79f6b2c923d1c2366b68a431756bde6e4a04ae86.tar.gz
grecs-79f6b2c923d1c2366b68a431756bde6e4a04ae86.tar.bz2
Redo versioning support.
* am/grecs.m4: Define GRECS_VEROK_AT if package version matches the standard scheme. Define GRECS_DISTCK_AT if install flag is set. * src/grecs.h (GRECS_VERSION_MAJOR) (GRECS_VERSION_MINOR): New defines. (grecs_version_info)<buffer>: New member. (grecs_version): Return allocated grecs_version_info structure. (grecs_version_cmp): Change prototype. (grecs_version_ok) (grecs_version_info_cmp) (grecs_version_split) (grecs_version_info_free): New protos. * src/version.c: Rewrite. * src/libgrecs.m4 (AM_LIBGRECS): Use grecs_version_ok * tests/.gitignore: Add distck. * tests/Makefile.am: Add new tests. * tests/testsuite.at: Add new tests. * tests/gcfver.c: Update. * tests/vercmp.at: Rewrite. * tests/verok.at: New file (from old vercmp.at). * tests/distck.at: New file. * tests/distck.c: New file.
Diffstat (limited to 'src/version.c')
-rw-r--r--src/version.c178
1 files changed, 139 insertions, 39 deletions
diff --git a/src/version.c b/src/version.c
index d34b8b5..3e251d7 100644
--- a/src/version.c
+++ b/src/version.c
@@ -21,13 +21,32 @@
#include <string.h>
#include <ctype.h>
-void
-grecs_version(struct grecs_version_info *pv)
+const char *grecs_version_string;
+
+struct grecs_version_info *
+grecs_version_split(const char *vstr)
{
char *p;
- memset(pv, 0, sizeof(*pv));
- pv->package = PACKAGE_NAME;
- pv->version = PACKAGE_VERSION;
+ size_t len;
+ struct grecs_version_info *pv = grecs_zalloc(sizeof(*pv));
+
+ pv->buffer = grecs_strdup(vstr);
+ len = strcspn(pv->buffer, " \t");
+ if (pv->buffer[len]) {
+ pv->package = pv->buffer;
+ pv->buffer[len++] = 0;
+ for (; pv->buffer[len] && isspace(pv->buffer[len]); len++)
+ ;
+ } else {
+ pv->package = NULL;
+ len = 0;
+ }
+ if (!pv->buffer[len]) {
+ free(pv->buffer);
+ free(pv);
+ return NULL;
+ }
+ pv->version = pv->buffer + len;
pv->major = strtoul(pv->version, &p, 10);
if (*p && *p == '.') {
pv->minor = strtoul(p + 1, &p, 10);
@@ -42,45 +61,126 @@ grecs_version(struct grecs_version_info *pv)
}
}
pv->suffix = p;
+ return pv;
+}
+
+void
+grecs_version_info_free(struct grecs_version_info *pv)
+{
+ if (pv) {
+ if (pv->buffer)
+ grecs_free(pv->buffer);
+ free(pv);
+ }
+}
+
+struct grecs_version_info *
+grecs_version(void)
+{
+ struct grecs_version_info *pv = grecs_zalloc(sizeof(*pv));
+ size_t size = 0;
+
+ pv->package = PACKAGE_NAME;
+#ifdef GRECS_VERSION_PATCHLEVEL
+# ifdef GRECS_VERSION_SUFFIX
+ grecs_asprintf(&pv->buffer, &size,
+ "%d.%d.%d%s",
+ GRECS_VERSION_MAJOR, GRECS_VERSION_MINOR,
+ GRECS_VERSION_PATCHLEVEL, GRECS_VERSION_SUFFIX);
+# else
+ grecs_asprintf(&pv->buffer, &size,
+ "%d.%d.%d",
+ GRECS_VERSION_MAJOR, GRECS_VERSION_MINOR,
+ GRECS_VERSION_PATCHLEVEL);
+# endif
+#else
+# ifdef GRECS_VERSION_SUFFIX
+ grecs_asprintf(&pv->buffer, &size,
+ "%d.%d%s",
+ GRECS_VERSION_MAJOR, GRECS_VERSION_MINOR,
+ GRECS_VERSION_SUFFIX);
+# else
+ grecs_asprintf(&pv->buffer, &size,
+ "%d.%d",
+ GRECS_VERSION_MAJOR, GRECS_VERSION_MINOR);
+# endif
+#endif
+ pv->version = pv->buffer;
+ pv->major = GRECS_VERSION_MAJOR;
+ pv->minor = GRECS_VERSION_MINOR;
+#ifdef GRECS_VERSION_PATCHLEVEL
+ pv->patch = GRECS_VERSION_PATCHLEVEL;
+#endif
+#ifdef GRECS_VERSION_SUFFIX
+ pv->suffix = GRECS_VERSION_SUFFIX;
+#endif
+ return pv;
}
int
-grecs_version_cmp(const char *vstr)
+grecs_version_info_cmp(struct grecs_version_info *vx,
+ struct grecs_version_info *vy,
+ int *pres)
{
- struct grecs_version_info v;
- char *p;
- unsigned long n;
- size_t len;
- int check;
+ if (vx->package && vy->package && strcmp(vx->package, vy->package))
+ return 1;
+ else if (vx->major > vy->major)
+ *pres = 1;
+ else if (vx->major < vy->major)
+ *pres = -1;
+ else if (vx->minor > vy->minor)
+ *pres = 1;
+ else if (vx->minor < vy->minor)
+ *pres = -1;
+ else if (vx->patch > vy->patch)
+ *pres = 1;
+ else if (vx->patch < vy->patch)
+ *pres = -1;
+ else if (vx->suffix && vy->suffix)
+ *pres = strcmp(vx->suffix, vy->suffix);
+ else
+ *pres = 0;
+ return 0;
+}
+
+int
+grecs_version_cmp(const char *vstr1, const char *vstr2, int *pres)
+{
+ struct grecs_version_info *v1, *v2;
+ int rc;
- if (!vstr)
+ if (!vstr1 || !vstr2)
+ return -1;
+ v1 = grecs_version_split(vstr1);
+ if (!v1)
+ return -1;
+ v2 = grecs_version_split(vstr2);
+ if (!v2) {
+ grecs_version_info_free(v1);
return -1;
- grecs_version(&v);
- len = strcspn(vstr, " \t");
- if (vstr[len]) {
- if (len != strlen(v.package) || memcmp(v.package, vstr, len))
- return 1;
- for (vstr += len; *vstr && isspace(*vstr); vstr++)
- ;
- }
- if (!*vstr)
- return 1;
- n = strtoul(vstr, &p, 10);
- if (n > v.major)
- return 1;
- check = n == v.major;
- if (*p && *p == '.') {
- n = strtoul(p + 1, &p, 10);
- if (check && n > v.minor)
- return 1;
- check = n == v.minor;
- if (*p && *p == '.') {
- n = strtoul(p + 1, &p, 10);
- if (check && n > v.patch)
- return 1;
- }
}
- if (*p && (!v.suffix || strcmp(p, v.suffix)))
- return 1;
- return 0;
+ rc = grecs_version_info_cmp(v1, v2, pres);
+ grecs_version_info_free(v1);
+ grecs_version_info_free(v2);
+ return rc;
+}
+
+int
+grecs_version_ok(const char *vstr)
+{
+ struct grecs_version_info *vmy, *vreq;
+ int rc, res;
+
+ if (!vstr)
+ return -1;
+ vreq = grecs_version_split(vstr);
+ if (!vreq)
+ return -1;
+ vmy = grecs_version();
+ if (vreq->suffix && !vmy->suffix)
+ vmy->suffix = "";
+ rc = grecs_version_info_cmp(vmy, vreq, &res);
+ grecs_version_info_free(vmy);
+ grecs_version_info_free(vreq);
+ return rc == 0 && res >= 0;
}

Return to:

Send suggestions and report system problems to the System administrator.