]> git.rm.cloudns.org Git - xonotic/darkplaces.git/commitdiff
(WIP) cmd: Keep writing to the same node if not terminated by \n, \r or ;
authorCloudwalk <cloudwalk009@gmail.com>
Fri, 7 Aug 2020 15:35:54 +0000 (11:35 -0400)
committerCloudwalk <cloudwalk009@gmail.com>
Fri, 7 Aug 2020 15:35:54 +0000 (11:35 -0400)
Major refactor as well.

All that's left to do now is to merge defer support into the same system

cmd.c
cmd.h

diff --git a/cmd.c b/cmd.c
index abeb6cc94864be25b494035bbcc79f13d4adc8f5..e7d6dacff0b10b74e859d12fa97bceeaff493b33 100644 (file)
--- a/cmd.c
+++ b/cmd.c
@@ -196,6 +196,13 @@ static cbuf_cmd_t *Cbuf_LinkInsert(cbuf_cmd_t *insert, cbuf_cmd_t *list)
        return insert;
 }
 
+static void Cbuf_LinkWrite(cmd_state_t *cmd, cbuf_cmd_t *node, const char *text, size_t size)
+{
+       strlcpy(&node->text[node->size], text, size + 1);
+       node->size += size;
+       node->source = cmd;
+}
+
 /*
 ============
 Cbuf_ParseText
@@ -206,21 +213,27 @@ for each individual command. Returns a
 pointer to the head.
 ============
 */
-
 static cbuf_cmd_t *Cbuf_ParseText(cmd_state_t *cmd, const char *text)
 {
        int i = 0;
        cbuf_t *cbuf = cmd->cbuf;
-       cbuf_cmd_t *start = NULL;
+       cbuf_cmd_t *head = NULL;
        cbuf_cmd_t *current = NULL;
-       cbuf_cmd_t *end = NULL;
        qboolean quotes = false;
        qboolean comment = false;
        qboolean escaped = false;
        qboolean mark = false;
+       qboolean noalloc;
        char *offset = NULL;
        size_t cmdsize = 0;
 
+       if(cbuf->pending)
+       {
+               // If not from the same interpreter, weird things could happen.
+               if(cbuf->start->source != cmd)
+                       cbuf->pending = false;
+       }
+
        /*
         * Allow escapes in quotes. Ignore newlines and
         * comments. Return NULL if input consists solely
@@ -228,58 +241,70 @@ static cbuf_cmd_t *Cbuf_ParseText(cmd_state_t *cmd, const char *text)
         */
        while(text[i])
        {
+               noalloc = cbuf->pending;
+
                switch (text[i])
                {
-                       case '"':
-                               if (!escaped)
-                                       quotes = !quotes;
-                               else
-                                       escaped = false;
-                               break;
-                       case '\\':
-                               if (!escaped && quotes)
-                                       escaped = true;
-                               else if (escaped)
-                                       escaped = false;
-                               break;
                        case '/':
                                if(!quotes && text[i+1] == '/' && (i == 0 || ISWHITESPACE(text[i-1])))
+                               {
                                        comment = true;
-                               if(offset)
+                                       cbuf->pending = false;
                                        mark = true;
+                               }
                                break;
                        case ';':
-                               if(offset && !quotes && !comment)
+                               if(!quotes && !comment)
+                               {
+                                       cbuf->pending = false;
                                        mark = true;
+                               }
                                break;
                        case '\r':
                        case '\n':
                                comment = false;
                                quotes = false;
-                               if(offset)
-                                       mark = true;
+                               cbuf->pending = false;
+                               mark = true;
                                break;
                        default:
-                               if (!comment)
+                               if(!comment)
                                {
+                                       switch(text[i])
+                                       {
+                                               case '"':
+                                                       if (!escaped)
+                                                               quotes = !quotes;
+                                                       else
+                                                               escaped = false;
+                                                       break;
+                                               case '\\':
+                                                       if (!escaped && quotes)
+                                                               escaped = true;
+                                                       else if (escaped)
+                                                               escaped = false;
+                                                       break;
+                                       }
+                                       // If there's no trailing newline, mark it as pending
+                                       if(!mark && text[i+1] == 0)
+                                       {
+                                               cbuf->pending = true;
+                                               mark = true;
+                                       }
+
                                        if(!offset)
+                                               // Allow i to run until the end of a comment
                                                offset = (char *)&text[i];
+                                       cmdsize++;
                                }
-                               break;
                }
 
-               // Got a valid command.
-               if(offset)
+               if(!current)
                {
-                       cmdsize++;
-
-                       // If there's no trailing newline, mark it as pending
-                       if(!mark && text[i+1] == 0)
-                               mark = true;
-
-                       if(mark)
+                       if(noalloc)
+                               current = cbuf->start;
+                       else if(offset)
                        {
-                               // Create a cyclic doubly linked list.
                                if(cbuf->free)
                                {
                                        current = cbuf->free;
@@ -292,40 +317,40 @@ static cbuf_cmd_t *Cbuf_ParseText(cmd_state_t *cmd, const char *text)
                                }
                                else
                                        current = (cbuf_cmd_t *)Z_Malloc(sizeof(cbuf_cmd_t));
+                       }
+               }
 
-                               if(!start)
+               // Create a cyclic doubly linked list.
+               if(mark)
+               {
+                       // Data write stage
+                       if(offset)
+                       {
+                               Cbuf_LinkWrite(cmd, current, offset, cmdsize);
+
+                               if(!noalloc)
                                {
-                                       start = current;
-                                       end = start;
+                                       // Link stage
+                                       current->prev = current->next = current;
+                                       if(!head)
+                                               head = current;
+                                       else
+                                               Cbuf_LinkAdd(current, head);
                                }
-
-                               // Data write stage
-                               current->size = cmdsize + 1;
-                               strlcpy(current->text, offset, current->size);
-                               current->source = cmd;
-
-                               // Link stage
-                               current->prev = end;
-                               end->next = current;
-                               end = current;
-                               end->next = start;
-                               start->prev = end;
-
-                               cbuf->size += current->size;
-
-                               // Reset stage
-                               current = NULL;
-                               offset = NULL;
-                               cmdsize = 0;
-                               escaped = false;
-                               mark = false;
                        }
-               }
 
+                       // Reset stage
+                       offset = NULL;
+                       escaped = false;
+                       cbuf->size += cmdsize;
+                       cmdsize = 0;
+                       mark = false;
+                       current = NULL;
+               }
                i++;
        }
 
-       return start;
+       return head;
 }
 
 /*
@@ -339,7 +364,7 @@ void Cbuf_AddText (cmd_state_t *cmd, const char *text)
 {
        size_t l = strlen(text);
        cbuf_t *cbuf = cmd->cbuf;
-       cbuf_cmd_t *add = NULL, *temp;
+       cbuf_cmd_t *add = NULL;
 
        Cbuf_Lock(cbuf);
 
@@ -371,7 +396,7 @@ FIXME: actually change the command buffer to do less copying
 void Cbuf_InsertText (cmd_state_t *cmd, const char *text)
 {
        cbuf_t *cbuf = cmd->cbuf;
-       cbuf_cmd_t *insert = NULL, *temp;
+       cbuf_cmd_t *insert = NULL;
        size_t l = strlen(text);
 
        Cbuf_Lock(cbuf);
@@ -443,12 +468,15 @@ Cbuf_Execute
 static qboolean Cmd_PreprocessString(cmd_state_t *cmd, const char *intext, char *outtext, unsigned maxoutlen, cmdalias_t *alias );
 void Cbuf_Execute (cbuf_t *cbuf)
 {
-       cbuf_cmd_t *current, *temp;
+       cbuf_cmd_t *current;
        char preprocessed[MAX_INPUTLINE];
        char *firstchar;
 
        // LadyHavoc: making sure the tokenizebuffer doesn't get filled up by repeated crashes
-       //current->tokenizebufferpos = 0;
+       cbuf->tokenizebufferpos = 0;
+
+       // Assume we're rolling with the current command-line.
+       cbuf->pending = false;
 
        while (cbuf->size)
        {
@@ -1624,6 +1652,8 @@ void Cmd_Init(void)
        cbuf_t *cbuf = (cbuf_t *)Z_Malloc(sizeof(cbuf_t));
        cbuf->maxsize = 655360;
        cbuf->lock = Thread_CreateMutex();
+       cbuf->pending = false;
+       cbuf->wait = false;
        host.cbuf = cbuf;
 
        for (cmd_iter = cmd_iter_all; cmd_iter->cmd; cmd_iter++)
@@ -1797,14 +1827,14 @@ static void Cmd_TokenizeString (cmd_state_t *cmd, const char *text)
                if (cmd->argc < MAX_ARGS)
                {
                        l = (int)strlen(com_token) + 1;
-                       if (cmd->tokenizebufferpos + l > CMD_TOKENIZELENGTH)
+                       if (cmd->cbuf->tokenizebufferpos + l > CMD_TOKENIZELENGTH)
                        {
                                Con_Printf("Cmd_TokenizeString: ran out of %i character buffer space for command arguments\n", CMD_TOKENIZELENGTH);
                                break;
                        }
-                       memcpy (cmd->tokenizebuffer + cmd->tokenizebufferpos, com_token, l);
-                       cmd->argv[cmd->argc] = cmd->tokenizebuffer + cmd->tokenizebufferpos;
-                       cmd->tokenizebufferpos += l;
+                       memcpy (cmd->cbuf->tokenizebuffer + cmd->cbuf->tokenizebufferpos, com_token, l);
+                       cmd->argv[cmd->argc] = cmd->cbuf->tokenizebuffer + cmd->cbuf->tokenizebufferpos;
+                       cmd->cbuf->tokenizebufferpos += l;
                        cmd->argc++;
                }
        }
@@ -2172,7 +2202,7 @@ void Cmd_ExecuteString (cmd_state_t *cmd, const char *text, cmd_source_t src, qb
        cmdalias_t *a;
        if (lockmutex)
                Cbuf_Lock(cmd->cbuf);
-       oldpos = cmd->tokenizebufferpos;
+       oldpos = cmd->cbuf->tokenizebufferpos;
        cmd->source = src;
 
        Cmd_TokenizeString (cmd, text);
@@ -2239,7 +2269,7 @@ void Cmd_ExecuteString (cmd_state_t *cmd, const char *text, cmd_source_t src, qb
        if (!Cvar_Command(cmd) && host.framecount > 0)
                Con_Printf("Unknown command \"%s\"\n", Cmd_Argv(cmd, 0));
 done:
-       cmd->tokenizebufferpos = oldpos;
+       cmd->cbuf->tokenizebufferpos = oldpos;
        if (lockmutex)
                Cbuf_Unlock(cmd->cbuf);
 }
diff --git a/cmd.h b/cmd.h
index 7190053010962ac3dbb5b8b3c99a92a65be7a016..ca4742445e487641296b7edf6fe12621738935f1 100644 (file)
--- a/cmd.h
+++ b/cmd.h
@@ -107,9 +107,6 @@ typedef struct cmd_state_s
 
        mempool_t *mempool;
 
-       char tokenizebuffer[CMD_TOKENIZELENGTH];
-       int tokenizebufferpos;
-
        cmddeferred_t *deferred_list;
        double deferred_oldrealtime;
 
@@ -159,9 +156,12 @@ typedef struct cbuf_s
 {
        cbuf_cmd_t *start;
        cbuf_cmd_t *free;
+       qboolean pending;
        qboolean wait;
        size_t maxsize;
        size_t size;
+       char tokenizebuffer[CMD_TOKENIZELENGTH];
+       int tokenizebufferpos;
        void *lock;
 } cbuf_t;