00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "ui_expression.h"
00026 #include "ui_main.h"
00027 #include "ui_internal.h"
00028 #include "ui_parse.h"
00029 #include "ui_actions.h"
00030 #include "node/ui_node_abstractnode.h"
00031 #include "../../shared/parse.h"
00032
00040 uiNode_t* UI_GetNodeFromExpression (uiAction_t *expression, const uiCallContext_t *context, const value_t **property)
00041 {
00042 if (property != NULL)
00043 *property = NULL;
00044
00045 switch (expression->type & EA_HIGHT_MASK) {
00046 case EA_VALUE:
00047 switch (expression->type) {
00048 case EA_VALUE_VAR:
00049 {
00050 uiValue_t *variable = UI_GetVariable(context, expression->d.terminal.d1.integer);
00051 switch (variable->type) {
00052 case EA_VALUE_NODE:
00053 return variable->value.node;
00054 default:
00055 break;
00056 }
00057 }
00058 break;
00059
00060 case EA_VALUE_PATHNODE:
00061 case EA_VALUE_PATHNODE_WITHINJECTION:
00062 {
00063 uiNode_t *node;
00064 const value_t *propertyTmp;
00065 const char *path = expression->d.terminal.d1.string;
00066 if (expression->type == EA_VALUE_PATHNODE_WITHINJECTION)
00067 path = UI_GenInjectedString(path, qfalse, context);
00068
00069 UI_ReadNodePath(path, context->source, &node, &propertyTmp);
00070 if (!node) {
00071 Com_Printf("UI_GetNodeFromExpression: Node '%s' wasn't found; NULL returned\n", path);
00072 return NULL;
00073 }
00074 if (propertyTmp != NULL)
00075 Com_Printf("UI_GetNodeFromExpression: No property expected, but path '%s' contain a property. Property ignored.\n", path);
00076
00077 return node;
00078 }
00079
00080 case EA_VALUE_PATHPROPERTY:
00081 case EA_VALUE_PATHPROPERTY_WITHINJECTION:
00082 {
00083 uiNode_t *node;
00084 const value_t *propertyTmp;
00085 const char *path = expression->d.terminal.d1.string;
00086 if (expression->type == EA_VALUE_PATHPROPERTY_WITHINJECTION)
00087 path = UI_GenInjectedString(path, qfalse, context);
00088
00089 UI_ReadNodePath(path, context->source, &node, &propertyTmp);
00090 if (!node) {
00091 Com_Printf("UI_GetNodeFromExpression: Node '%s' wasn't found; NULL returned\n", path);
00092 return NULL;
00093 }
00094 if (property == NULL) {
00095 if (propertyTmp != NULL)
00096 Com_Printf("UI_GetNodeFromExpression: No property expected, but path '%s' contain a property. Property ignored.\n", path);
00097 } else {
00098 *property = propertyTmp;
00099 }
00100
00101 return node;
00102 }
00103
00104 case EA_VALUE_THIS:
00105 return context->source;
00106
00107 case EA_VALUE_PARENT:
00108 return context->source->parent;
00109
00110 case EA_VALUE_WINDOW:
00111 return context->source->root;
00112
00113 default:
00114 break;
00115 }
00116
00117 case EA_OPERATOR_UNARY:
00118 switch (expression->type) {
00119 case EA_OPERATOR_PATHPROPERTYFROM:
00120 {
00121 uiNode_t *relativeTo = UI_GetNodeFromExpression(expression->d.nonTerminal.left, context, NULL);
00122 uiNode_t *node;
00123 const value_t *propertyTmp;
00124 const char* path = expression->d.terminal.d2.constString;
00125 UI_ReadNodePath(path, relativeTo, &node, &propertyTmp);
00126 if (!node) {
00127 Com_Printf("UI_GetNodeFromExpression: Path '%s' from node '%s' found no node; NULL returned\n", path, UI_GetPath(relativeTo));
00128 return NULL;
00129 }
00130 if (property == NULL) {
00131 if (propertyTmp != NULL)
00132 Com_Printf("UI_GetNodeFromExpression: No property expected, but path '%s' from node '%s' found no node; NULL returned\n", path, UI_GetPath(relativeTo));
00133 } else {
00134 *property = propertyTmp;
00135 }
00136 return node;
00137 }
00138 default:
00139 break;
00140 }
00141
00142 default:
00143 break;
00144 }
00145
00146 return NULL;
00147 }
00148
00149
00153 float UI_GetFloatFromExpression (uiAction_t *expression, const uiCallContext_t *context)
00154 {
00155 switch (expression->type & EA_HIGHT_MASK) {
00156 case EA_VALUE:
00157 switch (expression->type) {
00158 case EA_VALUE_VAR:
00159 {
00160 uiValue_t *variable = UI_GetVariable(context, expression->d.terminal.d1.integer);
00161 switch (variable->type) {
00162 case EA_VALUE_STRING:
00163 if (variable->value.string == NULL) {
00164 Com_Printf("UI_GetFloatFromExpression: String variable not initialized. '0' returned");
00165 return 0;
00166 }
00167 return atof(variable->value.string);
00168 case EA_VALUE_FLOAT:
00169 return variable->value.number;
00170 case EA_VALUE_CVAR:
00171 {
00172 cvar_t *cvar = variable->value.cvar;
00173 if (cvar == NULL) {
00174 Com_Printf("UI_GetFloatFromExpression: Cvar variable not initialized. '0' returned");
00175 return 0;
00176 }
00177 return cvar->value;
00178 }
00179 default:
00180 Com_Printf("UI_GetFloatFromExpression: Unsupported variable type: %i. '0' returned", variable->type);
00181 return 0;
00182 }
00183 }
00184 case EA_VALUE_STRING:
00185 case EA_VALUE_STRING_WITHINJECTION:
00186 {
00187 const char* string = expression->d.terminal.d1.string;
00188 if (expression->type == EA_VALUE_STRING_WITHINJECTION)
00189 string = UI_GenInjectedString(string, qfalse, context);
00190 return atof(string);
00191 }
00192 case EA_VALUE_FLOAT:
00193 return expression->d.terminal.d1.number;
00194 case EA_VALUE_CVARNAME:
00195 case EA_VALUE_CVARNAME_WITHINJECTION:
00196 {
00197 cvar_t *cvar = NULL;
00198 const char *cvarName = expression->d.terminal.d1.string;
00199 if (expression->type == EA_VALUE_CVARNAME_WITHINJECTION)
00200 cvarName = UI_GenInjectedString(cvarName, qfalse, context);
00201 cvar = Cvar_Get(cvarName, "", 0, "Cvar from UI script expression");
00202 return cvar->value;
00203 }
00204 case EA_VALUE_PATHPROPERTY:
00205 case EA_VALUE_PATHPROPERTY_WITHINJECTION:
00206 {
00207 uiNode_t *node;
00208 const value_t *property;
00209 node = UI_GetNodeFromExpression(expression, context, &property);
00210 if (!node) {
00211 Com_Printf("UI_GetFloatFromParam: Node wasn't found; '0'\n");
00212 return 0;
00213 }
00214 if (!property) {
00215 Com_Printf("UI_GetFloatFromParam: Property wasn't found; '0' returned\n");
00216 return 0;
00217 }
00218 return UI_GetFloatFromNodeProperty(node, property);
00219 }
00220 case EA_VALUE_PARAM:
00221 {
00222 const int paramId = expression->d.terminal.d1.integer;
00223 const char *string = UI_GetParam(context, paramId);
00224 if (string[0] == '\0') {
00225 Com_Printf("UI_GetFloatFromParam: Param '%i' is out of range, or empty; '0' returned\n", paramId);
00226 return 0;
00227 }
00228 return atof(string);
00229 }
00230 case EA_VALUE_PARAMCOUNT:
00231 return UI_GetParamNumber(context);
00232 }
00233 break;
00234
00235 case EA_OPERATOR_FLOAT2FLOAT:
00236 {
00237 const float value1 = UI_GetFloatFromExpression(expression->d.nonTerminal.left, context);
00238 const float value2 = UI_GetFloatFromExpression(expression->d.nonTerminal.right, context);
00239
00240 switch (expression->type) {
00241 case EA_OPERATOR_ADD:
00242 return value1 + value2;
00243 case EA_OPERATOR_SUB:
00244 return value1 - value2;
00245 case EA_OPERATOR_MUL:
00246 return value1 * value2;
00247 case EA_OPERATOR_DIV:
00248 if (value2 == 0) {
00249 Com_Printf("UI_GetFloatFromExpression: Div by 0. '0' returned");
00250 return 0;
00251 } else
00252 return value1 / value2;
00253 case EA_OPERATOR_MOD:
00254 {
00255 const int v1 = value1;
00256 const int v2 = value2;
00258 return v1 % v2;
00259 }
00260 }
00261 }
00262 break;
00263
00264 case EA_OPERATOR_UNARY:
00265 switch (expression->type) {
00266 case EA_OPERATOR_PATHPROPERTYFROM:
00267 {
00268 uiNode_t *node;
00269 const value_t *property;
00270 node = UI_GetNodeFromExpression(expression, context, &property);
00271 return UI_GetFloatFromNodeProperty(node, property);
00272 }
00273 default:
00274 Com_Error(ERR_FATAL, "UI_GetFloatFromExpression: (EA_OPERATOR_UNARY) Invalid expression type %i", expression->type);
00275 }
00276
00277 }
00278
00279 Com_Printf("UI_GetFloatFromExpression: Unsupported expression type: %i. '0' returned", expression->type);
00280 return 0;
00281 }
00282
00288 const char* UI_GetStringFromExpression (uiAction_t *expression, const uiCallContext_t *context)
00289 {
00290 switch (expression->type & EA_HIGHT_MASK) {
00291 case EA_VALUE:
00292 switch (expression->type) {
00293 case EA_VALUE_VAR:
00294 {
00295 uiValue_t *variable = UI_GetVariable(context, expression->d.terminal.d1.integer);
00296 switch (variable->type) {
00297 case EA_VALUE_STRING:
00298 if (variable->value.string == NULL) {
00299 Com_Printf("UI_GetStringFromExpression: String variable not initialized. Empty string returned");
00300 return "";
00301 }
00302 return variable->value.string;
00303 case EA_VALUE_FLOAT:
00304 {
00305 const float number = variable->value.number;
00306 const int integer = number;
00308 if (number == integer)
00309 return va("%i", integer);
00310 else
00311 return va("%f", number);
00312 }
00313 case EA_VALUE_CVAR:
00314 {
00315 cvar_t *cvar = variable->value.cvar;
00316 if (cvar == NULL) {
00317 Com_Printf("UI_GetStringFromExpression: Cvar variable not initialized. Empty string returned");
00318 return "";
00319 }
00320 return cvar->string;
00321 }
00322 default:
00323 Com_Printf("UI_GetStringFromExpression: Unsupported variable type: %i. Empty string returned", variable->type);
00324 return "";
00325 }
00326 }
00327 case EA_VALUE_STRING:
00328 case EA_VALUE_STRING_WITHINJECTION:
00329 {
00330 const char* string = expression->d.terminal.d1.string;
00331 if (expression->type == EA_VALUE_STRING_WITHINJECTION)
00332 string = UI_GenInjectedString(string, qfalse, context);
00333 return string;
00334 }
00335 case EA_VALUE_FLOAT:
00336 {
00337 const float number = expression->d.terminal.d1.number;
00338 const int integer = number;
00340 if (number == integer)
00341 return va("%i", integer);
00342 else
00343 return va("%f", number);
00344 }
00345 case EA_VALUE_CVARNAME:
00346 case EA_VALUE_CVARNAME_WITHINJECTION:
00347 {
00348 cvar_t *cvar = NULL;
00349 const char *cvarName = expression->d.terminal.d1.string;
00350 if (expression->type == EA_VALUE_CVARNAME_WITHINJECTION)
00351 cvarName = UI_GenInjectedString(cvarName, qfalse, context);
00352 cvar = Cvar_Get(cvarName, "", 0, "Cvar from UI script expression");
00353 return cvar->string;
00354 }
00355 case EA_VALUE_PATHPROPERTY:
00356 case EA_VALUE_PATHPROPERTY_WITHINJECTION:
00357 {
00358 uiNode_t *node;
00359 const value_t *property;
00360 const char* string;
00361 node = UI_GetNodeFromExpression(expression, context, &property);
00362 if (!node) {
00363 Com_Printf("UI_GetStringFromExpression: Node wasn't found; Empty string returned\n");
00364 return "";
00365 }
00366 if (!property) {
00367 Com_Printf("UI_GetStringFromExpression: Property wasn't found; Empty string returned\n");
00368 return "";
00369 }
00370 string = UI_GetStringFromNodeProperty(node, property);
00371 if (string == NULL) {
00372 Com_Printf("UI_GetStringFromExpression: String getter for '%s@%s' property do not exists; '' returned\n", node->behaviour->name, property->string);
00373 return "";
00374 }
00375 return string;
00376 }
00377 break;
00378 case EA_VALUE_PARAM:
00379 return UI_GetParam(context, expression->d.terminal.d1.integer);
00380 case EA_VALUE_PARAMCOUNT:
00381 return va("%i", UI_GetParamNumber(context));
00382 }
00383 break;
00384
00385 case EA_OPERATOR_UNARY:
00386 switch (expression->type) {
00387 case EA_OPERATOR_PATHPROPERTYFROM:
00388 {
00389 uiNode_t *node;
00390 const value_t *property;
00391 node = UI_GetNodeFromExpression(expression, context, &property);
00392 return UI_GetStringFromNodeProperty(node, property);
00393 }
00394 default:
00395 Com_Error(ERR_FATAL, "UI_GetFloatFromExpression: (EA_OPERATOR_UNARY) Invalid expression type %i", expression->type);
00396 }
00397
00398 case EA_OPERATOR_BOOLEAN2BOOLEAN:
00399 case EA_OPERATOR_FLOAT2BOOLEAN:
00400 case EA_OPERATOR_STRING2BOOLEAN:
00401 {
00402 const qboolean v = UI_GetBooleanFromExpression(expression, context);
00403 return (v)?"1":"0";
00404 }
00405
00406 case EA_OPERATOR_FLOAT2FLOAT:
00407 {
00408 const float number = UI_GetFloatFromExpression(expression, context);
00409 const int integer = number;
00411 if (number == integer)
00412 return va("%i", integer);
00413 else
00414 return va("%f", number);
00415 }
00416 }
00417
00418 Com_Printf("UI_GetStringFromExpression: Unsupported expression type: %i", expression->type);
00419 return "";
00420 }
00421
00426 qboolean UI_GetBooleanFromExpression (uiAction_t *expression, const uiCallContext_t *context)
00427 {
00428 if (expression == NULL)
00429 return qfalse;
00430
00431 switch (expression->type & EA_HIGHT_MASK) {
00432 case EA_VALUE:
00433 return UI_GetFloatFromExpression(expression, context) != 0;
00434
00435 case EA_OPERATOR_BOOLEAN2BOOLEAN:
00436 {
00437 const qboolean value1 = UI_GetBooleanFromExpression(expression->d.nonTerminal.left, context);
00438 const qboolean value2 = UI_GetBooleanFromExpression(expression->d.nonTerminal.right, context);
00439
00440 switch (expression->type) {
00441 case EA_OPERATOR_AND:
00442 return value1 && value2;
00443 case EA_OPERATOR_OR:
00444 return value1 || value2;
00445 case EA_OPERATOR_XOR:
00446 return value1 ^ value2;
00447 case EA_OPERATOR_NOT:
00448 return !value1;
00449 default:
00450 Com_Error(ERR_FATAL, "UI_GetBooleanFromExpression: (BOOL2BOOL) Invalid expression type");
00451 }
00452 }
00453
00454 case EA_OPERATOR_FLOAT2BOOLEAN:
00455 {
00456 const float value1 = UI_GetFloatFromExpression(expression->d.nonTerminal.left, context);
00457 const float value2 = UI_GetFloatFromExpression(expression->d.nonTerminal.right, context);
00458
00459 switch (expression->type) {
00460 case EA_OPERATOR_EQ:
00461 return value1 == value2;
00462 case EA_OPERATOR_LE:
00463 return value1 <= value2;
00464 case EA_OPERATOR_GE:
00465 return value1 >= value2;
00466 case EA_OPERATOR_GT:
00467 return value1 > value2;
00468 case EA_OPERATOR_LT:
00469 return value1 < value2;
00470 case EA_OPERATOR_NE:
00471 return value1 != value2;
00472 default:
00473 Com_Error(ERR_FATAL, "UI_GetBooleanFromExpression: (FLOAT2BOOL) Invalid expression type");
00474 }
00475 }
00476
00477 case EA_OPERATOR_UNARY:
00478 switch (expression->type) {
00479 case EA_OPERATOR_EXISTS:
00480 {
00481 const uiAction_t *e = expression->d.nonTerminal.left;
00482 const char* cvarName;
00483 assert(e);
00484 assert(e->type == EA_VALUE_CVARNAME || e->type == EA_VALUE_CVARNAME_WITHINJECTION);
00485 cvarName = e->d.terminal.d1.string;
00486 if (e->type == EA_VALUE_CVARNAME_WITHINJECTION)
00487 cvarName = UI_GenInjectedString(cvarName, qfalse, context);
00488 return Cvar_FindVar(cvarName) != NULL;
00489 }
00490 case EA_OPERATOR_PATHPROPERTYFROM:
00491 return UI_GetFloatFromExpression(expression, context) != 0;
00492 default:
00493 Com_Error(ERR_FATAL, "UI_GetBooleanFromExpression: (EA_OPERATOR_UNARY) Invalid expression type %i", expression->type);
00494 }
00495
00496 case EA_OPERATOR_STRING2BOOLEAN:
00497 {
00498 const char* value1 = UI_GetStringFromExpression(expression->d.nonTerminal.left, context);
00499 const char* value2 = UI_GetStringFromExpression(expression->d.nonTerminal.right, context);
00500
00501 switch (expression->type) {
00502 case EA_OPERATOR_STR_EQ:
00503 return strcmp(value1, value2) == 0;
00504 case EA_OPERATOR_STR_NE:
00505 return strcmp(value1, value2) != 0;
00506 default:
00507 Com_Error(ERR_FATAL, "UI_GetBooleanFromExpression: (STRING2BOOL) Invalid expression type");
00508 }
00509 }
00510
00511 default:
00512 Com_Error(ERR_FATAL, "UI_GetBooleanFromExpression: Unsupported expression type: %i", expression->type);
00513 }
00514 }
00515
00521 uiAction_t *UI_AllocStaticStringCondition (const char *description)
00522 {
00523 const char *text, *base;
00524 uiAction_t *expression;
00525
00526 base = va("( %s )", description);
00527 text = base;
00528 expression = UI_ParseExpression(&text);
00529 if (!expression) {
00530 Com_Printf("UI_AllocStaticStringCondition: Parse error on expression \"%s\"\n", base);
00531 return NULL;
00532 }
00533
00534 return expression;
00535 }
00536
00541 static uiAction_t *UI_ParseValueExpression (const char **text)
00542 {
00543 const char* token;
00544 uiAction_t *expression = UI_AllocStaticAction();
00545
00546 token = Com_Parse(text);
00547 if (*text == NULL) {
00548 Com_Printf("UI_ParseTerminalExpression: Token expected\n");
00549 return NULL;
00550 }
00551
00552
00553 if (Com_ParsedTokenIsQuoted() || token[0] == '<') {
00554 expression->d.terminal.d1.string = UI_AllocStaticString(token, 0);
00555 if (UI_IsInjectedString(token))
00556 expression->type = EA_VALUE_STRING_WITHINJECTION;
00557 else
00558 expression->type = EA_VALUE_STRING;
00559 return expression;
00560 }
00561
00562
00563 if (!Q_strncasecmp(token, "param", 5)) {
00564 if (!Q_strcasecmp(token, "paramcount")) {
00565 expression->type = EA_VALUE_PARAMCOUNT;
00566 return expression;
00567 } else if (token[5] >= '1' && token[5] <= '9') {
00568 int i;
00569 if (sscanf(token + 5, "%i", &i) == 1) {
00570
00571 assert(i != 0);
00573 expression->type = EA_VALUE_PARAM;
00574 expression->d.terminal.d1.integer = i;
00575 return expression;
00576 }
00577 }
00578 }
00579
00580
00581 if (!strncmp(token, "*cvar:", 6)) {
00582 const char* cvarName = token + 6;
00583 expression->d.terminal.d1.string = UI_AllocStaticString(cvarName, 0);
00584 if (UI_IsInjectedString(cvarName))
00585 expression->type = EA_VALUE_CVARNAME_WITHINJECTION;
00586 else
00587 expression->type = EA_VALUE_CVARNAME;
00588 return expression;
00589 }
00590
00591
00593 if (!strncmp(token, "*node:", 6) || !strncmp(token, "*", 1)) {
00594 const char* path = token + 1;
00595 const char *propertyName;
00596 qboolean relativeToNode;
00597 #if 0
00598 const value_t *property;
00599 #endif
00600
00601 relativeToNode = !strncmp(path, "node:", 5);
00602 if (relativeToNode)
00603 path = path + 5;
00604
00605 if (UI_IsInjectedString(path))
00606 expression->type = EA_VALUE_PATHPROPERTY_WITHINJECTION;
00607 else
00608 expression->type = EA_VALUE_PATHPROPERTY;
00609 if (!relativeToNode) {
00610 Com_Printf("UI_ParseExpression: Old syntax, please prefix '%s' with \"*node:root.\" \n", token);
00611 path = va("root.%s", path);
00612 }
00613 expression->d.terminal.d1.string = UI_AllocStaticString(path, 0);
00614
00615
00616 propertyName = strchr(path, '@');
00617 if (propertyName == NULL) {
00618 if (expression->type == EA_VALUE_PATHPROPERTY_WITHINJECTION)
00619 expression->type = EA_VALUE_PATHNODE_WITHINJECTION;
00620 else
00621 expression->type = EA_VALUE_PATHNODE;
00622 return expression;
00623 }
00624 propertyName++;
00625
00626 return expression;
00627 }
00628
00629
00630 if ((token[0] >= '0' && token[0] <= '9')
00631 || (token[0] == '-' && token[1] >= '0' && token[1] <= '9')) {
00633 float f = atof(token);
00634 expression->d.terminal.d1.number = f;
00635 expression->type = EA_VALUE_FLOAT;
00636 return expression;
00637 }
00638
00639
00640 if (!strcmp(token, "true")) {
00641 expression->d.terminal.d1.number = 1.0;
00642 expression->type = EA_VALUE_FLOAT;
00643 return expression;
00644 }
00645 if (!strcmp(token, "false")) {
00646 expression->d.terminal.d1.number = 0.0;
00647 expression->type = EA_VALUE_FLOAT;
00648 return expression;
00649 }
00650
00651 Com_Error(ERR_FATAL, "UI_ParseValueExpression: Token \"%s\" unknown. String must use quotes, cvar and nodes must use prefix.\n", token);
00652 }
00653
00654 uiAction_t *UI_ParseExpression (const char **text)
00655 {
00656 const char* token;
00657
00658 token = Com_Parse(text);
00659 if (*text == NULL)
00660 return NULL;
00661
00662 if (!strcmp(token, "(")) {
00663 uiAction_t *expression;
00664 uiAction_t *e;
00665
00666 e = UI_ParseExpression(text);
00667
00668 token = Com_Parse(text);
00669 if (*text == NULL)
00670 return NULL;
00671
00672
00673 if (!strcmp(token, ")"))
00674 return e;
00675
00676
00677 expression = UI_AllocStaticAction();
00678 expression->d.nonTerminal.left = e;
00679 expression->type = UI_GetActionTokenType(token, EA_BINARYOPERATOR);
00680 if (expression->type == EA_NULL) {
00681 Com_Printf("UI_ParseExpression: Invalid 'expression' statement. Unknown '%s' operator\n", token);
00682 return NULL;
00683 }
00684
00685 e = UI_ParseExpression(text);
00686 expression->d.nonTerminal.right = e;
00687
00688 token = Com_Parse(text);
00689 if (*text == NULL)
00690 return NULL;
00691 if (strcmp(token, ")") != 0) {
00692 Com_Printf("UI_ParseExpression: Token ')' expected\n");
00693 return NULL;
00694 }
00695
00696 return expression;
00697 } else {
00698 const int type = UI_GetActionTokenType(token, EA_UNARYOPERATOR);
00699 if (type == EA_NULL) {
00700 Com_UnParseLastToken();
00701 return UI_ParseValueExpression(text);
00702 } else {
00703 uiAction_t *expression = UI_AllocStaticAction();
00704 uiAction_t *e;
00705
00706 e = UI_ParseExpression(text);
00707 expression->type = type;
00708 expression->d.nonTerminal.left = e;
00709
00710 if (expression->type == EA_OPERATOR_EXISTS) {
00711 if (e->type != EA_VALUE_CVARNAME && e->type != EA_VALUE_CVARNAME_WITHINJECTION) {
00712 Com_Printf("UI_ParseExpression: Cvar expected, but type %d found\n", e->type);
00713 return NULL;
00714 }
00715 }
00716 return expression;
00717 }
00718 }
00719 }