diff --git a/require-ess/src/require.c b/require-ess/src/require.c index 43ba75a78a431d4c04319750d5e843e2ec5a60db..c725f37d6e3cdce1d939ce1abac6d0672a0f8d34 100644 --- a/require-ess/src/require.c +++ b/require-ess/src/require.c @@ -38,6 +38,7 @@ epicsShareFunc int epicsShareAPI iocshCmd(const char *cmd); #include <osiFileName.h> #include <epicsExport.h> +#include "version.h" #include "require.h" int requireDebug; @@ -827,12 +828,9 @@ static int compareDigit(int found, int requested, char *name) */ static int compareVersions(const char *found, const char *request, int already_matched) { - int found_major = 0, found_minor = 0, found_patch = 0, found_parts = 0, found_build = 0; - int req_major = 0, req_minor = 0, req_patch = 0, req_parts = 0, req_build = 0; + semver_t sv_found, sv_request; int match; - const char *version_string = "%d.%d.%d-%d"; - debug("require: compareVersions(found=%s, request=%s)\n", found, request); if (request == NULL || request[0] == 0) @@ -846,12 +844,14 @@ static int compareVersions(const char *found, const char *request, int already_m return MISMATCH; } - found_parts = sscanf(found, version_string, &found_major, &found_minor, &found_patch, &found_build); + /*sv_found = (semver_t *)calloc(1, sizeof(semver_t)); + sv_request = (semver_t *)calloc(1, sizeof(semver_t));*/ - req_parts = sscanf(request, version_string, &req_major, &req_minor, &req_patch, &req_build); + parse_semver(found, &sv_found); + parse_semver(request, &sv_request); // test version, look for exact. - if (req_parts == 0 || req_parts == 1 || req_parts == 2) + if (strlen(sv_request.test_str) > 0) { if (strcmp(found, request) == 0) { @@ -859,7 +859,7 @@ static int compareVersions(const char *found, const char *request, int already_m return EXACT; } - if (found_parts == 0 || found_parts == 1 || found_parts == 2) + if (strlen(sv_found.test_str) > 0) { debug("require: compareVersions: Test versions requested and found, no match\n"); return MISMATCH; @@ -869,24 +869,25 @@ static int compareVersions(const char *found, const char *request, int already_m return HIGHER; } - if (found_parts == 0 || found_parts == 1 || found_parts == 2) + if (strlen(sv_found.test_str) > 0) { debug("require: compareVersions: Numeric version requested, test version found\n"); return MISMATCH; } // At least three digits specifed - match = compareDigit(found_major, req_major, "major"); + match = compareDigit(sv_found.major, sv_request.major, "major"); if (match != MATCH) return match; - match = compareDigit(found_minor, req_minor, "minor"); + match = compareDigit(sv_found.minor, sv_request.minor, "minor"); if (match != MATCH) return match; - match = compareDigit(found_patch, req_patch, "patch"); + match = compareDigit(sv_found.patch, sv_request.patch, "patch"); if (match != MATCH) return match; - if (req_parts == 3) + // build number not specified + if (sv_request.build == -1) { if (already_matched) { @@ -899,7 +900,7 @@ static int compareVersions(const char *found, const char *request, int already_m return MATCH; } } - return compareDigit(found_build, req_build, "build"); + return compareDigit(sv_found.build, sv_request.build, "build"); } /* require (module) diff --git a/require-ess/src/version.c b/require-ess/src/version.c new file mode 100644 index 0000000000000000000000000000000000000000..c239fbdf4ecebe3a638cf46dc964b60fd3b32331 --- /dev/null +++ b/require-ess/src/version.c @@ -0,0 +1,70 @@ +#include <regex.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include "version.h" + +void cleanup_semver(semver_t *s) { + free(s->version_str); + free(s); +} + +void init_semver(const char *version, semver_t *s) { + s->version_str = calloc(strlen(version) + 1, sizeof(char)); + strcpy(s->version_str, version); + s->test_str = ""; + + s->major = 0; + s->minor = 0; + s->patch = 0; + s->build = -1; +} + +void fetch_part(char *version_str, regmatch_t *groups, unsigned int ix, int *part) { + char tmp; + + tmp = version_str[groups[ix].rm_eo]; + version_str[groups[ix].rm_eo] = 0; + *part = atoi(version_str + groups[ix].rm_so); + version_str[groups[ix].rm_eo] = tmp; +} + +int parse_semver(const char *version, semver_t *s) { + regex_t compiled; + regmatch_t groups[MAX_REGEX_GROUPS]; + + init_semver(version, s); + + if (s->version_str == NULL || s->version_str[0] == 0) { + return 1; + } + + if (regcomp(&compiled, VERSION_REGEX, REG_EXTENDED)) { + return 1; + } + + if (regexec(&compiled, s->version_str, MAX_REGEX_GROUPS, groups, 0) == 0) { + fetch_part(s->version_str, groups, MAJ_IX, &s->major); + fetch_part(s->version_str, groups, MIN_IX, &s->minor); + fetch_part(s->version_str, groups, PATCH_IX, &s->patch); + if (groups[BUILD_IX].rm_so != (size_t)-1) { + fetch_part(s->version_str, groups, BUILD_IX, &s->build); + } + s->test_str = s->version_str + groups[TEST_IX].rm_so; + } + return 0; +} + + +/*int main(int argc, char **argv) { + if (argc < 1) return 0; + if (strlen(argv[1]) == 0) return 0; + + semver_t *s = (semver_t *)calloc(1,sizeof(semver_t)); + + parse_semver(argv[1], s); + ps("main", s); + + cleanup_semver(s); + return 0; +}*/ \ No newline at end of file diff --git a/require-ess/src/version.h b/require-ess/src/version.h new file mode 100644 index 0000000000000000000000000000000000000000..dd251116b9aec1f9e67f9bee50bbaa63f4ad813c --- /dev/null +++ b/require-ess/src/version.h @@ -0,0 +1,23 @@ +#define VERSION_REGEX "^(([0-9]+)\\.([0-9]+)\\.([0-9]+)(\\-([0-9]+))?)?(.*)$" +#define MAX_REGEX_GROUPS (7+1) + +#define MAJ_IX 2 +#define MIN_IX 3 +#define PATCH_IX 4 +#define BUILD_IX 6 +#define TEST_IX 7 + +typedef struct semver_t { + char *version_str; + int major; + int minor; + int patch; + int build; // can be negative; implies that build has not been specified + char *test_str; +} semver_t; + +void cleanup_semver(semver_t *s); + +void init_semver(const char *version, semver_t *s); + +int parse_semver(const char *version, semver_t *s); \ No newline at end of file diff --git a/require.Makefile b/require.Makefile index a1acaf6e63f00b635920647bd1ccdf503b9ff172..d07ccfc6f8ede6bcd2435cae8bbb4334af16f8d9 100644 --- a/require.Makefile +++ b/require.Makefile @@ -41,6 +41,7 @@ APPSRC := $(APP)/src APPDB := $(APP)/Db SOURCES += $(APPSRC)/require.c +SOURCES += $(APPSRC)/version.c DBDS += $(APPSRC)/require.dbd SOURCES += $(APPSRC)/runScript.c DBDS += $(APPSRC)/runScript.dbd