windows-nt/Source/XPSP1/NT/admin/wmi/wbem/tools/wmic/cmdtokenizer.cpp
2020-09-26 16:20:57 +08:00

517 lines
14 KiB
C++

/****************************************************************************
Copyright information : Copyright (c) 1998-1999 Microsoft Corporation
File Name : CmdTokenizer.cpp
Project Name : WMI Command Line
Author Name : Ch. Sriramachandramurthy
Date of Creation (dd/mm/yy) : 27th-September-2000
Version Number : 1.0
Brief Description : The CCmdTokenizer class provides with the
functionality for tokenizing a command entered
as input on the command line, following the
pre-defined rules for tokenizing.
Revision History :
Last Modified By : P. Sashank
Last Modified Date : 10th-April-2001
****************************************************************************/
#include "Precomp.h"
#include "CmdTokenizer.h"
/*------------------------------------------------------------------------
Name :CCmdTokenizer
Synopsis :This function initializes the member variables when
an object of the class type is instantiated
Type :Constructor
Input parameter :None
Output parameters :None
Return Type :None
Global Variables :None
Calling Syntax :None
Notes :None
------------------------------------------------------------------------*/
CCmdTokenizer::CCmdTokenizer()
{
m_nTokenOffSet = 0;
m_nTokenStart = 0;
m_pszCommandLine = NULL;
m_bEscapeSeq = FALSE;
m_bFormatToken = FALSE;
}
/*------------------------------------------------------------------------
Name :~CCmdTokenizer
Synopsis :This function uninitializes the member variables
when an object of the class type goes out of scope.
Type :Destructor
Input parameter :None
Output parameters :None
Return Type :None
Global Variables :None
Calling Syntax :None
Notes :None
------------------------------------------------------------------------*/
CCmdTokenizer::~CCmdTokenizer()
{
Uninitialize();
}
/*------------------------------------------------------------------------
Name :Uninitialize
Synopsis :This function uninitializes the member variables
when the execution of a command string issued on the
command line is completed.
Type :Member Function
Input parameter :None
Output parameters :None
Return Type :None
Global Variables :None
Calling Syntax :Uninitialize()
Notes :None
------------------------------------------------------------------------*/
void CCmdTokenizer::Uninitialize()
{
m_nTokenOffSet = 0;
m_nTokenStart = 0;
m_bEscapeSeq = FALSE;
SAFEDELETE(m_pszCommandLine);
CleanUpCharVector(m_cvTokens);
}
/*------------------------------------------------------------------------
Name :TokenizeCommand
Synopsis :This function tokenizes the command string entered
as input based on the pre-identified delimiters and
stores the tokens in the list of m_cvTokens.
Type :Member Function
Input parameter :
pszCommandInpout - Command line Input
Output parameters :None
Return Type :BOOL
Global Variables :None
Calling Syntax :TokenizeCommand(pszCommandInput)
Notes :None
------------------------------------------------------------------------*/
BOOL CCmdTokenizer::TokenizeCommand(_TCHAR* pszCommandInput) throw(WMICLIINT)
{
BOOL bResult = TRUE;
// Free the memory pointed by the member variable m_pszCommandLine
// if the pointer is not NULL.
SAFEDELETE(m_pszCommandLine);
if(pszCommandInput)
{
try
{
// Allocate the memory for the command line string.
m_pszCommandLine = new _TCHAR [lstrlen(pszCommandInput) + 1];
if (m_pszCommandLine != NULL)
{
// Copy the contents to the member variable m_pszCommandLine
lstrcpy(m_pszCommandLine, pszCommandInput);
// Set the token-offset and token-start counters to '0'
m_nTokenOffSet = 0;
m_nTokenStart = 0;
WMICLIINT nCmdLength = lstrlen(m_pszCommandLine);
// Tokenize the command string.
while (m_nTokenOffSet < nCmdLength)
{
NextToken();
}
}
else
throw OUT_OF_MEMORY;
}
catch(...)
{
bResult = FALSE;
}
}
return bResult;
}
/*------------------------------------------------------------------------
Name :NextToken
Synopsis :This function dissects the command string entered
as input, and adjusts the the token-offset and
token-start positions, and call the Token()
function for extracting the token out of the
input string.
Type :Member Function
Input parameter :None
Output parameters :None
Return Type :_TCHAR*
Global Variables :None
Calling Syntax :NextToken
Notes :None
------------------------------------------------------------------------*/
_TCHAR* CCmdTokenizer::NextToken()
{
WMICLIINT nCmdLength = lstrlen(m_pszCommandLine);
// step over leading whitespace(s)
while ((m_pszCommandLine[m_nTokenOffSet] == _T(' ') ||
m_pszCommandLine[m_nTokenOffSet] == _T('\t'))
&& (m_nTokenOffSet < nCmdLength))
{
m_nTokenOffSet++;
}
m_nTokenStart = m_nTokenOffSet;
CHARVECTOR::iterator theIterator;
theIterator = m_cvTokens.end();
//step up to next delimiter i.e '/', '-' or '?'
if ((m_pszCommandLine[m_nTokenOffSet] == _T('/'))
|| (m_pszCommandLine[m_nTokenOffSet] == _T('-'))
|| (m_pszCommandLine[m_nTokenOffSet] == _T(','))
|| (m_pszCommandLine[m_nTokenOffSet] == _T('('))
|| (m_pszCommandLine[m_nTokenOffSet] == _T(')'))
|| (m_pszCommandLine[m_nTokenOffSet] == _T('=') &&
!CompareTokens(*(theIterator-1), CLI_TOKEN_WHERE) &&
!CompareTokens(*(theIterator-1), CLI_TOKEN_PATH)))
{
// To handle optional parenthesis with WHERE
if (m_pszCommandLine[m_nTokenOffSet] == _T('('))
{
if (m_cvTokens.size())
{
//Check whether the previous token is "WHERE"
if (CompareTokens(*(theIterator-1), CLI_TOKEN_WHERE))
{
m_nTokenOffSet++;
while ((m_nTokenOffSet < nCmdLength)
&& (m_pszCommandLine[m_nTokenOffSet] != _T(')')))
{
m_nTokenOffSet++;
}
}
}
}
m_nTokenOffSet++;
}
else
{
while (m_nTokenOffSet < nCmdLength)
{
if ((m_pszCommandLine[m_nTokenOffSet] == _T('/'))
|| (m_pszCommandLine[m_nTokenOffSet] == _T('-'))
|| (m_pszCommandLine[m_nTokenOffSet] == _T(' '))
|| (m_pszCommandLine[m_nTokenOffSet] == _T('\t'))
|| (m_pszCommandLine[m_nTokenOffSet] == _T(','))
|| (m_pszCommandLine[m_nTokenOffSet] == _T('('))
|| (m_pszCommandLine[m_nTokenOffSet] == _T(')'))
|| (m_pszCommandLine[m_nTokenOffSet] == _T('=') &&
!CompareTokens(*(theIterator-1), CLI_TOKEN_WHERE) &&
!CompareTokens(*(theIterator-1), CLI_TOKEN_PATH)))
{
break;
}
// if the command option is specified in quotes
if (m_pszCommandLine[m_nTokenOffSet] == _T('"'))
{
m_nTokenOffSet++;
// To include " within an quoted string it should
// be preceded by \
while (m_nTokenOffSet < nCmdLength)
{
if (m_pszCommandLine[m_nTokenOffSet] == _T('"'))
{
if (m_pszCommandLine[m_nTokenOffSet-1] == _T('\\'))
{
m_bEscapeSeq = TRUE;
}
else
break;
}
m_nTokenOffSet++;
}
}
m_nTokenOffSet++;
}
}
return Token();
}
/*------------------------------------------------------------------------
Name :Token
Synopsis :This function extracts the portion of the command
string using the token-start and token-offset value.
If the token is not NULL, adds it to the list of
tokens in the token vector.
Type :Member Function
Input parameter :None
Output parameters :None
Return Type :_TCHAR*
Global Variables :None
Calling Syntax :Token()
Notes :None
------------------------------------------------------------------------*/
_TCHAR* CCmdTokenizer::Token() throw(WMICLIINT)
{
WMICLIINT nLength = (m_nTokenOffSet - m_nTokenStart);
_TCHAR* sToken = NULL;
CHARVECTOR::iterator theIterator = NULL;
if (nLength > 0)
{
// Allocate the memory for the new token.
sToken = new _TCHAR [nLength + 1];
if (sToken)
{
try
{
WMICLIINT nLoop = 0;
WMICLIINT nInd = 0;
BOOL bSpecialChar = FALSE;
BOOL bPush = TRUE;
// Form the token(s).
while(nInd < nLength)
{
BOOL bPush = TRUE;
while (nInd < nLength)
{
//If the character is ':'
if(m_pszCommandLine[nInd + m_nTokenStart] == _T(':') &&
bSpecialChar == FALSE)
{
_TCHAR* sToktemp = NULL;
sToktemp = new _TCHAR [nLoop + 1];
if (sToktemp == NULL)
throw OUT_OF_MEMORY;
if(lstrlen(sToken) > 0)
{
lstrcpyn(sToktemp,sToken,nLoop + 1);
sToktemp[nLoop] = _T('\0');
//if ':' is preceeded by ASSOC token
if(CompareTokens(sToktemp,CLI_TOKEN_ASSOC))
{
bSpecialChar = TRUE;
bPush = FALSE;
SAFEDELETE(sToktemp);
break;
}
//if ':' is preceded by FORMAT token
else if(CompareTokens(sToktemp,CLI_TOKEN_FORMAT))
{ theIterator = m_cvTokens.end();
if((theIterator - 1) >= m_cvTokens.begin() &&
IsOption(*(theIterator - 1)))
{
m_bFormatToken = TRUE;
bSpecialChar = TRUE;
bPush = FALSE;
SAFEDELETE(sToktemp);
break;
}
}
SAFEDELETE(sToktemp);
}
if (!m_cvTokens.empty())
{
theIterator = m_cvTokens.end();
//if ':' is present previous token is '/'
//(case arises when ':'
//is specified without space after a switch)
if( (theIterator - 1) >= m_cvTokens.begin() &&
IsOption(*(theIterator - 1)))
{
bSpecialChar = TRUE;
bPush = FALSE;
break;
}
//if ':' is first character in the new token
//(case arises when ':' is preceded by blank space)
else if(m_nTokenStart != 0 &&
m_pszCommandLine[m_nTokenStart] == _T(':'))
{
bSpecialChar = TRUE;
bPush = FALSE;
break;
}
//if ':' is encountered after format switch
//and previous token is ':' or a ','
//(case arises for specifying format switch)
else if(m_bFormatToken == TRUE &&
(CompareTokens(*(theIterator - 1),_T(":"))) ||
(CompareTokens(*(theIterator - 1), CLI_TOKEN_COMMA)) ||
(IsOption(*(theIterator - 1))))
{
bSpecialChar = TRUE;
bPush = FALSE;
break;
}
//if ':' is preceded by '?' and '?' in turn
//is preceded by '/'
//(case arises for specifying help option)
else
{
theIterator = m_cvTokens.end();
if(theIterator &&
(theIterator - 2) >= m_cvTokens.begin() &&
(CompareTokens(*(theIterator - 1),_T("?"))) &&
(IsOption(*(theIterator - 2))))
{
bSpecialChar = TRUE;
bPush = FALSE;
break;
}
}
}
}
//if character is '?'(for help switch)
else if(m_pszCommandLine[nInd + m_nTokenStart] ==
_T('?') && bSpecialChar == FALSE)
{
if (!m_cvTokens.empty())
{
theIterator = m_cvTokens.end();
//if character is '?' and preceded by '/'(for help switch)
if( (theIterator - 1) >= m_cvTokens.begin() &&
IsOption(*(theIterator - 1)))
{
bSpecialChar = TRUE;
bPush = FALSE;
break;
}
}
}
sToken[nLoop] = m_pszCommandLine[nInd + m_nTokenStart];
nLoop++;
nInd++;
if(m_pszCommandLine[nInd - 1 + m_nTokenStart] == _T('"'))
{
while(nInd < nLength)
{
sToken[nLoop] = m_pszCommandLine[
nInd + m_nTokenStart];
nLoop++;
nInd++;
if(nInd < nLength &&
m_pszCommandLine[nInd + m_nTokenStart]
== _T('"'))
{
if(m_pszCommandLine[nInd - 1 + m_nTokenStart]
== _T('\\'))
{
m_bEscapeSeq = TRUE;
}
else
{
sToken[nLoop] = m_pszCommandLine[
nInd + m_nTokenStart];
nLoop++;
nInd++;
break;
}
}
}
}
}
// terminate the string with '\0'
sToken[nLoop] = _T('\0');
UnQuoteString(sToken);
// If Escape sequence flag is set
if (m_bEscapeSeq)
{
try
{
CHString sTemp((WCHAR*)sToken);
/* Remove the escape sequence character i.e \ */
RemoveEscapeChars(sTemp);
lstrcpy(sToken, sTemp);
m_bEscapeSeq = FALSE;
}
catch(CHeap_Exception)
{
throw OUT_OF_MEMORY;
}
catch(...)
{
throw OUT_OF_MEMORY;
}
}
_TCHAR* sTokenTemp = NULL;
sTokenTemp = new _TCHAR[nLoop + 1];
if (sTokenTemp == NULL)
throw OUT_OF_MEMORY;
lstrcpy(sTokenTemp,sToken);
if(bPush == TRUE || lstrlen(sTokenTemp) > 0)
m_cvTokens.push_back(sTokenTemp);
else
SAFEDELETE(sTokenTemp);
//reset m_FormatToken if next switch is expected
if(m_bFormatToken == TRUE && IsOption(sTokenTemp))
m_bFormatToken = FALSE;
//if the character is found to be a special character
if(bSpecialChar == TRUE)
{
sToken[0] = m_pszCommandLine[nInd + m_nTokenStart];
sToken[1] = _T('\0');
sTokenTemp = new _TCHAR[2];
if (sTokenTemp == NULL)
throw OUT_OF_MEMORY;
lstrcpy(sTokenTemp,sToken);
bSpecialChar = FALSE;
nLoop = 0;
nInd++;
m_cvTokens.push_back(sTokenTemp);
bPush = TRUE;
theIterator++;
}
}
SAFEDELETE(sToken);
}
catch(...)
{
SAFEDELETE(sToken);
throw OUT_OF_MEMORY;
}
}
else
throw OUT_OF_MEMORY;
}
return sToken;
}
/*------------------------------------------------------------------------
Name :GetTokenVector
Synopsis :This function returns a reference to the token
vector
Type :Member Function
Input parameter :None
Output parameters :None
Return Type :CHARVECTOR&
Global Variables :None
Calling Syntax :GetTokenVector()
Notes :None
------------------------------------------------------------------------*/
CHARVECTOR& CCmdTokenizer::GetTokenVector()
{
return m_cvTokens;
}