Prerequestite libraries: OSlib
/*
* Copyright (C) Stewart Brodie, 1996
*
* Use freely, no liability accepted for any losses, etc.
*
* This file: moduleversion.h
*
* This code performs the first half of a *RMEnsure procedure - rather
* than executing an arbitrary *-command, the version number is (optionally)
* returned and a flag indicating whether the module was found, older than
* same as, or newer than the version specified.
*
*/
#ifndef _moduleversion_h_included
#define _moduleversion_h_included
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
moduleversion_NOT_FOUND,
moduleversion_TOO_OLD,
moduleversion_MATCH,
moduleversion_NEWER
} module_version_flags;
typedef struct {
int major;
int minor;
} module_version_number;
/* Determine the presence/absence and optionally the version number of
* a RISC OS module.
*
* Parameters:
* name: module name, cannot be NULL
* wanted: pointer to a structure containing minimum acceptable version
* (may be NULL if looking for any version - treated as 0.00)
* present: pointer to a structure in which to store the version number
* of the module if it was found (and if it is non-NULL).
* Structure is not updated if function returns NOT_FOUND
*
* Returns:
* one of the values of module_version_flags defined above.
* The `present' structure is not touched if this value is
* moduleversion_TOO_OLD, but is with any other result
*/
extern module_version_flags moduleversion_check(const char */*name*/,
module_version_number */*wanted*/, module_version_number */*present*/);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (C) Stewart Brodie, 1996
*
* Use freely, no liability accepted for any losses, etc.
*
* This file: moduleversion.c
*
*/
#include "moduleversion.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "OS:osmodule.h"
module_version_flags moduleversion_check(const char *name,
module_version_number *wanted, module_version_number *present)
{
byte *code;
const int *module_header;
const char *help_string;
int count;
module_version_number want = { 0,0 };
module_version_number found = { -1, -1 };
module_version_flags flags = moduleversion_NOT_FOUND;
os_error *err = xosmodule_lookup(name, NULL, NULL, &code, NULL, NULL);
if (err) {
return flags;
}
if (wanted) want = *wanted;
module_header = (const int *)code;
if (!module_header[5]) {
return flags;
}
help_string = (char *)(code + module_header[5]);
count = 0;
while (*help_string) {
if (*help_string == '\t') {
++help_string;
count = (count + 8) & ~7;
continue;
}
if (count >= 16 && isdigit(*help_string)) {
/* think we've found it */
if (help_string[1] == '.' ||
(isdigit(help_string[1]) && help_string[2] == '.')) {
/* We're pretty sure now */
count = sscanf(help_string, "%u.%u",
&found.major, &found.minor);
if (count != 2) {
return flags;
}
if (present) *present = found;
if (found.major > want.major) {
return moduleversion_NEWER;
}
if (found.major < want.major) {
return moduleversion_TOO_OLD;
}
if (found.minor > want.minor) {
return moduleversion_NEWER;
}
if (found.minor < want.minor) {
return moduleversion_TOO_OLD;
}
return moduleversion_MATCH;
}
/* Doesn't look like a version number .. carry on */
}
++help_string;
++count;
}
/* We reached the end of the string - we are now confused */
return moduleversion_NOT_FOUND;
}
#ifdef TEST
int main(int argc, char **argv)
{
module_version_flags flags;
module_version_number wanted, present;
++argv;
--argc;
for (;argc >= 2;argc-=2,argv+=2) {
if (sscanf(argv[1], "%u.%u", &wanted.major, &wanted.minor) != 2) continue;
flags = moduleversion_check(argv[0], &wanted, &present);
(void) printf("%s: ", argv[0]);
switch (flags) {
case moduleversion_NOT_FOUND:
(void) printf("not found\n");
break;
case moduleversion_MATCH:
(void) printf("%u.%02u found - exact version match\n",
present.major, present.minor);
break;
case moduleversion_TOO_OLD:
(void) printf("%u.%02u found - too old\n",
present.major, present.minor);
break;
case moduleversion_NEWER:
(void) printf("%u.%02u found - newer than minimum\n",
present.major, present.minor);
break;
}
}
return 0;
}
#endif