|
|
/****************************************************************************
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) || CallSetOrCreatePresent() ) { 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(',')){ m_nTokenOffSet--; break; } if (m_pszCommandLine[m_nTokenOffSet] == _T('"')) { if (m_pszCommandLine[m_nTokenOffSet-1] == _T('\\')) { m_bEscapeSeq = TRUE; } else break; } m_nTokenOffSet++; } } else 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(',')){ m_nTokenOffSet--; break; } 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(nInd > 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(":"))) || (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('\\')) { if (0 == nInd) { 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; }
/*------------------------------------------------------------------------
Name :CallSetOrCreatePresent Synopsis :This function checks whether CALL or SET or CREATE is present in the tokens vector. Type :Member Function Input parameter :None Output parameters :None Return Type :BOOL Global Variables :None Calling Syntax :CallSetOrCreatePresent() Notes :None ------------------------------------------------------------------------*/ BOOL CCmdTokenizer::CallSetOrCreatePresent() { BOOL bRet = FALSE; WMICLIINT nSizeOfVector = m_cvTokens.size();
// Check is there any CALL or SET verbs in the vector
for(WMICLIINT i=0; i<nSizeOfVector; ++i) { if( CompareTokens(m_cvTokens[i], CLI_TOKEN_CALL) || CompareTokens(m_cvTokens[i], CLI_TOKEN_SET) || CompareTokens(m_cvTokens[i], CLI_TOKEN_CREATE) ) { bRet = TRUE; break; } }
return bRet; }
|