console.cpp

Go to the documentation of this file.
00001 /* $Id: console.cpp 18809 2010-01-15 16:41:15Z rubidium $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "stdafx.h"
00013 #include "console_internal.h"
00014 #include "network/network.h"
00015 #include "network/network_func.h"
00016 #include "debug.h"
00017 #include "console_func.h"
00018 
00019 #include <stdarg.h>
00020 
00021 #define ICON_BUFFER 79
00022 #define ICON_HISTORY_SIZE 20
00023 #define ICON_LINE_HEIGHT 12
00024 #define ICON_RIGHT_BORDERWIDTH 10
00025 #define ICON_BOTTOM_BORDERWIDTH 12
00026 #define ICON_MAX_ALIAS_LINES 40
00027 #define ICON_TOKEN_COUNT 20
00028 
00029 /* console parser */
00030 IConsoleCmd   *_iconsole_cmds;    
00031 IConsoleVar   *_iconsole_vars;    
00032 IConsoleAlias *_iconsole_aliases; 
00033 
00034 /* ** stdlib ** */
00035 byte _stdlib_developer = 1;
00036 bool _stdlib_con_developer = false;
00037 FILE *_iconsole_output_file;
00038 
00039 void IConsoleInit()
00040 {
00041   _iconsole_output_file = NULL;
00042 #ifdef ENABLE_NETWORK /* Initialize network only variables */
00043   _redirect_console_to_client = INVALID_CLIENT_ID;
00044 #endif
00045 
00046   IConsoleGUIInit();
00047 
00048   IConsoleStdLibRegister();
00049 }
00050 
00051 static void IConsoleWriteToLogFile(const char *string)
00052 {
00053   if (_iconsole_output_file != NULL) {
00054     /* if there is an console output file ... also print it there */
00055     const char *header = GetLogPrefix();
00056     if (fwrite(header, strlen(header), 1, _iconsole_output_file) != 1 ||
00057         fwrite(string, strlen(string), 1, _iconsole_output_file) != 1 ||
00058         fwrite("\n", 1, 1, _iconsole_output_file) != 1) {
00059       fclose(_iconsole_output_file);
00060       _iconsole_output_file = NULL;
00061       IConsolePrintF(CC_DEFAULT, "cannot write to log file");
00062     }
00063   }
00064 }
00065 
00066 bool CloseConsoleLogIfActive()
00067 {
00068   if (_iconsole_output_file != NULL) {
00069     IConsolePrintF(CC_DEFAULT, "file output complete");
00070     fclose(_iconsole_output_file);
00071     _iconsole_output_file = NULL;
00072     return true;
00073   }
00074 
00075   return false;
00076 }
00077 
00078 void IConsoleFree()
00079 {
00080   IConsoleGUIFree();
00081   CloseConsoleLogIfActive();
00082 }
00083 
00093 void IConsolePrint(ConsoleColour colour_code, const char *string)
00094 {
00095   char *str;
00096 #ifdef ENABLE_NETWORK
00097   if (_redirect_console_to_client != INVALID_CLIENT_ID) {
00098     /* Redirect the string to the client */
00099     NetworkServerSendRcon(_redirect_console_to_client, colour_code, string);
00100     return;
00101   }
00102 #endif
00103 
00104   /* Create a copy of the string, strip if of colours and invalid
00105    * characters and (when applicable) assign it to the console buffer */
00106   str = strdup(string);
00107   str_strip_colours(str);
00108   str_validate(str, str + strlen(str));
00109 
00110   if (_network_dedicated) {
00111     fprintf(stdout, "%s%s\n", GetLogPrefix(), str);
00112     fflush(stdout);
00113     IConsoleWriteToLogFile(str);
00114     free(str); // free duplicated string since it's not used anymore
00115     return;
00116   }
00117 
00118   IConsoleWriteToLogFile(str);
00119   IConsoleGUIPrint(colour_code, str);
00120 }
00121 
00127 void CDECL IConsolePrintF(ConsoleColour colour_code, const char *format, ...)
00128 {
00129   va_list va;
00130   char buf[ICON_MAX_STREAMSIZE];
00131 
00132   va_start(va, format);
00133   vsnprintf(buf, sizeof(buf), format, va);
00134   va_end(va);
00135 
00136   IConsolePrint(colour_code, buf);
00137 }
00138 
00147 void IConsoleDebug(const char *dbg, const char *string)
00148 {
00149   if (_stdlib_developer > 1)
00150     IConsolePrintF(CC_DEBUG, "dbg: [%s] %s", dbg, string);
00151 }
00152 
00158 void IConsoleWarning(const char *string)
00159 {
00160   if (_stdlib_developer > 0)
00161     IConsolePrintF(CC_WARNING, "WARNING: %s", string);
00162 }
00163 
00168 void IConsoleError(const char *string)
00169 {
00170   IConsolePrintF(CC_ERROR, "ERROR: %s", string);
00171 }
00172 
00180 bool GetArgumentInteger(uint32 *value, const char *arg)
00181 {
00182   char *endptr;
00183 
00184   if (strcmp(arg, "on") == 0 || strcmp(arg, "true") == 0) {
00185     *value = 1;
00186     return true;
00187   }
00188   if (strcmp(arg, "off") == 0 || strcmp(arg, "false") == 0) {
00189     *value = 0;
00190     return true;
00191   }
00192 
00193   *value = strtoul(arg, &endptr, 0);
00194   return arg != endptr;
00195 }
00196 
00197 /*  * *************************
00198     * hooking code            *
00199     * *************************/
00200 
00207 static void IConsoleHookAdd(IConsoleHooks *hooks, IConsoleHookTypes type, IConsoleHook *proc)
00208 {
00209   if (hooks == NULL || proc == NULL) return;
00210 
00211   switch (type) {
00212     case ICONSOLE_HOOK_ACCESS:
00213       hooks->access = proc;
00214       break;
00215     case ICONSOLE_HOOK_PRE_ACTION:
00216       hooks->pre = proc;
00217       break;
00218     case ICONSOLE_HOOK_POST_ACTION:
00219       hooks->post = proc;
00220       break;
00221     default: NOT_REACHED();
00222   }
00223 }
00224 
00233 static bool IConsoleHookHandle(const IConsoleHooks *hooks, IConsoleHookTypes type)
00234 {
00235   IConsoleHook *proc = NULL;
00236   if (hooks == NULL) return false;
00237 
00238   switch (type) {
00239     case ICONSOLE_HOOK_ACCESS:
00240       proc = hooks->access;
00241       break;
00242     case ICONSOLE_HOOK_PRE_ACTION:
00243       proc = hooks->pre;
00244       break;
00245     case ICONSOLE_HOOK_POST_ACTION:
00246       proc = hooks->post;
00247       break;
00248     default: NOT_REACHED();
00249   }
00250 
00251   return (proc == NULL) ? true : proc();
00252 }
00253 
00260 void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc)
00261 {
00262   IConsoleCmd *cmd = IConsoleCmdGet(name);
00263   if (cmd == NULL) return;
00264   IConsoleHookAdd(&cmd->hook, type, proc);
00265 }
00266 
00273 void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc)
00274 {
00275   IConsoleVar *var = IConsoleVarGet(name);
00276   if (var == NULL) return;
00277   IConsoleHookAdd(&var->hook, type, proc);
00278 }
00279 
00285 #define IConsoleAddSorted(_base, item_new, IConsoleType, type)                 \
00286 {                                                                              \
00287   IConsoleType *item, *item_before;                                            \
00288   /* first command */                                                          \
00289   if (_base == NULL) {                                                         \
00290     _base = item_new;                                                          \
00291     return;                                                                    \
00292   }                                                                            \
00293                                                                                \
00294   item_before = NULL;                                                          \
00295   item = _base;                                                                \
00296                                                                                \
00297   /* BEGIN - Alphabetically insert the commands into the linked list */        \
00298   while (item != NULL) {                                                       \
00299     int i = strcmp(item->name, item_new->name);                                \
00300     if (i == 0) {                                                              \
00301       IConsoleError(type " with this name already exists; insertion aborted"); \
00302       free(item_new);                                                          \
00303       return;                                                                  \
00304     }                                                                          \
00305                                                                                \
00306     if (i > 0) break; /* insert at this position */                            \
00307                                                                                \
00308     item_before = item;                                                        \
00309     item = item->next;                                                         \
00310   }                                                                            \
00311                                                                                \
00312   if (item_before == NULL) {                                                   \
00313     _base = item_new;                                                          \
00314   } else {                                                                     \
00315     item_before->next = item_new;                                              \
00316   }                                                                            \
00317                                                                                \
00318   item_new->next = item;                                                       \
00319   /* END - Alphabetical insert */                                              \
00320 }
00321 
00327 void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc)
00328 {
00329   char *new_cmd = strdup(name);
00330   IConsoleCmd *item_new = MallocT<IConsoleCmd>(1);
00331 
00332   item_new->next = NULL;
00333   item_new->proc = proc;
00334   item_new->name = new_cmd;
00335 
00336   item_new->hook.access = NULL;
00337   item_new->hook.pre = NULL;
00338   item_new->hook.post = NULL;
00339 
00340   IConsoleAddSorted(_iconsole_cmds, item_new, IConsoleCmd, "a command");
00341 }
00342 
00348 IConsoleCmd *IConsoleCmdGet(const char *name)
00349 {
00350   IConsoleCmd *item;
00351 
00352   for (item = _iconsole_cmds; item != NULL; item = item->next) {
00353     if (strcmp(item->name, name) == 0) return item;
00354   }
00355   return NULL;
00356 }
00357 
00363 void IConsoleAliasRegister(const char *name, const char *cmd)
00364 {
00365   char *new_alias = strdup(name);
00366   char *cmd_aliased = strdup(cmd);
00367   IConsoleAlias *item_new = MallocT<IConsoleAlias>(1);
00368 
00369   item_new->next = NULL;
00370   item_new->cmdline = cmd_aliased;
00371   item_new->name = new_alias;
00372 
00373   IConsoleAddSorted(_iconsole_aliases, item_new, IConsoleAlias, "an alias");
00374 }
00375 
00381 IConsoleAlias *IConsoleAliasGet(const char *name)
00382 {
00383   IConsoleAlias *item;
00384 
00385   for (item = _iconsole_aliases; item != NULL; item = item->next) {
00386     if (strcmp(item->name, name) == 0) return item;
00387   }
00388 
00389   return NULL;
00390 }
00391 
00393 static inline int IConsoleCopyInParams(char *dst, const char *src, uint bufpos)
00394 {
00395   /* len is the amount of bytes to add excluding the '\0'-termination */
00396   int len = min(ICON_MAX_STREAMSIZE - bufpos - 1, (uint)strlen(src));
00397   strecpy(dst, src, dst + len);
00398 
00399   return len;
00400 }
00401 
00409 static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char *tokens[ICON_TOKEN_COUNT])
00410 {
00411   const char *cmdptr;
00412   char *aliases[ICON_MAX_ALIAS_LINES], aliasstream[ICON_MAX_STREAMSIZE];
00413   uint i;
00414   uint a_index, astream_i;
00415 
00416   memset(&aliases, 0, sizeof(aliases));
00417   memset(&aliasstream, 0, sizeof(aliasstream));
00418 
00419   if (_stdlib_con_developer)
00420     IConsolePrintF(CC_DEBUG, "condbg: requested command is an alias; parsing...");
00421 
00422   aliases[0] = aliasstream;
00423   for (cmdptr = alias->cmdline, a_index = 0, astream_i = 0; *cmdptr != '\0'; cmdptr++) {
00424     if (a_index >= lengthof(aliases) || astream_i >= lengthof(aliasstream)) break;
00425 
00426     switch (*cmdptr) {
00427     case '\'': // ' will double for ""
00428       aliasstream[astream_i++] = '"';
00429       break;
00430     case ';': // Cmd seperator, start new command
00431       aliasstream[astream_i] = '\0';
00432       aliases[++a_index] = &aliasstream[++astream_i];
00433       cmdptr++;
00434       break;
00435     case '%': // Some or all parameters
00436       cmdptr++;
00437       switch (*cmdptr) {
00438       case '+': { // All parameters seperated: "[param 1]" "[param 2]"
00439         for (i = 0; i != tokencount; i++) {
00440           aliasstream[astream_i++] = '"';
00441           astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[i], astream_i);
00442           aliasstream[astream_i++] = '"';
00443           aliasstream[astream_i++] = ' ';
00444         }
00445       } break;
00446       case '!': { // Merge the parameters to one: "[param 1] [param 2] [param 3...]"
00447         aliasstream[astream_i++] = '"';
00448         for (i = 0; i != tokencount; i++) {
00449           astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[i], astream_i);
00450           aliasstream[astream_i++] = ' ';
00451         }
00452         aliasstream[astream_i++] = '"';
00453 
00454       } break;
00455         default: { // One specific parameter: %A = [param 1] %B = [param 2] ...
00456         int param = *cmdptr - 'A';
00457 
00458         if (param < 0 || param >= tokencount) {
00459           IConsoleError("too many or wrong amount of parameters passed to alias, aborting");
00460           IConsolePrintF(CC_WARNING, "Usage of alias '%s': %s", alias->name, alias->cmdline);
00461           return;
00462         }
00463 
00464         aliasstream[astream_i++] = '"';
00465         astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[param], astream_i);
00466         aliasstream[astream_i++] = '"';
00467       } break;
00468       } break;
00469 
00470     default:
00471       aliasstream[astream_i++] = *cmdptr;
00472       break;
00473     }
00474   }
00475 
00476   for (i = 0; i <= a_index; i++) IConsoleCmdExec(aliases[i]); // execute each alias in turn
00477 }
00478 
00488 void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help)
00489 {
00490   IConsoleVar *var;
00491   IConsoleVarRegister(name, addr, ICONSOLE_VAR_STRING, help);
00492   var = IConsoleVarGet(name);
00493   var->size = size;
00494 }
00495 
00503 void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help)
00504 {
00505   char *new_cmd = strdup(name);
00506   IConsoleVar *item_new = MallocT<IConsoleVar>(1);
00507 
00508   item_new->help = (help != NULL) ? strdup(help) : NULL;
00509 
00510   item_new->next = NULL;
00511   item_new->name = new_cmd;
00512   item_new->addr = addr;
00513   item_new->proc = NULL;
00514   item_new->type = type;
00515 
00516   item_new->hook.access = NULL;
00517   item_new->hook.pre = NULL;
00518   item_new->hook.post = NULL;
00519 
00520   IConsoleAddSorted(_iconsole_vars, item_new, IConsoleVar, "a variable");
00521 }
00522 
00528 IConsoleVar *IConsoleVarGet(const char *name)
00529 {
00530   IConsoleVar *item;
00531   for (item = _iconsole_vars; item != NULL; item = item->next) {
00532     if (strcmp(item->name, name) == 0) return item;
00533   }
00534 
00535   return NULL;
00536 }
00537 
00542 static char *IConsoleVarGetStringValue(const IConsoleVar *var)
00543 {
00544   static char tempres[50];
00545   char *value = tempres;
00546 
00547   switch (var->type) {
00548     case ICONSOLE_VAR_BOOLEAN:
00549       snprintf(tempres, sizeof(tempres), "%s", (*(bool*)var->addr) ? "on" : "off");
00550       break;
00551     case ICONSOLE_VAR_BYTE:
00552       snprintf(tempres, sizeof(tempres), "%u", *(byte*)var->addr);
00553       break;
00554     case ICONSOLE_VAR_UINT16:
00555       snprintf(tempres, sizeof(tempres), "%u", *(uint16*)var->addr);
00556       break;
00557     case ICONSOLE_VAR_UINT32:
00558       snprintf(tempres, sizeof(tempres), "%u",  *(uint32*)var->addr);
00559       break;
00560     case ICONSOLE_VAR_INT16:
00561       snprintf(tempres, sizeof(tempres), "%i", *(int16*)var->addr);
00562       break;
00563     case ICONSOLE_VAR_INT32:
00564       snprintf(tempres, sizeof(tempres), "%i",  *(int32*)var->addr);
00565       break;
00566     case ICONSOLE_VAR_STRING:
00567       value = (char*)var->addr;
00568       break;
00569     default: NOT_REACHED();
00570   }
00571 
00572   return value;
00573 }
00574 
00579 static void IConsoleVarPrintSetValue(const IConsoleVar *var)
00580 {
00581   char *value = IConsoleVarGetStringValue(var);
00582   IConsolePrintF(CC_WARNING, "'%s' changed to:  %s", var->name, value);
00583 }
00584 
00590 static void IConsoleVarSetValue(const IConsoleVar *var, uint32 value)
00591 {
00592   IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_PRE_ACTION);
00593   switch (var->type) {
00594     case ICONSOLE_VAR_BOOLEAN:
00595       *(bool*)var->addr = (value != 0);
00596       break;
00597     case ICONSOLE_VAR_BYTE:
00598       *(byte*)var->addr = (byte)value;
00599       break;
00600     case ICONSOLE_VAR_UINT16:
00601       *(uint16*)var->addr = (uint16)value;
00602       break;
00603     case ICONSOLE_VAR_INT16:
00604       *(int16*)var->addr = (int16)value;
00605       break;
00606     case ICONSOLE_VAR_UINT32:
00607       *(uint32*)var->addr = (uint32)value;
00608       break;
00609     case ICONSOLE_VAR_INT32:
00610       *(int32*)var->addr = (int32)value;
00611       break;
00612     default: NOT_REACHED();
00613   }
00614 
00615   IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_POST_ACTION);
00616   IConsoleVarPrintSetValue(var);
00617 }
00618 
00625 static void IConsoleVarSetStringvalue(const IConsoleVar *var, const char *value)
00626 {
00627   if (var->type != ICONSOLE_VAR_STRING || var->addr == NULL) return;
00628 
00629   IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_PRE_ACTION);
00630   ttd_strlcpy((char*)var->addr, value, var->size);
00631   IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_POST_ACTION);
00632   IConsoleVarPrintSetValue(var); // print out the new value, giving feedback
00633   return;
00634 }
00635 
00641 static uint32 IConsoleVarGetValue(const IConsoleVar *var)
00642 {
00643   uint32 result = 0;
00644 
00645   switch (var->type) {
00646     case ICONSOLE_VAR_BOOLEAN:
00647       result = *(bool*)var->addr;
00648       break;
00649     case ICONSOLE_VAR_BYTE:
00650       result = *(byte*)var->addr;
00651       break;
00652     case ICONSOLE_VAR_UINT16:
00653       result = *(uint16*)var->addr;
00654       break;
00655     case ICONSOLE_VAR_INT16:
00656       result = *(int16*)var->addr;
00657       break;
00658     case ICONSOLE_VAR_UINT32:
00659       result = *(uint32*)var->addr;
00660       break;
00661     case ICONSOLE_VAR_INT32:
00662       result = *(int32*)var->addr;
00663       break;
00664     default: NOT_REACHED();
00665   }
00666   return result;
00667 }
00668 
00672 void IConsoleVarPrintGetValue(const IConsoleVar *var)
00673 {
00674   char *value;
00675   /* Some variables need really specific handling, handle this in its
00676    * callback function */
00677   if (var->proc != NULL) {
00678     var->proc(0, NULL);
00679     return;
00680   }
00681 
00682   value = IConsoleVarGetStringValue(var);
00683   IConsolePrintF(CC_WARNING, "Current value for '%s' is:  %s", var->name, value);
00684 }
00685 
00693 static void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[ICON_TOKEN_COUNT])
00694 {
00695   const char *tokenptr = token[0];
00696   byte t_index = tokencount;
00697   uint32 value;
00698 
00699   if (_stdlib_con_developer)
00700     IConsolePrintF(CC_DEBUG, "condbg: requested command is a variable");
00701 
00702   if (tokencount == 0) { // Just print out value
00703     IConsoleVarPrintGetValue(var);
00704     return;
00705   }
00706 
00707   /* Use of assignment sign is not mandatory but supported, so just 'ignore it appropiately' */
00708   if (strcmp(tokenptr, "=") == 0) tokencount--;
00709 
00710   if (tokencount == 1) {
00711     /* Some variables need really special handling, handle it in their callback procedure */
00712     if (var->proc != NULL) {
00713       var->proc(tokencount, &token[t_index - tokencount]); // set the new value
00714       return;
00715     }
00716     /* Strings need special processing. No need to convert the argument to
00717      * an integer value, just copy over the argument on a one-by-one basis */
00718     if (var->type == ICONSOLE_VAR_STRING) {
00719       IConsoleVarSetStringvalue(var, token[t_index - tokencount]);
00720       return;
00721     } else if (GetArgumentInteger(&value, token[t_index - tokencount])) {
00722       IConsoleVarSetValue(var, value);
00723       return;
00724     }
00725 
00726     /* Increase or decrease the value by one. This of course can only happen to 'number' types */
00727     if (strcmp(tokenptr, "++") == 0 && var->type != ICONSOLE_VAR_STRING) {
00728       IConsoleVarSetValue(var, IConsoleVarGetValue(var) + 1);
00729       return;
00730     }
00731 
00732     if (strcmp(tokenptr, "--") == 0 && var->type != ICONSOLE_VAR_STRING) {
00733       IConsoleVarSetValue(var, IConsoleVarGetValue(var) - 1);
00734       return;
00735     }
00736   }
00737 
00738   IConsoleError("invalid variable assignment");
00739 }
00740 
00747 void IConsoleVarProcAdd(const char *name, IConsoleCmdProc *proc)
00748 {
00749   IConsoleVar *var = IConsoleVarGet(name);
00750   if (var == NULL) return;
00751   var->proc = proc;
00752 }
00753 
00759 void IConsoleCmdExec(const char *cmdstr)
00760 {
00761   IConsoleCmd   *cmd    = NULL;
00762   IConsoleAlias *alias  = NULL;
00763   IConsoleVar   *var    = NULL;
00764 
00765   const char *cmdptr;
00766   char *tokens[ICON_TOKEN_COUNT], tokenstream[ICON_MAX_STREAMSIZE];
00767   uint t_index, tstream_i;
00768 
00769   bool longtoken = false;
00770   bool foundtoken = false;
00771 
00772   if (cmdstr[0] == '#') return; // comments
00773 
00774   for (cmdptr = cmdstr; *cmdptr != '\0'; cmdptr++) {
00775     if (!IsValidChar(*cmdptr, CS_ALPHANUMERAL)) {
00776       IConsoleError("command contains malformed characters, aborting");
00777       IConsolePrintF(CC_ERROR, "ERROR: command was: '%s'", cmdstr);
00778       return;
00779     }
00780   }
00781 
00782   if (_stdlib_con_developer)
00783     IConsolePrintF(CC_DEBUG, "condbg: executing cmdline: '%s'", cmdstr);
00784 
00785   memset(&tokens, 0, sizeof(tokens));
00786   memset(&tokenstream, 0, sizeof(tokenstream));
00787 
00788   /* 1. Split up commandline into tokens, seperated by spaces, commands
00789    * enclosed in "" are taken as one token. We can only go as far as the amount
00790    * of characters in our stream or the max amount of tokens we can handle */
00791   for (cmdptr = cmdstr, t_index = 0, tstream_i = 0; *cmdptr != '\0'; cmdptr++) {
00792     if (t_index >= lengthof(tokens) || tstream_i >= lengthof(tokenstream)) break;
00793 
00794     switch (*cmdptr) {
00795     case ' ': // Token seperator
00796       if (!foundtoken) break;
00797 
00798       if (longtoken) {
00799         tokenstream[tstream_i] = *cmdptr;
00800       } else {
00801         tokenstream[tstream_i] = '\0';
00802         foundtoken = false;
00803       }
00804 
00805       tstream_i++;
00806       break;
00807     case '"': // Tokens enclosed in "" are one token
00808       longtoken = !longtoken;
00809       break;
00810     case '\\': // Escape character for ""
00811       if (cmdptr[1] == '"' && tstream_i + 1 < lengthof(tokenstream)) {
00812         tokenstream[tstream_i++] = *++cmdptr;
00813         break;
00814       }
00815       /* fallthrough */
00816     default: // Normal character
00817       tokenstream[tstream_i++] = *cmdptr;
00818 
00819       if (!foundtoken) {
00820         tokens[t_index++] = &tokenstream[tstream_i - 1];
00821         foundtoken = true;
00822       }
00823       break;
00824     }
00825   }
00826 
00827   if (_stdlib_con_developer) {
00828     uint i;
00829 
00830     for (i = 0; tokens[i] != NULL; i++) {
00831       IConsolePrintF(CC_DEBUG, "condbg: token %d is: '%s'", i, tokens[i]);
00832     }
00833   }
00834 
00835   if (tokens[0] == '\0') return; // don't execute empty commands
00836   /* 2. Determine type of command (cmd, alias or variable) and execute
00837    * First try commands, then aliases, and finally variables. Execute
00838    * the found action taking into account its hooking code
00839    */
00840   cmd = IConsoleCmdGet(tokens[0]);
00841   if (cmd != NULL) {
00842     if (IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_ACCESS)) {
00843       IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_PRE_ACTION);
00844       if (cmd->proc(t_index, tokens)) { // index started with 0
00845         IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_POST_ACTION);
00846       } else {
00847         cmd->proc(0, NULL); // if command failed, give help
00848       }
00849     }
00850     return;
00851   }
00852 
00853   t_index--; // ignore the variable-name for comfort for both aliases and variaables
00854   alias = IConsoleAliasGet(tokens[0]);
00855   if (alias != NULL) {
00856     IConsoleAliasExec(alias, t_index, &tokens[1]);
00857     return;
00858   }
00859 
00860   var = IConsoleVarGet(tokens[0]);
00861   if (var != NULL) {
00862     if (IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_ACCESS)) {
00863       IConsoleVarExec(var, t_index, &tokens[1]);
00864     }
00865     return;
00866   }
00867 
00868   IConsoleError("command or variable not found");
00869 }

Generated on Wed Jan 20 23:38:34 2010 for OpenTTD by  doxygen 1.5.6