X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=cmd.c;h=391b0c7b0a4eed5cfd4a169536d6f5e8179b2778;hb=e36b2f6c58b8a8c736c10e0133108acd9bc3a630;hp=5d9b0a892a3689265a63f3f21272c58eeb15748d;hpb=ac029734277dab95241936ad14aee465e8ee70c9;p=xonotic%2Fdarkplaces.git diff --git a/cmd.c b/cmd.c index 5d9b0a89..391b0c7b 100644 --- a/cmd.c +++ b/cmd.c @@ -25,7 +25,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // this is the largest script file that can be executed in one step // LordHavoc: inreased this from 8192 to 32768 // div0: increased this from 32k to 128k -#define CMDBUFSIZE 131072 +// div0: increased this from 128k to 640k which ought to be enough for anyone +#define CMDBUFSIZE 655360 // maximum number of parameters to a command #define MAX_ARGS 80 // maximum tokenizable commandline length (counting NUL terminations) @@ -70,7 +71,7 @@ typedef struct cmddeferred_s double time; } cmddeferred_t; -static cmddeferred_t *cmd_deferred_list; +static cmddeferred_t *cmd_deferred_list = NULL; /* ============ @@ -89,25 +90,44 @@ static void Cmd_Defer_f (void) Con_Printf("No commands are pending.\n"); while(next) { - Con_Printf("-> In %'9.2f: %s\n", next->time-time, next->value); + Con_Printf("-> In %9.2f: %s\n", next->time-time, next->value); next = next->next; } - } else if(Cmd_Argc() != 3) + } else if(Cmd_Argc() == 2 && !strcasecmp("clear", Cmd_Argv(1))) + { + while(cmd_deferred_list) + { + cmddeferred_t *cmd = cmd_deferred_list; + cmd_deferred_list = cmd->next; + Mem_Free(cmd->value); + Mem_Free(cmd); + } + } else if(Cmd_Argc() == 3) { - Con_Printf("usage: defer \n"); - return; - } else { const char *value = Cmd_Argv(2); cmddeferred_t *defcmd = (cmddeferred_t*)Mem_Alloc(tempmempool, sizeof(*defcmd)); - unsigned int len = strlen(value); + size_t len = strlen(value); defcmd->time = Sys_DoubleTime() + atof(Cmd_Argv(1)); defcmd->value = (char*)Mem_Alloc(tempmempool, len+1); - memcpy(defcmd->value, value, len); - defcmd->value[len] = 0; + memcpy(defcmd->value, value, len+1); + defcmd->next = NULL; - defcmd->next = cmd_deferred_list; - cmd_deferred_list = defcmd; + if(cmd_deferred_list) + { + cmddeferred_t *next = cmd_deferred_list; + while(next->next) + next = next->next; + next->next = defcmd; + } else + cmd_deferred_list = defcmd; + /* Stupid me... this changes the order... so commands with the same delay go blub :S + defcmd->next = cmd_deferred_list; + cmd_deferred_list = defcmd;*/ + } else { + Con_Printf("usage: defer \n" + " defer clear\n"); + return; } } @@ -240,18 +260,19 @@ void Cbuf_Execute_Deferred (void) if(cmd->time <= time) { Cbuf_AddText(cmd->value); + Cbuf_AddText(";\n"); Mem_Free(cmd->value); - - if(prev) + + if(prev) { prev->next = cmd->next; - else + Mem_Free(cmd); + cmd = prev->next; + } else { cmd_deferred_list = cmd->next; - - Mem_Free(cmd); - - cmd = prev; - if(!cmd) - return; + Mem_Free(cmd); + cmd = cmd_deferred_list; + } + continue; } prev = cmd; cmd = cmd->next; @@ -271,7 +292,7 @@ void Cbuf_Execute (void) char line[MAX_INPUTLINE]; char preprocessed[MAX_INPUTLINE]; char *firstchar; - int quotes; + qboolean quotes, comment; // LordHavoc: making sure the tokenizebuffer doesn't get filled up by repeated crashes cmd_tokenizebufferpos = 0; @@ -282,17 +303,31 @@ void Cbuf_Execute (void) // find a \n or ; line break text = (char *)cmd_text.data; - quotes = 0; - for (i=0 ; i< cmd_text.cursize ; i++) + quotes = false; + comment = false; + for (i=0 ; i < cmd_text.cursize ; i++) { - if (text[i] == '"') - quotes ^= 1; - // make sure i doesn't get > cursize which causes a negative - // size in memmove, which is fatal --blub - if (i < (cmd_text.cursize-1) && (text[i] == '\\' && (text[i+1] == '"' || text[i+1] == '\\'))) - i++; - if ( !quotes && text[i] == ';') - break; // don't break if inside a quoted string + if(!comment) + { + if (text[i] == '"') + quotes = !quotes; + + if(quotes) + { + // make sure i doesn't get > cursize which causes a negative + // size in memmove, which is fatal --blub + if (i < (cmd_text.cursize-1) && (text[i] == '\\' && (text[i+1] == '"' || text[i+1] == '\\'))) + i++; + } + else + { + if(text[i] == '/' && text[i + 1] == '/' && (i == 0 || ISWHITESPACE(text[i-1]))) + comment = true; + if(text[i] == ';') + break; // don't break if inside a quoted string or comment + } + } + if (text[i] == '\r' || text[i] == '\n') break; } @@ -574,7 +609,7 @@ static void Cmd_Alias_f (void) { Con_Print("Current alias commands:\n"); for (a = cmd_alias ; a ; a=a->next) - Con_Printf("%s : %s\n", a->name, a->value); + Con_Printf("%s : %s", a->name, a->value); return; } @@ -625,6 +660,8 @@ static void Cmd_Alias_f (void) strlcat (cmd, "\n", sizeof (cmd)); alloclen = strlen (cmd) + 1; + if(alloclen >= 2) + cmd[alloclen - 2] = '\n'; // to make sure a newline is appended even if too long a->value = (char *)Z_Malloc (alloclen); memcpy (a->value, cmd, alloclen); } @@ -692,7 +729,7 @@ static const char *Cmd_GetDirectCvarValue(const char *varname, cmdalias_t *alias *is_multiple = true; // kill pre-argument whitespace - for (;*p && *p <= ' ';p++) + for (;*p && ISWHITESPACE(*p);p++) ; return p; @@ -806,7 +843,8 @@ static const char *Cmd_GetCvarValue(const char *var, size_t varlen, cmdalias_t * // Exception: $* and $n- don't use the quoted form by default varstr = Cmd_GetDirectCvarValue(varname, alias, &is_multiple); if(is_multiple) - varfunc = "asis"; + if(!varfunc) + varfunc = "asis"; } if(!varstr) @@ -838,7 +876,7 @@ static const char *Cmd_GetCvarValue(const char *var, size_t varlen, cmdalias_t * /* Cmd_PreprocessString -Preprocesses strings and replaces $*, $param#, $cvar accordingly +Preprocesses strings and replaces $*, $param#, $cvar accordingly. Also strips comments. */ static void Cmd_PreprocessString( const char *intext, char *outtext, unsigned maxoutlen, cmdalias_t *alias ) { const char *in; @@ -945,9 +983,9 @@ static void Cmd_PreprocessString( const char *intext, char *outtext, unsigned ma --eat; } } - } else { - outtext[outlen++] = *in++; } + else + outtext[outlen++] = *in++; } outtext[outlen] = 0; } @@ -987,12 +1025,14 @@ static void Cmd_List_f (void) { cmd_function_t *cmd; const char *partial; - int len, count; + size_t len; + int count; + qboolean ispattern; if (Cmd_Argc() > 1) { partial = Cmd_Argv (1); - len = (int)strlen(partial); + len = strlen(partial); } else { @@ -1000,21 +1040,84 @@ static void Cmd_List_f (void) len = 0; } + ispattern = partial && (strchr(partial, '*') || strchr(partial, '?')); + count = 0; for (cmd = cmd_functions; cmd; cmd = cmd->next) { - if (partial && strncmp(partial, cmd->name, len)) + if (partial && (ispattern ? !matchpattern_with_separator(cmd->name, partial, false, "", false) : strncmp(partial, cmd->name, len))) continue; Con_Printf("%s : %s\n", cmd->name, cmd->description); count++; } - if (partial) - Con_Printf("%i Command%s beginning with \"%s\"\n\n", count, (count > 1) ? "s" : "", partial); + if (len) + { + if(ispattern) + Con_Printf("%i Command%s matching \"%s\"\n\n", count, (count > 1) ? "s" : "", partial); + else + Con_Printf("%i Command%s beginning with \"%s\"\n\n", count, (count > 1) ? "s" : "", partial); + } else Con_Printf("%i Command%s\n\n", count, (count > 1) ? "s" : ""); } +static void Cmd_Apropos_f(void) +{ + cmd_function_t *cmd; + cvar_t *cvar; + cmdalias_t *alias; + const char *partial; + size_t len; + int count; + qboolean ispattern; + + if (Cmd_Argc() > 1) + { + partial = Cmd_Args(); + len = strlen(partial); + } + else + { + Con_Printf("usage: apropos \n"); + return; + } + + ispattern = partial && (strchr(partial, '*') || strchr(partial, '?')); + if(!ispattern) + { + partial = va("*%s*", partial); + len += 2; + } + + count = 0; + for (cvar = cvar_vars; cvar; cvar = cvar->next) + { + if (!matchpattern_with_separator(cvar->name, partial, true, "", false)) + if (!matchpattern_with_separator(cvar->description, partial, true, "", false)) + continue; + Con_Printf ("cvar ^3%s^7 is \"%s\" [\"%s\"] %s\n", cvar->name, cvar->string, cvar->defstring, cvar->description); + count++; + } + for (cmd = cmd_functions; cmd; cmd = cmd->next) + { + if (!matchpattern_with_separator(cmd->name, partial, true, "", false)) + if (!matchpattern_with_separator(cmd->description, partial, true, "", false)) + continue; + Con_Printf("command ^2%s^7: %s\n", cmd->name, cmd->description); + count++; + } + for (alias = cmd_alias; alias; alias = alias->next) + { + if (!matchpattern_with_separator(alias->name, partial, true, "", false)) + if (!matchpattern_with_separator(alias->value, partial, true, "", false)) + continue; + Con_Printf("alias ^5%s^7: %s", alias->name, alias->value); + count++; + } + Con_Printf("%i result%s\n\n", count, (count > 1) ? "s" : ""); +} + /* ============ Cmd_Init @@ -1037,16 +1140,20 @@ void Cmd_Init_Commands (void) Cmd_AddCommand ("stuffcmds",Cmd_StuffCmds_f, "execute commandline parameters (must be present in quake.rc script)"); Cmd_AddCommand ("exec",Cmd_Exec_f, "execute a script file"); Cmd_AddCommand ("echo",Cmd_Echo_f, "print a message to the console (useful in scripts)"); - Cmd_AddCommand ("alias",Cmd_Alias_f, "create a script function (parameters are passed in as $1 through $9, and $* for all parameters)"); + Cmd_AddCommand ("alias",Cmd_Alias_f, "create a script function (parameters are passed in as $X (being X a number), $* for all parameters, $X- for all parameters starting from $X). Without arguments show the list of all alias"); Cmd_AddCommand ("cmd", Cmd_ForwardToServer, "send a console commandline to the server (used by some mods)"); Cmd_AddCommand ("wait", Cmd_Wait_f, "make script execution wait for next rendered frame"); Cmd_AddCommand ("set", Cvar_Set_f, "create or change the value of a console variable"); Cmd_AddCommand ("seta", Cvar_SetA_f, "create or change the value of a console variable that will be saved to config.cfg"); +#ifdef FILLALLCVARSWITHRUBBISH + Cmd_AddCommand ("fillallcvarswithrubbish", Cvar_FillAll_f, "fill all cvars with a specified number of characters to provoke buffer overruns"); +#endif /* FILLALLCVARSWITHRUBBISH */ // 2000-01-09 CmdList, CvarList commands By Matthias "Maddes" Buecher // Added/Modified by EvilTypeGuy eviltypeguy@qeradiant.com Cmd_AddCommand ("cmdlist", Cmd_List_f, "lists all console commands beginning with the specified prefix"); Cmd_AddCommand ("cvarlist", Cvar_List_f, "lists all console variables beginning with the specified prefix"); + Cmd_AddCommand ("apropos", Cmd_Apropos_f, "lists all console variables/commands/aliases containing the specified string in the name or description"); Cmd_AddCommand ("cvar_lockdefaults", Cvar_LockDefaults_f, "stores the current values of all cvars into their default values, only used once during startup after parsing default.cfg"); Cmd_AddCommand ("cvar_resettodefaults_all", Cvar_ResetToDefaults_All_f, "sets all cvars to their locked default values"); @@ -1122,7 +1229,7 @@ static void Cmd_TokenizeString (const char *text) while (1) { // skip whitespace up to a /n - while (*text && *text <= ' ' && *text != '\r' && *text != '\n') + while (*text && ISWHITESPACE(*text) && *text != '\r' && *text != '\n') text++; // line endings: @@ -1329,7 +1436,7 @@ void Cmd_CompleteCommandPrint (const char *partial) // Loop through the command list and print all matches for (cmd = cmd_functions; cmd; cmd = cmd->next) if (!strncasecmp(partial, cmd->name, len)) - Con_Printf("%s : %s\n", cmd->name, cmd->description); + Con_Printf("^2%s^7: %s\n", cmd->name, cmd->description); } /* @@ -1367,7 +1474,7 @@ void Cmd_CompleteAliasPrint (const char *partial) // Loop through the alias list and print all matches for (alias = cmd_alias; alias; alias = alias->next) if (!strncasecmp(partial, alias->name, len)) - Con_Printf("%s : %s\n", alias->name, alias->value); + Con_Printf("^5%s^7: %s", alias->name, alias->value); } @@ -1448,11 +1555,13 @@ FIXME: lookupnoadd the token to speed search? void Cmd_ExecuteString (const char *text, cmd_source_t src) { int oldpos; + int found; cmd_function_t *cmd; cmdalias_t *a; oldpos = cmd_tokenizebufferpos; cmd_source = src; + found = false; Cmd_TokenizeString (text); @@ -1487,8 +1596,9 @@ void Cmd_ExecuteString (const char *text, cmd_source_t src) } else Con_Printf("Command \"%s\" can not be executed\n", Cmd_Argv(0)); - cmd_tokenizebufferpos = oldpos; - return; + found = true; + goto command_found; + break; case src_client: if (cmd->clientfunction) { @@ -1501,11 +1611,13 @@ void Cmd_ExecuteString (const char *text, cmd_source_t src) break; } } +command_found: // if it's a client command and no command was found, say so. if (cmd_source == src_client) { Con_Printf("player \"%s\" tried to %s\n", host_client->name, text); + cmd_tokenizebufferpos = oldpos; return; } @@ -1520,6 +1632,12 @@ void Cmd_ExecuteString (const char *text, cmd_source_t src) } } + if(found) // if the command was hooked and found, all is good + { + cmd_tokenizebufferpos = oldpos; + return; + } + // check cvars if (!Cvar_Command () && host_framecount > 0) Con_Printf("Unknown command \"%s\"\n", Cmd_Argv(0));