00001
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "common.h"
00035 #include "msg.h"
00036 #include "../shared/parse.h"
00037
00038 void Cmd_ForwardToServer(void);
00039 #define ALIAS_HASH_SIZE 32
00040
00041 #define MAX_ALIAS_NAME 32
00042
00043 typedef struct cmd_alias_s {
00044 char name[MAX_ALIAS_NAME];
00045 char *value;
00046 qboolean archive;
00047 struct cmd_alias_s *hash_next;
00048 struct cmd_alias_s *next;
00049 } cmd_alias_t;
00050
00051 static cmd_alias_t *cmd_alias;
00052 static cmd_alias_t *cmd_alias_hash[ALIAS_HASH_SIZE];
00053 static qboolean cmdWait;
00054 static qboolean cmdClosed;
00055
00056 #define ALIAS_LOOP_COUNT 16
00057 static int alias_count;
00058
00059
00064 static void Cmd_Open_f (void)
00065 {
00066 Com_DPrintf(DEBUG_COMMANDS, "Cmd_Close_f: command buffer opened again\n");
00067 cmdClosed = qfalse;
00068 }
00069
00075 static void Cmd_Close_f (void)
00076 {
00077 Com_DPrintf(DEBUG_COMMANDS, "Cmd_Close_f: command buffer closed\n");
00078 cmdClosed = qtrue;
00079 }
00080
00086 static void Cmd_Wait_f (void)
00087 {
00088 cmdWait = qtrue;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097 #define CMD_BUFFER_SIZE 8192
00098 static sizebuf_t cmd_text;
00099 static byte cmd_text_buf[CMD_BUFFER_SIZE];
00100 static char defer_text_buf[CMD_BUFFER_SIZE];
00101
00105 void Cbuf_Init (void)
00106 {
00107 SZ_Init(&cmd_text, cmd_text_buf, sizeof(cmd_text_buf));
00108 }
00109
00114 void Cbuf_AddText (const char *text)
00115 {
00116 int l;
00117
00118 if (cmdClosed) {
00119 text = strstr(text, "cmdopen");
00120 if (text == NULL) {
00121 Com_DPrintf(DEBUG_COMMANDS, "Cbuf_AddText: currently closed\n");
00122 return;
00123 }
00124 }
00125
00126 l = strlen(text);
00127
00128 if (cmd_text.cursize + l >= cmd_text.maxsize) {
00129 Com_Printf("Cbuf_AddText: overflow (%i) (%s)\n", cmd_text.maxsize, text);
00130 Com_Printf("buffer content: %s\n", cmd_text_buf);
00131 return;
00132 }
00133 SZ_Write(&cmd_text, text, l);
00134 }
00135
00136
00142 void Cbuf_InsertText (const char *text)
00143 {
00144 char *temp;
00145 int templen;
00146
00147 if (!text || !*text)
00148 return;
00149
00150
00151 templen = cmd_text.cursize;
00152 if (templen) {
00153 temp = Mem_Alloc(templen);
00154 memcpy(temp, cmd_text.data, templen);
00155 SZ_Clear(&cmd_text);
00156 } else
00157 temp = NULL;
00158
00159
00160 Cbuf_AddText(text);
00161
00162
00163 if (templen) {
00164 SZ_Write(&cmd_text, temp, templen);
00165 Mem_Free(temp);
00166 }
00167 }
00168
00169
00176 void Cbuf_CopyToDefer (void)
00177 {
00178 memcpy(defer_text_buf, cmd_text_buf, cmd_text.cursize);
00179 defer_text_buf[cmd_text.cursize] = 0;
00180 cmd_text.cursize = 0;
00181 }
00182
00186 void Cbuf_InsertFromDefer (void)
00187 {
00188 Cbuf_InsertText(defer_text_buf);
00189 defer_text_buf[0] = 0;
00190 }
00191
00199 void Cbuf_Execute (void)
00200 {
00201 unsigned int i;
00202 char line[1024];
00203
00204
00205 alias_count = 0;
00206
00207 while (cmd_text.cursize) {
00208
00209 char *text = (char *) cmd_text.data;
00210 int quotes = 0;
00211
00212 for (i = 0; i < cmd_text.cursize; i++) {
00213 if (text[i] == '"')
00214 quotes++;
00215
00216 if (!(quotes & 1) && text[i] == ';')
00217 break;
00218 if (text[i] == '\n')
00219 break;
00220 }
00221
00222 if (i > sizeof(line) - 1)
00223 i = sizeof(line) - 1;
00224
00225 memcpy(line, text, i);
00226 line[i] = 0;
00227
00228
00229
00230
00231 if (i == cmd_text.cursize)
00232 cmd_text.cursize = 0;
00233 else {
00234 i++;
00235 cmd_text.cursize -= i;
00236 memmove(text, text + i, cmd_text.cursize);
00237 }
00238
00239
00240 Cmd_ExecuteString(line);
00241
00242 if (cmdWait) {
00243
00244
00245 cmdWait = qfalse;
00246 break;
00247 }
00248 }
00249 }
00250
00251
00260 void Cbuf_AddEarlyCommands (qboolean clear)
00261 {
00262 int i;
00263
00264 for (i = 0; i < Com_Argc(); i++) {
00265 const char *s = Com_Argv(i);
00266 if (strncmp(s, "+set", 4))
00267 continue;
00268 Cbuf_AddText(va("set %s %s\n", Com_Argv(i + 1), Com_Argv(i + 2)));
00269 if (clear) {
00270 Com_ClearArgv(i);
00271 Com_ClearArgv(i + 1);
00272 Com_ClearArgv(i + 2);
00273 }
00274 i += 2;
00275 }
00276 }
00277
00284 qboolean Cbuf_AddLateCommands (void)
00285 {
00286 int i, j;
00287 int s;
00288 char *text, *build, c;
00289 int argc;
00290 qboolean ret;
00291
00292
00293 s = 0;
00294 argc = Com_Argc();
00295 for (i = 1; i < argc; i++) {
00296 s += strlen(Com_Argv(i)) + 1;
00297 }
00298 if (!s)
00299 return qfalse;
00300
00301 text = Mem_Alloc(s + 1);
00302 text[0] = 0;
00303 for (i = 1; i < argc; i++) {
00304 Q_strcat(text, Com_Argv(i), s);
00305 if (i != argc - 1)
00306 Q_strcat(text, " ", s);
00307 }
00308
00309
00310 build = Mem_Alloc(s + 1);
00311 build[0] = 0;
00312
00313 for (i = 0; i < s - 1; i++) {
00314 if (text[i] == '+') {
00315 i++;
00316
00317 for (j = i; text[j] != '+' && text[j] != '-' && text[j] != 0; j++) {}
00318
00319 c = text[j];
00320 text[j] = 0;
00321
00322 Q_strcat(build, text + i, s);
00323 Q_strcat(build, "\n", s);
00324 text[j] = c;
00325 i = j - 1;
00326 }
00327 }
00328
00329 ret = (build[0] != 0);
00330 if (ret)
00331 Cbuf_AddText(build);
00332
00333 Mem_Free(text);
00334 Mem_Free(build);
00335
00336 return ret;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346 static void Cmd_Exec_f (void)
00347 {
00348 byte *f;
00349 char *f2;
00350 int len;
00351
00352 if (Cmd_Argc() != 2) {
00353 Com_Printf("Usage: %s <filename> : execute a script file\n", Cmd_Argv(0));
00354 return;
00355 }
00356
00357 len = FS_LoadFile(Cmd_Argv(1), &f);
00358 if (!f) {
00359 Com_Printf("couldn't execute %s\n", Cmd_Argv(1));
00360 return;
00361 }
00362 Com_Printf("executing %s\n", Cmd_Argv(1));
00363
00364
00365 f2 = Mem_Alloc(len + 2);
00366 memcpy(f2, f, len);
00367
00368 f2[len] = '\n';
00369 f2[len + 1] = 0;
00370
00371 Cbuf_InsertText(f2);
00372
00373 Mem_Free(f2);
00374 FS_FreeFile(f);
00375 }
00376
00377
00381 static void Cmd_Echo_f (void)
00382 {
00383 int i;
00384
00385 for (i = 1; i < Cmd_Argc(); i++)
00386 Com_Printf("%s ", Cmd_Argv(i));
00387 Com_Printf("\n");
00388 }
00389
00393 static void Cmd_Alias_f (void)
00394 {
00395 cmd_alias_t *a;
00396 char cmd[MAX_STRING_CHARS];
00397 size_t len;
00398 unsigned int hash;
00399 int i, c;
00400 const char *s;
00401
00402 if (Cmd_Argc() == 1) {
00403 Com_Printf("Current alias commands:\n");
00404 for (a = cmd_alias; a; a = a->next)
00405 Com_Printf("%s : %s\n", a->name, a->value);
00406 return;
00407 }
00408
00409 s = Cmd_Argv(1);
00410 len = strlen(s);
00411 if (len == 0)
00412 return;
00413
00414 if (len >= MAX_ALIAS_NAME) {
00415 Com_Printf("Alias name is too long\n");
00416 return;
00417 }
00418
00419
00420 hash = Com_HashKey(s, ALIAS_HASH_SIZE);
00421 for (a = cmd_alias_hash[hash]; a; a = a->hash_next) {
00422 if (!strcmp(s, a->name)) {
00423 Mem_Free(a->value);
00424 break;
00425 }
00426 }
00427
00428 if (!a) {
00429 a = Mem_PoolAlloc(sizeof(*a), com_aliasSysPool, 0);
00430 a->next = cmd_alias;
00431
00432 a->hash_next = cmd_alias_hash[hash];
00433 cmd_alias_hash[hash] = a;
00434 cmd_alias = a;
00435 }
00436 Q_strncpyz(a->name, s, sizeof(a->name));
00437
00438
00439 cmd[0] = 0;
00440 c = Cmd_Argc();
00441 for (i = 2; i < c; i++) {
00442 Q_strcat(cmd, Cmd_Argv(i), sizeof(cmd));
00443 if (i != (c - 1))
00444 Q_strcat(cmd, " ", sizeof(cmd));
00445 }
00446
00447 if (!strcmp(Cmd_Argv(0), "aliasa"))
00448 a->archive = qtrue;
00449
00450 a->value = Mem_PoolStrDup(cmd, com_aliasSysPool, 0);
00451 }
00452
00458 void Cmd_WriteAliases (qFILE *f)
00459 {
00460 cmd_alias_t *a;
00461
00462 for (a = cmd_alias; a; a = a->next)
00463 if (a->archive) {
00464 int i;
00465 FS_Printf(f, "aliasa %s \"", a->name);
00466 for (i = 0; i < strlen(a->value); i++) {
00467 if (a->value[i] == '"')
00468 FS_Printf(f, "\\\"");
00469 else
00470 FS_Printf(f, "%c", a->value[i]);
00471 }
00472 FS_Printf(f, "\"\n");
00473 }
00474 }
00475
00476
00477
00478
00479
00480
00481
00482 #define CMD_HASH_SIZE 32
00483
00484 typedef struct cmd_function_s {
00485 struct cmd_function_s *next;
00486 struct cmd_function_s *hash_next;
00487 const char *name;
00488 const char *description;
00489 xcommand_t function;
00490 int (*completeParam) (const char *partial, const char **match);
00491 void* userdata;
00492 } cmd_function_t;
00493
00494 static int cmd_argc;
00495 static char *cmd_argv[MAX_STRING_TOKENS];
00496 static char cmd_args[MAX_STRING_CHARS];
00497 static void *cmd_userdata;
00498
00499 static cmd_function_t *cmd_functions;
00500 static cmd_function_t *cmd_functions_hash[CMD_HASH_SIZE];
00501
00507 int Cmd_Argc (void)
00508 {
00509 return cmd_argc;
00510 }
00511
00518 const char *Cmd_Argv (int arg)
00519 {
00520 if (arg >= cmd_argc)
00521 return "";
00522 return cmd_argv[arg];
00523 }
00524
00528 const char *Cmd_Args (void)
00529 {
00530 return cmd_args;
00531 }
00532
00536 void *Cmd_Userdata (void)
00537 {
00538 return cmd_userdata;
00539 }
00540
00545 void Cmd_BufClear (void)
00546 {
00547 int i;
00548
00549
00550 for (i = 0; i < cmd_argc; i++) {
00551 Mem_Free(cmd_argv[i]);
00552 cmd_argv[i] = NULL;
00553 }
00554
00555 cmd_argc = 0;
00556 cmd_args[0] = 0;
00557 cmd_userdata = NULL;
00558 }
00559
00568 void Cmd_TokenizeString (const char *text, qboolean macroExpand)
00569 {
00570 const char *com_token, *expanded;
00571
00572 Cmd_BufClear();
00573
00574
00575 if (macroExpand) {
00576 expanded = Com_MacroExpandString(text);
00577 if (expanded)
00578 text = expanded;
00579 }
00580
00581 while (1) {
00582
00583 while (*text && *text <= ' ' && *text != '\n') {
00584 text++;
00585 }
00586
00587 if (*text == '\n') {
00588 text++;
00589 break;
00590 }
00591
00592 if (!*text)
00593 return;
00594
00595
00596 if (cmd_argc == 1) {
00597 size_t l;
00598
00599 Q_strncpyz(cmd_args, text, sizeof(cmd_args));
00600
00601
00602 l = strlen(cmd_args) - 1;
00603 for (; l >= 0; l--)
00604 if (cmd_args[l] <= ' ')
00605 cmd_args[l] = 0;
00606 else
00607 break;
00608 }
00609
00610 com_token = Com_Parse(&text);
00611 if (!text)
00612 return;
00613
00614 if (cmd_argc < MAX_STRING_TOKENS) {
00615
00616 if (com_token[0] == '*') {
00617 com_token++;
00618 com_token = Cvar_GetString(com_token);
00619 }
00620 assert(!cmd_argv[cmd_argc]);
00621 cmd_argv[cmd_argc] = Mem_PoolStrDup(com_token, com_cmdSysPool, 0);
00622 cmd_argc++;
00623 }
00624 }
00625 }
00626
00633 const char* Cmd_GetCommandDesc (const char* cmd_name)
00634 {
00635 cmd_function_t *cmd;
00636 char *sep = NULL;
00637 unsigned int hash;
00638 char searchName[MAX_VAR];
00639
00640
00641 Q_strncpyz(searchName, cmd_name, sizeof(searchName));
00642 sep = strstr(searchName, " ");
00643 if (sep)
00644 *sep = '\0';
00645
00646
00647 hash = Com_HashKey(searchName, CMD_HASH_SIZE);
00648 for (cmd = cmd_functions_hash[hash]; cmd; cmd = cmd->hash_next) {
00649 if (!strcmp(searchName, cmd->name)) {
00650 if (cmd->description)
00651 return cmd->description;
00652 else
00653 return "";
00654 }
00655 }
00656 return "";
00657 }
00658
00667 int Cmd_GenericCompleteFunction (size_t len, const char **match, int matches, const char **list)
00668 {
00669 static char matchString[MAX_QPATH];
00670 int lenResult = 0;
00671 int i;
00672
00673 switch (matches) {
00674
00675 case 1:
00676 *match = list[0];
00677 lenResult = strlen(list[0]);
00678 break;
00679
00680 case 0:
00681 break;
00682
00683 default:
00684
00685 lenResult = len;
00686 while (qtrue) {
00687 const char matchChar = list[0][lenResult];
00688 for (i = 1; i < matches; i++) {
00689 if (matchChar != list[i][lenResult])
00690 break;
00691 }
00692 if (i != matches)
00693 break;
00694 else
00695 lenResult++;
00696 }
00697 break;
00698 }
00699
00700 if (matches && len != lenResult) {
00701 if (lenResult >= MAX_QPATH)
00702 lenResult = MAX_QPATH - 1;
00703 Q_strncpyz(matchString, list[0], lenResult + 1);
00704 *match = matchString;
00705 }
00706 return matches;
00707 }
00708
00715 void Cmd_AddParamCompleteFunction (const char *cmd_name, int (*function)(const char *partial, const char **match))
00716 {
00717 cmd_function_t *cmd;
00718 unsigned int hash;
00719
00720 if (!cmd_name || !cmd_name[0])
00721 return;
00722
00723 hash = Com_HashKey(cmd_name, CMD_HASH_SIZE);
00724 for (cmd = cmd_functions_hash[hash]; cmd; cmd = cmd->hash_next) {
00725 if (!strcmp(cmd_name, cmd->name)) {
00726 cmd->completeParam = function;
00727 return;
00728 }
00729 }
00730 }
00731
00741 void* Cmd_GetUserdata (const char *cmd_name)
00742 {
00743 cmd_function_t *cmd;
00744 unsigned int hash;
00745
00746 if (!cmd_name || !cmd_name[0]) {
00747 Com_Printf("Cmd_GetUserdata: Invalide parameter\n");
00748 return NULL;
00749 }
00750
00751 hash = Com_HashKey(cmd_name, CMD_HASH_SIZE);
00752 for (cmd = cmd_functions_hash[hash]; cmd; cmd = cmd->hash_next) {
00753 if (!strcmp(cmd_name, cmd->name)) {
00754 return cmd->userdata;
00755 }
00756 }
00757
00758 Com_Printf("Cmd_GetUserdata: '%s' not found\n", cmd_name);
00759 return NULL;
00760 }
00761
00770 void Cmd_AddUserdata (const char *cmd_name, void* userdata)
00771 {
00772 cmd_function_t *cmd;
00773 unsigned int hash;
00774
00775 if (!cmd_name || !cmd_name[0])
00776 return;
00777
00778 hash = Com_HashKey(cmd_name, CMD_HASH_SIZE);
00779 for (cmd = cmd_functions_hash[hash]; cmd; cmd = cmd->hash_next) {
00780 if (!strcmp(cmd_name, cmd->name)) {
00781 cmd->userdata = userdata;
00782 return;
00783 }
00784 }
00785 }
00786
00794 void Cmd_AddCommand (const char *cmd_name, xcommand_t function, const char *desc)
00795 {
00796 cmd_function_t *cmd;
00797 unsigned int hash;
00798
00799 if (!cmd_name || !cmd_name[0])
00800 return;
00801
00802
00803 if (Cvar_GetString(cmd_name)[0]) {
00804 Com_Printf("Cmd_AddCommand: %s already defined as a var\n", cmd_name);
00805 return;
00806 }
00807
00808
00809 hash = Com_HashKey(cmd_name, CMD_HASH_SIZE);
00810 for (cmd = cmd_functions_hash[hash]; cmd; cmd = cmd->hash_next) {
00811 if (!strcmp(cmd_name, cmd->name)) {
00812 Com_DPrintf(DEBUG_COMMANDS, "Cmd_AddCommand: %s already defined\n", cmd_name);
00813 return;
00814 }
00815 }
00816
00817 cmd = Mem_PoolAlloc(sizeof(*cmd), com_cmdSysPool, 0);
00818 cmd->name = cmd_name;
00819 cmd->description = desc;
00820 cmd->function = function;
00821 cmd->completeParam = NULL;
00822 HASH_Add(cmd_functions_hash, cmd, hash);
00823 cmd->next = cmd_functions;
00824 cmd_functions = cmd;
00825 }
00826
00832 void Cmd_RemoveCommand (const char *cmd_name)
00833 {
00834 cmd_function_t *cmd, **back;
00835 unsigned int hash;
00836 hash = Com_HashKey(cmd_name, CMD_HASH_SIZE);
00837 back = &cmd_functions_hash[hash];
00838
00839 while (1) {
00840 cmd = *back;
00841 if (!cmd) {
00842 Com_Printf("Cmd_RemoveCommand: %s not added\n", cmd_name);
00843 return;
00844 }
00845 if (!Q_strcasecmp(cmd_name, cmd->name)) {
00846 *back = cmd->hash_next;
00847 break;
00848 }
00849 back = &cmd->hash_next;
00850 }
00851
00852 back = &cmd_functions;
00853 while (1) {
00854 cmd = *back;
00855 if (!cmd) {
00856 Com_Printf("Cmd_RemoveCommand: %s not added\n", cmd_name);
00857 return;
00858 }
00859 if (!strcmp(cmd_name, cmd->name)) {
00860 *back = cmd->next;
00861 Mem_Free(cmd);
00862 return;
00863 }
00864 back = &cmd->next;
00865 }
00866 }
00867
00872 qboolean Cmd_Exists (const char *cmd_name)
00873 {
00874 cmd_function_t *cmd;
00875 unsigned int hash;
00876 hash = Com_HashKey(cmd_name, CMD_HASH_SIZE);
00877
00878 for (cmd = cmd_functions_hash[hash]; cmd; cmd = cmd->hash_next) {
00879 if (!strcmp(cmd_name, cmd->name))
00880 return qtrue;
00881 }
00882
00883 return qfalse;
00884 }
00885
00894 int Cmd_CompleteCommandParameters (const char *command, const char *partial, const char **match)
00895 {
00896 const cmd_function_t *cmd;
00897 unsigned int hash;
00898
00899
00900 hash = Com_HashKey(command, CMD_HASH_SIZE);
00901 for (cmd = cmd_functions_hash[hash]; cmd; cmd = cmd->hash_next) {
00902 if (!Q_strcasecmp(command, cmd->name)) {
00903 if (!cmd->completeParam)
00904 return 0;
00905 return cmd->completeParam(partial, match);
00906 }
00907 }
00908 return 0;
00909 }
00910
00918 int Cmd_CompleteCommand (const char *partial, const char **match)
00919 {
00920 const cmd_function_t *cmd;
00921 const cmd_alias_t *a;
00922 const char *localMatch[MAX_COMPLETE];
00923 int len, matches = 0;
00924
00925 len = strlen(partial);
00926
00927 if (!len)
00928 return 0;
00929
00930
00931 for (cmd = cmd_functions; cmd; cmd = cmd->next) {
00932 if (!strncmp(partial, cmd->name, len)) {
00933 Com_Printf("[cmd] %s\n", cmd->name);
00934 if (cmd->description)
00935 Com_Printf(COLORED_GREEN " %s\n", cmd->description);
00936 localMatch[matches++] = cmd->name;
00937 if (matches >= MAX_COMPLETE)
00938 break;
00939 }
00940 }
00941
00942
00943 if (matches < MAX_COMPLETE) {
00944 for (a = cmd_alias; a; a = a->next) {
00945 if (!strncmp(partial, a->name, len)) {
00946 Com_Printf("[ali] %s\n", a->name);
00947 localMatch[matches++] = a->name;
00948 if (matches >= MAX_COMPLETE)
00949 break;
00950 }
00951 }
00952 }
00953
00954 return Cmd_GenericCompleteFunction(len, match, matches, localMatch);
00955 }
00956
00957
00962 void Cmd_ExecuteString (const char *text)
00963 {
00964 const cmd_function_t *cmd;
00965 const cmd_alias_t *a;
00966 const char *str;
00967 unsigned int hash;
00968
00969 Com_DPrintf(DEBUG_COMMANDS, "ExecuteString: '%s'\n", text);
00970
00971 Cmd_TokenizeString(text, qtrue);
00972
00973
00974 if (!Cmd_Argc())
00975
00976 return;
00977
00978 str = Cmd_Argv(0);
00979
00980
00981 hash = Com_HashKey(str, CMD_HASH_SIZE);
00982 for (cmd = cmd_functions_hash[hash]; cmd; cmd = cmd->hash_next) {
00983 if (!Q_strcasecmp(str, cmd->name)) {
00984 if (!cmd->function) {
00985 Cmd_ExecuteString(va("cmd %s", text));
00986 } else {
00987 cmd_userdata = cmd->userdata;
00988 cmd->function();
00989 }
00990 return;
00991 }
00992 }
00993
00994
00995 hash = Com_HashKey(str, ALIAS_HASH_SIZE);
00996 for (a = cmd_alias_hash[hash]; a; a = a->hash_next) {
00997 if (!Q_strcasecmp(str, a->name)) {
00998 if (++alias_count == ALIAS_LOOP_COUNT) {
00999 Com_Printf("ALIAS_LOOP_COUNT\n");
01000 return;
01001 }
01002 Cbuf_InsertText(a->value);
01003 return;
01004 }
01005 }
01006
01007
01008 if (Cvar_Command())
01009 return;
01010
01011
01012 Cmd_ForwardToServer();
01013 }
01014
01018 static void Cmd_List_f (void)
01019 {
01020 const cmd_function_t *cmd;
01021 const cmd_alias_t *alias;
01022 int i = 0, j = 0, c, l = 0;
01023 const char *token = NULL;
01024
01025 c = Cmd_Argc();
01026
01027 if (c == 2) {
01028 token = Cmd_Argv(1);
01029 l = strlen(token);
01030 }
01031
01032 for (cmd = cmd_functions; cmd; cmd = cmd->next, i++) {
01033 if (c == 2 && strncmp(cmd->name, token, l)) {
01034 i--;
01035 continue;
01036 }
01037 Com_Printf("[cmd] %s\n", cmd->name);
01038 if (cmd->description)
01039 Com_Printf(COLORED_GREEN " %s\n", cmd->description);
01040 }
01041
01042 for (alias = cmd_alias; alias; alias = alias->next, j++) {
01043 if (c == 2 && strncmp(alias->name, token, l)) {
01044 j--;
01045 continue;
01046 }
01047 Com_Printf("[ali] %s\n", alias->name);
01048 }
01049 Com_Printf("%i commands\n", i);
01050 Com_Printf("%i macros\n", j);
01051 }
01052
01053
01060 static int Cmd_CompleteExecCommand (const char *partial, const char **match)
01061 {
01062 const char *filename;
01063 size_t len;
01064
01065 FS_BuildFileList("*.cfg");
01066
01067 len = strlen(partial);
01068 if (!len) {
01069 while ((filename = FS_NextFileFromFileList("*.cfg")) != NULL) {
01070 Com_Printf("%s\n", filename);
01071 }
01072 }
01073
01074 FS_NextFileFromFileList(NULL);
01075 return 0;
01076 }
01077
01081 void Cmd_Dummy_f (void)
01082 {
01083 }
01084
01085 #ifdef DEBUG
01086
01091 static void Cmd_Test_f (void)
01092 {
01093 cmd_function_t *cmd;
01094
01095 for (cmd = cmd_functions; cmd; cmd = cmd->next) {
01096 if (strcmp(cmd->name, "quit"))
01097 Cmd_ExecuteString(cmd->name);
01098 }
01099 }
01100
01101 void Cmd_PrintDebugCommands (void)
01102 {
01103 const cmd_function_t *cmd;
01104 const char* otherCommands[] = {"mem_stats", "cl_configstrings", "cl_userinfo", "devmap"};
01105 int num = lengthof(otherCommands);
01106
01107 Com_Printf("Debug commands:\n");
01108 for (cmd = cmd_functions; cmd; cmd = cmd->next) {
01109 if (!strncmp(cmd->name, "debug_", 6))
01110 Com_Printf(" * %s\n %s\n", cmd->name, cmd->description);
01111 }
01112
01113 Com_Printf("Other useful commands:\n");
01114 while (num) {
01115 const char *desc = Cmd_GetCommandDesc(otherCommands[num - 1]);
01116 Com_Printf(" * %s\n %s\n", otherCommands[num - 1], desc);
01117 num--;
01118 }
01119 Com_Printf(" * sv debug_showall\n"
01120 " make everything visible to everyone\n"
01121 " * sv debug_actorinvlist\n"
01122 " Show the whole inv of all actors on the server console\n"
01123 );
01124 Com_Printf("\n");
01125 }
01126 #endif
01127
01128 void Cmd_Init (void)
01129 {
01130
01131 Cmd_AddCommand("cmdlist", Cmd_List_f, "List all commands to game console");
01132 Cmd_AddCommand("exec", Cmd_Exec_f, "Execute a script file");
01133 Cmd_AddParamCompleteFunction("exec", Cmd_CompleteExecCommand);
01134 Cmd_AddCommand("echo", Cmd_Echo_f, "Print to game console");
01135 Cmd_AddCommand("wait", Cmd_Wait_f, NULL);
01136 Cmd_AddCommand("alias", Cmd_Alias_f, "Creates a new command that executes a command string");
01137 Cmd_AddCommand("aliasa", Cmd_Alias_f, "Creates a new, persistent command that executes a command string");
01138 Cmd_AddCommand("cmdclose", Cmd_Close_f, "Close the command buffer");
01139 Cmd_AddCommand("cmdopen", Cmd_Open_f, "Open the command buffer again");
01140 #ifdef DEBUG
01141 Cmd_AddCommand("debug_cmdtest", Cmd_Test_f, "Calls every command in the current list");
01142 #endif
01143 }
01144
01145 void Cmd_Shutdown (void)
01146 {
01147 memset(cmd_functions_hash, 0, sizeof(cmd_functions_hash));
01148 memset(cmd_functions, 0, sizeof(cmd_functions));
01149 cmd_argc = 0;
01150 }