/*** ntalias.cpp - Alias command processor for NT debugger * * Copyright 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 ); }