summaryrefslogtreecommitdiffabout
path: root/src
authorSergey Poznyakoff <gray@gnu.org.ua>2011-05-08 12:13:59 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2011-05-08 12:13:59 (GMT)
commit79f6b2c923d1c2366b68a431756bde6e4a04ae86 (patch) (side-by-side diff)
tree75087c12a3b763634bd5ea9ae616e6dd447b3f9d /src
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') (more/less context) (ignore whitespace changes)
-rw-r--r--src/grecs.h14
-rw-r--r--src/libgrecs.m42
-rw-r--r--src/version.c178
3 files changed, 152 insertions, 42 deletions
diff --git a/src/grecs.h b/src/grecs.h
index 25f068f..8f0ddc6 100644
--- a/src/grecs.h
+++ b/src/grecs.h
@@ -37,6 +37,9 @@
# define N_(s) s
#endif
+#define GRECS_VERSION_MAJOR 1
+#define GRECS_VERSION_MINOR 0
+
struct grecs_version_info {
const char *package;
const char *version;
@@ -44,6 +47,7 @@ struct grecs_version_info {
int minor;
int patch;
char *suffix;
+ char *buffer;
};
typedef struct {
@@ -163,8 +167,14 @@ struct grecs_sockaddr {
struct sockaddr *sa;
};
-void grecs_version(struct grecs_version_info *pv);
-int grecs_version_cmp(const char *vstr);
+struct grecs_version_info *grecs_version(void);
+int grecs_version_cmp(const char *vstr1, const char *vstr2, int *pres);
+int grecs_version_ok(const char *vstr);
+void grecs_version_info_free(struct grecs_version_info *pv);
+struct grecs_version_info *grecs_version_split(const char *vstr);
+int grecs_version_info_cmp(struct grecs_version_info *vx,
+ struct grecs_version_info *vy,
+ int *pres);
extern void *(*grecs_malloc_fun)(size_t size);
extern void *(*grecs_realloc_fun)(void *ptr, size_t size);
diff --git a/src/libgrecs.m4 b/src/libgrecs.m4
index 88ce312..68abcef 100644
--- a/src/libgrecs.m4
+++ b/src/libgrecs.m4
@@ -27,7 +27,7 @@ AC_DEFUN([AM_LIBGRECS],[
AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include <stdlib.h>
#include <grecs.h>
]],
- [exit(grecs_version_cmp("[libgrecs ]$1"));])],
+ [exit(grecs_version_ok("[libgrecs ]$1"));])],
[],
[cv_libgrecs=no])])
if test "$cv_libgrecs" = "yes"; then
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.