Quake II RTX doxygen
1.0 dev
|
|
Go to the documentation of this file.
20 #include "shared/shared.h"
21 #include "shared/list.h"
22 #include "common/cmd.h"
23 #include "common/common.h"
24 #include "common/cvar.h"
25 #include "common/error.h"
26 #include "common/files.h"
27 #include "common/prompt.h"
28 #include "common/utils.h"
35 #define Cmd_Malloc(size) Z_TagMalloc(size, TAG_CMD)
36 #define Cmd_CopyString(string) Z_TagCopyString(string, TAG_CMD)
97 size_t l = strlen(text);
99 if (buf->cursize + l > buf->maxsize) {
100 Com_WPrintf(
"%s: overflow\n", __func__);
103 memcpy(buf->text + buf->cursize, text, l);
111 if (buf->cursize + len > buf->maxsize) {
114 text = buf->text + buf->cursize;
130 size_t l = strlen(text);
136 if (buf->cursize + l + 1 > buf->maxsize) {
137 Com_WPrintf(
"%s: overflow\n", __func__);
141 memmove(buf->text + l + 1, buf->text, buf->cursize);
142 memcpy(buf->text, text, l);
144 buf->cursize += l + 1;
156 char line[MAX_STRING_CHARS];
159 while (buf->cursize) {
160 if (buf->waitCount > 0) {
170 for (i = 0; i < buf->cursize; i++) {
173 if (!(quotes & 1) && text[i] ==
';')
180 if (i >
sizeof(line) - 1) {
181 i =
sizeof(line) - 1;
184 memcpy(line, text, i);
190 if (i == buf->cursize) {
195 memmove(text, text + i, buf->cursize);
200 buf->exec(buf, line);
214 #define ALIAS_HASH_SIZE 64
216 #define FOR_EACH_ALIAS_HASH(alias, hash) \
217 LIST_FOR_EACH(cmdalias_t, alias, &cmd_aliasHash[hash], hashEntry)
218 #define FOR_EACH_ALIAS(alias) \
219 LIST_FOR_EACH(cmdalias_t, alias, &cmd_alias, listEntry)
243 if (!strcmp(name, alias->
name)) {
279 memcpy(a->
name, name, len + 1);
314 Com_Printf(
"No alias commands registered.\n");
317 Com_Printf(
"Registered alias commands:\n");
319 Com_Printf(
"\"%s\" = \"%s\"\n", a->
name, a->
value);
326 Com_Printf(
"\"%s\" already defined as a command\n", s);
331 Com_Printf(
"\"%s\" already defined as a cvar\n", s);
338 Com_Printf(
"\"%s\" = \"%s\"\n", a->
name, a->
value);
340 Com_Printf(
"\"%s\" is undefined\n", s);
352 static const cmd_option_t options[] = {
353 {
"h",
"help",
"display this message" },
354 {
"a",
"all",
"delete everything" },
365 Com_Printf(
"Usage: %s [-ha] [name]\n",
Cmd_Argv(0));
377 Com_Printf(
"Removed all alias commands.\n");
385 Com_Printf(
"Missing alias name.\n"
386 "Try %s --help for more information.\n",
394 Com_Printf(
"\"%s\" is undefined.\n", s);
406 void Cmd_WriteAliases(qhandle_t f)
440 #define FOR_EACH_TRIGGER(trig) \
441 LIST_FOR_EACH(cmd_trigger_t, trig, &cmd_triggers, entry)
442 #define FOR_EACH_TRIGGER_SAFE(trig, next) \
443 LIST_FOR_EACH_SAFE(cmd_trigger_t, trig, next, &cmd_triggers, entry)
458 if (!strcmp(trigger->
command, command) && !strcmp(trigger->
match, match)) {
471 Com_Printf(
"No current message triggers\n");
475 Com_Printf(
"Current message triggers:\n");
477 Com_Printf(
"\"%s\" = \"%s\"\n", trigger->
command, trigger->
match);
489 const char *command, *match;
490 size_t cmdlen, matchlen;
498 Com_Printf(
"Usage: %s <command> <match>\n",
Cmd_Argv(0));
510 cmdlen = strlen(command) + 1;
511 matchlen = strlen(match) + 1;
513 Com_Printf(
"Match string is too short\n");
517 trigger = Z_Malloc(
sizeof(*trigger) + cmdlen + matchlen);
518 trigger->
command = (
char *)(trigger + 1);
520 memcpy(trigger->
command, command, cmdlen);
521 memcpy(trigger->
match, match, matchlen);
528 const char *command, *match;
536 Com_Printf(
"No current message triggers\n");
541 if (!Q_stricmp(
Cmd_Argv(1),
"all")) {
549 Com_Printf(
"Removed %d trigger%s\n", count, count == 1 ?
"" :
"s");
554 Com_Printf(
"Usage: %s <command> <match>\n",
Cmd_Argv(0));
563 Com_Printf(
"Can't find trigger \"%s\" = \"%s\"\n", command, match);
567 List_Remove(&trigger->
entry);
584 if (match && Com_WildCmp(match,
string)) {
612 Com_Printf(
"Usage: if <expr> <op> <expr> [then] <command> [else <command>]\n");
621 if (!strcmp(op,
"==")) {
622 matched = numeric ? atof(a) == atof(b) : !strcmp(a, b);
623 }
else if (!strcmp(op,
"!=") || !strcmp(op,
"<>")) {
624 matched = numeric ? atof(a) != atof(b) : strcmp(a, b);
625 }
else if (!strcmp(op,
"<")) {
628 Com_Printf(
"Can't use '%s' with non-numeric expression(s)\n", op);
631 matched = atof(a) < atof(b);
632 }
else if (!strcmp(op,
"<=")) {
635 matched = atof(a) <= atof(b);
636 }
else if (!strcmp(op,
">")) {
639 matched = atof(a) > atof(b);
640 }
else if (!strcmp(op,
">=")) {
643 matched = atof(a) >= atof(b);
644 }
else if (!Q_stricmp(op,
"isin")) {
645 matched = strstr(b, a) != NULL;
646 }
else if (!Q_stricmp(op,
"!isin")) {
647 matched = strstr(b, a) == NULL;
648 }
else if (!Q_stricmp(op,
"isini")) {
649 matched = Q_stristr(b, a) != NULL;
650 }
else if (!Q_stricmp(op,
"!isini")) {
651 matched = Q_stristr(b, a) == NULL;
652 }
else if (!Q_stricmp(op,
"eq")) {
653 matched = !Q_stricmp(a, b);
654 }
else if (!Q_stricmp(op,
"ne")) {
655 matched = Q_stricmp(a, b);
657 Com_Printf(
"Unknown operator '%s'\n", op);
658 Com_Printf(
"Valid are: ==, != or <>, <, <=, >, >=, [!]isin[i], eq, ne\n");
664 if (!Q_stricmp(
Cmd_Argv(i),
"then")) {
670 if (!Q_stricmp(
Cmd_Argv(i),
"else")) {
697 Com_Printf(
"openurl expects a single argument that is the URL to open");
702 if (Q_stricmpn(url,
"http://", 7) && Q_stricmpn(url,
"https://", 8))
704 Com_Printf(
"the URL must start with http:// or https://");
712 char * args[] = {
"xdg-open", url, NULL};
713 execv(
"/usr/bin/xdg-open", args);
717 ShellExecuteA(0, 0, url, 0, 0, SW_SHOW);
729 #define MACRO_HASH_SIZE 64
745 for (macro =
cmd_macroHash[hash]; macro; macro = macro->hashNext) {
746 if (!strcmp(macro->name, name)) {
777 Com_WPrintf(
"%s: %s already defined as a cvar\n", __func__, name);
784 if (macro->function !=
function) {
785 Com_WPrintf(
"%s: %s already defined\n", __func__, name);
792 macro->function =
function;
810 #define CMD_HASH_SIZE 128
812 #define FOR_EACH_CMD_HASH(cmd, hash) \
813 LIST_FOR_EACH(cmd_function_t, cmd, &cmd_hash[hash], hashEntry)
814 #define FOR_EACH_CMD(cmd) \
815 LIST_FOR_EACH(cmd_function_t, cmd, &cmd_functions, listEntry)
942 for (i = 1; i <
cmd_argc - 1; i++) {
990 for (i = from; i <
cmd_argc - 1; i++) {
1003 if (from < 0 || from >=
cmd_argc) {
1012 for (i = from; i < to; i++) {
1025 if (from < 0 || from >=
cmd_argc) {
1059 const cmd_option_t *o;
1088 if ((p = strchr(s,
'=')) != NULL) {
1093 for (o = opt; o->sh; o++) {
1094 if (!strcmp(o->lo, s)) {
1104 if (o->sh[1] !=
':') {
1113 for (o = opt; o->sh; o++) {
1114 if (o->sh[0] == *s) {
1118 if (!o->sh || s[1]) {
1125 if (!p && o->sh[1] ==
':') {
1145 Com_Printf(
"Usage: %s [-",
cmd_argv[0]);
1147 Com_Printf(
"%c", opt->sh[0]);
1148 if (opt->sh[1] ==
':') {
1154 Com_Printf(
"] %s\n", suffix);
1164 Com_Printf(
"\nAvailable options:\n");
1166 if (opt->sh[1] ==
':') {
1168 opt->lo,
"=<", opt->sh + 2,
">", NULL);
1170 Q_strlcpy(buffer, opt->lo,
sizeof(buffer));
1172 Com_Printf(
"-%c | --%-16.16s | %s\n", opt->sh[0], buffer, opt->help);
1180 Com_Printf(
"Try '%s --help' for more information.\n",
cmd_argv[0]);
1183 void Cmd_Option_c(
const cmd_option_t *opt, xgenerator_t g, genctx_t *ctx,
int argnum)
1185 if (ctx->partial[0] ==
'-') {
1186 for (; opt->sh; opt++) {
1187 if (ctx->count >= ctx->size) {
1190 if (ctx->partial[1] ==
'-') {
1191 if (!strncmp(opt->lo, ctx->partial + 2, ctx->length - 2)) {
1192 ctx->matches[ctx->count++] = Z_CopyString(
va(
"--%s", opt->lo));
1194 }
else if (!ctx->partial[1] || opt->sh[0] == ctx->partial[1]) {
1195 ctx->matches[ctx->count++] = Z_CopyString(
va(
"-%c", opt->sh[0]));
1206 }
else if (!ctx->partial[0] && ctx->count < ctx->size) {
1207 ctx->matches[ctx->count++] = Z_CopyString(
"-");
1224 static char expanded[MAX_STRING_CHARS];
1225 char temporary[MAX_STRING_CHARS];
1226 char buffer[MAX_STRING_CHARS];
1233 if (len >= MAX_STRING_CHARS) {
1234 Com_Printf(
"Line exceeded %i chars, discarded.\n", MAX_STRING_CHARS);
1238 scan = memcpy(expanded, text, len + 1);
1243 for (i = 0; i < len; i++) {
1247 if (scan[i] ==
'"') {
1253 if (scan[i] !=
'$') {
1258 start = scan + i + 1;
1265 if (*start ==
'$') {
1266 memmove(scan + i, start, len - i);
1271 while (*start && *start <= 32) {
1277 if (*start ==
'{') {
1280 if (*start ==
'$') {
1284 if (*start ==
'}') {
1288 *token++ = *start++;
1292 while (*start > 32) {
1293 if (*start ==
'$') {
1297 *token++ = *start++;
1303 if (token == temporary) {
1311 if (!strcmp(temporary,
"@")) {
1318 arg1 = strtoul(temporary, &s, 10);
1321 arg2 = strtoul(s + 1, &s, 10);
1329 }
else if (s[0] == 0) {
1339 macro->function(buffer, MAX_STRING_CHARS - len);
1344 if (var && !(var->flags & CVAR_PRIVATE)) {
1345 token = var->string;
1347 }
else if (!strcmp(temporary,
"qt")) {
1349 }
else if (!strcmp(temporary,
"sc")) {
1359 if (len >= MAX_STRING_CHARS) {
1360 Com_Printf(
"Expanded line exceeded %i chars, discarded.\n",
1362 Com_Printf(
"was %s\n", text);
1366 strncpy(temporary, scan, i);
1367 strcpy(temporary + i, token);
1368 strcpy(temporary + i + j, start);
1370 strcpy(expanded, temporary);
1377 if (++count == 100) {
1378 Com_Printf(
"Macro expansion loop, discarded.\n");
1384 Com_Printf(
"Line has unmatched quote, discarded.\n");
1402 char *data, *start, *dest;
1431 Com_Printf(
"Line exceeded %i chars, discarded.\n", MAX_STRING_CHARS);
1447 while (
cmd_argc < MAX_STRING_TOKENS) {
1449 while (*data <=
' ') {
1453 if (*data ==
'\n') {
1472 if (*data ==
'\"') {
1474 while (*data !=
'\"') {
1486 while (*data >
' ') {
1487 if (*data ==
'\"') {
1515 if (!strcmp(cmd->
name, name)) {
1530 Com_WPrintf(
"%s: %s already defined as a cvar\n", __func__, reg->name);
1538 Com_WPrintf(
"%s: %s already defined\n", __func__, reg->name);
1547 cmd->
name = (
char *)reg->name;
1567 reg.function =
function;
1568 reg.completer = NULL;
1599 Com_DPrintf(
"%s: %s not added\n", __func__, name);
1617 return cmd ? qtrue : qfalse;
1658 Com_Printf(
"Can't \"%s\", not connected\n",
cmd_argv[0]);
1666 if (buf->aliasCount >= ALIAS_LOOP_COUNT) {
1667 Com_WPrintf(
"Runaway alias loop\n");
1687 Com_Printf(
"Unknown command \"%s\"\n",
cmd_argv[0]);
1717 len =
FS_LoadFileEx(path, (
void **)&f, flags, TAG_FILESYSTEM);
1723 if (memchr(f, 0, len)) {
1724 ret = Q_ERR_INVALID_FORMAT;
1730 if (len > CMD_BUFFER_SIZE) {
1740 if (++buf->aliasCount > ALIAS_LOOP_COUNT) {
1741 ret = Q_ERR_RUNAWAY_LOOP;
1746 if (buf->cursize + len + 1 > buf->maxsize) {
1747 ret = Q_ERR_STRING_TRUNCATED;
1752 Com_Printf(
"Execing %s\n", path);
1754 ret = Q_ERR_SUCCESS;
1768 char buffer[MAX_QPATH];
1773 Com_Printf(
"%s <filename> : execute a script file\n",
Cmd_Argv(0));
1778 if (len >=
sizeof(buffer)) {
1779 Q_PrintError(
"exec", Q_ERR_NAMETOOLONG);
1784 Q_PrintError(
"exec", Q_ERR_NAMETOOSHORT);
1789 if (ret == Q_ERR_NOENT && COM_CompareExtension(buffer,
".cfg")) {
1791 len =
Q_strlcat(buffer,
".cfg",
sizeof(buffer));
1792 if (len >=
sizeof(buffer)) {
1793 Q_PrintError(
"exec", Q_ERR_NAMETOOLONG);
1801 Com_Printf(
"Couldn't exec %s: %s\n", buffer,
Q_ErrorString(ret));
1807 FS_File_g(NULL,
"*.cfg", FS_SEARCH_SAVEPATH | FS_SEARCH_BYFILTER | FS_SEARCH_STRIPEXT, ctx);
1830 {
"h",
"help",
"display this message" },
1831 {
"e",
"escapes",
"enable interpretation of backslash escapes" },
1832 {
"c:color",
"color",
"print text in this color" },
1833 {
"n",
"no-newline",
"do not output the trailing newline" },
1848 if (src[0] ==
'\\' && src[1]) {
1850 case 'a': *p++ =
'\a';
break;
1851 case 'b': *p++ =
'\b';
break;
1852 case 't': *p++ =
'\t';
break;
1853 case 'n': *p++ =
'\n';
break;
1854 case 'v': *p++ =
'\v';
break;
1855 case 'f': *p++ =
'\f';
break;
1856 case 'r': *p++ =
'\r';
break;
1857 case '\\': *p++ =
'\\';
break;
1859 if ((c1 = Q_charhex(src[2])) == -1) {
1862 if ((c2 = Q_charhex(src[3])) == -1) {
1865 *p++ = (c1 << 4) | c2;
1884 char buffer[MAX_STRING_CHARS], *s;
1885 qboolean escapes = qfalse;
1886 color_index_t
color = COLOR_NONE;
1887 const char *newline =
"\n";
1894 Com_Printf(
"Print a line of text into the console.\n");
1917 Com_Printf(
"%s%s", s, newline);
1930 char *filter = NULL;
1939 if (filter && !Com_WildCmp(filter, cmd->
name)) {
1942 Com_Printf(
"%s\n", cmd->
name);
1945 Com_Printf(
"%i of %i commands\n", i, total);
1957 char *filter = NULL;
1958 char buffer[MAX_QPATH];
1965 for (macro =
cmd_macros, total = 0; macro; macro = macro->next, total++) {
1966 if (filter && !Com_WildCmp(filter, macro->name)) {
1969 macro->function(buffer,
sizeof(buffer));
1970 Com_Printf(
"%-16s %s\n", macro->name, buffer);
1973 Com_Printf(
"%i of %i macros\n", i, total);
1990 Com_Printf(
"Usage: %s <command>",
cmd_argv[0]);
1998 Com_Printf(
"%s is already defined as a cvar\n", name);
2009 len = strlen(name) + 1;
2011 cmd->
name = (
char *)(cmd + 1);
2012 memcpy(cmd->
name, name, len);
color_index_t Com_ParseColor(const char *s, color_index_t last)
void Cmd_Alias_g(genctx_t *ctx)
static size_t cmd_string_len
size_t Q_strlcat(char *dst, const char *src, size_t size)
static const cmdreg_t c_cmd[]
qboolean COM_IsFloat(const char *s)
size_t Cmd_WhiteSpaceTail(void)
qerror_t Cmd_ExecuteFile(const char *path, unsigned flags)
static void Cmd_Trigger_f(void)
xcompleter_t Cmd_FindCompleter(const char *name)
void Cmd_AddCommand(const char *name, xcommand_t function)
qboolean CL_ForwardToServer(void)
void Cmd_Command_g(genctx_t *ctx)
struct cmdalias_s cmdalias_t
static void Cmd_Wait_f(void)
const char * Q_ErrorString(qerror_t error)
unsigned Com_HashString(const char *s, unsigned size)
qboolean Cmd_Exists(const char *name)
static void Cmd_UnAlias_c(genctx_t *ctx, int argnum)
void Cmd_ExecTrigger(const char *string)
void Cmd_ExecuteString(cmdbuf_t *buf, const char *text)
ssize_t FS_FPrintf(qhandle_t f, const char *format,...)
void Cmd_Config_g(genctx_t *ctx)
static void list_triggers(void)
void Cmd_PrintUsage(const cmd_option_t *opt, const char *suffix)
struct cmd_function_s cmd_function_t
static char cmd_string[MAX_STRING_CHARS]
static char * cmd_argv[MAX_STRING_TOKENS]
#define FOR_EACH_TRIGGER_SAFE(trig, next)
void Cbuf_InsertText(cmdbuf_t *buf, const char *text)
void Cmd_TokenizeString(const char *text, qboolean macroExpand)
static cmdalias_t * Cmd_AliasFind(const char *name)
size_t Cmd_ArgsBuffer(char *buffer, size_t size)
char * Cmd_RawArgsFrom(int from)
void Cmd_Deregister(const cmdreg_t *reg)
static void Cmd_MacroList_f(void)
qboolean Prompt_AddMatch(genctx_t *ctx, const char *s)
static void Cmd_If_f(void)
void Cmd_ExecuteCommand(cmdbuf_t *buf)
qboolean Cvar_Exists(const char *var_name, qboolean weak)
void Com_Generic_c(genctx_t *ctx, int argnum)
#define FOR_EACH_TRIGGER(trig)
size_t FS_NormalizePathBuffer(char *out, const char *in, size_t size)
char * Cmd_ArgsFrom(int from)
void Cmd_RemoveCommand(const char *name)
static size_t cmd_offsets[MAX_STRING_TOKENS]
static void Cmd_EchoEx_c(genctx_t *ctx, int argnum)
static void Cmd_Complete_f(void)
static void Cmd_UnTrigger_f(void)
static list_t cmd_aliasHash[ALIAS_HASH_SIZE]
static void Cmd_List_f(void)
int Cmd_ParseOptions(const cmd_option_t *opt)
#define FOR_EACH_ALIAS_HASH(alias, hash)
static char cmd_args[MAX_STRING_CHARS]
static cmd_function_t * Cmd_Find(const char *name)
static cmd_trigger_t * find_trigger(const char *command, const char *match)
char * Cmd_MacroExpandString(const char *text, qboolean aliasHack)
void Cbuf_AddText(cmdbuf_t *buf, const char *text)
char * va(const char *format,...)
void FS_File_g(const char *path, const char *ext, unsigned flags, genctx_t *ctx)
static void Cmd_Exec_c(genctx_t *ctx, int argnum)
void Cmd_Register(const cmdreg_t *reg)
static const cmd_option_t o_echo[]
static list_t cmd_hash[CMD_HASH_SIZE]
static void Cmd_Text_f(void)
char * Cbuf_Alloc(cmdbuf_t *buf, size_t len)
static cmd_macro_t * cmd_macros
#define FOR_EACH_ALIAS(alias)
size_t Q_strlcpy(char *dst, const char *src, size_t size)
size_t COM_Compress(char *data)
static char cmd_data[MAX_STRING_CHARS]
static char * cmd_null_string
char * Cmd_AliasCommand(const char *name)
static char * unescape_string(char *dst, const char *src)
static void Cmd_UnAlias_f(void)
void Cmd_Macro_g(genctx_t *ctx)
static list_t cmd_triggers
static void Cmd_EchoEx_f(void)
static cmd_macro_t * cmd_macroHash[MACRO_HASH_SIZE]
static char * Cmd_ArgsRange(int from, int to)
#define FOR_EACH_CMD_HASH(cmd, hash)
int Cmd_FindArgForOffset(size_t offset)
void Cvar_Command(cvar_t *v)
static void Cmd_RegCommand(const cmdreg_t *reg)
static void Cmd_Echo_f(void)
void Cmd_AliasSet(const char *name, const char *cmd)
void Com_SetColor(color_index_t color)
void Cbuf_Execute(cmdbuf_t *buf)
size_t Cmd_ArgvBuffer(int arg, char *buffer, size_t size)
void Cmd_PrintHelp(const cmd_option_t *opt)
void Cmd_Option_c(const cmd_option_t *opt, xgenerator_t g, genctx_t *ctx, int argnum)
void Cmd_AddMacro(const char *name, xmacro_t function)
cvar_t * Cvar_FindVar(const char *var_name)
static void Cmd_Alias_c(genctx_t *ctx, int argnum)
size_t Q_concat(char *dest, size_t size,...)
static void Cmd_Exec_f(void)
#define FOR_EACH_CMD(cmd)
cmd_macro_t * Cmd_FindMacro(const char *name)
ssize_t FS_LoadFileEx(const char *path, void **buffer, unsigned flags, memtag_t tag)
char * Cmd_RawString(void)
static list_t cmd_functions
xcommand_t Cmd_FindFunction(const char *name)
#define Cmd_CopyString(string)
size_t Cmd_ArgOffset(int arg)
char cmd_buffer_text[CMD_BUFFER_SIZE]
static void Cmd_OpenURL_f(void)
static size_t cmd_string_tail