entitiesdef.c

Go to the documentation of this file.
00001 
00006 /*
00007 All original material Copyright (C) 2002-2010 UFO: Alien Invasion.
00008 
00009 Copyright (C) 1997-2001 Id Software, Inc.
00010 
00011 This program is free software; you can redistribute it and/or
00012 modify it under the terms of the GNU General Public License
00013 as published by the Free Software Foundation; either version 2
00014 of the License, or (at your option) any later version.
00015 
00016 This program is distributed in the hope that it will be useful,
00017 but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00019 
00020 See the GNU General Public License for more details.
00021 
00022 You should have received a copy of the GNU General Public License
00023 along with this program; if not, write to the Free Software
00024 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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     /* now we know how many there are in this entity, malloc */
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     /* and copy from temp buffer */
00104     memcpy(eDef->keyDefs, newKeyDefs, numKeyDefs * sizeof(entityKeyDef_t));
00105 
00106     /* set NULLs at the end, to enable looping through using a pointer */
00107     memset(&eDef->keyDefs[numKeyDefs], 0, sizeof(entityKeyDef_t));
00108 
00109     /* classname is commonly used, put it in its own field, copied from keyDefs[0] */
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         /* names equal. both abstract or both not abstract */
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; /* previous tok was the last real one, don't waste time */
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; /* previous tok was the last real one, don't waste time */
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     /* V_INTs are protected from octal and hex as strtol with base 10 is used.
00284      * this test is useful for V_INT, as it gives a specific error message.
00285      * V_FLOATs are not protected from hex, inf, nan, so this check is here.
00286      * strstr is used for hex, as 0x may not be the start of the string.
00287      * eg -0x0.2 is a negative hex float  */
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     /* if strto* did not use the whole token, then there is some non-number part to it */
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     /* there may be a range for each element of the value, or there may only be one */
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; /* if no range defined, that is 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));/* logical exclusive or */
00374     while (buf_p) {
00375         const char *tok = Com_Parse(&buf_p);
00376         int_float_tu parsedNumber;
00377         if (tok[0] == '\0')
00378             break; /* previous tok was the last real one, don't waste time */
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: /* string is the default */
00427         return ED_OK; /* all strings are good */
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'; /* be safe, in case an error is found, and we return early */
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     /* need a copy, as parsedToken is held in a static buffer in the
00467      * Com_Parse function */
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);/* get next token */
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 {/* default is string */
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; /* default is 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     /* start a new range */
00553     char *newStr = strdup(rangeStr);
00554     entityKeyRange_t *newRange = (entityKeyRange_t *)malloc(sizeof(entityKeyRange_t));
00555     memset(newRange, 0, sizeof(*newRange));
00556     /* resize array of pointers */
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     /* check if there is already a key def */
00577     entityKeyDef_t *keyDef = ED_FindKeyDefInArray(keyDefsBuf, *numKeyDefsSoFar_p, newName, mode);
00578 
00579     /* create one if required */
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     /* multiple range defs are permitted, different elements can have different ranges */
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     /* store information */
00594     switch (mode) {
00595     case ED_MANDATORY:
00596     case ED_OPTIONAL:
00597     case ED_ABSTRACT: /* intentional fall-through */
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         /* only optional or mandatory keys may have types, not possible to test for this here,
00607          * as the type block may come before the optional or mandatory block */
00608         ED_PASS_ERROR(ED_ParseType(keyDef, newVal));
00609         return ED_OK;
00610     case ED_RANGE:
00611         /* only typed keys may have ranges, this may only be tested after
00612          * the whole ent has been parsed: the blocks may come in any order */
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; /* many lines should have a pair of tokens on, this toggles 0, 1 to indicate progress */
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; /* reset, as toggle is only for counting proper text tokens, not braces */
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; /* reset, as toggle is only for counting proper text tokens, not braces */
00653             if (braceLevel == 0) { /* finished parsing entity def and prepare for the next one */
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) /* ending a default, mandatory, etc block, go back to default parse mode */
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) {/* classname of entity, start parsing new entity */
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)); /* ensure pointers are not carried over from previous entity */
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 { /* braceLevel > 0 */
00682             const int newMode = ED_Block2Constant(parsedToken);
00683             if (ED_ERROR == newMode) { /* must be a key name or value */
00684                 if (toggle) { /* store key name til after next token is parsed */
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 { /* store key-value pair in buffer until whole entity is parsed */
00690                     ED_PASS_ERROR(ED_PairParsed(keyDefBuf, &keyIndex, lastTokenBuf, parsedToken, mode));
00691                 }
00692             } else {
00693                 mode = newMode;
00694                 toggle ^= 1; /* start of a mode changing block is the only time that only one non-brace token is on a line */
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 { /* ED_TYPE_FLOAT */
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     /* only do this once, repeat calls are OK */
00801     static int done = 0;
00802     if (done)
00803         return ED_OK;
00804 
00805     snprintf(lastErr, sizeof(lastErr), "no error");
00806     /* memset to NULL now so that looping through the ones that have already
00807      * been parsed is possible while the rest are parsed */
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; /* do not do it again */
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

Generated by  doxygen 1.6.2