console.cpp

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

Generated on Mon Feb 16 23:12:06 2009 for openttd by  doxygen 1.5.6