[NTOS:KDBG] Move command history management in a separate file. Simplify duplicated...
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Mon, 27 Mar 2023 20:40:09 +0000 (22:40 +0200)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Mon, 27 Mar 2023 21:31:34 +0000 (23:31 +0200)
ntoskrnl/kdbg/kdb.h
ntoskrnl/kdbg/kdb_cli.c
ntoskrnl/kdbg/kdb_cmdhist.c [new file with mode: 0644]
ntoskrnl/ntos.cmake

index cd7a0b5..ac3f8b1 100644 (file)
@@ -104,6 +104,15 @@ KdbpCliMainLoop(
 VOID
 KdbpCliInterpretInitFile(VOID);
 
+VOID
+KdbpCommandHistoryAppend(
+    _In_ PCSTR Command);
+
+PCSTR
+KdbGetHistoryEntry(
+    _Inout_ PLONG NextIndex,
+    _In_ BOOLEAN Next);
+
 SIZE_T
 KdbpReadCommand(
     _Out_ PCHAR Buffer,
index f114a86..b50d18b 100644 (file)
@@ -140,11 +140,6 @@ static PKDBG_CLI_ROUTINE KdbCliCallbacks[10];
 static BOOLEAN KdbUseIntelSyntax = FALSE; /* Set to TRUE for intel syntax */
 static BOOLEAN KdbBreakOnModuleLoad = FALSE; /* Set to TRUE to break into KDB when a module is loaded */
 
-static CHAR KdbCommandHistoryBuffer[2048]; /* Command history string ringbuffer */
-static PCHAR KdbCommandHistory[sizeof(KdbCommandHistoryBuffer) / 8] = { NULL }; /* Command history ringbuffer */
-static LONG KdbCommandHistoryBufferIndex = 0;
-static LONG KdbCommandHistoryIndex = 0;
-
 static ULONG KdbNumberOfRowsPrinted = 0;
 static ULONG KdbNumberOfColsPrinted = 0;
 static BOOLEAN KdbOutputAborted = FALSE;
@@ -3262,77 +3257,6 @@ KdbpPrintUnicodeString(
 }
 
 
-/*!\brief Appends a command to the command history
- *
- * \param Command  Pointer to the command to append to the history.
- */
-static VOID
-KdbpCommandHistoryAppend(
-    IN PCHAR Command)
-{
-    SIZE_T Length1 = strlen(Command) + 1;
-    SIZE_T Length2 = 0;
-    INT i;
-    PCHAR Buffer;
-
-    ASSERT(Length1 <= RTL_NUMBER_OF(KdbCommandHistoryBuffer));
-
-    if (Length1 <= 1 ||
-        (KdbCommandHistory[KdbCommandHistoryIndex] &&
-         strcmp(KdbCommandHistory[KdbCommandHistoryIndex], Command) == 0))
-    {
-        return;
-    }
-
-    /* Calculate Length1 and Length2 */
-    Buffer = KdbCommandHistoryBuffer + KdbCommandHistoryBufferIndex;
-    KdbCommandHistoryBufferIndex += Length1;
-    if (KdbCommandHistoryBufferIndex >= (LONG)RTL_NUMBER_OF(KdbCommandHistoryBuffer))
-    {
-        KdbCommandHistoryBufferIndex -= RTL_NUMBER_OF(KdbCommandHistoryBuffer);
-        Length2 = KdbCommandHistoryBufferIndex;
-        Length1 -= Length2;
-    }
-
-    /* Remove previous commands until there is enough space to append the new command */
-    for (i = KdbCommandHistoryIndex; KdbCommandHistory[i];)
-    {
-        if ((Length2 > 0 &&
-            (KdbCommandHistory[i] >= Buffer ||
-             KdbCommandHistory[i] < (KdbCommandHistoryBuffer + KdbCommandHistoryBufferIndex))) ||
-            (Length2 <= 0 &&
-             (KdbCommandHistory[i] >= Buffer &&
-              KdbCommandHistory[i] < (KdbCommandHistoryBuffer + KdbCommandHistoryBufferIndex))))
-        {
-            KdbCommandHistory[i] = NULL;
-        }
-
-        i--;
-        if (i < 0)
-            i = RTL_NUMBER_OF(KdbCommandHistory) - 1;
-
-        if (i == KdbCommandHistoryIndex)
-            break;
-    }
-
-    /* Make sure the new command history entry is free */
-    KdbCommandHistoryIndex++;
-    KdbCommandHistoryIndex %= RTL_NUMBER_OF(KdbCommandHistory);
-    if (KdbCommandHistory[KdbCommandHistoryIndex])
-    {
-        KdbCommandHistory[KdbCommandHistoryIndex] = NULL;
-    }
-
-    /* Append command */
-    KdbCommandHistory[KdbCommandHistoryIndex] = Buffer;
-    ASSERT((KdbCommandHistory[KdbCommandHistoryIndex] + Length1) <= KdbCommandHistoryBuffer + RTL_NUMBER_OF(KdbCommandHistoryBuffer));
-    memcpy(KdbCommandHistory[KdbCommandHistoryIndex], Command, Length1);
-    if (Length2 > 0)
-    {
-        memcpy(KdbCommandHistoryBuffer, Command + Length1, Length2);
-    }
-}
-
 /**
  * @brief   Reads a line of user input from the terminal.
  *
@@ -3358,8 +3282,7 @@ KdbpReadCommand(
     BOOLEAN EchoOn;
     static CHAR LastCommand[1024];
     static CHAR NextKey = '\0';
-    INT CmdHistIndex = -1;
-    INT_PTR i;
+    LONG CmdHistIndex = -1; // Start at end of history.
 
     /* Bail out if the buffer is zero-sized */
     if (Size == 0)
@@ -3445,6 +3368,7 @@ KdbpReadCommand(
         }
         else if (Key == KEY_BS || Key == KEY_DEL)
         {
+            /* Erase the last character */
             if (Buffer > Orig)
             {
                 Buffer--;
@@ -3456,29 +3380,15 @@ KdbpReadCommand(
                     KdpDprintf(" %c", KEY_BS);
             }
         }
-        else if (ScanCode == KEY_SCAN_UP)
+        else if (ScanCode == KEY_SCAN_UP || ScanCode == KEY_SCAN_DOWN)
         {
-            BOOLEAN Print = TRUE;
-
-            if (CmdHistIndex < 0)
+            PCSTR CmdHistory = KdbGetHistoryEntry(&CmdHistIndex,
+                                                  (ScanCode == KEY_SCAN_DOWN));
+            if (CmdHistory)
             {
-                CmdHistIndex = KdbCommandHistoryIndex;
-            }
-            else
-            {
-                i = CmdHistIndex - 1;
-
-                if (i < 0)
-                    CmdHistIndex = RTL_NUMBER_OF(KdbCommandHistory) - 1;
-
-                if (KdbCommandHistory[i] && i != KdbCommandHistoryIndex)
-                    CmdHistIndex = i;
-                else
-                    Print = FALSE;
-            }
+                SIZE_T i;
 
-            if (Print && KdbCommandHistory[CmdHistIndex])
-            {
+                /* Erase the whole line */
                 while (Buffer > Orig)
                 {
                     Buffer--;
@@ -3490,43 +3400,13 @@ KdbpReadCommand(
                         KdpDprintf(" %c", KEY_BS);
                 }
 
-                i = min(strlen(KdbCommandHistory[CmdHistIndex]), Size - 1);
-                memcpy(Orig, KdbCommandHistory[CmdHistIndex], i);
+                i = min(strlen(CmdHistory), Size - 1);
+                memcpy(Orig, CmdHistory, i);
                 Orig[i] = '\0';
                 Buffer = Orig + i;
                 KdpDprintf("%s", Orig);
             }
         }
-        else if (ScanCode == KEY_SCAN_DOWN)
-        {
-            if (CmdHistIndex > 0 && CmdHistIndex != KdbCommandHistoryIndex)
-            {
-                i = CmdHistIndex + 1;
-                if (i >= (INT)RTL_NUMBER_OF(KdbCommandHistory))
-                    i = 0;
-
-                if (KdbCommandHistory[i])
-                {
-                    CmdHistIndex = i;
-                    while (Buffer > Orig)
-                    {
-                        Buffer--;
-                        *Buffer = '\0';
-
-                        if (EchoOn)
-                            KdpDprintf("%c %c", KEY_BS, KEY_BS);
-                        else
-                            KdpDprintf(" %c", KEY_BS);
-                    }
-
-                    i = min(strlen(KdbCommandHistory[CmdHistIndex]), Size - 1);
-                    memcpy(Orig, KdbCommandHistory[CmdHistIndex], i);
-                    Orig[i] = '\0';
-                    Buffer = Orig + i;
-                    KdpDprintf("%s", Orig);
-                }
-            }
-        }
         else
         {
             /* Don't accept any key if the buffer is full */
diff --git a/ntoskrnl/kdbg/kdb_cmdhist.c b/ntoskrnl/kdbg/kdb_cmdhist.c
new file mode 100644 (file)
index 0000000..c1f1fcb
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * PROJECT:     ReactOS KDBG Kernel Debugger
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     Command History helpers
+ * COPYRIGHT:   Copyright 2005 Gregor Anich <blight@blight.eu.org>
+ *              Copyright 2023 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+
+/* GLOBALS *******************************************************************/
+
+/**
+ * History range in ring buffer:
+ * (KdbCommandHistoryIndex; RTL_NUMBER_OF(KdbCommandHistory) - 1]
+ *   and [0; KdbCommandHistoryIndex].
+ **/
+
+/* Command history string ring buffer */
+static CHAR KdbCommandHistoryBuffer[2048];
+/* Command history ring buffer */
+static PCHAR KdbCommandHistory[sizeof(KdbCommandHistoryBuffer) / 8] = { NULL };
+static LONG KdbCommandHistoryBufferIndex = 0;
+static LONG KdbCommandHistoryIndex = 0;
+
+/* FUNCTIONS *****************************************************************/
+
+/**
+ * @brief   Appends a command to the command history.
+ *
+ * @param[in]   Command
+ * Pointer to the command to append to the history.
+ **/
+VOID
+KdbpCommandHistoryAppend(
+    _In_ PCSTR Command)
+{
+    SIZE_T Length1 = strlen(Command) + 1;
+    SIZE_T Length2 = 0;
+    LONG i;
+    PCHAR Buffer;
+
+    ASSERT(Length1 <= RTL_NUMBER_OF(KdbCommandHistoryBuffer));
+
+    /*
+     * Do not append the string if:
+     * - it is empty (just the NULL terminator);
+     * - or the last command is the same.
+     */
+    if (Length1 <= 1 ||
+        (KdbCommandHistory[KdbCommandHistoryIndex] &&
+         strcmp(KdbCommandHistory[KdbCommandHistoryIndex], Command) == 0))
+    {
+        return;
+    }
+
+    /* Calculate Length1 and Length2 */
+    Buffer = KdbCommandHistoryBuffer + KdbCommandHistoryBufferIndex;
+    KdbCommandHistoryBufferIndex += Length1;
+    if (KdbCommandHistoryBufferIndex >= (LONG)RTL_NUMBER_OF(KdbCommandHistoryBuffer))
+    {
+        KdbCommandHistoryBufferIndex -= RTL_NUMBER_OF(KdbCommandHistoryBuffer);
+        Length2 = KdbCommandHistoryBufferIndex;
+        Length1 -= Length2;
+    }
+
+    /* Remove previous commands until there is enough space to append the new command */
+    for (i = KdbCommandHistoryIndex; KdbCommandHistory[i];)
+    {
+        if ((Length2 > 0 &&
+            (KdbCommandHistory[i] >= Buffer ||
+             KdbCommandHistory[i] < (KdbCommandHistoryBuffer + KdbCommandHistoryBufferIndex))) ||
+            (Length2 <= 0 &&
+             (KdbCommandHistory[i] >= Buffer &&
+              KdbCommandHistory[i] < (KdbCommandHistoryBuffer + KdbCommandHistoryBufferIndex))))
+        {
+            KdbCommandHistory[i] = NULL;
+        }
+
+        i--;
+        if (i < 0)
+            i = RTL_NUMBER_OF(KdbCommandHistory) - 1;
+
+        if (i == KdbCommandHistoryIndex)
+            break;
+    }
+
+    /* Make sure the new command history entry is free */
+    KdbCommandHistoryIndex++;
+    KdbCommandHistoryIndex %= RTL_NUMBER_OF(KdbCommandHistory);
+    if (KdbCommandHistory[KdbCommandHistoryIndex])
+    {
+        KdbCommandHistory[KdbCommandHistoryIndex] = NULL;
+    }
+
+    /* Append command */
+    KdbCommandHistory[KdbCommandHistoryIndex] = Buffer;
+    ASSERT((KdbCommandHistory[KdbCommandHistoryIndex] + Length1) <= KdbCommandHistoryBuffer + RTL_NUMBER_OF(KdbCommandHistoryBuffer));
+    memcpy(KdbCommandHistory[KdbCommandHistoryIndex], Command, Length1);
+    if (Length2 > 0)
+    {
+        memcpy(KdbCommandHistoryBuffer, Command + Length1, Length2);
+    }
+}
+
+static PCSTR
+KdbpGetPrevHistoryEntry(
+    _Inout_ PLONG NextIndex)
+{
+    if (*NextIndex < 0)
+    {
+        /* Start at the end of the history */
+        *NextIndex = KdbCommandHistoryIndex;
+    }
+    else
+    {
+        LONG i = *NextIndex - 1;
+        if (i < 0)
+            *NextIndex = RTL_NUMBER_OF(KdbCommandHistory) - 1;
+
+        if (KdbCommandHistory[i] && i != KdbCommandHistoryIndex)
+            *NextIndex = i;
+        else
+            return NULL;
+    }
+
+    return KdbCommandHistory[*NextIndex];
+}
+
+static PCSTR
+KdbpGetNextHistoryEntry(
+    _Inout_ PLONG NextIndex)
+{
+    LONG i;
+
+    if (!(*NextIndex > 0 && *NextIndex != KdbCommandHistoryIndex))
+        return NULL;
+
+    i = *NextIndex + 1;
+    if (i >= (LONG)RTL_NUMBER_OF(KdbCommandHistory))
+        i = 0;
+
+    if (KdbCommandHistory[i])
+        *NextIndex = i;
+
+    return KdbCommandHistory[i];
+}
+
+PCSTR
+KdbGetHistoryEntry(
+    _Inout_ PLONG NextIndex,
+    _In_ BOOLEAN Next)
+{
+    if (Next)
+        return KdbpGetNextHistoryEntry(NextIndex);
+    else
+        return KdbpGetPrevHistoryEntry(NextIndex);
+}
+
+/* EOF */
index 6816452..648de8f 100644 (file)
@@ -405,6 +405,7 @@ if(NOT _WINKD_)
         list(APPEND SOURCE
             ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/kdb.c
             ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/kdb_cli.c
+            ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/kdb_cmdhist.c
             ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/kdb_expr.c
             ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/kdb_symbols.c)
     endif()