00001
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <config.h>
00043
00044 #include <assert.h>
00045 #include <ctype.h>
00046 #include <stdio.h>
00047 #include <stdlib.h>
00048 #include <string.h>
00049
00050 #include <discover.h>
00051
00052 #include "utils.h"
00053
00055 #define MAXBUFLEN 256
00056
00058 typedef enum range_states {
00059 START,
00060 OPEN,
00061 VERSION1,
00062 VERSEP1,
00063 PAUSE1,
00064 SEPARATOR,
00065 I, N, F,
00066 VERSION2,
00067 VERSEP2,
00068 PAUSE2,
00069 CLOSE,
00070 ERROR
00071 }
00073 range_state;
00074
00075
00076
00077
00078
00079 static int
00080 is_versep_char(char c)
00081 {
00082 return c == '.';
00083 }
00084
00085
00086
00087
00088
00089 static int
00090 is_version_char(char c)
00091 {
00092 return isdigit(c);
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 static int
00108 version_compare(const char *const v1, const char *const v2)
00109 {
00110 int int1, int2;
00111 char *word1, *word2;
00112 char *version1, *version2;
00113 char *buffer1;
00114 char *buffer2;
00115
00116 if (strcmp(v1, v2) == 0) {
00117 return -1;
00118 }
00119
00120 if (strcmp(v1, "inf") == 0) {
00121 return 1;
00122 }
00123
00124 if (strcmp(v2, "inf") == 0) {
00125 return 0;
00126 }
00127
00128 buffer1 = _discover_xmalloc(MAXBUFLEN);
00129 buffer2 = _discover_xmalloc(MAXBUFLEN);
00130
00131 version1 = _discover_xstrdup(v1);
00132 version2 = _discover_xstrdup(v2);
00133
00134 word1 = strtok_r(version1, ".", &buffer1);
00135 word2 = strtok_r(version2, ".", &buffer2);
00136
00137 do {
00138 sscanf(word1, "%d", &int1);
00139 sscanf(word2, "%d", &int2);
00140
00141 if (int1 != int2) {
00142 return int1 > int2;
00143 }
00144
00145 word1 = strtok_r(NULL, ".", &buffer1);
00146 word2 = strtok_r(NULL, ".", &buffer2);
00147
00148 } while(word1 != NULL && word2 != NULL);
00149
00150 free(version1);
00151 free(version2);
00152
00153 if (word2 == NULL && word1 == NULL) {
00154 return -1;
00155 }
00156 if (word2 == NULL) {
00157 return 1;
00158 }
00159 return -0;
00160 }
00161
00162
00163 static int
00164 determine_range(char * range_text, char **upper,
00165 int *upper_inclusive, char **lower, int *lower_inclusive,
00166 char **next)
00167 {
00168 char *current = range_text;
00169 char c;
00170 char last_char = '\0';
00171
00172 char buffer1[MAXBUFLEN];
00173 char *bufptr1 = buffer1;
00174
00175 char buffer2[MAXBUFLEN];
00176 char *bufptr2 = buffer2;
00177
00178 range_state state = START;
00179 range_state last_good_state = START;
00180 int first_inclusive = -1, second_inclusive = -1;
00181
00182 while(1) {
00183 c = *current;
00184
00185 switch(state) {
00186 case START:
00187 if (isspace(c)) {
00188 state = START;
00189 } else if (c == '(' || c == '[') {
00190 state = OPEN;
00191 } else {
00192 last_good_state = state;
00193 state = ERROR;
00194 }
00195 break;
00196
00197 case OPEN:
00198 if (last_char == '[') {
00199 first_inclusive = 1;
00200 } else {
00201 first_inclusive = 0;
00202 }
00203
00204 if (isspace(c)) {
00205 state = OPEN;
00206 } else if (is_version_char(c)) {
00207 state = VERSION1;
00208 } else {
00209 last_good_state = state;
00210 state = ERROR;
00211 }
00212 break;
00213
00214 case VERSION1:
00215 if (bufptr1 - buffer1 > 254) {
00216 last_good_state = state;
00217 state = ERROR;
00218 break;
00219 }
00220
00221 *bufptr1 = last_char;
00222 bufptr1++;
00223
00224 if (isspace(c) || c == ',') {
00225 *bufptr1 = '\0';
00226
00227 if (c == ',') {
00228 state = SEPARATOR;
00229 } else {
00230 state = PAUSE1;
00231 }
00232 } else if (is_version_char(c)) {
00233 state = VERSION1;
00234 } else if (is_versep_char(c)) {
00235 state = VERSEP1;
00236 } else {
00237 last_good_state = VERSION1;
00238 state = ERROR;
00239 }
00240 break;
00241
00242 case VERSEP1:
00243 if (bufptr1 - buffer1 > 254) {
00244 last_good_state = state;
00245 state = ERROR;
00246 break;
00247 }
00248
00249 *bufptr1 = last_char;
00250 bufptr1++;
00251
00252 if (is_version_char(c)) {
00253 state = VERSION1;
00254 } else {
00255 last_good_state = VERSION1;
00256 state = ERROR;
00257 }
00258 break;
00259
00260 case PAUSE1:
00261 if (isspace(c)) {
00262 state = PAUSE1;
00263 } else if (c == ',') {
00264 state = SEPARATOR;
00265 } else {
00266 last_good_state = PAUSE1;
00267 state = ERROR;
00268 }
00269 break;
00270
00271 case SEPARATOR:
00272 if (isspace(c)) {
00273 state = SEPARATOR;
00274 } else if (is_version_char(c)) {
00275 state = VERSION2;
00276 } else if (c == 'i') {
00277 state = I;
00278 } else {
00279 last_good_state = SEPARATOR;
00280 state = ERROR;
00281 }
00282 break;
00283
00284 case I:
00285 if (c == 'n') {
00286 state = N;
00287 } else {
00288 last_good_state = state;
00289 state = ERROR;
00290 }
00291 break;
00292
00293 case N:
00294 if (c == 'f') {
00295 state = F;
00296 } else {
00297 last_good_state = state;
00298 state = ERROR;
00299 }
00300 break;
00301
00302 case F:
00303 strcpy(bufptr2, "inf");
00304 if (isspace(c)) {
00305 state = PAUSE2;
00306 } else if (c == ')' || c == ']') {
00307 state = CLOSE;
00308 } else {
00309 last_good_state = state;
00310 state = ERROR;
00311 }
00312 break;
00313
00314 case VERSION2:
00315 if (bufptr2 - buffer2 > 254) {
00316 last_good_state = state;
00317 state = ERROR;
00318 break;
00319 }
00320
00321 *bufptr2 = last_char;
00322 bufptr2++;
00323
00324 if (isspace(c) || c == ')' || c == ']') {
00325 *bufptr2 = '\0';
00326
00327 if (c == ')' || c == ']') {
00328 state = CLOSE;
00329 } else {
00330 state = PAUSE2;
00331 }
00332 } else if (is_version_char(c)) {
00333 state = VERSION2;
00334 } else if (is_versep_char(c)) {
00335 state = VERSEP2;
00336 } else {
00337 last_good_state = VERSION2;
00338 state = ERROR;
00339 }
00340 break;
00341
00342 case VERSEP2:
00343 if (bufptr2 - buffer2 > 254) {
00344 last_good_state = state;
00345 state = ERROR;
00346 break;
00347 }
00348
00349 *bufptr2 = last_char;
00350 bufptr2++;
00351
00352 if (is_version_char(c)) {
00353 state = VERSION2;
00354 } else {
00355 last_good_state = VERSION2;
00356 state = ERROR;
00357 }
00358 break;
00359
00360 case PAUSE2:
00361 if (isspace(c)) {
00362 state = PAUSE2;
00363 } else if (c == ')' || c == ']') {
00364 state = CLOSE;
00365 } else {
00366 last_good_state = PAUSE2;
00367 state = ERROR;
00368 }
00369 break;
00370
00371 case CLOSE:
00372 *next = current;
00373
00374 if (last_char == ')') {
00375 second_inclusive = 0;
00376 } else if (last_char == ']') {
00377 second_inclusive = 1;
00378 }
00379
00380 if (version_compare(buffer1, buffer2) == 1) {
00381 *upper = _discover_xmalloc(bufptr1 - buffer1 + 1);
00382 strcpy(*upper, buffer1);
00383 *upper_inclusive = first_inclusive;
00384
00385 *lower = _discover_xmalloc(bufptr2 - buffer2 + 1);
00386 strcpy(*lower, buffer2);
00387 *lower_inclusive = second_inclusive;
00388 } else {
00389 *lower = _discover_xmalloc(bufptr1 - buffer1 + 1);
00390 strcpy(*lower, buffer1);
00391 *lower_inclusive = first_inclusive;
00392
00393 *upper = _discover_xmalloc(bufptr2 - buffer2 + 1);
00394 strcpy(*upper, buffer2);
00395 *upper_inclusive = second_inclusive;
00396 }
00397
00398
00399 return 1;
00400
00401 default:
00402 state = ERROR;
00403 last_good_state = -1;
00404 break;
00405 }
00406
00407 if (state == ERROR) {
00408
00409 return 0;
00410 }
00411
00412
00413
00414
00415
00416 if (!isspace(*current)) {
00417 last_char = *current;
00418 }
00419
00420 current++;
00421 }
00422 }
00423
00437 int
00438 discover_xml_version_cmp(char *range, char *version, discover_error_t *status)
00439 {
00440 char *upper, *lower;
00441 int upper_inclusive, lower_inclusive;
00442 char *next_range;
00443 int range_count = 0;
00444
00445 assert(range != NULL);
00446 assert(version != NULL);
00447 assert(status != NULL);
00448
00449 next_range = range;
00450
00451 while(*next_range != '\0') {
00452 range_count++;
00453 if (determine_range(next_range, &upper, &upper_inclusive,
00454 &lower, &lower_inclusive, &next_range)) {
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 if (version_compare(version, upper) == -1
00467 && upper_inclusive) {
00468 return range_count;
00469 } else if (version_compare(version, lower) == -1
00470 && lower_inclusive) {
00471 return range_count;
00472 } else if (version_compare(version, lower) > 0 &&
00473 version_compare(upper, version) > 0) {
00474 return range_count;
00475 }
00476
00477 } else {
00478 status->code = DISCOVER_EBADVERSION;
00479 return -1;
00480 }
00481 }
00482
00483 return 0;
00484 }
00485