ui_expression.c

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 2002-2010 UFO: Alien Invasion.
00007 
00008 This program is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either version 2
00011 of the License, or (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016 
00017 See the GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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     /* it is a const string (or an injection tag for compatibility) */
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     /* it is a param */
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                 /* token range 1-9 already avoid 0 */
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     /* it is a cvarname */
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     /* it is a node property or it is a OLD syntax node property */
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   /* it looks useless, an unused cache */
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         /* get property name */
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     /* unsigned and signed number */
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     /* boolean */
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         /* unary operator or unneed "( ... )" */
00673         if (!strcmp(token, ")"))
00674             return e;
00675 
00676         /* then its an operator */
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 }

Generated by  doxygen 1.6.2