Added a mempool parameter to FS_LoadFile
[xonotic/darkplaces.git] / cmd.c
diff --git a/cmd.c b/cmd.c
index d46db84..acba139 100644 (file)
--- a/cmd.c
+++ b/cmd.c
@@ -25,9 +25,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 typedef struct cmdalias_s
 {
-       struct cmdalias_s       *next;
-       char    name[MAX_ALIAS_NAME];
-       char    *value;
+       struct cmdalias_s *next;
+       char name[MAX_ALIAS_NAME];
+       char *value;
 } cmdalias_t;
 
 static cmdalias_t *cmd_alias;
@@ -36,6 +36,10 @@ static qboolean cmd_wait;
 
 static mempool_t *cmd_mempool;
 
+#define CMD_TOKENIZELENGTH 4096
+static char cmd_tokenizebuffer[CMD_TOKENIZELENGTH];
+static int cmd_tokenizebufferpos = 0;
+
 //=============================================================================
 
 /*
@@ -81,7 +85,7 @@ Cbuf_AddText
 Adds command text at the end of the buffer
 ============
 */
-void Cbuf_AddText (char *text)
+void Cbuf_AddText (const char *text)
 {
        int             l;
 
@@ -89,7 +93,7 @@ void Cbuf_AddText (char *text)
 
        if (cmd_text.cursize + l >= cmd_text.maxsize)
        {
-               Con_Print("Cbuf_AddText: overflow\n");
+               Con_Print("Cbuf_AddText: overflow\n");
                return;
        }
 
@@ -106,7 +110,7 @@ Adds a \n to the text
 FIXME: actually change the command buffer to do less copying
 ============
 */
-void Cbuf_InsertText (char *text)
+void Cbuf_InsertText (const char *text)
 {
        char    *temp;
        int             templen;
@@ -140,10 +144,13 @@ Cbuf_Execute
 */
 void Cbuf_Execute (void)
 {
-       int             i;
-       char    *text;
-       char    line[1024];
-       int             quotes;
+       int i;
+       char *text;
+       char line[1024];
+       int quotes;
+
+       // LordHavoc: making sure the tokenizebuffer doesn't get filled up by repeated crashes
+       cmd_tokenizebufferpos = 0;
 
        while (cmd_text.cursize)
        {
@@ -157,7 +164,7 @@ void Cbuf_Execute (void)
                                quotes++;
                        if ( !(quotes&1) &&  text[i] == ';')
                                break;  // don't break if inside a quoted string
-                       if (text[i] == '\n')
+                       if (text[i] == '\r' || text[i] == '\n')
                                break;
                }
 
@@ -174,7 +181,7 @@ void Cbuf_Execute (void)
                {
                        i++;
                        cmd_text.cursize -= i;
-                       memcpy (text, text+i, cmd_text.cursize);
+                       memcpy (cmd_text.data, text+i, cmd_text.cursize);
                }
 
 // execute the command line
@@ -215,7 +222,7 @@ void Cmd_StuffCmds_f (void)
 
        if (Cmd_Argc () != 1)
        {
-               Con_Print("stuffcmds : execute command line parameters\n");
+               Con_Print("stuffcmds : execute command line parameters\n");
                return;
        }
 
@@ -279,21 +286,21 @@ Cmd_Exec_f
 */
 static void Cmd_Exec_f (void)
 {
-       char    *f;
+       char *f;
 
        if (Cmd_Argc () != 2)
        {
-               Con_Print("exec <filename> : execute a script file\n");
+               Con_Print("exec <filename> : execute a script file\n");
                return;
        }
 
-       f = (char *)COM_LoadFile (Cmd_Argv(1), false);
+       f = (char *)FS_LoadFile (Cmd_Argv(1), tempmempool, false);
        if (!f)
        {
-               Con_Printf ("couldn't exec %s\n",Cmd_Argv(1));
+               Con_Printf("couldn't exec %s\n",Cmd_Argv(1));
                return;
        }
-       Con_Printf ("execing %s\n",Cmd_Argv(1));
+       Con_DPrintf("execing %s\n",Cmd_Argv(1));
 
        Cbuf_InsertText (f);
        Mem_Free(f);
@@ -312,8 +319,8 @@ static void Cmd_Echo_f (void)
        int             i;
 
        for (i=1 ; i<Cmd_Argc() ; i++)
-               Con_Printf ("%s ",Cmd_Argv(i));
-       Con_Print("\n");
+               Con_Printf("%s ",Cmd_Argv(i));
+       Con_Print("\n");
 }
 
 /*
@@ -323,10 +330,9 @@ Cmd_Alias_f
 Creates a new command that executes a command string (possibly ; seperated)
 ===============
 */
-
 static char *CopyString (char *in)
 {
-       char    *out;
+       char *out;
 
        out = Z_Malloc (strlen(in)+1);
        strcpy (out, in);
@@ -338,20 +344,20 @@ static void Cmd_Alias_f (void)
        cmdalias_t      *a;
        char            cmd[1024];
        int                     i, c;
-       char            *s;
+       const char              *s;
 
        if (Cmd_Argc() == 1)
        {
-               Con_Print("Current alias commands:\n");
+               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\n", a->name, a->value);
                return;
        }
 
        s = Cmd_Argv(1);
        if (strlen(s) >= MAX_ALIAS_NAME)
        {
-               Con_Print("Alias name is too long\n");
+               Con_Print("Alias name is too long\n");
                return;
        }
 
@@ -371,18 +377,18 @@ static void Cmd_Alias_f (void)
                a->next = cmd_alias;
                cmd_alias = a;
        }
-       strcpy (a->name, s);
+       strlcpy (a->name, s, sizeof (a->name));
 
 // copy the rest of the command line
        cmd[0] = 0;             // start out with a null string
        c = Cmd_Argc();
        for (i=2 ; i< c ; i++)
        {
-               strcat (cmd, Cmd_Argv(i));
+               strlcat (cmd, Cmd_Argv(i), sizeof (cmd));
                if (i != c)
-                       strcat (cmd, " ");
+                       strlcat (cmd, " ", sizeof (cmd));
        }
-       strcat (cmd, "\n");
+       strlcat (cmd, "\n", sizeof (cmd));
 
        a->value = CopyString (cmd);
 }
@@ -397,18 +403,18 @@ static void Cmd_Alias_f (void)
 
 typedef struct cmd_function_s
 {
-       struct cmd_function_s   *next;
-       char                                    *name;
-       xcommand_t                              function;
+       struct cmd_function_s *next;
+       const char *name;
+       xcommand_t function;
 } cmd_function_t;
 
 
 #define        MAX_ARGS                80
 
 static int cmd_argc;
-static char *cmd_argv[MAX_ARGS];
-static char *cmd_null_string = "";
-static char *cmd_args = NULL;
+static const char *cmd_argv[MAX_ARGS];
+static const char *cmd_null_string = "";
+static const char *cmd_args = NULL;
 
 cmd_source_t cmd_source;
 
@@ -426,32 +432,35 @@ Cmd_List
 */
 static void Cmd_List_f (void)
 {
-       cmd_function_t  *cmd;
-       char                    *partial;
-       int                             len;
-       int                             count;
+       cmd_function_t *cmd;
+       const char *partial;
+       int len, count;
 
-       if (Cmd_Argc() > 1) {
+       if (Cmd_Argc() > 1)
+       {
                partial = Cmd_Argv (1);
                len = strlen(partial);
-       } else {
+       }
+       else
+       {
                partial = NULL;
                len = 0;
        }
 
        count = 0;
-       for (cmd = cmd_functions; cmd; cmd = cmd->next) {
+       for (cmd = cmd_functions; cmd; cmd = cmd->next)
+       {
                if (partial && strncmp(partial, cmd->name, len))
                        continue;
-               Con_Printf ("%s\n", cmd->name);
+               Con_Printf("%s\n", cmd->name);
                count++;
        }
 
-       Con_Printf ("%i Command%s", count, (count > 1) ? "s" : "");
+       Con_Printf("%i Command%s", count, (count > 1) ? "s" : "");
        if (partial)
                Con_Printf(" beginning with \"%s\"", partial);
 
-       Con_Print("\n\n");
+       Con_Print("\n\n");
 }
 
 /*
@@ -492,7 +501,7 @@ int         Cmd_Argc (void)
 Cmd_Argv
 ============
 */
-char   *Cmd_Argv (int arg)
+const char *Cmd_Argv (int arg)
 {
        if (arg >= cmd_argc )
                return cmd_null_string;
@@ -504,15 +513,12 @@ char      *Cmd_Argv (int arg)
 Cmd_Args
 ============
 */
-char   *Cmd_Args (void)
+const char *Cmd_Args (void)
 {
        return cmd_args;
 }
 
 
-#define CMD_TOKENIZELENGTH 4096
-char cmd_tokenizebuffer[CMD_TOKENIZELENGTH];
-
 /*
 ============
 Cmd_TokenizeString
@@ -520,25 +526,22 @@ Cmd_TokenizeString
 Parses the given string into command line tokens.
 ============
 */
-static void Cmd_TokenizeString (char *text)
+static void Cmd_TokenizeString (const char *text)
 {
        int l;
-       int pos;
-       pos = 0;
 
        cmd_argc = 0;
        cmd_args = NULL;
 
        while (1)
        {
-// skip whitespace up to a /n
+               // skip whitespace up to a /n
                while (*text && *text <= ' ' && *text != '\n')
-               {
                        text++;
-               }
 
                if (*text == '\n')
-               {       // a newline seperates commands in the buffer
+               {
+                       // a newline seperates commands in the buffer
                        text++;
                        break;
                }
@@ -549,18 +552,17 @@ static void Cmd_TokenizeString (char *text)
                if (cmd_argc == 1)
                         cmd_args = text;
 
-               text = COM_Parse (text);
-               if (!text)
+               if (!COM_ParseTokenConsole(&text))
                        return;
 
                if (cmd_argc < MAX_ARGS)
                {
                        l = strlen(com_token) + 1;
-                       if (pos + l > CMD_TOKENIZELENGTH)
+                       if (cmd_tokenizebufferpos + l > CMD_TOKENIZELENGTH)
                                Sys_Error("Cmd_TokenizeString: ran out of %i character buffer space for command arguements\n", CMD_TOKENIZELENGTH);
-                       cmd_argv[cmd_argc] = cmd_tokenizebuffer + pos;
-                       pos += l;
-                       strcpy (cmd_argv[cmd_argc], com_token);
+                       strcpy (cmd_tokenizebuffer + cmd_tokenizebufferpos, com_token);
+                       cmd_argv[cmd_argc] = cmd_tokenizebuffer + cmd_tokenizebufferpos;
+                       cmd_tokenizebufferpos += l;
                        cmd_argc++;
                }
        }
@@ -573,14 +575,14 @@ static void Cmd_TokenizeString (char *text)
 Cmd_AddCommand
 ============
 */
-void   Cmd_AddCommand (char *cmd_name, xcommand_t function)
+void Cmd_AddCommand (const char *cmd_name, xcommand_t function)
 {
-       cmd_function_t  *cmd;
+       cmd_function_t *cmd;
 
 // fail if the command is a variable name
        if (Cvar_VariableString(cmd_name)[0])
        {
-               Con_Printf ("Cmd_AddCommand: %s already defined as a var\n", cmd_name);
+               Con_Printf("Cmd_AddCommand: %s already defined as a var\n", cmd_name);
                return;
        }
 
@@ -589,7 +591,7 @@ void        Cmd_AddCommand (char *cmd_name, xcommand_t function)
        {
                if (!strcmp (cmd_name, cmd->name))
                {
-                       Con_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name);
+                       Con_Printf("Cmd_AddCommand: %s already defined\n", cmd_name);
                        return;
                }
        }
@@ -606,7 +608,7 @@ void        Cmd_AddCommand (char *cmd_name, xcommand_t function)
 Cmd_Exists
 ============
 */
-qboolean       Cmd_Exists (char *cmd_name)
+qboolean Cmd_Exists (const char *cmd_name)
 {
        cmd_function_t  *cmd;
 
@@ -623,10 +625,10 @@ qboolean  Cmd_Exists (char *cmd_name)
 Cmd_CompleteCommand
 ============
 */
-char *Cmd_CompleteCommand (char *partial)
+const char *Cmd_CompleteCommand (const char *partial)
 {
-       cmd_function_t  *cmd;
-       int                             len;
+       cmd_function_t *cmd;
+       int len;
 
        len = strlen(partial);
 
@@ -650,11 +652,10 @@ char *Cmd_CompleteCommand (char *partial)
        Thanks to taniwha
 
 */
-int Cmd_CompleteCountPossible (char *partial)
+int Cmd_CompleteCountPossible (const char *partial)
 {
-       cmd_function_t  *cmd;
-       int                             len;
-       int                             h;
+       cmd_function_t *cmd;
+       int len, h;
 
        h = 0;
        len = strlen(partial);
@@ -679,16 +680,16 @@ int Cmd_CompleteCountPossible (char *partial)
        Thanks to taniwha
 
 */
-char **Cmd_CompleteBuildList (char *partial)
+const char **Cmd_CompleteBuildList (const char *partial)
 {
-       cmd_function_t  *cmd;
-       int                             len = 0;
-       int                             bpos = 0;
-       int                             sizeofbuf = (Cmd_CompleteCountPossible (partial) + 1) * sizeof (char *);
-       char                    **buf;
+       cmd_function_t *cmd;
+       int len = 0;
+       int bpos = 0;
+       int sizeofbuf = (Cmd_CompleteCountPossible (partial) + 1) * sizeof (const char *);
+       const char **buf;
 
        len = strlen(partial);
-       buf = Mem_Alloc(tempmempool, sizeofbuf + sizeof (char *));
+       buf = Mem_Alloc(tempmempool, sizeofbuf + sizeof (const char *));
        // Loop through the alias list and print all matches
        for (cmd = cmd_functions; cmd; cmd = cmd->next)
                if (!strncasecmp(partial, cmd->name, len))
@@ -707,10 +708,10 @@ char **Cmd_CompleteBuildList (char *partial)
        Thanks to taniwha
 
 */
-char *Cmd_CompleteAlias (char * partial)
+const char *Cmd_CompleteAlias (const char *partial)
 {
-       cmdalias_t      *alias;
-       int                     len;
+       cmdalias_t *alias;
+       int len;
 
        len = strlen(partial);
 
@@ -734,7 +735,7 @@ char *Cmd_CompleteAlias (char * partial)
        Thanks to taniwha
 
 */
-int Cmd_CompleteAliasCountPossible (char *partial)
+int Cmd_CompleteAliasCountPossible (const char *partial)
 {
        cmdalias_t      *alias;
        int                     len;
@@ -764,16 +765,16 @@ int Cmd_CompleteAliasCountPossible (char *partial)
        Thanks to taniwha
 
 */
-char **Cmd_CompleteAliasBuildList (char *partial)
+const char **Cmd_CompleteAliasBuildList (const char *partial)
 {
-       cmdalias_t      *alias;
-       int                     len = 0;
-       int                     bpos = 0;
-       int                     sizeofbuf = (Cmd_CompleteAliasCountPossible (partial) + 1) * sizeof (char *);
-       char            **buf;
+       cmdalias_t *alias;
+       int len = 0;
+       int bpos = 0;
+       int sizeofbuf = (Cmd_CompleteAliasCountPossible (partial) + 1) * sizeof (const char *);
+       const char **buf;
 
        len = strlen(partial);
-       buf = Mem_Alloc(tempmempool, sizeofbuf + sizeof (char *));
+       buf = Mem_Alloc(tempmempool, sizeofbuf + sizeof (const char *));
        // Loop through the alias list and print all matches
        for (alias = cmd_alias; alias; alias = alias->next)
                if (!strncasecmp(partial, alias->name, len))
@@ -791,41 +792,56 @@ A complete command line has been parsed, so try to execute it
 FIXME: lookupnoadd the token to speed search?
 ============
 */
-void   Cmd_ExecuteString (char *text, cmd_source_t src)
+void Cmd_ExecuteString (const char *text, cmd_source_t src)
 {
-       cmd_function_t  *cmd;
-       cmdalias_t              *a;
+       int oldpos;
+       cmd_function_t *cmd;
+       cmdalias_t *a;
 
+       oldpos = cmd_tokenizebufferpos;
        cmd_source = src;
        Cmd_TokenizeString (text);
 
 // execute the command line
        if (!Cmd_Argc())
+       {
+               cmd_tokenizebufferpos = oldpos;
                return;         // no tokens
+       }
 
-// check functions
-       for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
+// check functions (only after host_initialized)
+       if (host_initialized || !strcasecmp(cmd_argv[0], "exec"))
        {
-               if (!Q_strcasecmp (cmd_argv[0],cmd->name))
+               for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
                {
-                       cmd->function ();
-                       return;
+                       if (!strcasecmp (cmd_argv[0],cmd->name))
+                       {
+                               cmd->function ();
+                               cmd_tokenizebufferpos = oldpos;
+                               return;
+                       }
                }
        }
 
-// check alias
-       for (a=cmd_alias ; a ; a=a->next)
+// check alias (only after host_initialized)
+       if (host_initialized)
        {
-               if (!Q_strcasecmp (cmd_argv[0], a->name))
+               for (a=cmd_alias ; a ; a=a->next)
                {
-                       Cbuf_InsertText (a->value);
-                       return;
+                       if (!strcasecmp (cmd_argv[0], a->name))
+                       {
+                               Cbuf_InsertText (a->value);
+                               cmd_tokenizebufferpos = oldpos;
+                               return;
+                       }
                }
        }
 
-// check cvars
-       if (!Cvar_Command ())
-               Con_Printf ("Unknown command \"%s\"\n", Cmd_Argv(0));
+// check cvars (always)
+       if (!Cvar_Command () && host_initialized)
+               Con_Printf("Unknown command \"%s\"\n", Cmd_Argv(0));
+
+       cmd_tokenizebufferpos = oldpos;
 }
 
 
@@ -838,25 +854,25 @@ Sends the entire command line over to the server
 */
 void Cmd_ForwardToServer (void)
 {
+       const char *s;
        if (cls.state != ca_connected)
        {
-               Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
+               Con_Printf("Can't \"%s\", not connected\n", Cmd_Argv(0));
                return;
        }
 
        if (cls.demoplayback)
                return;         // not really connected
 
-       MSG_WriteByte (&cls.message, clc_stringcmd);
-       if (Q_strcasecmp(Cmd_Argv(0), "cmd") != 0)
-       {
-               SZ_Print (&cls.message, Cmd_Argv(0));
-               SZ_Print (&cls.message, " ");
-       }
-       if (Cmd_Argc() > 1)
-               SZ_Print (&cls.message, Cmd_Args());
+       // LordHavoc: thanks to Fuh for bringing the pure evil of SZ_Print to my
+       // attention, it has been eradicated from here, its only (former) use in
+       // all of darkplaces.
+       if (strcasecmp(Cmd_Argv(0), "cmd") != 0)
+               s = va("%s %s", Cmd_Argv(0), Cmd_Argc() > 1 ? Cmd_Args() : "\n");
        else
-               SZ_Print (&cls.message, "\n");
+               s = Cmd_Argc() > 1 ? Cmd_Args() : "\n";
+       MSG_WriteByte(&cls.message, clc_stringcmd);
+       SZ_Write(&cls.message, s, strlen(s) + 1);
 }
 
 
@@ -869,7 +885,7 @@ where the given parameter apears, or 0 if not present
 ================
 */
 
-int Cmd_CheckParm (char *parm)
+int Cmd_CheckParm (const char *parm)
 {
        int i;
 
@@ -877,7 +893,7 @@ int Cmd_CheckParm (char *parm)
                Sys_Error ("Cmd_CheckParm: NULL");
 
        for (i = 1; i < Cmd_Argc (); i++)
-               if (!Q_strcasecmp (parm, Cmd_Argv (i)))
+               if (!strcasecmp (parm, Cmd_Argv (i)))
                        return i;
 
        return 0;