#include "vers_rsrc.h"
int isreleasestate(char c) {
return (c == 'd' || c == 'a' || c == 'b' || c == 'f');
}
UInt8 BCD_digit_for_char(char c) {
switch (c) {
case '0': return 0; break;
case '1': return 1; break;
case '2': return 2; break;
case '3': return 3; break;
case '4': return 4; break;
case '5': return 5; break;
case '6': return 6; break;
case '7': return 7; break;
case '8': return 8; break;
case '9': return 9; break;
default: return BCD_illegal; break;
}
return BCD_illegal;
}
char BCD_char_for_digit(UInt8 digit) {
switch (digit) {
case 0: return '0'; break;
case 1: return '1'; break;
case 2: return '2'; break;
case 3: return '3'; break;
case 4: return '4'; break;
case 5: return '5'; break;
case 6: return '6'; break;
case 7: return '7'; break;
case 8: return '8'; break;
case 9: return '9'; break;
default: return '?'; break;
}
return '?';
}
VERS_revision VERS_revision_for_string(char ** string_p) {
char * string;
if (!string_p || !*string_p) {
return VERS_invalid;
}
string = *string_p;
if (isspace(string[0]) || string[0] == '\0') {
return VERS_release;
} else {
switch (string[0]) {
case 'd':
if (isdigit(string[1])) {
*string_p = &string[1];
return VERS_development;
}
break;
case 'a':
if (isdigit(string[1])) {
*string_p = &string[1];
return VERS_alpha;
}
break;
case 'b':
if (isdigit(string[1])) {
*string_p = &string[1];
return VERS_beta;
}
break;
case 'f':
if (isdigit(string[1])) {
*string_p = &string[1];
return VERS_candidate;
} else if (string[1] == 'c' && isdigit(string[2])) {
*string_p = &string[2];
return VERS_candidate;
} else {
return VERS_invalid;
}
break;
default:
return VERS_invalid;
break;
}
}
return VERS_invalid;
}
int VERS_parse_string(char * vers_string, UInt32 * version_num) {
int result = 1;
VERS_version vers;
char * current_char_p;
UInt8 scratch;
if (!vers_string || *vers_string == '\0') {
return 0;
}
vers.vnum = 0;
current_char_p = &vers_string[0];
vers.bytes[0] = BCD_digit_for_char(*current_char_p);
if (vers.bytes[0] == BCD_illegal) {
return 0;
}
current_char_p++;
if (*current_char_p == '\0') {
vers.bytes[2] = VERS_release;
vers.bytes[3] = 0xff;
goto finish;
} else if (isdigit(*current_char_p)) {
scratch = BCD_digit_for_char(*current_char_p);
if (scratch == BCD_illegal) {
return 0;
}
vers.bytes[0] = BCD_combine(vers.bytes[0], scratch);
current_char_p++;
if (*current_char_p == '\0') {
vers.bytes[2] = VERS_release;
vers.bytes[3] = 0xff;
goto finish;
} else if (isreleasestate(*current_char_p)) {
goto release_state;
} else if (*current_char_p == '.') {
current_char_p++;
} else {
return 0;
}
} else if (isreleasestate(*current_char_p)) {
goto release_state;
} else if (*current_char_p == '.') {
current_char_p++;
} else {
return 0;
}
if (*current_char_p == '\0') {
vers.bytes[2] = VERS_release;
vers.bytes[3] = 0xff;
goto finish;
} else if (isdigit(*current_char_p)) {
vers.bytes[1] = BCD_digit_for_char(*current_char_p);
if (vers.bytes[1] == BCD_illegal) {
return 0;
}
vers.bytes[1] = BCD_combine(vers.bytes[1], 0);
current_char_p++;
if (*current_char_p == '\0') {
vers.bytes[2] = VERS_release;
vers.bytes[3] = 0xff;
goto finish;
} else if (isreleasestate(*current_char_p)) {
goto release_state;
} else if (*current_char_p == '.') {
current_char_p++;
} else {
return 0;
}
} else {
return 0;
}
if (*current_char_p == '\0') {
vers.bytes[2] = VERS_release;
vers.bytes[3] = 0xff;
goto finish;
} else if (isdigit(*current_char_p)) {
scratch = BCD_digit_for_char(*current_char_p);
if (scratch == BCD_illegal) {
return 0;
}
vers.bytes[1] = vers.bytes[1] | scratch;
current_char_p++;
if (*current_char_p == '\0') {
vers.bytes[2] = VERS_release;
vers.bytes[3] = 0xff;
goto finish;
} else if (isreleasestate(*current_char_p)) {
goto release_state;
} else {
return 0;
}
} else {
return 0;
}
release_state:
if (*current_char_p == '\0') {
vers.bytes[2] = VERS_release;
vers.bytes[3] = 0xff;
goto finish;
} else {
vers.bytes[2] = VERS_revision_for_string(¤t_char_p);
if (vers.bytes[2] == VERS_invalid) {
return 0;
}
}
if (vers.bytes[2] != VERS_release) {
UInt32 revision_num = 0;
int i;
if (*current_char_p == '\0' || !isdigit(*current_char_p)) {
return 0;
}
for (i = 0; i < 3 && *current_char_p != '\0'; i++, current_char_p++) {
UInt8 scratch_digit;
scratch_digit = BCD_digit_for_char(*current_char_p);
if (scratch_digit == BCD_illegal) {
return 0;
}
revision_num *= 10;
revision_num += scratch_digit;
}
if (isdigit(*current_char_p) || revision_num > 255) {
return 0;
}
vers.bytes[3] = (UInt8)revision_num;
}
if (vers.bytes[2] == VERS_release) {
vers.bytes[3] = 0xff;
} else {
if (vers.bytes[2] == VERS_candidate) {
if (vers.bytes[3] == 0) {
return 0;
} else {
vers.bytes[2] = VERS_release;
vers.bytes[3]--;
}
}
}
finish:
*version_num = vers.vnum;
return result;
}
#define VERS_STRING_MAX_LEN (12)
int VERS_string(char * buffer, UInt32 length, UInt32 vers) {
VERS_version version;
int cpos = 0;
int result = 1;
char major1;
char major2;
char minor;
char bugfix;
version.vnum = vers;
if (!buffer || length < VERS_STRING_MAX_LEN) {
result = -1;
goto finish;
}
bzero(buffer, length * sizeof(char));
major1 = BCD_char_for_digit(BCD_get_left(version.bytes[0]));
if (major1 == '?') {
result = 0;
}
if (major1 != '0') {
buffer[cpos] = major1;
cpos++;
}
major2 = BCD_char_for_digit(BCD_get_right(version.bytes[0]));
if (major2 == '?') {
result = 0;
}
buffer[cpos] = major2;
cpos++;
minor = BCD_char_for_digit(BCD_get_left(version.bytes[1]));
if (minor == '?') {
result = 0;
}
bugfix = BCD_char_for_digit(BCD_get_right(version.bytes[1]));
if (bugfix == '?') {
result = 0;
}
buffer[cpos] = '.';
cpos++;
buffer[cpos] = minor;
cpos++;
if (bugfix != '0') {
buffer[cpos] = '.';
cpos++;
buffer[cpos] = bugfix;
cpos++;
}
if (version.bytes[2] == VERS_release && version.bytes[3] == 255) {
result = 0;
goto finish;
}
switch (version.bytes[2]) {
case VERS_development:
buffer[cpos] = 'd';
cpos++;
break;
case VERS_alpha:
buffer[cpos] = 'a';
cpos++;
break;
case VERS_beta:
buffer[cpos] = 'b';
cpos++;
break;
case VERS_release:
if (version.bytes[3] < 255) {
buffer[cpos] = 'f';
buffer[cpos+1] = 'c';
cpos += 2;
} else {
result = 1;
goto finish;
}
break;
default:
result = 0;
buffer[cpos] = '?';
cpos++;
break;
}
if (version.bytes[2] != VERS_release) {
sprintf(&buffer[cpos], "%d", version.bytes[3]);
} else {
if (version.bytes[3] < 255) {
sprintf(&buffer[cpos], "%d", version.bytes[3] + 1);
}
}
finish:
return result;
}