[NTOS:KDBG] Move command history management in a separate file. Simplify duplicated code in KdbpReadCommand.

This commit is contained in:
Hermès Bélusca-Maïto 2023-03-27 22:40:09 +02:00
parent eb02a85214
commit 6084da8c84
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
4 changed files with 182 additions and 130 deletions

View 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,

View 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;
SIZE_T i;
if (i < 0)
CmdHistIndex = RTL_NUMBER_OF(KdbCommandHistory) - 1;
if (KdbCommandHistory[i] && i != KdbCommandHistoryIndex)
CmdHistIndex = i;
else
Print = FALSE;
}
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 */

162
ntoskrnl/kdbg/kdb_cmdhist.c Normal file
View file

@ -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 */

View 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()