/* grecs - Gray's Extensible Configuration System Copyright (C) 2007-2011 Sergey Poznyakoff Grecs is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Grecs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Grecs. If not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include "gitid.h" const char *grecs_vcs_id = "$Id: " GRECS_GIT_ID " $"; struct grecs_version_info * grecs_version_split(const char *vstr) { char *p; 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; pv->patch = strtoul(p + 1, &q, 10); if (q == p + 1) 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 pv->id = GRECS_GIT_ID; return pv; } int grecs_version_info_cmp(struct grecs_version_info *vx, struct grecs_version_info *vy, int *pres) { 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 (!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; } 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; }