00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <string.h>
00029 #include <stdlib.h>
00030 #include <assert.h>
00031 #include <stdio.h>
00032 #include <math.h>
00033
00034 #include "parse.h"
00035 #include "entitiesdef.h"
00036
00037 #define ED_MAX_KEYS_PER_ENT 32
00038 #define ED_MAX_TOKEN_LEN 512
00039 #define ED_MAX_ERR_LEN 512
00040
00041 static char lastErr[ED_MAX_ERR_LEN];
00042 static char lastErrExtra[ED_MAX_ERR_LEN];
00044 int numEntityDefs;
00045 entityDef_t entityDefs[ED_MAX_DEFS + 1];
00046
00051 #define ED_RETURN_ERROR(...) \
00052 { \
00053 snprintf(lastErr, sizeof(lastErr), __VA_ARGS__); \
00054 return ED_ERROR; \
00055 }
00056
00061 #define ED_TEST_RETURN_ERROR(condition,...) \
00062 if (condition) { \
00063 snprintf(lastErr, sizeof(lastErr), __VA_ARGS__); \
00064 return ED_ERROR; \
00065 }
00066
00072 #define ED_PASS_ERROR(function_call) \
00073 if ((function_call) == ED_ERROR) { \
00074 return ED_ERROR; \
00075 }
00076
00083 #define ED_PASS_ERROR_EXTRAMSG(function_call,...) \
00084 if ((function_call) == ED_ERROR) { \
00085 snprintf(lastErrExtra, sizeof(lastErr), __VA_ARGS__); \
00086 strncat(lastErr, lastErrExtra, sizeof(lastErr) - strlen(lastErr) -1); \
00087 return ED_ERROR; \
00088 }
00089
00094 static int ED_AllocEntityDef (entityKeyDef_t *newKeyDefs, int numKeyDefs, int entityIndex)
00095 {
00096 entityDef_t *eDef = &entityDefs[entityIndex];
00097
00098
00099 eDef->keyDefs = (entityKeyDef_t *) malloc((numKeyDefs + 1) * sizeof(entityKeyDef_t));
00100 ED_TEST_RETURN_ERROR(!eDef->keyDefs, "ED_AllocEntityDef: out of memory");
00101 eDef->numKeyDefs = numKeyDefs;
00102
00103
00104 memcpy(eDef->keyDefs, newKeyDefs, numKeyDefs * sizeof(entityKeyDef_t));
00105
00106
00107 memset(&eDef->keyDefs[numKeyDefs], 0, sizeof(entityKeyDef_t));
00108
00109
00110 eDef->classname = strdup(eDef->keyDefs->desc);
00111 ED_TEST_RETURN_ERROR(!eDef->classname, "ED_AllocEntityDef: out of memory");
00112
00113 return ED_OK;
00114 }
00115
00120 static entityKeyDef_t *ED_FindKeyDefInArray (entityKeyDef_t keyDefs[], int numDefs, const char *name, int parseMode)
00121 {
00122 int i;
00123 for (i = 0; i < numDefs; i++) {
00124 const entityKeyDef_t *keyDef = &keyDefs[i];
00125
00126 if (!strcmp(keyDef->name, name) && !((keyDef->flags ^ parseMode) & ED_ABSTRACT)) {
00127 return &keyDefs[i];
00128 }
00129 }
00130 return NULL;
00131 }
00132
00138 static int ED_Type2Constant (const char *strType)
00139 {
00140 if (!strcmp(strType, "V_FLOAT"))
00141 return ED_TYPE_FLOAT;
00142 else if (!strcmp(strType, "V_INT"))
00143 return ED_TYPE_INT;
00144 else if (!strcmp(strType, "V_STRING"))
00145 return ED_TYPE_STRING;
00146
00147 ED_RETURN_ERROR("ED_Type2Constant: type string not recognised: \"%s\"", strType);
00148 }
00149
00155 static const char *ED_Constant2Type (int constInt)
00156 {
00157 switch (constInt) {
00158 case ED_TYPE_FLOAT:
00159 return "V_FLOAT";
00160 case ED_TYPE_INT:
00161 return "V_INT";
00162 case ED_TYPE_STRING:
00163 return "V_STRING";
00164 default:
00165 snprintf(lastErr, sizeof(lastErr), "ED_Constant2Type: constant not recognised");
00166 return NULL;
00167 }
00168 }
00169
00179 static int ED_GetIntVectorFromString (const char *str, int v[], const int n)
00180 {
00181 int i;
00182 const char *buf_p = str;
00183
00184 for (i = 0; buf_p; i++) {
00185 const char *tok = Com_Parse(&buf_p);
00186 if (tok[0] == '\0')
00187 break;
00188 ED_TEST_RETURN_ERROR(i >= n, "ED_GetIntVectorFromString: v[%i] too small for ints from string \"%s\"", n, str);
00189 v[i] = atoi(tok);
00190 }
00191 ED_TEST_RETURN_ERROR(i != n, "ED_GetIntVectorFromString: v[%i] wrong size for ints from string \"%s\"", n, str);
00192 return ED_OK;
00193 }
00194
00204 static int ED_GetFloatVectorFromString (const char *str, float v[], const int n)
00205 {
00206 int i;
00207 const char *buf_p = str;
00208
00209 for (i = 0; buf_p; i++) {
00210 const char *tok = Com_Parse(&buf_p);
00211 if (tok[0] == '\0')
00212 break;
00213 ED_TEST_RETURN_ERROR(i >= n, "ED_GetFloatVectorFromString: v[%i] too small for floats from string \"%s\"", n, str);
00214 v[i] = atof(tok);
00215 }
00216 ED_TEST_RETURN_ERROR(i != n, "ED_GetFloatVectorFromString: v[%i] wrong size for floats from string \"%s\"", n, str);
00217 return ED_OK;
00218 }
00219
00230 int ED_GetDefaultFloat (float *defaultBuf, const int n, const entityKeyDef_t *kd)
00231 {
00232 ED_TEST_RETURN_ERROR(!kd->defaultVal, "ED_GetDefaultFloat: no default available");
00233 ED_TEST_RETURN_ERROR(!(kd->flags & ED_TYPE_FLOAT), "ED_GetDefaultFloat: key does not define V_FLOAT");
00234 ED_PASS_ERROR(ED_GetFloatVectorFromString(kd->defaultVal, defaultBuf, n));
00235 return ED_OK;
00236 }
00237
00248 int ED_GetDefaultInt (int *defaultBuf, const int n, const entityKeyDef_t *kd)
00249 {
00250 ED_TEST_RETURN_ERROR(!kd->defaultVal, "ED_GetDefaultInt: no default available");
00251 ED_TEST_RETURN_ERROR(!(kd->flags & ED_TYPE_INT), "ED_GetDefaultInt: key does not define V_INT");
00252 ED_PASS_ERROR(ED_GetIntVectorFromString(kd->defaultVal, defaultBuf, n));
00253 return ED_OK;
00254 }
00255
00265 int ED_GetIntVector (const entityKeyDef_t *kd, int v[], const int n)
00266 {
00267 ED_PASS_ERROR(ED_GetIntVectorFromString(kd->desc, v, n));
00268 return ED_OK;
00269 }
00270
00280 static int ED_CheckNumber (const char *value, const int floatOrInt, const int insistPositive, int_float_tu *parsedNumber)
00281 {
00282 char *end_p;
00283
00284
00285
00286
00287
00288 ED_TEST_RETURN_ERROR(value[0] == 'i' || value[0] == 'I' || value[0] == 'n' || value[0] == 'N'
00289 || strstr(value, "0x") || strstr(value, "0X"),
00290 "infinity, NaN, hex (0x...) not allowed. found \"%s\"", value);
00291 switch (floatOrInt) {
00292 case ED_TYPE_FLOAT:
00293 parsedNumber->f = strtof(value, &end_p);
00294 ED_TEST_RETURN_ERROR(insistPositive && parsedNumber->f < 0.0f, "ED_CheckNumber: not positive %s", value);
00295 break;
00296 case ED_TYPE_INT:
00297 parsedNumber->i = (int)strtol(value, &end_p, 10);
00298 ED_TEST_RETURN_ERROR(insistPositive && parsedNumber->i < 0, "ED_CheckNumber: not positive %s", value);
00299 break;
00300 default:
00301 ED_RETURN_ERROR("ED_CheckNumber: type to test against not recognised");
00302 }
00303
00304 ED_TEST_RETURN_ERROR(strlen(value) != (unsigned int)(end_p-value),
00305 "problem with numeric value: \"%s\" declared as %s. (might be relevant: only use whitespace to delimit values)",
00306 value, ED_Constant2Type(floatOrInt));
00307 return ED_OK;
00308 }
00309
00316 static int ED_CheckRange (const entityKeyDef_t *keyDef, const int floatOrInt, const int index, int_float_tu parsedNumber)
00317 {
00318
00319 const int useRangeIndex = (keyDef->numRanges == 1) ? 0 : index;
00320 entityKeyRange_t *kr;
00321 const float discreteFloatEpsilon = 0.0001f;
00322 if (0 == keyDef->numRanges)
00323 return ED_OK;
00324 assert(useRangeIndex < keyDef->numRanges);
00325 kr = keyDef->ranges[useRangeIndex];
00326 switch (floatOrInt) {
00327 case ED_TYPE_FLOAT:
00328 if (kr->continuous) {
00329 ED_TEST_RETURN_ERROR(parsedNumber.f < kr->fArr[0] || parsedNumber.f > kr->fArr[1],
00330 "ED_CheckRange: %.1f out of range, \"%s\" in %s",
00331 parsedNumber.f, kr->str, keyDef->name);
00332 return ED_OK;
00333 } else {
00334 int j;
00335 for (j = 0; j < kr->numElements; j++)
00336 if (fabs(parsedNumber.f - kr->fArr[j]) < discreteFloatEpsilon)
00337 return ED_OK;
00338 }
00339 break;
00340 case ED_TYPE_INT:
00341 if (kr->continuous) {
00342 ED_TEST_RETURN_ERROR(parsedNumber.i < kr->iArr[0] || parsedNumber.i > kr->iArr[1],
00343 "ED_CheckRange: %i out of range, \"%s\" in %s",
00344 parsedNumber.i, kr->str, keyDef->name);
00345 return ED_OK;
00346 } else {
00347 int j;
00348 for (j = 0; j < kr->numElements; j++)
00349 if (kr->iArr[j] == parsedNumber.i)
00350 return ED_OK;
00351 }
00352 break;
00353 default:
00354 ED_RETURN_ERROR( "ED_CheckRange: type to test against not recognised in %s", keyDef->name);
00355 }
00356 ED_RETURN_ERROR("ED_CheckRange: value not specified in range definition, \"%s\" in %s",
00357 kr->str, keyDef->name);
00358 }
00359
00366 static int ED_CheckNumericType (const entityKeyDef_t *keyDef, const char *value, const int floatOrInt)
00367 {
00368 int i = 0;
00369 static char tokBuf[64];
00370 const char *buf_p = tokBuf;
00371
00372 strncpy(tokBuf, value, sizeof(tokBuf));
00373 assert(!(floatOrInt & ED_TYPE_INT) != !(floatOrInt & ED_TYPE_FLOAT));
00374 while (buf_p) {
00375 const char *tok = Com_Parse(&buf_p);
00376 int_float_tu parsedNumber;
00377 if (tok[0] == '\0')
00378 break;
00379
00380 ED_PASS_ERROR_EXTRAMSG(ED_CheckNumber(tok, floatOrInt, keyDef->flags & ED_INSIST_POSITIVE, &parsedNumber),
00381 " in key \"%s\"", keyDef->name);
00382
00383 ED_PASS_ERROR(ED_CheckRange(keyDef, floatOrInt, i, parsedNumber));
00384
00385 i++;
00386 }
00387
00388 ED_TEST_RETURN_ERROR(i != keyDef->vLen, "ED_CheckNumericType: %i elements in vector that should have %i for \"%s\" key",
00389 i, keyDef->vLen, keyDef->name);
00390
00391 return ED_OK;
00392 }
00393
00402 int ED_Check (const char *classname, const char *key, const char *value)
00403 {
00404 const entityKeyDef_t *kd = ED_GetKeyDef(classname, key, 0);
00405 if (!kd)
00406 return ED_ERROR;
00407
00408 return ED_CheckKey(kd, value);
00409 }
00410
00417 int ED_CheckKey (const entityKeyDef_t *kd, const char *value)
00418 {
00419 ED_TEST_RETURN_ERROR(!kd, "ED_CheckTypeEntityKey: null key def");
00420 switch (kd->flags & ED_KEY_TYPE) {
00421 case ED_TYPE_FLOAT:
00422 return ED_CheckNumericType(kd, value, ED_TYPE_FLOAT);
00423 case ED_TYPE_INT:
00424 return ED_CheckNumericType(kd, value, ED_TYPE_INT);
00425 case ED_TYPE_STRING:
00426 case 0:
00427 return ED_OK;
00428 default:
00429 ED_RETURN_ERROR("ED_CheckTypeEntityKey: type not recognised in key def");
00430 }
00431 }
00432
00442 int ED_GetDefaultString (char *defaultBuf, const size_t n, const entityKeyDef_t *kd)
00443 {
00444 ED_TEST_RETURN_ERROR(n < 1, "ED_GetDefaultString: n is %lu", (unsigned long)n);
00445 defaultBuf[0] = '\0';
00446 ED_TEST_RETURN_ERROR(!kd->defaultVal, "ED_GetDefaultString: no default available");
00447 strncpy(defaultBuf, kd->defaultVal, n - 1);
00448 ED_TEST_RETURN_ERROR(strlen(defaultBuf) < strlen(kd->defaultVal),
00449 "ED_GetDefaultString: target buffer supplied is too small");
00450 return ED_OK;
00451 }
00452
00457 static int ED_ParseType (entityKeyDef_t *kd, const char *parsedToken)
00458 {
00459 static char tokBuf[64];
00460 const char *buf_p;
00461 int type;
00462 int vectorLen;
00463 const char *partToken;
00464 int_float_tu parsedNumber;
00465
00466
00467
00468 ED_TEST_RETURN_ERROR((strlen(parsedToken) + 1) > sizeof(tokBuf),
00469 "ED_ParseType: type string too long for buffer for key %s", kd->name);
00470 strncpy(tokBuf, parsedToken, sizeof(tokBuf));
00471 tokBuf[sizeof(tokBuf) - 1] = '\0';
00472 buf_p = tokBuf;
00473
00474 partToken = Com_Parse(&buf_p);
00475
00476 if (!strcmp("SIGNED", partToken)) {
00477 partToken = Com_Parse(&buf_p);
00478 } else if (!strcmp("UNSIGNED", partToken)) {
00479 kd->flags |= ED_INSIST_POSITIVE;
00480 partToken = Com_Parse(&buf_p);
00481 }
00482
00483 if (partToken[0] != '\0') {
00484 type = ED_Type2Constant(partToken);
00485 ED_PASS_ERROR(type);
00486 } else {
00487 type = ED_TYPE_STRING;
00488 }
00489
00490 kd->flags |= type;
00491 partToken = Com_Parse(&buf_p);
00492 vectorLen = atoi(partToken);
00493 if (vectorLen)
00494 ED_TEST_RETURN_ERROR(ED_ERROR == ED_CheckNumber(partToken, ED_TYPE_INT, 1, &parsedNumber),
00495 "ED_ParseType: problem with vector length \"%s\" in key %s",
00496 partToken, kd->name);
00497 kd->vLen = strlen(partToken) ? (vectorLen ? vectorLen : 1) : 1;
00498 return ED_OK;
00499 }
00500
00505 static int ED_Block2Constant (const char *blockName)
00506 {
00507 if (!strcmp("optional", blockName))
00508 return ED_OPTIONAL;
00509 else if (!strcmp("mandatory", blockName))
00510 return ED_MANDATORY;
00511 else if (!strcmp("abstract", blockName))
00512 return ED_ABSTRACT;
00513 else if (!strcmp("default", blockName))
00514 return ED_DEFAULT;
00515 else if (!strcmp("type", blockName))
00516 return ED_MODE_TYPE;
00517 else if (!strcmp("range", blockName))
00518 return ED_RANGE;
00519 else
00520 ED_RETURN_ERROR("parse mode not recognised");
00521 }
00522
00528 static const char *ED_Constant2Block (int constInt)
00529 {
00530 switch (constInt) {
00531 case ED_OPTIONAL:
00532 return "optional";
00533 case ED_MANDATORY:
00534 return "mandatory";
00535 case ED_ABSTRACT:
00536 return "abstract";
00537 case ED_DEFAULT:
00538 return "default";
00539 case ED_MODE_TYPE:
00540 return "type";
00541 case ED_RANGE:
00542 return "range";
00543 default:
00544 snprintf(lastErr, sizeof(lastErr), "ED_Constant2Block: constant not recognised");
00545 return NULL;
00546 }
00547 }
00548
00549 static int ED_AllocRange (entityKeyDef_t *kd, const char *rangeStr)
00550 {
00551 entityKeyRange_t **newRanges;
00552
00553 char *newStr = strdup(rangeStr);
00554 entityKeyRange_t *newRange = (entityKeyRange_t *)malloc(sizeof(entityKeyRange_t));
00555 memset(newRange, 0, sizeof(*newRange));
00556
00557 newRanges = (entityKeyRange_t **)malloc((kd->numRanges + 1) * sizeof(entityKeyRange_t *));
00558 ED_TEST_RETURN_ERROR(!newRanges || !newStr || !newRange, "ED_AllocRange: out of memory");
00559 newRange->str = newStr;
00560 newRanges[kd->numRanges] = newRange;
00561 if (kd->ranges) {
00562 memcpy(newRanges, kd->ranges, kd->numRanges * sizeof(entityKeyRange_t *));
00563 free(kd->ranges);
00564 }
00565 kd->numRanges++;
00566 kd->ranges = newRanges;
00567 return ED_OK;
00568 }
00569
00573 static int ED_PairParsed (entityKeyDef_t keyDefsBuf[], int *numKeyDefsSoFar_p,
00574 const char *newName, const char *newVal, const int mode)
00575 {
00576
00577 entityKeyDef_t *keyDef = ED_FindKeyDefInArray(keyDefsBuf, *numKeyDefsSoFar_p, newName, mode);
00578
00579
00580 if (!keyDef) {
00581 keyDef = &keyDefsBuf[(*numKeyDefsSoFar_p)++];
00582 ED_TEST_RETURN_ERROR(*numKeyDefsSoFar_p >= ED_MAX_KEYS_PER_ENT, "ED_PairParsed: too many keys for buffer");
00583 keyDef->name = strdup(newName);
00584 ED_TEST_RETURN_ERROR(!keyDef->name, "ED_PairParsed: out of memory");
00585 }
00586
00587
00588 ED_TEST_RETURN_ERROR(keyDef->flags & mode & ~ED_RANGE,
00589 "Duplicate %s for %s key. second value: %s", ED_Constant2Block(mode), newName, newVal);
00590
00591 keyDef->flags |= mode;
00592
00593
00594 switch (mode) {
00595 case ED_MANDATORY:
00596 case ED_OPTIONAL:
00597 case ED_ABSTRACT:
00598 keyDef->desc = strdup(newVal);
00599 ED_TEST_RETURN_ERROR(!keyDef->desc, "ED_PairParsed: out of memory while storing string.");
00600 return ED_OK;
00601 case ED_DEFAULT:
00602 keyDef->defaultVal = strdup(newVal);
00603 ED_TEST_RETURN_ERROR(!keyDef->defaultVal, "ED_PairParsed: out of memory while storing string.");
00604 return ED_OK;
00605 case ED_MODE_TYPE:
00606
00607
00608 ED_PASS_ERROR(ED_ParseType(keyDef, newVal));
00609 return ED_OK;
00610 case ED_RANGE:
00611
00612
00613 ED_PASS_ERROR(ED_AllocRange(keyDef, newVal));
00614 return ED_OK;
00615 default:
00616 ED_RETURN_ERROR("ED_PairParsed: parse mode not recognised");
00617 }
00618 }
00619
00623 static int ED_ParseEntities (const char **data_p)
00624 {
00625 int braceLevel = 0;
00626 int tokensOnLevel0 = 0;
00627 int mode = ED_ABSTRACT;
00628 entityKeyDef_t keyDefBuf[ED_MAX_KEYS_PER_ENT];
00629 char lastTokenBuf[ED_MAX_TOKEN_LEN];
00630 int keyIndex = 0;
00631 int toggle = 0;
00632
00633 while (data_p) {
00634 const char *parsedToken = Com_Parse(data_p);
00635 toggle ^= 1;
00636
00637 if (parsedToken[0] == '\0' && braceLevel == 0)
00638 break;
00639
00640 if (parsedToken[0] == '{') {
00641 braceLevel++;
00642 ED_TEST_RETURN_ERROR(braceLevel > 2, "Too many open braces, nested %i deep", braceLevel);
00643 ED_TEST_RETURN_ERROR(!toggle, "ED_ParseEntities: Incorrect number of tokens before '{'");
00644 toggle ^= 1;
00645 tokensOnLevel0 = 0;
00646 continue;
00647 }
00648
00649 if (parsedToken[0] == '}') {
00650 braceLevel--;
00651 ED_TEST_RETURN_ERROR(braceLevel < 0, "Too many close braces. after %i entities", numEntityDefs);
00652 toggle ^= 1;
00653 if (braceLevel == 0) {
00654 ED_PASS_ERROR(ED_AllocEntityDef(keyDefBuf, keyIndex, numEntityDefs));
00655 numEntityDefs++;
00656 ED_TEST_RETURN_ERROR(numEntityDefs >= ED_MAX_DEFS, "ED_ParseEntities: too many entity defs for buffer");
00657 }
00658 if (braceLevel == 1)
00659 mode = ED_ABSTRACT;
00660
00661 continue;
00662 }
00663
00664 if (braceLevel == 0) {
00665 if (tokensOnLevel0 == 0 && strcmp(parsedToken, "entity"))
00666 ED_RETURN_ERROR( "Next entity expected, found \"%s\"", parsedToken);
00667
00668 if (tokensOnLevel0 == 1) {
00669 const entityDef_t *prevED = ED_GetEntityDef(parsedToken);
00670 ED_TEST_RETURN_ERROR(prevED, "ED_ParseEntities: duplicate entity definition \"%s\"", parsedToken);
00671 memset(keyDefBuf, 0, sizeof(keyDefBuf));
00672 keyIndex = 0;
00673 ED_PASS_ERROR(ED_PairParsed(keyDefBuf, &keyIndex, "classname", parsedToken, ED_MANDATORY));
00674 mode = ED_ABSTRACT;
00675 }
00676
00677 if (tokensOnLevel0 > 1)
00678 ED_RETURN_ERROR( "Start of entity block expected found \"%s\"", parsedToken);
00679
00680 tokensOnLevel0++;
00681 } else {
00682 const int newMode = ED_Block2Constant(parsedToken);
00683 if (ED_ERROR == newMode) {
00684 if (toggle) {
00685 if ('\0' == parsedToken[0])
00686 ED_RETURN_ERROR("key name null string, \"\", or missing closing brace");
00687 strncpy(lastTokenBuf, parsedToken, sizeof(lastTokenBuf));
00688 lastTokenBuf[sizeof(lastTokenBuf) - 1] = '\0';
00689 } else {
00690 ED_PASS_ERROR(ED_PairParsed(keyDefBuf, &keyIndex, lastTokenBuf, parsedToken, mode));
00691 }
00692 } else {
00693 mode = newMode;
00694 toggle ^= 1;
00695 }
00696 }
00697 }
00698
00699 return ED_OK;
00700 }
00701
00707 static int ED_CheckDefaultTypes (void)
00708 {
00709 const entityDef_t *ed;
00710 const entityKeyDef_t *kd;
00711 for (ed = entityDefs; ed->numKeyDefs; ed++)
00712 for (kd = ed->keyDefs; kd->name; kd++)
00713 if (kd->defaultVal)
00714 ED_PASS_ERROR_EXTRAMSG(ED_CheckKey(kd, kd->defaultVal),
00715 " while checking default block entry agrees with type")
00716
00717 return ED_OK;
00718 }
00719
00726 static int ED_ProcessRanges (void)
00727 {
00728 static int ibuf[32];
00729 static float fbuf[32];
00730
00731 entityDef_t *ed;
00732 for (ed = entityDefs; ed->numKeyDefs; ed++) {
00733 entityKeyDef_t *kd;
00734 for (kd = ed->keyDefs; kd->name; kd++) {
00735 const int keyType = kd->flags & ED_KEY_TYPE;
00736 int i;
00737 for (i = 0; i < kd->numRanges ;i++) {
00738 int numElements = 0;
00739 entityKeyRange_t *kr = kd->ranges[i];
00740 const char *tmpRange_p = kr->str;
00741 ED_TEST_RETURN_ERROR(!keyType || (keyType & ED_TYPE_STRING), "ED_ProcessRanges: ranges may not be specified for strings. note that V_STRING is the default type. %s in %s",
00742 kd->name, ed->classname);
00743 while (tmpRange_p) {
00744 int_float_tu parsedNumber;
00745 const char *tok = Com_Parse(&tmpRange_p);
00746 if (tok[0] == '\0')
00747 break;
00748 if (!strcmp("-", tok)) {
00749 kr->continuous = 1;
00750 ED_TEST_RETURN_ERROR(numElements != 1, "ED_ProcessRanges: problem with continuous range, \"%s\" in %s in %s",
00751 kr->str, kd->name, ed->classname);
00752 continue;
00753 }
00754 ED_PASS_ERROR(ED_CheckNumber(tok, keyType, kd->flags & ED_INSIST_POSITIVE, &parsedNumber));
00755 switch (keyType) {
00756 case ED_TYPE_INT:
00757 ibuf[numElements++] = atoi(tok);
00758 break;
00759 case ED_TYPE_FLOAT:
00760 fbuf[numElements++] = atof(tok);
00761 break;
00762 default:
00763 ED_RETURN_ERROR("ED_ProcessRanges: unexpected type");
00764 }
00765 }
00766 kr->numElements = numElements;
00767 ED_TEST_RETURN_ERROR(kr->continuous && numElements != 2,
00768 "ED_ProcessRanges: continuous range should only have 2 elements, upper and lower bounds, \"%s\" in %s in %s",
00769 kr->str, kd->name, ed->classname);
00770 if (ED_TYPE_INT == keyType) {
00771 const size_t size = numElements * sizeof(int);
00772 kr->iArr = (int *)malloc(size);
00773 ED_TEST_RETURN_ERROR(!kr->iArr, "ED_ProcessRanges: out of memory");
00774 memcpy(kr->iArr, ibuf, size);
00775 } else {
00776 const size_t size = numElements * sizeof(float);
00777 kr->fArr = (float *)malloc(size);
00778 ED_TEST_RETURN_ERROR(!kr->fArr, "ED_ProcessRanges: out of memory");
00779 memcpy(kr->fArr, fbuf, size);
00780 }
00781 }
00782 ED_TEST_RETURN_ERROR(kd->numRanges && kd->numRanges != 1 && kd->vLen != kd->numRanges,
00783 "ED_ProcessRanges: if range definitions are supplied, "
00784 "there must be one (which is applied to each element of a vector), "
00785 "or one for each element of the vector. "
00786 "%s in %s has %i elements in vector and %i range definitions",
00787 ed->classname, kd->name, kd->vLen, kd->numRanges);
00788 }
00789 }
00790 return ED_OK;
00791 }
00792
00798 int ED_Parse (const char *data_p)
00799 {
00800
00801 static int done = 0;
00802 if (done)
00803 return ED_OK;
00804
00805 snprintf(lastErr, sizeof(lastErr), "no error");
00806
00807
00808 memset(entityDefs, 0, (ED_MAX_DEFS + 1) * sizeof(entityDef_t));
00809 numEntityDefs = 0;
00810
00811 ED_PASS_ERROR(ED_ParseEntities(&data_p));
00812 ED_TEST_RETURN_ERROR(numEntityDefs == 0, "ED_Parse: Zero entity definitions found");
00813
00814 ED_PASS_ERROR(ED_ProcessRanges());
00815
00816 ED_PASS_ERROR(ED_CheckDefaultTypes());
00817
00818 done = 1;
00819
00820 #ifdef DEBUG_ED
00821 ED_Dump();
00822 #endif
00823
00824 return ED_OK;
00825 }
00826
00827 const char *ED_GetLastError (void)
00828 {
00829 return lastErr;
00830 }
00831
00837 const entityKeyDef_t *ED_GetKeyDef (const char *classname, const char *keyname, const int abstract)
00838 {
00839 const entityDef_t *ed = ED_GetEntityDef(classname);
00840 return ED_GetKeyDefEntity(ed, keyname, abstract);
00841 }
00842
00849 const entityKeyDef_t *ED_GetKeyDefEntity (const entityDef_t *ed, const char *keyname, const int abstract)
00850 {
00851 const entityKeyDef_t *kd;
00852
00853 if (!ed)
00854 return NULL;
00855
00856 for (kd = ed->keyDefs; kd->name; kd++)
00857 if (!strcmp(keyname, kd->name)) {
00858 if (abstract) {
00859 if (kd->flags & ED_ABSTRACT)
00860 return kd;
00861 } else {
00862 if (!(kd->flags & ED_ABSTRACT))
00863 return kd;
00864 }
00865 }
00866
00867 snprintf(lastErr, sizeof(lastErr), "ED_GetKeyDefEntity: no key definition for %s found in entity %s entities.ufo", keyname, ed->classname);
00868 return NULL;
00869 }
00870
00875 const entityDef_t *ED_GetEntityDef (const char *classname)
00876 {
00877 const entityDef_t *ed;
00878
00879 for (ed = entityDefs; ed->numKeyDefs; ed++)
00880 if (!strcmp(classname, ed->classname))
00881 return ed;
00882
00883 snprintf(lastErr, sizeof(lastErr), "ED_GetEntityDef: no entity definition for %s found in entities.ufo", classname);
00884 return NULL;
00885 }
00886
00887 void ED_Free (void)
00888 {
00889 if (numEntityDefs) {
00890 entityDef_t *ed;
00891 for (ed = entityDefs; ed->numKeyDefs; ed++) {
00892 entityKeyDef_t *kd;
00893 free(ed->classname);
00894 for (kd = ed->keyDefs; kd->name; kd++) {
00895 if (kd->name)
00896 free(kd->name);
00897 if (kd->desc)
00898 free(kd->desc);
00899 if (kd->defaultVal)
00900 free(kd->defaultVal);
00901 if (kd->numRanges) {
00902 int i;
00903 for (i = 0; i < kd->numRanges ;i++) {
00904 entityKeyRange_t *kr = kd->ranges[i];
00905 if (kr->iArr)
00906 free(kr->iArr);
00907 if (kr->fArr)
00908 free(kr->fArr);
00909 free(kr->str);
00910 free(kr);
00911 }
00912 free(kd->ranges);
00913 }
00914 }
00915 free(kd = ed->keyDefs);
00916 }
00917 }
00918 }
00919
00920 #ifdef DEBUG_ED
00921
00922 void ED_PrintRange (const entityKeyRange_t *kr)
00923 {
00924 int i;
00925 printf(" rge:%c:%c>", kr->continuous ? 'c' : 'd', kr->iArr ? 'i' : 'f');
00926 for (i = 0; i < kr->numElements; i++) {
00927 if (kr->iArr)
00928 printf("%i ", kr->iArr[i]);
00929 else
00930 printf("%.1f ",kr->fArr[i]);
00931 }
00932 printf("\b<");
00933 }
00934
00935 void ED_PrintParsedDefault (const entityKeyDef_t *kd)
00936 {
00937 float fa[32];
00938 int ia[32];
00939 char ca[128];
00940 int i;
00941
00942 if (!kd->defaultVal)
00943 return;
00944
00945 printf(" parsed default>");
00946
00947 switch (kd->flags & ED_KEY_TYPE) {
00948 case ED_TYPE_INT:
00949 ED_GetDefaultInt(ia, kd->vLen, kd);
00950 for (i = 0; i < kd->vLen; i++)
00951 printf("%i ", ia[i]);
00952 break;
00953 case ED_TYPE_FLOAT:
00954 ED_GetDefaultFloat(fa, kd->vLen, kd);
00955 for (i = 0; i < kd->vLen; i++)
00956 printf("%f ", fa[i]);
00957 break;
00958 case ED_TYPE_STRING:
00959 ED_GetDefaultString(ca, sizeof(ca) - 1, kd);
00960 printf("%s", ca);
00961 break;
00962 }
00963
00964 printf("<");
00965 }
00966
00967 void ED_PrintKeyDef (const entityKeyDef_t *kd)
00968 {
00969 printf(" >%s< mandtry:%i opt:%i abst:%i type:%i", kd->name,
00970 kd->flags & ED_MANDATORY ? 1 : 0,
00971 kd->flags & ED_OPTIONAL ? 1 : 0,
00972 kd->flags & ED_ABSTRACT ? 1 : 0,
00973 kd->flags & ED_MODE_TYPE ? 1 : 0);
00974 if (kd->flags & ED_MODE_TYPE)
00975 printf(" type:%s[%i]", ED_Constant2Type(kd->flags & ED_KEY_TYPE), kd->vLen);
00976
00977 if (kd->defaultVal)
00978 printf(" default>%s<",kd->defaultVal);
00979
00980 if (kd->numRanges) {
00981 int i;
00982 for (i = 0; i < kd->numRanges; i++) {
00983 ED_PrintRange(kd->ranges[i]);
00984 }
00985 }
00986
00987 ED_PrintParsedDefault(kd);
00988
00989 printf("\n");
00990 }
00991
00995 void ED_Dump (void)
00996 {
00997 const entityDef_t *ed;
00998 printf("ED_Dump:\n");
00999 for (ed = entityDefs; ed->numKeyDefs; ed++) {
01000 const entityKeyDef_t *kd;
01001 printf("entity def >%s<\n", ed->classname);
01002 for (kd = &ed->keyDefs[0]; kd->name; kd++) {
01003 ED_PrintKeyDef(kd);
01004 }
01005 }
01006 }
01007 #endif