console.cpp

Go to the documentation of this file.
00001 /* $Id: console.cpp 14431 2008-10-02 00:08:45Z rubidium $ */
00002 
00005 #include "stdafx.h"
00006 #include "core/alloc_func.hpp"
00007 #include "string_func.h"
00008 #include "strings_type.h"
00009 #include "core/math_func.hpp"
00010 #include "console_internal.h"
00011 #include "network/network.h"
00012 #include "network/network_func.h"
00013 #include "rev.h"
00014 
00015 #include <stdarg.h>
00016 
00017 #include "table/strings.h"
00018 
00019 #define ICON_BUFFER 79
00020 #define ICON_HISTORY_SIZE 20
00021 #define ICON_LINE_HEIGHT 12
00022 #define ICON_RIGHT_BORDERWIDTH 10
00023 #define ICON_BOTTOM_BORDERWIDTH 12
00024 #define ICON_MAX_ALIAS_LINES 40
00025 #define ICON_TOKEN_COUNT 20
00026 
00027 /* console parser */
00028 IConsoleCmd   *_iconsole_cmds;    
00029 IConsoleVar   *_iconsole_vars;    
00030 IConsoleAlias *_iconsole_aliases; 
00031 
00032 /* ** stdlib ** */
00033 byte _stdlib_developer = 1;
00034 bool _stdlib_con_developer = false;
00035 FILE *_iconsole_output_file;
00036 
00037 void IConsoleInit()
00038 {
00039   _iconsole_output_file = NULL;
00040 #ifdef ENABLE_NETWORK /* Initialize network only variables */
00041   _redirect_console_to_client = 0;
00042 #endif
00043 
00044   IConsoleGUIInit();
00045 
00046   IConsoleStdLibRegister();
00047 }
00048 
00049 static void IConsoleWriteToLogFile(const char *string)
00050 {
00051   if (_iconsole_output_file != NULL) {
00052     /* if there is an console output file ... also print it there */
00053     if (fwrite(string, strlen(string), 1, _iconsole_output_file) != 1 ||
00054         fwrite("\n", 1, 1, _iconsole_output_file) != 1) {
00055       fclose(_iconsole_output_file);
00056       _iconsole_output_file = NULL;
00057       IConsolePrintF(CC_DEFAULT, "cannot write to log file");
00058     }
00059   }
00060 }
00061 
00062 bool CloseConsoleLogIfActive()
00063 {
00064   if (_iconsole_output_file != NULL) {
00065     IConsolePrintF(CC_DEFAULT, "file output complete");
00066     fclose(_iconsole_output_file);
00067     _iconsole_output_file = NULL;
00068     return true;
00069   }
00070 
00071   return false;
00072 }
00073 
00074 void IConsoleFree()
00075 {
00076   IConsoleGUIFree();
00077   CloseConsoleLogIfActive();
00078 }
00079 
00089 void IConsolePrint(ConsoleColour color_code, const char *string)
00090 {
00091   char *str;
00092 #ifdef ENABLE_NETWORK
00093   if (_redirect_console_to_client != 0) {
00094     /* Redirect the string to the client */
00095     NetworkServerSendRcon(_redirect_console_to_client, color_code, string);
00096     return;
00097   }
00098 #endif
00099 
00100   /* Create a copy of the string, strip if of colours and invalid
00101    * characters and (when applicable) assign it to the console buffer */
00102   str = strdup(string);
00103   str_strip_colours(str);
00104   str_validate(str);
00105 
00106   if (_network_dedicated) {
00107     fprintf(stdout, "%s\n", str);
00108     fflush(stdout);
00109     IConsoleWriteToLogFile(str);
00110     free(str); // free duplicated string since it's not used anymore
00111     return;
00112   }
00113 
00114   IConsoleWriteToLogFile(str);
00115   IConsoleGUIPrint(color_code, str);
00116 }
00117 
00123 void CDECL IConsolePrintF(ConsoleColour color_code, const char *s, ...)
00124 {
00125   va_list va;
00126   char buf[ICON_MAX_STREAMSIZE];
00127 
00128   va_start(va, s);
00129   vsnprintf(buf, sizeof(buf), s, va);
00130   va_end(va);
00131 
00132   IConsolePrint(color_code, buf);
00133 }
00134 
00143 void IConsoleDebug(const char *dbg, const char *string)
00144 {
00145   if (_stdlib_developer > 1)
00146     IConsolePrintF(CC_DEBUG, "dbg: [%s] %s", dbg, string);
00147 }
00148 
00154 void IConsoleWarning(const char *string)
00155 {
00156   if (_stdlib_developer > 0)
00157     IConsolePrintF(CC_WARNING, "WARNING: %s", string);
00158 }
00159 
00164 void IConsoleError(const char *string)
00165 {
00166   IConsolePrintF(CC_ERROR, "ERROR: %s", string);
00167 }
00168 
00176 bool GetArgumentInteger(uint32 *value, const char *arg)
00177 {
00178   char *endptr;
00179 
00180   if (strcmp(arg, "on") == 0 || strcmp(arg, "true") == 0) {
00181     *value = 1;
00182     return true;
00183   }
00184   if (strcmp(arg, "off") == 0 || strcmp(arg, "false") == 0) {
00185     *value = 0;
00186     return true;
00187   }
00188 
00189   *value = strtoul(arg, &endptr, 0);
00190   return arg != endptr;
00191 }
00192 
00193 /*  * *************************
00194     * hooking code            *
00195     * *************************/
00196 
00203 static void IConsoleHookAdd(IConsoleHooks *hooks, IConsoleHookTypes type, IConsoleHook *proc)
00204 {
00205   if (hooks == NULL || proc == NULL) return;
00206 
00207   switch (type) {
00208     case ICONSOLE_HOOK_ACCESS:
00209       hooks->access = proc;
00210       break;
00211     case ICONSOLE_HOOK_PRE_ACTION:
00212       hooks->pre = proc;
00213       break;
00214     case ICONSOLE_HOOK_POST_ACTION:
00215       hooks->post = proc;
00216       break;
00217     default: NOT_REACHED();
00218   }
00219 }
00220 
00229 static bool IConsoleHookHandle(const IConsoleHooks *hooks, IConsoleHookTypes type)
00230 {
00231   IConsoleHook *proc = NULL;
00232   if (hooks == NULL) return false;
00233 
00234   switch (type) {
00235     case ICONSOLE_HOOK_ACCESS:
00236       proc = hooks->access;
00237       break;
00238     case ICONSOLE_HOOK_PRE_ACTION:
00239       proc = hooks->pre;
00240       break;
00241     case ICONSOLE_HOOK_POST_ACTION:
00242       proc = hooks->post;
00243       break;
00244     default: NOT_REACHED();
00245   }
00246 
00247   return (proc == NULL) ? true : proc();
00248 }
00249 
00256 void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc)
00257 {
00258   IConsoleCmd *cmd = IConsoleCmdGet(name);
00259   if (cmd == NULL) return;
00260   IConsoleHookAdd(&cmd->hook, type, proc);
00261 }
00262 
00269 void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc)
00270 {
00271   IConsoleVar *var = IConsoleVarGet(name);
00272   if (var == NULL) return;
00273   IConsoleHookAdd(&var->hook, type, proc);
00274 }
00275 
00281 #define IConsoleAddSorted(_base, item_new, IConsoleType, type)                 \
00282 {                                                                              \
00283   IConsoleType *item, *item_before;                                            \
00284   /* first command */                                                          \
00285   if (_base == NULL) {                                                         \
00286     _base = item_new;                                                          \
00287     return;                                                                    \
00288   }                                                                            \
00289                                                                                \
00290   item_before = NULL;                                                          \
00291   item = _base;                                                                \
00292                                                                                \
00293   /* BEGIN - Alphabetically insert the commands into the linked list */        \
00294   while (item != NULL) {                                                       \
00295     int i = strcmp(item->name, item_new->name);                                \
00296     if (i == 0) {                                                              \
00297       IConsoleError(type " with this name already exists; insertion aborted"); \
00298       free(item_new);                                                          \
00299       return;                                                                  \
00300     }                                                                          \
00301                                                                                \
00302     if (i > 0) break; /* insert at this position */                            \
00303                                                                                \
00304     item_before = item;                                                        \
00305     item = item->next;                                                         \
00306   }                                                                            \
00307                                                                                \
00308   if (item_before == NULL) {                                                   \
00309     _base = item_new;                                                          \
00310   } else {                                                                     \
00311     item_before->next = item_new;                                              \
00312   }                                                                            \
00313                                                                                \
00314   item_new->next = item;                                                       \
00315   /* END - Alphabetical insert */                                              \
00316 }
00317 
00323 void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc)
00324 {
00325   char *new_cmd = strdup(name);
00326   IConsoleCmd *item_new = MallocT<IConsoleCmd>(1);
00327 
00328   item_new->next = NULL;
00329   item_new->proc = proc;
00330   item_new->name = new_cmd;
00331 
00332   item_new->hook.access = NULL;
00333   item_new->hook.pre = NULL;
00334   item_new->hook.post = NULL;
00335 
00336   IConsoleAddSorted(_iconsole_cmds, item_new, IConsoleCmd, "a command");
00337 }
00338 
00344 IConsoleCmd *IConsoleCmdGet(const char *name)
00345 {
00346   IConsoleCmd *item;
00347 
00348   for (item = _iconsole_cmds; item != NULL; item = item->next) {
00349     if (strcmp(item->name, name) == 0) return item;
00350   }
00351   return NULL;
00352 }
00353 
00359 void IConsoleAliasRegister(const char *name, const char *cmd)
00360 {
00361   char *new_alias = strdup(name);
00362   char *cmd_aliased = strdup(cmd);
00363   IConsoleAlias *item_new = MallocT<IConsoleAlias>(1);
00364 
00365   item_new->next = NULL;
00366   item_new->cmdline = cmd_aliased;
00367   item_new->name = new_alias;
00368 
00369   IConsoleAddSorted(_iconsole_aliases, item_new, IConsoleAlias, "an alias");
00370 }
00371 
00377 IConsoleAlias *IConsoleAliasGet(const char *name)
00378 {
00379   IConsoleAlias* item;
00380 
00381   for (item = _iconsole_aliases; item != NULL; item = item->next) {
00382     if (strcmp(item->name, name) == 0) return item;
00383   }
00384 
00385   return NULL;
00386 }
00387 
00389 static inline int IConsoleCopyInParams(char *dst, const char *src, uint bufpos)
00390 {
00391   /* len is the amount of bytes to add excluding the '\0'-termination */
00392   int len = min(ICON_MAX_STREAMSIZE - bufpos - 1, (uint)strlen(src));
00393   strecpy(dst, src, dst + len);
00394 
00395   return len;
00396 }
00397 
00405 static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char *tokens[ICON_TOKEN_COUNT])
00406 {
00407   const char *cmdptr;
00408   char *aliases[ICON_MAX_ALIAS_LINES], aliasstream[ICON_MAX_STREAMSIZE];
00409   uint i;
00410   uint a_index, astream_i;
00411 
00412   memset(&aliases, 0, sizeof(aliases));
00413   memset(&aliasstream, 0, sizeof(aliasstream));
00414 
00415   if (_stdlib_con_developer)
00416     IConsolePrintF(CC_DEBUG, "condbg: requested command is an alias; parsing...");
00417 
00418   aliases[0] = aliasstream;
00419   for (cmdptr = alias->cmdline, a_index = 0, astream_i = 0; *cmdptr != '\0'; cmdptr++) {
00420     if (a_index >= lengthof(aliases) || astream_i >= lengthof(aliasstream)) break;
00421 
00422     switch (*cmdptr) {
00423     case '\'': // ' will double for ""
00424       aliasstream[astream_i++] = '"';
00425       break;
00426     case ';': // Cmd seperator, start new command
00427       aliasstream[astream_i] = '\0';
00428       aliases[++a_index] = &aliasstream[++astream_i];
00429       cmdptr++;
00430       break;
00431     case '%': // Some or all parameters
00432       cmdptr++;
00433       switch (*cmdptr) {
00434       case '+': { // All parameters seperated: "[param 1]" "[param 2]"
00435         for (i = 0; i != tokencount; i++) {
00436           aliasstream[astream_i++] = '"';
00437           astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[i], astream_i);
00438           aliasstream[astream_i++] = '"';
00439           aliasstream[astream_i++] = ' ';
00440         }
00441       } break;
00442       case '!': { // Merge the parameters to one: "[param 1] [param 2] [param 3...]"
00443         aliasstream[astream_i++] = '"';
00444         for (i = 0; i != tokencount; i++) {
00445           astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[i], astream_i);
00446           aliasstream[astream_i++] = ' ';
00447         }
00448         aliasstream[astream_i++] = '"';
00449 
00450       } break;
00451         default: { // One specific parameter: %A = [param 1] %B = [param 2] ...
00452         int param = *cmdptr - 'A';
00453 
00454         if (param < 0 || param >= tokencount) {
00455           IConsoleError("too many or wrong amount of parameters passed to alias, aborting");
00456           IConsolePrintF(CC_WARNING, "Usage of alias '%s': %s", alias->name, alias->cmdline);
00457           return;
00458         }
00459 
00460         aliasstream[astream_i++] = '"';
00461         astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[param], astream_i);
00462         aliasstream[astream_i++] = '"';
00463       } break;
00464       } break;
00465 
00466     default:
00467       aliasstream[astream_i++] = *cmdptr;
00468       break;
00469     }
00470   }
00471 
00472   for (i = 0; i <= a_index; i++) IConsoleCmdExec(aliases[i]); // execute each alias in turn
00473 }
00474 
00484 void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help)
00485 {
00486   IConsoleVar *var;
00487   IConsoleVarRegister(name, addr, ICONSOLE_VAR_STRING, help);
00488   var = IConsoleVarGet(name);
00489   var->size = size;
00490 }
00491 
00499 void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help)
00500 {
00501   char *new_cmd = strdup(name);
00502   IConsoleVar *item_new = MallocT<IConsoleVar>(1);
00503 
00504   item_new->help = (help != NULL) ? strdup(help) : NULL;
00505 
00506   item_new->next = NULL;
00507   item_new->name = new_cmd;
00508   item_new->addr = addr;
00509   item_new->proc = NULL;
00510   item_new->type = type;
00511 
00512   item_new->hook.access = NULL;
00513   item_new->hook.pre = NULL;
00514   item_new->hook.post = NULL;
00515 
00516   IConsoleAddSorted(_iconsole_vars, item_new, IConsoleVar, "a variable");
00517 }
00518 
00524 IConsoleVar *IConsoleVarGet(const char *name)
00525 {
00526   IConsoleVar *item;
00527   for (item = _iconsole_vars; item != NULL; item = item->next) {
00528     if (strcmp(item->name, name) == 0) return item;
00529   }
00530 
00531   return NULL;
00532 }
00533 
00539 static void IConsoleVarSetValue(const IConsoleVar *var, uint32 value)
00540 {
00541   IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_PRE_ACTION);
00542   switch (var->type) {
00543     case ICONSOLE_VAR_BOOLEAN:
00544       *(bool*)var->addr = (value != 0);
00545       break;
00546     case ICONSOLE_VAR_BYTE:
00547       *(byte*)var->addr = (byte)value;
00548       break;
00549     case ICONSOLE_VAR_UINT16:
00550       *(uint16*)var->addr = (uint16)value;
00551       break;
00552     case ICONSOLE_VAR_INT16:
00553       *(int16*)var->addr = (int16)value;
00554       break;
00555     case ICONSOLE_VAR_UINT32:
00556       *(uint32*)var->addr = (uint32)value;
00557       break;
00558     case ICONSOLE_VAR_INT32:
00559       *(int32*)var->addr = (int32)value;
00560       break;
00561     default: NOT_REACHED();
00562   }
00563 
00564   IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_POST_ACTION);
00565   IConsoleVarPrintSetValue(var);
00566 }
00567 
00574 static void IConsoleVarSetStringvalue(const IConsoleVar *var, const char *value)
00575 {
00576   if (var->type != ICONSOLE_VAR_STRING || var->addr == NULL) return;
00577 
00578   IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_PRE_ACTION);
00579   ttd_strlcpy((char*)var->addr, value, var->size);
00580   IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_POST_ACTION);
00581   IConsoleVarPrintSetValue(var); // print out the new value, giving feedback
00582   return;
00583 }
00584 
00590 static uint32 IConsoleVarGetValue(const IConsoleVar *var)
00591 {
00592   uint32 result = 0;
00593 
00594   switch (var->type) {
00595     case ICONSOLE_VAR_BOOLEAN:
00596       result = *(bool*)var->addr;
00597       break;
00598     case ICONSOLE_VAR_BYTE:
00599       result = *(byte*)var->addr;
00600       break;
00601     case ICONSOLE_VAR_UINT16:
00602       result = *(uint16*)var->addr;
00603       break;
00604     case ICONSOLE_VAR_INT16:
00605       result = *(int16*)var->addr;
00606       break;
00607     case ICONSOLE_VAR_UINT32:
00608       result = *(uint32*)var->addr;
00609       break;
00610     case ICONSOLE_VAR_INT32:
00611       result = *(int32*)var->addr;
00612       break;
00613     default: NOT_REACHED();
00614   }
00615   return result;
00616 }
00617 
00622 static char *IConsoleVarGetStringValue(const IConsoleVar *var)
00623 {
00624   static char tempres[50];
00625   char *value = tempres;
00626 
00627   switch (var->type) {
00628     case ICONSOLE_VAR_BOOLEAN:
00629       snprintf(tempres, sizeof(tempres), "%s", (*(bool*)var->addr) ? "on" : "off");
00630       break;
00631     case ICONSOLE_VAR_BYTE:
00632       snprintf(tempres, sizeof(tempres), "%u", *(byte*)var->addr);
00633       break;
00634     case ICONSOLE_VAR_UINT16:
00635       snprintf(tempres, sizeof(tempres), "%u", *(uint16*)var->addr);
00636       break;
00637     case ICONSOLE_VAR_UINT32:
00638       snprintf(tempres, sizeof(tempres), "%u",  *(uint32*)var->addr);
00639       break;
00640     case ICONSOLE_VAR_INT16:
00641       snprintf(tempres, sizeof(tempres), "%i", *(int16*)var->addr);
00642       break;
00643     case ICONSOLE_VAR_INT32:
00644       snprintf(tempres, sizeof(tempres), "%i",  *(int32*)var->addr);
00645       break;
00646     case ICONSOLE_VAR_STRING:
00647       value = (char*)var->addr;
00648       break;
00649     default: NOT_REACHED();
00650   }
00651 
00652   return value;
00653 }
00654 
00658 void IConsoleVarPrintGetValue(const IConsoleVar *var)
00659 {
00660   char *value;
00661   /* Some variables need really specific handling, handle this in its
00662    * callback function */
00663   if (var->proc != NULL) {
00664     var->proc(0, NULL);
00665     return;
00666   }
00667 
00668   value = IConsoleVarGetStringValue(var);
00669   IConsolePrintF(CC_WARNING, "Current value for '%s' is:  %s", var->name, value);
00670 }
00671 
00676 void IConsoleVarPrintSetValue(const IConsoleVar *var)
00677 {
00678   char *value = IConsoleVarGetStringValue(var);
00679   IConsolePrintF(CC_WARNING, "'%s' changed to:  %s", var->name, value);
00680 }
00681 
00689 void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[ICON_TOKEN_COUNT])
00690 {
00691   const char *tokenptr = token[0];
00692   byte t_index = tokencount;
00693   uint32 value;
00694 
00695   if (_stdlib_con_developer)
00696     IConsolePrintF(CC_DEBUG, "condbg: requested command is a variable");
00697 
00698   if (tokencount == 0) { /* Just print out value */
00699     IConsoleVarPrintGetValue(var);
00700     return;
00701   }
00702 
00703   /* Use of assignment sign is not mandatory but supported, so just 'ignore it appropiately' */
00704   if (strcmp(tokenptr, "=") == 0) tokencount--;
00705 
00706   if (tokencount == 1) {
00707     /* Some variables need really special handling, handle it in their callback procedure */
00708     if (var->proc != NULL) {
00709       var->proc(tokencount, &token[t_index - tokencount]); // set the new value
00710       return;
00711     }
00712     /* Strings need special processing. No need to convert the argument to
00713      * an integer value, just copy over the argument on a one-by-one basis */
00714     if (var->type == ICONSOLE_VAR_STRING) {
00715       IConsoleVarSetStringvalue(var, token[t_index - tokencount]);
00716       return;
00717     } else if (GetArgumentInteger(&value, token[t_index - tokencount])) {
00718       IConsoleVarSetValue(var, value);
00719       return;
00720     }
00721 
00722     /* Increase or decrease the value by one. This of course can only happen to 'number' types */
00723     if (strcmp(tokenptr, "++") == 0 && var->type != ICONSOLE_VAR_STRING) {
00724       IConsoleVarSetValue(var, IConsoleVarGetValue(var) + 1);
00725       return;
00726     }
00727 
00728     if (strcmp(tokenptr, "--") == 0 && var->type != ICONSOLE_VAR_STRING) {
00729       IConsoleVarSetValue(var, IConsoleVarGetValue(var) - 1);
00730       return;
00731     }
00732   }
00733 
00734   IConsoleError("invalid variable assignment");
00735 }
00736 
00743 void IConsoleVarProcAdd(const char *name, IConsoleCmdProc *proc)
00744 {
00745   IConsoleVar *var = IConsoleVarGet(name);
00746   if (var == NULL) return;
00747   var->proc = proc;
00748 }
00749 
00755 void IConsoleCmdExec(const char *cmdstr)
00756 {
00757   IConsoleCmd   *cmd    = NULL;
00758   IConsoleAlias *alias  = NULL;
00759   IConsoleVar   *var    = NULL;
00760 
00761   const char *cmdptr;
00762   char *tokens[ICON_TOKEN_COUNT], tokenstream[ICON_MAX_STREAMSIZE];
00763   uint t_index, tstream_i;
00764 
00765   bool longtoken = false;
00766   bool foundtoken = false;
00767 
00768   if (cmdstr[0] == '#') return; // comments
00769 
00770   for (cmdptr = cmdstr; *cmdptr != '\0'; cmdptr++) {
00771     if (!IsValidChar(*cmdptr, CS_ALPHANUMERAL)) {
00772       IConsoleError("command contains malformed characters, aborting");
00773       IConsolePrintF(CC_ERROR, "ERROR: command was: '%s'", cmdstr);
00774       return;
00775     }
00776   }
00777 
00778   if (_stdlib_con_developer)
00779     IConsolePrintF(CC_DEBUG, "condbg: executing cmdline: '%s'", cmdstr);
00780 
00781   memset(&tokens, 0, sizeof(tokens));
00782   memset(&tokenstream, 0, sizeof(tokenstream));
00783 
00784   /* 1. Split up commandline into tokens, seperated by spaces, commands
00785    * enclosed in "" are taken as one token. We can only go as far as the amount
00786    * of characters in our stream or the max amount of tokens we can handle */
00787   for (cmdptr = cmdstr, t_index = 0, tstream_i = 0; *cmdptr != '\0'; cmdptr++) {
00788     if (t_index >= lengthof(tokens) || tstream_i >= lengthof(tokenstream)) break;
00789 
00790     switch (*cmdptr) {
00791     case ' ': /* Token seperator */
00792       if (!foundtoken) break;
00793 
00794       if (longtoken) {
00795         tokenstream[tstream_i] = *cmdptr;
00796       } else {
00797         tokenstream[tstream_i] = '\0';
00798         foundtoken = false;
00799       }
00800 
00801       tstream_i++;
00802       break;
00803     case '"': // Tokens enclosed in "" are one token
00804       longtoken = !longtoken;
00805       break;
00806     case '\\': // Escape character for ""
00807       if (cmdptr[1] == '"' && tstream_i + 1 < lengthof(tokenstream)) {
00808         tokenstream[tstream_i++] = *++cmdptr;
00809         break;
00810       }
00811       /* fallthrough */
00812     default: // Normal character
00813       tokenstream[tstream_i++] = *cmdptr;
00814 
00815       if (!foundtoken) {
00816         tokens[t_index++] = &tokenstream[tstream_i - 1];
00817         foundtoken = true;
00818       }
00819       break;
00820     }
00821   }
00822 
00823   if (_stdlib_con_developer) {
00824     uint i;
00825 
00826     for (i = 0; tokens[i] != NULL; i++) {
00827       IConsolePrintF(CC_DEBUG, "condbg: token %d is: '%s'", i, tokens[i]);
00828     }
00829   }
00830 
00831   if (tokens[0] == '\0') return; // don't execute empty commands
00832   /* 2. Determine type of command (cmd, alias or variable) and execute
00833    * First try commands, then aliases, and finally variables. Execute
00834    * the found action taking into account its hooking code
00835    */
00836   cmd = IConsoleCmdGet(tokens[0]);
00837   if (cmd != NULL) {
00838     if (IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_ACCESS)) {
00839       IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_PRE_ACTION);
00840       if (cmd->proc(t_index, tokens)) { // index started with 0
00841         IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_POST_ACTION);
00842       } else {
00843         cmd->proc(0, NULL); // if command failed, give help
00844       }
00845     }
00846     return;
00847   }
00848 
00849   t_index--; // ignore the variable-name for comfort for both aliases and variaables
00850   alias = IConsoleAliasGet(tokens[0]);
00851   if (alias != NULL) {
00852     IConsoleAliasExec(alias, t_index, &tokens[1]);
00853     return;
00854   }
00855 
00856   var = IConsoleVarGet(tokens[0]);
00857   if (var != NULL) {
00858     if (IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_ACCESS)) {
00859       IConsoleVarExec(var, t_index, &tokens[1]);
00860     }
00861     return;
00862   }
00863 
00864   IConsoleError("command or variable not found");
00865 }

Generated on Fri Nov 21 19:01:32 2008 for openttd by  doxygen 1.5.6