476 lines
10 KiB
C++
476 lines
10 KiB
C++
/*** ntalias.cpp - Alias command processor for NT debugger
|
|
*
|
|
* Copyright <C> 1999-2001, Microsoft Corporation
|
|
*
|
|
* Purpose:
|
|
* To establish, maintain, and translate alias command tokens
|
|
*
|
|
*
|
|
* Revision History:
|
|
*
|
|
* [-] 08-Aug-1999 Richg Created.
|
|
*
|
|
*************************************************************************/
|
|
|
|
#include "ntsdp.hpp"
|
|
|
|
PALIAS g_AliasListHead; // List of alias elements
|
|
ULONG g_NumAliases;
|
|
|
|
|
|
HRESULT
|
|
SetAlias(PCSTR SrcText, PCSTR DstText)
|
|
{
|
|
PALIAS pPrevAlias;
|
|
PALIAS pCurAlias;
|
|
PALIAS pNewAlias;
|
|
|
|
pNewAlias = (PALIAS)malloc( sizeof(ALIAS) + strlen(SrcText) +
|
|
strlen(DstText) + 2 );
|
|
if (!pNewAlias)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
//
|
|
// Locate Alias, or insertion point
|
|
//
|
|
// This insertion scheme maintains a sorted list of
|
|
// alias elements by name.
|
|
//
|
|
|
|
pPrevAlias = NULL;
|
|
pCurAlias = g_AliasListHead;
|
|
|
|
while (( pCurAlias != NULL ) &&
|
|
( strcmp( SrcText, pCurAlias->Name ) > 0 ))
|
|
{
|
|
pPrevAlias = pCurAlias;
|
|
pCurAlias = pCurAlias->Next;
|
|
}
|
|
|
|
// If there is already an element by that name, clear it.
|
|
if (pCurAlias != NULL &&
|
|
!strcmp(SrcText, pCurAlias->Name))
|
|
{
|
|
PALIAS pTmpAlias = pCurAlias->Next;
|
|
free(pCurAlias);
|
|
pCurAlias = pTmpAlias;
|
|
g_NumAliases--;
|
|
}
|
|
|
|
pNewAlias->Next = pCurAlias;
|
|
if (pPrevAlias == NULL)
|
|
{
|
|
g_AliasListHead = pNewAlias;
|
|
}
|
|
else
|
|
{
|
|
pPrevAlias->Next = pNewAlias;
|
|
}
|
|
|
|
pNewAlias->Name = (PSTR)(pNewAlias + 1);
|
|
pNewAlias->Value = pNewAlias->Name + strlen(SrcText) + 1;
|
|
strcpy( pNewAlias->Name, SrcText );
|
|
strcpy( pNewAlias->Value, DstText );
|
|
g_NumAliases++;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*** ParseSetAlias - Set an alias expression
|
|
*
|
|
* Purpose:
|
|
* From the current command line position at g_CurCmd,
|
|
* read the alias name and value tokens. Once obtained
|
|
* perform an alias list lookup to see if it is a redefinition.
|
|
* If not allocate a new alias element and place it on the
|
|
* alias element list.
|
|
*
|
|
*
|
|
* Input:
|
|
* Global: g_CurCmd - command line position
|
|
* Global: g_AliasListHead
|
|
*
|
|
* Returns:
|
|
* Status
|
|
*
|
|
* Exceptions:
|
|
* error exit: SYNTAX errors
|
|
*
|
|
*************************************************************************/
|
|
|
|
void
|
|
ParseSetAlias(void)
|
|
{
|
|
PSTR pAliasName;
|
|
PSTR pAliasValue;
|
|
UCHAR ch;
|
|
|
|
//
|
|
// Locate alias name
|
|
//
|
|
PeekChar();
|
|
|
|
pAliasName = g_CurCmd;
|
|
|
|
do
|
|
{
|
|
ch = *g_CurCmd++;
|
|
} while (ch != ' ' && ch != '\t' && ch != '\0' && ch != ';');
|
|
|
|
if ( (ULONG_PTR)(g_CurCmd-1) == (ULONG_PTR)pAliasName )
|
|
{
|
|
error(SYNTAX);
|
|
}
|
|
|
|
*--g_CurCmd = '\0'; // Back up and null terminate
|
|
// the alias name token
|
|
g_CurCmd++; // -> next char
|
|
|
|
//
|
|
// Locate alias value, take remaining cmd line as value
|
|
//
|
|
|
|
PeekChar();
|
|
|
|
pAliasValue = g_CurCmd;
|
|
|
|
do
|
|
{
|
|
ch = *g_CurCmd++;
|
|
} while (ch != '\t' && ch != '\0');
|
|
|
|
if ( (ULONG_PTR)(g_CurCmd-1) == (ULONG_PTR)pAliasValue )
|
|
{
|
|
error(SYNTAX);
|
|
}
|
|
|
|
*--g_CurCmd = '\0'; // Back up and Null terminate
|
|
// the alias value token
|
|
|
|
if (SetAlias(pAliasName, pAliasValue) != S_OK)
|
|
{
|
|
error(MEMORY);
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
DeleteAlias(PCSTR SrcText)
|
|
{
|
|
PALIAS pCurAlias;
|
|
|
|
if (SrcText[0] == '*' && SrcText[1] == 0)
|
|
{
|
|
//
|
|
// Delete all aliases
|
|
//
|
|
while ( g_AliasListHead != NULL )
|
|
{
|
|
//
|
|
// Unchain the element and free it
|
|
//
|
|
pCurAlias = g_AliasListHead->Next;
|
|
free(g_AliasListHead);
|
|
g_AliasListHead = pCurAlias;
|
|
}
|
|
|
|
g_NumAliases = 0;
|
|
}
|
|
else
|
|
{
|
|
PALIAS pPrevAlias;
|
|
|
|
//
|
|
// Locate and delete the specified alias
|
|
//
|
|
|
|
pPrevAlias = NULL;
|
|
pCurAlias = g_AliasListHead;
|
|
|
|
while (( pCurAlias != NULL ) &&
|
|
( strcmp( SrcText, pCurAlias->Name )))
|
|
{
|
|
pPrevAlias = pCurAlias;
|
|
pCurAlias = pCurAlias->Next;
|
|
}
|
|
|
|
if ( pCurAlias == NULL )
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
//
|
|
// Unchain the element and free it
|
|
//
|
|
if (pPrevAlias == NULL)
|
|
{
|
|
g_AliasListHead = pCurAlias->Next;
|
|
}
|
|
else
|
|
{
|
|
pPrevAlias->Next = pCurAlias->Next;
|
|
}
|
|
free( pCurAlias );
|
|
g_NumAliases--;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*** ParseDeleteAlias - Delete an alias expression
|
|
*
|
|
* Purpose:
|
|
* From the current command line position at g_CurCmd,
|
|
* read the ALias name and perform an alias list lookup
|
|
* to see if it exists and unlink and delete the element.
|
|
*
|
|
*
|
|
* Input:
|
|
* Global: g_CurCmd - command line position
|
|
* Global: g_AliasListHead
|
|
*
|
|
* Returns:
|
|
* Status
|
|
*
|
|
* Exceptions:
|
|
* error exit: SYNTAX errors or non-existent element
|
|
*
|
|
*************************************************************************/
|
|
|
|
void
|
|
ParseDeleteAlias(void)
|
|
{
|
|
PSTR pAliasName;
|
|
UCHAR ch;
|
|
|
|
//
|
|
// Locate alias name on cmd line
|
|
//
|
|
PeekChar();
|
|
|
|
pAliasName = g_CurCmd;
|
|
|
|
do
|
|
{
|
|
ch = *g_CurCmd++;
|
|
} while (ch != ' ' && ch != '\t' && ch != '\0' && ch != ';');
|
|
|
|
if ( (ULONG_PTR)(g_CurCmd-1) == (ULONG_PTR)pAliasName )
|
|
{
|
|
error(SYNTAX);
|
|
}
|
|
|
|
*--g_CurCmd = '\0'; // Null terminate the token
|
|
if (ch != '\0')
|
|
{
|
|
g_CurCmd++;
|
|
}
|
|
|
|
if (DeleteAlias(pAliasName) != S_OK)
|
|
{
|
|
error(NOTFOUND);
|
|
}
|
|
}
|
|
|
|
/*** ListAliases - List the alias structures
|
|
*
|
|
* Purpose:
|
|
* Read and display all of the alias list elements.
|
|
*
|
|
*
|
|
* Input:
|
|
* Global: g_AliasListHead
|
|
*
|
|
* Returns:
|
|
* Status
|
|
*
|
|
* Exceptions:
|
|
* None
|
|
*
|
|
*************************************************************************/
|
|
|
|
void
|
|
ListAliases(void)
|
|
{
|
|
PALIAS pCurAlias;
|
|
|
|
pCurAlias = g_AliasListHead;
|
|
|
|
if ( pCurAlias == NULL )
|
|
{
|
|
dprintf( "No Alias entries to list. \n" );
|
|
return;
|
|
}
|
|
|
|
dprintf (" Alias Value \n");
|
|
dprintf (" ------- ------- \n");
|
|
|
|
while ( pCurAlias != NULL )
|
|
{
|
|
dprintf(" %-16s %s \n", pCurAlias->Name, pCurAlias->Value );
|
|
|
|
pCurAlias = pCurAlias->Next;
|
|
}
|
|
}
|
|
|
|
/*** ReplaceAliases - Replace aliases in the given command string
|
|
*
|
|
* Purpose:
|
|
* From the current command line position at g_CurCmd,
|
|
* read each token and build a new command line, replacing
|
|
* tokens with alias value data. A lookup is performed on
|
|
* each original command line token to determine if it is
|
|
* defined in the alias list. If so it is replaced on the
|
|
* new command line, otherwise the original token is
|
|
* placed on the new command line.
|
|
*
|
|
*
|
|
* Input:
|
|
* Global: g_CurCmd - command line position
|
|
* Global: g_AliasListHead
|
|
*
|
|
*
|
|
* Returns:
|
|
* Global: g_CurCmd - command line position
|
|
* Global: chCommand
|
|
* Status
|
|
*
|
|
*************************************************************************/
|
|
|
|
void
|
|
ReplaceAliases(PSTR CommandString)
|
|
{
|
|
PSTR Command = CommandString;
|
|
CHAR *pToken;
|
|
CHAR ch;
|
|
CHAR chdelim[2];
|
|
|
|
CHAR chAliasCommand[MAX_COMMAND]; // Alias build command area
|
|
CHAR *pchAliasCommand;
|
|
|
|
ULONG TokenLen;
|
|
|
|
PALIAS pPrevAlias;
|
|
PALIAS pCurAlias;
|
|
|
|
BOOLEAN LineEnd;
|
|
|
|
|
|
// If the incoming command looks like an alias-manipulation
|
|
// command don't replace aliases.
|
|
if (CommandString[0] == 'a' &&
|
|
(CommandString[1] == 'd' ||
|
|
CommandString[1] == 'l' ||
|
|
CommandString[1] == 's'))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// If the incoming command is all spaces it's probably
|
|
// the result of control characters getting mapped to
|
|
// spaces. Don't process it as there can't be any
|
|
// aliases and we don't want the trailing space trimming
|
|
// to remove the input space.
|
|
while (*Command == ' ')
|
|
{
|
|
Command++;
|
|
}
|
|
if (*Command == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Command = CommandString;
|
|
pchAliasCommand = chAliasCommand;
|
|
|
|
ZeroMemory( pchAliasCommand, sizeof(chAliasCommand) );
|
|
|
|
LineEnd = FALSE;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Locate command line token
|
|
//
|
|
while (isspace(*Command))
|
|
{
|
|
PSTR AliasCmdEnd =
|
|
pchAliasCommand + strlen(pchAliasCommand);
|
|
*AliasCmdEnd++ = *Command++;
|
|
*AliasCmdEnd = 0;
|
|
}
|
|
|
|
pToken = Command;
|
|
|
|
do
|
|
{
|
|
ch = *Command++;
|
|
} while (ch != ' ' &&
|
|
ch != '\'' &&
|
|
ch != '"' &&
|
|
ch != ';' &&
|
|
ch != '\t' &&
|
|
ch != '\0');
|
|
|
|
|
|
//
|
|
// Preserve the token delimiter
|
|
//
|
|
chdelim[0] = ch;
|
|
chdelim[1] = '\0';
|
|
|
|
if ( ch == '\0' )
|
|
{
|
|
LineEnd = TRUE;
|
|
}
|
|
|
|
TokenLen = (ULONG)((Command - 1) - pToken);
|
|
|
|
if ( TokenLen != 0 )
|
|
{
|
|
*--Command = '\0'; // Null terminate the string
|
|
Command++;
|
|
ch = *Command;
|
|
|
|
//
|
|
// Locate Alias or end of list
|
|
//
|
|
pCurAlias = g_AliasListHead;
|
|
|
|
while (( pCurAlias != NULL ) &&
|
|
( strcmp( pToken, pCurAlias->Name )))
|
|
{
|
|
pCurAlias = pCurAlias->Next;
|
|
}
|
|
|
|
if ( pCurAlias != NULL )
|
|
{
|
|
strcat( pchAliasCommand, pCurAlias->Value );
|
|
}
|
|
else
|
|
{
|
|
strcat( pchAliasCommand, pToken );
|
|
}
|
|
}
|
|
strcat( pchAliasCommand, chdelim );
|
|
|
|
} while( !LineEnd );
|
|
|
|
//
|
|
// Strip off any trailing blanks
|
|
//
|
|
pchAliasCommand += strlen( pchAliasCommand );
|
|
ch = *pchAliasCommand;
|
|
while ( ch == '\0' || ch == ' ' )
|
|
{
|
|
*pchAliasCommand = '\0';
|
|
ch = *--pchAliasCommand;
|
|
}
|
|
|
|
//
|
|
// Place the new command line in the command string buffer.
|
|
//
|
|
strcpy( CommandString, chAliasCommand );
|
|
}
|