UFO: Alien Invasion
Loading...
Searching...
No Matches
cmd.cpp
Go to the documentation of this file.
1
13
14/*
15Copyright (C) 1997-2001 Id Software, Inc.
16
17This program is free software; you can redistribute it and/or
18modify it under the terms of the GNU General Public License
19as published by the Free Software Foundation; either version 2
20of the License, or (at your option) any later version.
21
22This program is distributed in the hope that it will be useful,
23but WITHOUT ANY WARRANTY; without even the implied warranty of
24MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
25
26See the GNU General Public License for more details.
27
28You should have received a copy of the GNU General Public License
29along with this program; if not, write to the Free Software
30Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31
32*/
33
34#include "cmd.h"
35#include "common.h"
36#include "msg.h"
37#include "../shared/parse.h"
38
39void Cmd_ForwardToServer(void);
40#define ALIAS_HASH_SIZE 32
41
42#define MAX_ALIAS_NAME 32
43
44typedef struct cmd_alias_s {
46 char* value;
47 bool archive;
48 struct cmd_alias_s* hash_next;
49 struct cmd_alias_s* next;
51
52typedef std::vector<CmdListenerPtr> CmdListeners;
53
57static bool cmdWait;
58static bool cmdClosed;
59
60#define ALIAS_LOOP_COUNT 16
61static int alias_count; /* for detecting runaway loops */
62
63
68static void Cmd_Open_f (void)
69{
70 Com_DPrintf(DEBUG_COMMANDS, "Cmd_Close_f: command buffer opened again\n");
71 cmdClosed = false;
72}
73
79static void Cmd_Close_f (void)
80{
81 Com_DPrintf(DEBUG_COMMANDS, "Cmd_Close_f: command buffer closed\n");
82 cmdClosed = true;
83}
84
90static void Cmd_Wait_f (void)
91{
92 cmdWait = true;
93}
94
95/*
96=============================================================================
97COMMAND BUFFER
98=============================================================================
99*/
100
101#define CMD_BUFFER_SIZE 8192
105
109void Cbuf_Init (void)
110{
112}
113
117void Cbuf_Shutdown (void)
118{
119 SZ_Init(&cmd_text, nullptr, 0);
120}
121
126void Cbuf_AddText (const char* format, ...)
127{
128 va_list argptr;
129 static char text[CMD_BUFFER_SIZE];
130 va_start(argptr, format);
131 Q_vsnprintf(text, sizeof(text), format, argptr);
132 va_end(argptr);
133
134 if (cmdClosed) {
135 if (!Q_strstart(text, "cmdopen")) {
136 Com_DPrintf(DEBUG_COMMANDS, "Cbuf_AddText: currently closed\n");
137 return;
138 }
139 }
140
141 const int len = strlen(text);
142
143 if (cmd_text.cursize + len >= cmd_text.maxsize) {
144 Com_Printf("Cbuf_AddText: overflow (%i) (%s)\n", cmd_text.maxsize, text);
145 Com_Printf("buffer content: %s\n", cmd_text_buf);
146 return;
147 }
148 SZ_Write(&cmd_text, text, len);
149}
150
151
157void Cbuf_InsertText (const char* text)
158{
159 if (Q_strnull(text))
160 return;
161
162 /* copy off any commands still remaining in the exec buffer */
163 char* temp;
164 const int templen = cmd_text.cursize;
165
166 if (templen) {
167 temp = Mem_AllocTypeN(char, templen);
168 memcpy(temp, cmd_text.data, templen);
170 } else {
171 temp = nullptr; /* shut up compiler */
172 }
173
174 /* add the entire text of the file */
175 Cbuf_AddText("%s\n", text);
176
177 /* add the copied off data */
178 if (templen) {
179 SZ_Write(&cmd_text, temp, templen);
180 Mem_Free(temp);
181 }
182}
183
184
192{
193 memcpy(defer_text_buf, cmd_text_buf, cmd_text.cursize);
194 defer_text_buf[cmd_text.cursize] = 0;
195 cmd_text.cursize = 0;
196}
197
206
214void Cbuf_Execute (void)
215{
216 /* don't allow infinite alias loops */
217 alias_count = 0;
218
219 while (cmd_text.cursize) {
220 unsigned int i;
221 char line[1024];
222
223 /* find a \n or ; line break */
224 char* text = (char*) cmd_text.data;
225 int quotes = 0;
226
227 for (i = 0; i < cmd_text.cursize; i++) {
228 if (text[i] == '"')
229 quotes++;
230 /* don't break if inside a quoted string */
231 if (!(quotes & 1) && text[i] == ';')
232 break;
233 if (text[i] == '\n')
234 break;
235 }
236
237 if (i > sizeof(line) - 1)
238 i = sizeof(line) - 1;
239
240 memcpy(line, text, i);
241 line[i] = 0;
242
243 /* delete the text from the command buffer and move remaining commands down
244 * this is necessary because commands (exec, alias) can insert data at the
245 * beginning of the text buffer */
246 if (i == cmd_text.cursize)
247 cmd_text.cursize = 0;
248 else {
249 i++;
250 cmd_text.cursize -= i;
251 memmove(text, text + i, cmd_text.cursize);
252 }
253
254 /* execute the command line */
255 Cmd_ExecuteString("%s", line);
256
257 if (cmdWait) {
258 /* skip out while text still remains in buffer, leaving it
259 * for next frame */
260 cmdWait = false;
261 break;
262 }
263 }
264}
265
266
275void Cbuf_AddEarlyCommands (bool clear)
276{
277 const int argc = Com_Argc();
278 for (int i = 1; i < argc; i++) {
279 const char* s = Com_Argv(i);
280 if (!Q_streq(s, "+set"))
281 continue;
282 Cbuf_AddText("set %s %s\n", Com_Argv(i + 1), Com_Argv(i + 2));
283 if (clear) {
285 Com_ClearArgv(i + 1);
286 Com_ClearArgv(i + 2);
287 }
288 i += 2;
289 }
290}
291
299{
300 /* build the combined string to parse from */
301 int s = 0;
302 const int argc = Com_Argc();
303 for (int i = 1; i < argc; i++) {
304 s += strlen(Com_Argv(i)) + 1;
305 }
306 if (!s)
307 return false;
308
309 char* text = Mem_AllocTypeN(char, s + 1);
310 for (int i = 1; i < argc; i++) {
311 Q_strcat(text, s, "%s", Com_Argv(i));
312 if (i != argc - 1)
313 Q_strcat(text, s, " ");
314 }
315
316 /* pull out the commands */
317 char* build = Mem_AllocTypeN(char, s + 1);
318
319 for (int i = 0; i < s - 1; i++) {
320 if (text[i] != '+')
321 continue;
322 i++;
323
324 int j;
325 for (j = i; text[j] != '+' && text[j] != '-' && text[j] != '\0'; j++) {}
326
327 const char c = text[j];
328 text[j] = '\0';
329
330 Q_strcat(build, s, "%s\n", text + i);
331 text[j] = c;
332 i = j - 1;
333 }
334
335 const bool ret = build[0] != '\0';
336 if (ret)
337 Cbuf_AddText("%s", build);
338
339 Mem_Free(text);
340 Mem_Free(build);
341
342 return ret;
343}
344
345
346/*
347==============================================================================
348SCRIPT COMMANDS
349==============================================================================
350*/
351
352static void Cmd_Exec_f (void)
353{
354 if (Cmd_Argc() != 2) {
355 Com_Printf("Usage: %s <filename> : execute a script file\n", Cmd_Argv(0));
356 return;
357 }
358
359 byte* f;
360 const int len = FS_LoadFile(Cmd_Argv(1), &f);
361 if (!f) {
362 Com_Printf("couldn't execute %s\n", Cmd_Argv(1));
363 return;
364 }
365 Com_Printf("executing %s\n", Cmd_Argv(1));
366
367 /* the file doesn't have a trailing 0, so we need to copy it off */
368 char* f2 = Mem_AllocTypeN(char, len + 1);
369 memcpy(f2, f, len);
370 /* make really sure that there is a newline */
371 f2[len] = 0;
372
373 Cbuf_InsertText(f2);
374
375 Mem_Free(f2);
376 FS_FreeFile(f);
377}
378
379
383static void Cmd_Echo_f (void)
384{
385 for (int i = 1; i < Cmd_Argc(); i++)
386 Com_Printf("%s ", Cmd_Argv(i));
387 Com_Printf("\n");
388}
389
393static void Cmd_Alias_f (void)
394{
395 cmd_alias_t* a;
396
397 if (Cmd_Argc() == 1) {
398 Com_Printf("Current alias commands:\n");
399 for (a = cmd_alias; a; a = a->next)
400 Com_Printf("%s : %s\n", a->name, a->value);
401 return;
402 }
403
404 const char* s = Cmd_Argv(1);
405 const size_t len = strlen(s);
406 if (len == 0)
407 return;
408
409 if (len >= MAX_ALIAS_NAME) {
410 Com_Printf("Alias name is too long\n");
411 return;
412 }
413
414 /* if the alias already exists, reuse it */
415 const unsigned int hash = Com_HashKey(s, ALIAS_HASH_SIZE);
416 for (a = cmd_alias_hash[hash]; a; a = a->hash_next) {
417 if (Q_streq(s, a->name)) {
418 Mem_Free(a->value);
419 break;
420 }
421 }
422
423 if (!a) {
425 a->next = cmd_alias;
426 /* cmd_alias_hash should be null on the first run */
428 cmd_alias_hash[hash] = a;
429 cmd_alias = a;
430 }
431 Q_strncpyz(a->name, s, sizeof(a->name));
432
433 /* copy the rest of the command line */
434 char cmd[MAX_STRING_CHARS];
435 cmd[0] = 0; /* start out with a null string */
436 const int c = Cmd_Argc();
437 for (int i = 2; i < c; i++) {
438 Q_strcat(cmd, sizeof(cmd), "%s", Cmd_Argv(i));
439 if (i != (c - 1))
440 Q_strcat(cmd, sizeof(cmd), " ");
441 }
442
443 if (Q_streq(Cmd_Argv(0), "aliasa"))
444 a->archive = true;
445
447}
448
455{
456 for (cmd_alias_t* a = cmd_alias; a; a = a->next)
457 if (a->archive) {
458 FS_Printf(f, "aliasa %s \"", a->name);
459 for (int i = 0; i < strlen(a->value); i++) {
460 if (a->value[i] == '"')
461 FS_Printf(f, "\\\"");
462 else
463 FS_Printf(f, "%c", a->value[i]);
464 }
465 FS_Printf(f, "\"\n");
466 }
467}
468
469/*
470=============================================================================
471COMMAND EXECUTION
472=============================================================================
473*/
474
475#define CMD_HASH_SIZE 32
476
477typedef struct cmd_function_s {
478 struct cmd_function_s* next;
479 struct cmd_function_s* hash_next;
480 const char* name;
481 const char* description;
483 int (*completeParam) (const char* partial, const char** match);
484 void* userdata;
485
486 inline const char* getName() const {
487 return name;
488 }
490
491static int cmd_argc;
494static void* cmd_userdata;
495
496static cmd_function_t* cmd_functions; /* possible commands to execute */
498
505int Cmd_Argc (void)
506{
507 return cmd_argc;
508}
509
516const char* Cmd_Argv (int arg)
517{
518 if (arg >= cmd_argc)
519 return "";
520 return cmd_argv[arg];
521}
522
526const char* Cmd_Args (void)
527{
528 return cmd_args;
529}
530
534void* Cmd_Userdata (void)
535{
536 return cmd_userdata;
537}
538
543void Cmd_BufClear (void)
544{
545 /* clear the args from the last string */
546 for (int i = 0; i < cmd_argc; i++) {
548 cmd_argv[i] = nullptr;
549 }
550
551 cmd_argc = 0;
552 cmd_args[0] = 0;
553 cmd_userdata = nullptr;
554}
555
565void Cmd_TokenizeString (const char* text, bool macroExpand, bool replaceWhitespaces)
566{
567 Cmd_BufClear();
568
569 /* macro expand the text */
570 if (macroExpand) {
571 const char* expanded = Com_MacroExpandString(text);
572 if (expanded)
573 text = expanded;
574 }
575
576 while (1) {
577 /* skip whitespace up to a newline */
578 while (*text && *text <= ' ' && *text != '\n') {
579 text++;
580 }
581
582 if (*text == '\n') { /* a newline seperates commands in the buffer */
583 text++;
584 break;
585 }
586
587 if (!*text)
588 return;
589
590 /* set cmd_args to everything after the first arg */
591 if (cmd_argc == 1) {
592 Q_strncpyz(cmd_args, text, sizeof(cmd_args));
594 }
595
596 const char* com_token = Com_Parse(&text, nullptr, 0, replaceWhitespaces);
597 if (!text)
598 return;
599
601 /* check first char of string if it is a variable */
602 if (com_token[0] == '*') {
603 com_token++;
605 }
606 assert(!cmd_argv[cmd_argc]);
608 cmd_argc++;
609 }
610 }
611}
612
613static cmd_function_t* Cmd_TableFind (const char* cmdName)
614{
615 const unsigned int hash = Com_HashKey(cmdName, CMD_HASH_SIZE);
616 for (cmd_function_t* cmd = cmd_functions_hash[hash]; cmd; cmd = cmd->hash_next) {
617 if (Q_streq(cmdName, cmd->getName()))
618 return cmd;
619 }
620 return nullptr;
621}
622
629const char* Cmd_GetCommandDesc (const char* cmdName)
630{
631 char searchName[MAX_VAR];
632
633 /* remove parameters */
634 Q_strncpyz(searchName, cmdName, sizeof(searchName));
635 char* sep = strstr(searchName, " ");
636 if (sep)
637 *sep = '\0';
638
639 const cmd_function_t* cmd = Cmd_TableFind(searchName);
640 if (cmd) {
641 if (cmd->description)
642 return cmd->description;
643 return "";
644 }
645 return "";
646}
647
648bool Cmd_GenericCompleteFunction(char const* candidate, char const* partial, char const** match)
649{
650 static char matchString[MAX_QPATH];
651
652 if (!Q_strstart(candidate, partial))
653 return false;
654
655 if (!*match) {
656 /* First match. */
657 Q_strncpyz(matchString, candidate, sizeof(matchString));
658 *match = matchString;
659 } else {
660 /* Subsequent match, determine common prefix with previous match(es). */
661 char* dst = matchString;
662 char const* src = candidate;
663 while (*dst == *src) {
664 ++dst;
665 ++src;
666 }
667 *dst = '\0';
668 }
669
670 return true;
671}
672
679void Cmd_AddParamCompleteFunction (const char* cmdName, int (*function)(const char* partial, const char** match))
680{
681 if (!cmdName || !cmdName[0])
682 return;
683
684 cmd_function_t* cmd = Cmd_TableFind(cmdName);
685 if (cmd) {
686 cmd->completeParam = function;
687 return;
688 }
689}
690
700void* Cmd_GetUserdata (const char* cmdName)
701{
702 if (!cmdName || !cmdName[0]) {
703 Com_Printf("Cmd_GetUserdata: Invalide parameter\n");
704 return nullptr;
705 }
706
707 const cmd_function_t* cmd = Cmd_TableFind(cmdName);
708 if (cmd) {
709 return cmd->userdata;
710 }
711
712 Com_Printf("Cmd_GetUserdata: '%s' not found\n", cmdName);
713 return nullptr;
714}
715
724void Cmd_AddUserdata (const char* cmdName, void* userdata)
725{
726 if (!cmdName || !cmdName[0])
727 return;
728
729 cmd_function_t* cmd = Cmd_TableFind(cmdName);
730 if (cmd) {
731 cmd->userdata = userdata;
732 return;
733 }
734}
735
744void Cmd_AddCommand (const char* cmdName, xcommand_t function, const char* desc)
745{
746 if (!Q_strvalid(cmdName))
747 return;
748
749 /* fail if the command is a variable name */
750 if (Cvar_GetString(cmdName)[0]) {
751 Com_Printf("Cmd_AddCommand: %s already defined as a var\n", cmdName);
752 return;
753 }
754
755 /* fail if the command already exists */
756 const cmd_function_t* const cmdOld = Cmd_TableFind(cmdName);
757 if (cmdOld) {
758 Com_DPrintf(DEBUG_COMMANDS, "Cmd_AddCommand: %s already defined\n", cmdName);
759 return;
760 }
761
762 /* create the new command entry ... */
764 cmd->name = cmdName;
765 cmd->description = desc;
766 cmd->function = function;
767 cmd->completeParam = nullptr;
768
769 /* ... add it to the hashtable */
770 const unsigned int hash = Com_HashKey(cmdName, CMD_HASH_SIZE);
772 /* ... and to the cmd table */
773 cmd->next = cmd_functions;
774 cmd_functions = cmd;
775
776 for (CmdListeners::const_iterator i = cmdListeners.begin(); i != cmdListeners.end(); ++i) {
777 (*i)->onAdd(cmdName);
778 }
779}
780
786void Cmd_RemoveCommand (const char* cmdName)
787{
788 const unsigned int hash = Com_HashKey(cmdName, CMD_HASH_SIZE);
790
791 while (1) {
792 cmd_function_t* cmd = *back;
793 if (!cmd) {
794 Com_Printf("Cmd_RemoveCommand: %s not added\n", cmdName);
795 return;
796 }
797 if (Q_streq(cmdName, cmd->getName())) {
798 *back = cmd->hash_next;
799 break;
800 }
801 back = &cmd->hash_next;
802 }
803
804 back = &cmd_functions;
805 while (1) {
806 cmd_function_t* cmd = *back;
807 if (!cmd) {
808 Com_Printf("Cmd_RemoveCommand: %s not added\n", cmdName);
809 return;
810 }
811 if (Q_streq(cmdName, cmd->getName())) {
812 *back = cmd->next;
813 Mem_Free(cmd);
814 for (CmdListeners::const_iterator i = cmdListeners.begin(); i != cmdListeners.end(); ++i) {
815 (*i)->onRemove(cmdName);
816 }
817 return;
818 }
819 back = &cmd->next;
820 }
821}
822
826void Cmd_TableCheck (void)
827{
828#ifdef PARANOID
829 int cmdCount = 0;
830 for (cmd_function_t* cmd = cmd_functions; cmd; cmd = cmd->next) {
831 cmdCount++;
832 if (Q_streq("hugo", cmd->getName())) {
833 Com_Printf("Cmd_TableCheck: found bad entry\n");
834 return;
835 }
836 }
837 int hashCount = 0;
838 for (int i = 0; i < CMD_HASH_SIZE; i++) {
839 for (cmd_function_t* cmd = cmd_functions_hash[i]; cmd; cmd = cmd->hash_next) {
840 hashCount++;
841 if (Q_streq("hugo", cmd->getName())) {
842 Com_Printf("Cmd_TableCheck: found bad hash entry\n");
843 return;
844 }
845 }
846 }
847 /* This causes a <path/to/ufo>/(null)/ufoconsole.log to be created just to log this line
848 * file system shutdown has already run */
849 Com_Printf("cmdCount: %i hashCount: %i\n", cmdCount, hashCount);
850#endif
851}
852
853void Cmd_TableAddList (const cmdList_t* cmdList)
854{
855 for (const cmdList_t* cmd = cmdList; cmd->name; cmd++)
856 Cmd_AddCommand(cmd->name, cmd->function, cmd->description);
857}
858
859void Cmd_TableRemoveList (const cmdList_t* cmdList)
860{
861 for (const cmdList_t* cmd = cmdList; cmd->name; cmd++)
862 Cmd_RemoveCommand(cmd->name);
863}
864
870{
871 cmdListeners.push_back(listener);
872}
873
879{
880 cmdListeners.erase(std::remove(cmdListeners.begin(), cmdListeners.end(), listener), cmdListeners.end());
881}
882
887bool Cmd_Exists (const char* cmdName)
888{
889 const cmd_function_t* cmd = Cmd_TableFind(cmdName);
890 if (cmd)
891 return true;
892 return false;
893}
894
903int Cmd_CompleteCommandParameters (const char* command, const char* partial, const char** match)
904{
905 /* check for partial matches in commands */
906 const unsigned int hash = Com_HashKey(command, CMD_HASH_SIZE);
907 for (const cmd_function_t* cmd = cmd_functions_hash[hash]; cmd; cmd = cmd->hash_next) {
908 if (!Q_strcasecmp(command, cmd->getName())) {
909 if (!cmd->completeParam)
910 return 0;
911 return cmd->completeParam(partial, match);
912 }
913 }
914 return 0;
915}
916
924int Cmd_CompleteCommand (const char* partial, const char** match)
925{
926 if (partial[0] == '\0')
927 return 0;
928
929 int n = 0;
930
931 /* check for partial matches in commands */
932 for (cmd_function_t const* cmd = cmd_functions; cmd; cmd = cmd->next) {
933 if (Cmd_GenericCompleteFunction(cmd->getName(), partial, match)) {
934 Com_Printf("[cmd] %s\n", cmd->getName());
935 if (cmd->description)
936 Com_Printf(S_COLOR_GREEN " %s\n", cmd->description);
937 ++n;
938 }
939 }
940
941 /* and then aliases */
942 for (cmd_alias_t const* a = cmd_alias; a; a = a->next) {
943 if (Cmd_GenericCompleteFunction(a->name, partial, match)) {
944 Com_Printf("[ali] %s\n", a->name);
945 ++n;
946 }
947 }
948
949 return n;
950}
951
952void Cmd_vExecuteString (const char* fmt, va_list ap)
953{
954 char text[1024];
955 Q_vsnprintf(text, sizeof(text), fmt, ap);
956
957 Com_DPrintf(DEBUG_COMMANDS, "ExecuteString: '%s'\n", text);
958
959 Cmd_TokenizeString(text, true);
960
961 /* execute the command line */
962 if (!Cmd_Argc())
963 /* no tokens */
964 return;
965
966 const char* str = Cmd_Argv(0);
967
968 /* check functions */
969 unsigned int hash = Com_HashKey(str, CMD_HASH_SIZE);
970 for (const cmd_function_t* cmd = cmd_functions_hash[hash]; cmd; cmd = cmd->hash_next) {
971 if (!Q_strcasecmp(str, cmd->getName())) {
972 if (!cmd->function) { /* forward to server command */
973 Cmd_ExecuteString("cmd %s", text);
974 } else {
975 cmd_userdata = cmd->userdata;
976 cmd->function();
977 }
978 return;
979 }
980 }
981
982 /* check alias */
984 for (const cmd_alias_t* a = cmd_alias_hash[hash]; a; a = a->hash_next) {
985 if (!Q_strcasecmp(str, a->name)) {
986 if (++alias_count == ALIAS_LOOP_COUNT) {
987 Com_Printf("ALIAS_LOOP_COUNT\n");
988 return;
989 }
990 Cbuf_InsertText(a->value);
991 return;
992 }
993 }
994
995 /* check cvars */
996 if (Cvar_Command())
997 return;
998
999 /* send it as a server command if we are connected */
1001}
1002
1007void Cmd_ExecuteString (const char* text, ...)
1008{
1009 va_list ap;
1010
1011 va_start(ap, text);
1012 Cmd_vExecuteString(text, ap);
1013 va_end(ap);
1014}
1015
1019static void Cmd_Help_f (void)
1020{
1021 Com_Printf(S_COLOR_GREEN " Use cmdlist and cvarlist. Both accept a partial name.\n");
1022 Com_Printf(S_COLOR_GREEN " Note that both lists can vary depending on where in the game you are.\n");
1023}
1024
1028static void Cmd_List_f (void)
1029{
1030 int i = 0, j = 0, len = 0;
1031 const char* token = nullptr;
1032
1033 const int c = Cmd_Argc();
1034
1035 if (c == 2) {
1036 token = Cmd_Argv(1);
1037 len = strlen(token);
1038 }
1039
1040 for (const cmd_function_t* cmd = cmd_functions; cmd; cmd = cmd->next, i++) {
1041 if (c == 2 && strncmp(cmd->getName(), token, len)) {
1042 i--;
1043 continue;
1044 }
1045 Com_Printf("[cmd] %s\n", cmd->getName());
1046 if (cmd->description)
1047 Com_Printf(S_COLOR_GREEN " %s\n", cmd->description);
1048 }
1049 /* check alias */
1050 for (const cmd_alias_t* alias = cmd_alias; alias; alias = alias->next, j++) {
1051 if (c == 2 && strncmp(alias->name, token, len)) {
1052 j--;
1053 continue;
1054 }
1055 Com_Printf("[ali] %s\n", alias->name);
1056 }
1057 Com_Printf("%i commands\n", i);
1058 Com_Printf("%i macros\n", j);
1059}
1060
1061
1066static int Cmd_CompleteExecCommand (const char* partial, const char** match)
1067{
1068 int n = 0;
1069 while (char const* filename = FS_NextFileFromFileList("*.cfg")) {
1070 if (Cmd_GenericCompleteFunction(filename, partial, match)) {
1071 Com_Printf("%s\n", filename);
1072 ++n;
1073 }
1074 }
1075 FS_NextFileFromFileList(nullptr);
1076
1077 return n;
1078}
1079
1083void Cmd_Dummy_f (void)
1084{
1085}
1086
1087#ifdef DEBUG
1093static void Cmd_Test_f (void)
1094{
1095 for (cmd_function_t* cmd = cmd_functions; cmd; cmd = cmd->next) {
1096 if (!Q_streq(cmd->getName(), "quit"))
1097 Cmd_ExecuteString("%s", cmd->getName());
1098 }
1099}
1100
1101void Cmd_PrintDebugCommands (void)
1102{
1103 const char* otherCommands[] = {"mem_stats", "cl_configstrings", "cl_userinfo", "devmap"};
1104 int num = lengthof(otherCommands);
1105
1106 Com_Printf("Debug commands:\n");
1107 for (const cmd_function_t* cmd = cmd_functions; cmd; cmd = cmd->next) {
1108 if (Q_strstart(cmd->getName(), "debug_"))
1109 Com_Printf(" * %s\n %s\n", cmd->getName(), cmd->description);
1110 }
1111
1112 Com_Printf("Other useful commands:\n");
1113 while (num) {
1114 const char* desc = Cmd_GetCommandDesc(otherCommands[num - 1]);
1115 Com_Printf(" * %s\n %s\n", otherCommands[num - 1], desc);
1116 num--;
1117 }
1118 Com_Printf(" * sv debug_showall\n"
1119 " make everything visible to everyone\n"
1120 " * sv debug_actorinvlist\n"
1121 " Show the whole inv of all actors on the server console\n"
1122 );
1123 Com_Printf("\n");
1124}
1125#endif
1126
1127void Cmd_Init (void)
1128{
1129 /* register our commands */
1130 Cmd_AddCommand("help", Cmd_Help_f, "Display some help about cmd and cvar usage");
1131 Cmd_AddCommand("cmdlist", Cmd_List_f, "List all commands to game console");
1132 Cmd_AddCommand("exec", Cmd_Exec_f, "Execute a script file");
1134 Cmd_AddCommand("echo", Cmd_Echo_f, "Print to game console");
1135 Cmd_AddCommand("wait", Cmd_Wait_f);
1136 Cmd_AddCommand("alias", Cmd_Alias_f, "Creates a new command that executes a command string");
1137 Cmd_AddCommand("aliasa", Cmd_Alias_f, "Creates a new, persistent command that executes a command string");
1138 Cmd_AddCommand("cmdclose", Cmd_Close_f, "Close the command buffer");
1139 Cmd_AddCommand("cmdopen", Cmd_Open_f, "Open the command buffer again");
1140#ifdef DEBUG
1141 Cmd_AddCommand("debug_cmdtest", Cmd_Test_f, "Calls every command in the current list");
1142#endif
1143}
1144
1145void Cmd_Shutdown (void)
1146{
1148 cmd_functions = nullptr;
1149
1151 cmd_alias = nullptr;
1152 alias_count = 0;
1153
1155 cmd_argc = 0;
1156
1157 cmdWait = false;
1158 cmdClosed = false;
1159
1161}
void Cmd_ExecuteString(const char *text,...)
A complete command line has been parsed, so try to execute it.
Definition cmd.cpp:1007
void Cbuf_Shutdown(void)
Definition cmd.cpp:117
bool Cmd_Exists(const char *cmdName)
Checks whether a function exists already.
Definition cmd.cpp:887
const char * Cmd_Argv(int arg)
Returns a given argument.
Definition cmd.cpp:516
static bool cmdClosed
Definition cmd.cpp:58
static cmd_alias_t * cmd_alias
Definition cmd.cpp:55
static void Cmd_Alias_f(void)
Creates a new command that executes a command string (possibly ; separated).
Definition cmd.cpp:393
static cmd_function_t * cmd_functions_hash[CMD_HASH_SIZE]
Definition cmd.cpp:497
static void * cmd_userdata
Definition cmd.cpp:494
#define ALIAS_HASH_SIZE
Definition cmd.cpp:40
std::vector< CmdListenerPtr > CmdListeners
Definition cmd.cpp:52
void Cmd_WriteAliases(qFILE *f)
Write lines containing "aliasa alias value" for all aliases with the archive flag set to true.
Definition cmd.cpp:454
void Cbuf_InsertText(const char *text)
Adds command text immediately after the current command.
Definition cmd.cpp:157
void Cmd_AddParamCompleteFunction(const char *cmdName, int(*function)(const char *partial, const char **match))
Definition cmd.cpp:679
static CmdListeners cmdListeners
Definition cmd.cpp:54
void Cmd_TableAddList(const cmdList_t *cmdList)
Definition cmd.cpp:853
static void Cmd_Echo_f(void)
Just prints the rest of the line to the console.
Definition cmd.cpp:383
void Cmd_RemoveCommand(const char *cmdName)
Removes a command from script interface.
Definition cmd.cpp:786
static bool cmdWait
Definition cmd.cpp:57
void Cmd_Dummy_f(void)
Dummy binding if you don't want unknown commands forwarded to the server.
Definition cmd.cpp:1083
void Cbuf_Execute(void)
Pulls off terminated lines of text from the command buffer and sends them through Cmd_ExecuteString...
Definition cmd.cpp:214
void Cmd_AddUserdata(const char *cmdName, void *userdata)
Adds userdata to the console command.
Definition cmd.cpp:724
#define ALIAS_LOOP_COUNT
Definition cmd.cpp:60
static int alias_count
Definition cmd.cpp:61
void Cmd_TokenizeString(const char *text, bool macroExpand, bool replaceWhitespaces)
Parses the given string into command line tokens.
Definition cmd.cpp:565
int Cmd_CompleteCommandParameters(const char *command, const char *partial, const char **match)
Unix like tab completion for console commands parameters.
Definition cmd.cpp:903
void Cmd_RegisterCmdListener(CmdListenerPtr listener)
Registers a command listener.
Definition cmd.cpp:869
static char defer_text_buf[CMD_BUFFER_SIZE]
Definition cmd.cpp:104
void Cbuf_AddEarlyCommands(bool clear)
Adds command line parameters as script statements Commands lead with a +, and continue until another ...
Definition cmd.cpp:275
void Cmd_UnRegisterCmdListener(CmdListenerPtr listener)
Unregisters a command listener.
Definition cmd.cpp:878
static byte cmd_text_buf[CMD_BUFFER_SIZE]
Definition cmd.cpp:103
static void Cmd_Open_f(void)
Reopens the command buffer for writing.
Definition cmd.cpp:68
void Cmd_Init(void)
Definition cmd.cpp:1127
const char * Cmd_Args(void)
Returns a single string containing argv(1) to argv(argc()-1).
Definition cmd.cpp:526
bool Cmd_GenericCompleteFunction(char const *candidate, char const *partial, char const **match)
Definition cmd.cpp:648
static int cmd_argc
Definition cmd.cpp:491
#define CMD_BUFFER_SIZE
Definition cmd.cpp:101
static char cmd_args[MAX_STRING_CHARS]
Definition cmd.cpp:493
static cmd_function_t * cmd_functions
Definition cmd.cpp:496
#define CMD_HASH_SIZE
Definition cmd.cpp:475
static cmd_function_t * Cmd_TableFind(const char *cmdName)
Definition cmd.cpp:613
void Cmd_TableCheck(void)
Check both the functiontable and the associated hashtable for invalid entries.
Definition cmd.cpp:826
void Cbuf_Init(void)
allocates an initial text buffer that will grow as needed
Definition cmd.cpp:109
int Cmd_Argc(void)
Return the number of arguments of the current command. "command parameter" will result in a argc of 2...
Definition cmd.cpp:505
void * Cmd_GetUserdata(const char *cmdName)
Fetches the userdata for a console command.
Definition cmd.cpp:700
void Cmd_AddCommand(const char *cmdName, xcommand_t function, const char *desc)
Add a new command to the script interface.
Definition cmd.cpp:744
void Cbuf_InsertFromDefer(void)
Copies back any deferred commands.
Definition cmd.cpp:201
bool Cbuf_AddLateCommands(void)
Adds command line parameters as script statements.
Definition cmd.cpp:298
void Cbuf_CopyToDefer(void)
Defers any outstanding commands.
Definition cmd.cpp:191
static char * cmd_argv[MAX_STRING_TOKENS]
Definition cmd.cpp:492
void Cmd_vExecuteString(const char *fmt, va_list ap)
Definition cmd.cpp:952
#define MAX_ALIAS_NAME
Definition cmd.cpp:42
static void Cmd_Close_f(void)
Will no longer add any command to command buffer ...until cmd_close is false again.
Definition cmd.cpp:79
void Cmd_BufClear(void)
Clears the argv vector and set argc to zero.
Definition cmd.cpp:543
void Cmd_ForwardToServer(void)
adds the current command line as a clc_stringcmd to the client message. things like action,...
Definition cl_main.cpp:98
void Cbuf_AddText(const char *format,...)
Adds command text at the end of the buffer.
Definition cmd.cpp:126
static int Cmd_CompleteExecCommand(const char *partial, const char **match)
Autocomplete function for exec command.
Definition cmd.cpp:1066
static void Cmd_Wait_f(void)
Causes execution of the remainder of the command buffer to be delayed until next frame....
Definition cmd.cpp:90
const char * Cmd_GetCommandDesc(const char *cmdName)
Returns the command description for a given command.
Definition cmd.cpp:629
void Cmd_TableRemoveList(const cmdList_t *cmdList)
Definition cmd.cpp:859
void * Cmd_Userdata(void)
Return the userdata of the called command.
Definition cmd.cpp:534
static void Cmd_Exec_f(void)
Definition cmd.cpp:352
void Cmd_Shutdown(void)
Definition cmd.cpp:1145
static cmd_alias_t * cmd_alias_hash[ALIAS_HASH_SIZE]
Definition cmd.cpp:56
static sizebuf_t cmd_text
Definition cmd.cpp:102
static void Cmd_List_f(void)
List all available script interface functions.
Definition cmd.cpp:1028
static void Cmd_Help_f(void)
Display some help about cmd and cvar usage.
Definition cmd.cpp:1019
int Cmd_CompleteCommand(const char *partial, const char **match)
Unix like tab completion for console commands.
Definition cmd.cpp:924
Command text buffering and command execution header.
void(* xcommand_t)(void)
Definition cmd.h:84
SharedPtr< CmdListener > CmdListenerPtr
Definition cmd.h:103
memPool_t * com_cmdSysPool
Definition common.cpp:68
int Com_Argc(void)
Returns the script commandline argument count.
Definition common.cpp:600
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition common.cpp:440
memPool_t * com_aliasSysPool
Definition common.cpp:67
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
const char * Com_MacroExpandString(const char *text)
Expands strings with cvar values that are dereferenced by a '*cvar'.
Definition common.cpp:647
void Com_ClearArgv(int arg)
Reset com_argv entry to empty string.
Definition common.cpp:620
const char * Com_Argv(int arg)
Returns an argument of script commandline.
Definition common.cpp:608
definitions common between client and server, but not game lib
#define HASH_Add(hash, elem, index)
Definition common.h:407
#define S_COLOR_GREEN
Definition common.h:219
bool Cvar_Command(void)
Handles variable inspection and changing from the console.
Definition cvar.cpp:708
const char * Cvar_GetString(const char *varName)
Returns the value of cvar as string.
Definition cvar.cpp:210
#define MAX_STRING_TOKENS
Definition defines.h:92
#define DEBUG_COMMANDS
Definition defines.h:58
#define MAX_STRING_CHARS
Definition defines.h:90
int FS_Printf(qFILE *f, const char *msg,...)
Can print chunks for 1024 chars into a file.
Definition files.cpp:1497
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
Definition files.cpp:384
void FS_FreeFile(void *buffer)
Definition files.cpp:411
const char * FS_NextFileFromFileList(const char *files)
Returns the next file that is found in the virtual filesystem identified by the given file pattern.
Definition files.cpp:1081
#define MAX_QPATH
Definition filesys.h:40
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
const char * filename
Definition ioapi.h:41
#define Mem_FreePool(pool)
Definition mem.h:37
#define Mem_Free(ptr)
Definition mem.h:35
#define Mem_PoolStrDup(in, pool, tagNum)
Definition mem.h:50
#define Mem_AllocTypeN(type, n)
Definition mem.h:38
#define Mem_PoolAllocType(type, pool)
Definition mem.h:43
void SZ_Clear(sizebuf_t *buf)
Definition msg.cpp:36
void SZ_Init(sizebuf_t *buf, byte *data, int length)
Definition msg.cpp:29
void SZ_Write(sizebuf_t *buf, const void *data, int length)
Definition msg.cpp:52
Message IO functions - handles byte ordering and avoids alignment errors.
const char * Com_Parse(const char *data_p[], char *target, size_t size, bool replaceWhitespaces)
Parse a token out of a string.
Definition parse.cpp:107
static char com_token[4096]
Definition parse.cpp:32
Shared parsing functions.
void format(__printf__, 1, 2)))
static wrapCache_t * hash[MAX_WRAP_HASH]
Definition r_font.cpp:86
QGL_EXTERN GLuint GLchar GLuint * len
Definition r_gl.h:99
QGL_EXTERN GLfloat f
Definition r_gl.h:114
QGL_EXTERN GLint i
Definition r_gl.h:113
#define Q_strvalid(string)
Definition shared.h:141
#define Q_strcasecmp(a, b)
Definition shared.h:131
#define Q_streq(a, b)
Definition shared.h:136
bool Q_strnull(const char *string)
Definition shared.h:138
#define OBJZERO(obj)
Definition shared.h:178
#define MAX_VAR
Definition shared.h:36
#define lengthof(x)
Definition shared.h:105
char * Com_Chop(char *s)
Removed trailing whitespaces.
Definition shared.cpp:48
unsigned int Com_HashKey(const char *name, int hashsize)
returns hash key for a string
Definition shared.cpp:336
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition shared.cpp:457
int Q_vsnprintf(char *str, size_t size, const char *format, va_list ap)
Safe (null terminating) vsnprintf implementation.
Definition shared.cpp:535
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition shared.cpp:475
char const * Q_strstart(char const *str, char const *start)
Matches the start of a string.
Definition shared.cpp:587
struct cmd_alias_s * next
Definition cmd.cpp:49
char * value
Definition cmd.cpp:46
bool archive
Definition cmd.cpp:47
char name[MAX_ALIAS_NAME]
Definition cmd.cpp:45
struct cmd_alias_s * hash_next
Definition cmd.cpp:48
const char * name
Definition cmd.cpp:480
struct cmd_function_s * next
Definition cmd.cpp:478
void * userdata
Definition cmd.cpp:484
const char * getName() const
Definition cmd.cpp:486
struct cmd_function_s * hash_next
Definition cmd.cpp:479
int(* completeParam)(const char *partial, const char **match)
Definition cmd.cpp:483
const char * description
Definition cmd.cpp:481
xcommand_t function
Definition cmd.cpp:482
const char * name
Definition cmd.h:87