diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-08 15:13:59 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-08 15:13:59 +0300 |
commit | 79f6b2c923d1c2366b68a431756bde6e4a04ae86 (patch) | |
tree | 75087c12a3b763634bd5ea9ae616e6dd447b3f9d /src | |
parent | ced98e1b1e040bd0f50b2ebd146a22e74f5913c0 (diff) | |
download | grecs-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')
-rw-r--r-- | src/grecs.h | 14 | ||||
-rw-r--r-- | src/libgrecs.m4 | 2 | ||||
-rw-r--r-- | src/version.c | 178 |
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 @@ -34,19 +34,23 @@ # define _(msgid) gettext(msgid) #endif #ifndef N_ # 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; int major; int minor; int patch; char *suffix; + char *buffer; }; typedef struct { char *file; int line; } grecs_locus_t; @@ -160,14 +164,20 @@ struct grecs_keyword { struct grecs_sockaddr { int len; 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); extern void (*grecs_alloc_die_fun)(void); extern void (*grecs_free_fun)(void *ptr); diff --git a/src/libgrecs.m4 b/src/libgrecs.m4 index 88ce312..68abcef 100644 --- a/src/libgrecs.m4 +++ b/src/libgrecs.m4 @@ -24,13 +24,13 @@ AC_DEFUN([AM_LIBGRECS],[ if test "$cv_libgrecs" = "yes"; then LIBS="$save_LIBS -lgrecs" m4_if($1,,,[ 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 m4_if($2,,[ AC_DEFINE([HAVE_GRECS_H],[1], [Define if <grecs.h> is available]) diff --git a/src/version.c b/src/version.c index d34b8b5..3e251d7 100644 --- a/src/version.c +++ b/src/version.c @@ -18,19 +18,38 @@ # include <config.h> #endif #include <grecs.h> #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); if (*p && *p == '.') { char *q; @@ -39,48 +58,129 @@ grecs_version(struct grecs_version_info *pv) pv->patch = 0; else p = q; } } 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; } |