AppleWin/AppleWin/source/Debugger_Parser.cpp

947 lines
22 KiB
C++

/*
AppleWin : An Apple //e emulator for Windows
Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
Copyright (C) 2006, Tom Charlesworth, Michael Pohoreski
AppleWin is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
AppleWin is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with AppleWin; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Description: Debugger
*
* Author: Copyright (C) 2006, Michael Pohoreski
*/
#include "StdAfx.h"
#pragma hdrstop
// Args ___________________________________________________________________________________________
int g_nArgRaw;
Arg_t g_aArgRaw[ MAX_ARGS ]; // pre-processing
Arg_t g_aArgs [ MAX_ARGS ]; // post-processing (cooked)
const TCHAR TCHAR_LF = TEXT('\x0D');
const TCHAR TCHAR_CR = TEXT('\x0A');
const TCHAR TCHAR_SPACE = TEXT(' ');
const TCHAR TCHAR_TAB = TEXT('\t');
const TCHAR TCHAR_QUOTED = TEXT('"');
const TCHAR TCHAR_ESCAPE = TEXT('\x1B');
// NOTE: Token_e and g_aTokens must match!
const TokenTable_t g_aTokens[ NUM_TOKENS ] =
{ // Input
{ TOKEN_ALPHANUMERIC, TYPE_STRING , 0 }, // Default, if doen't match anything else
{ TOKEN_AMPERSAND , TYPE_OPERATOR, TEXT('&') }, // bit-and
// { TOKEN_AT , TYPE_OPERATOR, TEXT('@') }, // force Register? or PointerDeref?
{ TOKEN_BSLASH , TYPE_OPERATOR, TEXT('\\') },
{ TOKEN_CARET , TYPE_OPERATOR, TEXT('^') }, // bit-eor, C/C++: xor, Math: POWER
{ TOKEN_COLON , TYPE_OPERATOR, TEXT(':') },
{ TOKEN_COMMA , TYPE_OPERATOR, TEXT(',') },
{ TOKEN_DOLLAR , TYPE_STRING , TEXT('$') },
{ TOKEN_EQUAL , TYPE_OPERATOR, TEXT('=') },
{ TOKEN_EXCLAMATION , TYPE_OPERATOR, TEXT('!') }, // NOT
{ TOKEN_FSLASH , TYPE_OPERATOR, TEXT('/') }, // div
{ TOKEN_GREATER_THAN, TYPE_OPERATOR, TEXT('>') }, // TODO/FIXME: Parser will break up '>=' (needed for uber breakpoints)
{ TOKEN_HASH , TYPE_OPERATOR, TEXT('#') },
{ TOKEN_LEFT_PAREN , TYPE_OPERATOR, TEXT('(') },
{ TOKEN_LESS_THAN , TYPE_OPERATOR, TEXT('<') },
{ TOKEN_MINUS , TYPE_OPERATOR, TEXT('-') }, // sub
{ TOKEN_PERCENT , TYPE_OPERATOR, TEXT('%') }, // mod
{ TOKEN_PIPE , TYPE_OPERATOR, TEXT('|') }, // bit-or
{ TOKEN_PLUS , TYPE_OPERATOR, TEXT('+') }, // add
// { TOKEN_QUESTION , TYPE_OPERATOR, TEXT('?') }, // Not a token 1) wildcard needs to stay together with other chars
{ TOKEN_QUOTED , TYPE_QUOTED , TEXT('"') },
{ TOKEN_RIGHT_PAREN , TYPE_OPERATOR, TEXT(')') },
{ TOKEN_SEMI , TYPE_STRING , TEXT(';') },
{ TOKEN_SPACE , TYPE_STRING , TEXT(' ') } // space is also a delimiter between tokens/args
// { TOKEN_STAR , TYPE_OPERATOR, TEXT('*') }, // Not a token 1) wildcard needs to stay together with other chars
// { TOKEN_TAB , TYPE_STRING , TEXT('\t') }
// { TOKEN_TILDE , TYPE_OPERATOR, TEXT('~') }, // C/C++: Not. Used for console.
};
// const TokenTable_t g_aTokens2[ ] =
// { // Input
// { TOKEN_GREATER_EQUAL,TYPE_OPERATOR, TEXT(">=\x00") }, // TODO/FIXME: Parser will break up '>=' (needed for uber breakpoints)
// { TOKEN_LESS_EQUAL , TYPE_OPERATOR, TEXT("<=\x00") }, // TODO/FIXME: Parser will break up '<=' (needed for uber breakpoints)
// }
// Arg ____________________________________________________________________________________________
//===========================================================================
int _Arg_1( int nValue )
{
g_aArgs[1].nVal1 = nValue;
return 1;
}
//===========================================================================
int _Arg_1( LPTSTR pName )
{
int nLen = _tcslen( g_aArgs[1].sArg );
if (nLen < MAX_ARG_LEN)
{
_tcscpy( g_aArgs[1].sArg, pName );
}
else
{
_tcsncpy( g_aArgs[1].sArg, pName, MAX_ARG_LEN - 1 );
}
return 1;
}
/**
@description Copies Args[iSrc .. iEnd] to Args[0]
@param iSrc First argument to copy
@param iEnd Last argument to end
@return nArgs Number of new args
Usually called as: nArgs = _Arg_Shift( iArg, nArgs );
//=========================================================================== */
int _Arg_Shift( int iSrc, int iEnd, int iDst )
{
if (iDst < 0)
return ARG_SYNTAX_ERROR;
if (iDst > MAX_ARGS)
return ARG_SYNTAX_ERROR;
int nArgs = (iEnd - iSrc);
int nLen = nArgs + 1;
if ((iDst + nLen) > MAX_ARGS)
return ARG_SYNTAX_ERROR;
while (nLen--)
{
g_aArgs[iDst] = g_aArgs[iSrc];
iSrc++;
iDst++;
}
return nArgs;
}
//===========================================================================
void ArgsClear ()
{
Arg_t *pArg = &g_aArgs[0];
for (int iArg = 0; iArg < MAX_ARGS; iArg++ )
{
pArg->bSymbol = false;
pArg->eDevice = NUM_DEVICES; // none
pArg->eToken = NO_TOKEN ; // none
pArg->bType = TYPE_STRING;
pArg->nVal1 = 0;
pArg->nVal2 = 0;
pArg->sArg[0] = 0;
pArg++;
}
}
//===========================================================================
bool ArgsGetValue ( Arg_t *pArg, WORD * pAddressValue_, const int nBase )
{
TCHAR *pSrc = & (pArg->sArg[ 0 ]);
TCHAR *pEnd = NULL;
if (pArg && pAddressValue_)
{
*pAddressValue_ = (WORD)(_tcstoul( pSrc, &pEnd, nBase) & _6502_END_MEM_ADDRESS);
return true;
}
return false;
}
//===========================================================================
bool ArgsGetImmediateValue ( Arg_t *pArg, WORD * pAddressValue_ )
{
if (pArg && pAddressValue_)
{
if (pArg->eToken == TOKEN_HASH)
{
pArg++;
return ArgsGetValue( pArg, pAddressValue_ );
}
}
return false;
}
// Processes the raw args, turning them into tokens and types.
//===========================================================================
int ArgsGet ( TCHAR * pInput )
{
LPCTSTR pSrc = pInput;
LPCTSTR pEnd = NULL;
int nBuf;
ArgToken_e iTokenSrc = NO_TOKEN;
ArgToken_e iTokenEnd = NO_TOKEN;
ArgType_e iType = TYPE_STRING;
int nLen;
int iArg = 0;
int nArg = 0;
Arg_t *pArg = &g_aArgRaw[0]; // &g_aArgs[0];
g_pConsoleFirstArg = NULL;
// BP FAC8:FACA // Range=3
// BP FAC8,2 // Length=2
// ^ ^^ ^^
// | || |pSrc
// | || pSrc
// | |pSrc
// | pEnd
// pSrc
while ((*pSrc) && (iArg < MAX_ARGS))
{
// Technically, there shouldn't be any leading spaces,
// since pressing the spacebar is an alias for TRACE.
// However, there is spaces between arguments
pSrc = const_cast<char*>( SkipWhiteSpace( pSrc ));
if (pSrc)
{
pEnd = FindTokenOrAlphaNumeric( pSrc, g_aTokens, NUM_TOKENS, &iTokenSrc );
if ((iTokenSrc == NO_TOKEN) || (iTokenSrc == TOKEN_ALPHANUMERIC))
{
pEnd = SkipUntilToken( pSrc+1, g_aTokens, NUM_TOKENS, &iTokenEnd );
}
if (iTokenSrc == NO_TOKEN)
{
iTokenSrc = TOKEN_ALPHANUMERIC;
}
iType = g_aTokens[ iTokenSrc ].eType;
if (iTokenSrc == TOKEN_SEMI)
{
// TODO - command seperator, must handle non-quoted though!
}
if (iTokenSrc == TOKEN_QUOTED)
{
pSrc++; // Don't store start of quote
pEnd = SkipUntilChar( pSrc, CHAR_QUOTED );
}
if (pEnd)
{
nBuf = pEnd - pSrc;
}
if (nBuf > 0)
{
nLen = MIN( nBuf, MAX_ARG_LEN-1 );
_tcsncpy( pArg->sArg, pSrc, nLen );
pArg->sArg[ nLen ] = 0;
pArg->nArgLen = nLen;
pArg->eToken = iTokenSrc;
pArg->bType = iType;
if (iTokenSrc == TOKEN_QUOTED)
{
pEnd++;
}
pSrc = pEnd;
iArg++;
pArg++;
if (iArg == 1)
{
g_pConsoleFirstArg = pSrc;
}
}
}
}
if (iArg)
{
nArg = iArg - 1; // first arg is command
}
g_nArgRaw = iArg;
return nArg;
}
//===========================================================================
bool ArgsGetRegisterValue ( Arg_t *pArg, WORD * pAddressValue_ )
{
bool bStatus = false;
if (pArg && pAddressValue_)
{
// Check if we refer to reg A X Y P S
for( int iReg = 0; iReg < (NUM_BREAKPOINT_SOURCES-1); iReg++ )
{
// Skip Opcode/Instruction/Mnemonic
if (iReg == BP_SRC_OPCODE)
continue;
// Skip individual flag names
if ((iReg >= BP_SRC_FLAG_C) && (iReg <= BP_SRC_FLAG_N))
continue;
// Handle one char names
if ((pArg->nArgLen == 1) && (pArg->sArg[0] == g_aBreakpointSource[ iReg ][0]))
{
switch( iReg )
{
case BP_SRC_REG_A : *pAddressValue_ = regs.a & 0xFF; bStatus = true; break;
case BP_SRC_REG_P : *pAddressValue_ = regs.ps & 0xFF; bStatus = true; break;
case BP_SRC_REG_X : *pAddressValue_ = regs.x & 0xFF; bStatus = true; break;
case BP_SRC_REG_Y : *pAddressValue_ = regs.y & 0xFF; bStatus = true; break;
case BP_SRC_REG_S : *pAddressValue_ = regs.sp ; bStatus = true; break;
default:
break;
}
}
else
if (iReg == BP_SRC_REG_PC)
{
if ((pArg->nArgLen == 2) && (_tcscmp( pArg->sArg, g_aBreakpointSource[ iReg ] ) == 0))
{
*pAddressValue_ = regs.pc ; bStatus = true; break;
}
}
}
}
return bStatus;
}
//===========================================================================
void ArgsRawParse ( void )
{
const int BASE = 16; // hex
TCHAR *pSrc = NULL;
TCHAR *pEnd = NULL;
int iArg = 1;
Arg_t *pArg = & g_aArgRaw[ iArg ];
int nArg = g_nArgRaw;
WORD nAddressArg;
WORD nAddressSymbol;
WORD nAddressValue;
int nParamLen = 0;
while (iArg <= nArg)
{
pSrc = & (pArg->sArg[ 0 ]);
nAddressArg = (WORD)(_tcstoul( pSrc, &pEnd, BASE) & _6502_END_MEM_ADDRESS);
nAddressValue = nAddressArg;
bool bFound = false;
if (! (pArg->bType & TYPE_NO_SYM))
{
bFound = FindAddressFromSymbol( pSrc, & nAddressSymbol );
if (bFound)
{
nAddressValue = nAddressSymbol;
pArg->bSymbol = true;
}
}
if (! (pArg->bType & TYPE_VALUE)) // already up to date?
pArg->nVal1 = nAddressValue;
pArg->bType |= TYPE_ADDRESS;
iArg++;
pArg++;
}
}
// Note: The number of args can be changed via:
// address1,length Length
// address1:address2 Range
// address1+delta Delta
// address1-delta Delta
//===========================================================================
int ArgsCook ( const int nArgs )
{
const int BASE = 16; // hex
TCHAR *pSrc = NULL;
TCHAR *pEnd2 = NULL;
int nArg = nArgs;
int iArg = 1;
Arg_t *pArg = NULL;
Arg_t *pPrev = NULL;
Arg_t *pNext = NULL;
WORD nAddressArg;
WORD nAddressRHS;
WORD nAddressSym;
WORD nAddressVal;
int nParamLen = 0;
int nArgsLeft = 0;
while (iArg <= nArg)
{
pArg = & (g_aArgs[ iArg ]);
pSrc = & (pArg->sArg[ 0 ]);
if (pArg->eToken == TOKEN_DOLLAR) // address
{
// TODO: Need to flag was a DOLLAR token for assembler
pNext = NULL;
nArgsLeft = (nArg - iArg);
if (nArgsLeft > 0)
{
pNext = pArg + 1;
_Arg_Shift( iArg + 1, nArgs, iArg );
nArg--;
iArg--; // inc for start of next loop
// Don't do register lookup
pArg->bType |= TYPE_NO_REG;
}
else
return ARG_SYNTAX_ERROR;
}
if (pArg->bType & TYPE_OPERATOR) // prev op type == address?
{
pPrev = NULL; // pLHS
pNext = NULL; // pRHS
nParamLen = 0;
if (pArg->eToken == TOKEN_HASH) // HASH # immediate
nParamLen = 1;
nArgsLeft = (nArg - iArg);
if (nArgsLeft < nParamLen)
{
return ARG_SYNTAX_ERROR;
}
pPrev = pArg - 1;
if (nArgsLeft > 0) // These ops take at least 1 argument
{
pNext = pArg + 1;
pSrc = &pNext->sArg[0];
nAddressVal = 0;
if (ArgsGetValue( pNext, & nAddressRHS ))
nAddressVal = nAddressRHS;
bool bFound = FindAddressFromSymbol( pSrc, & nAddressSym );
if (bFound)
{
nAddressVal = nAddressSym;
pArg->bSymbol = true;
}
if (pArg->eToken == TOKEN_COMMA) // COMMMA , length
{
pPrev->nVal2 = nAddressVal;
pPrev->eToken = TOKEN_COMMA;
pPrev->bType |= TYPE_ADDRESS;
pPrev->bType |= TYPE_LENGTH;
nParamLen = 2;
}
if (pArg->eToken == TOKEN_COLON) // COLON : range
{
pPrev->nVal2 = nAddressVal;
pPrev->eToken = TOKEN_COLON;
pPrev->bType |= TYPE_ADDRESS;
pPrev->bType |= TYPE_RANGE;
nParamLen = 2;
}
if (pArg->eToken == TOKEN_AMPERSAND) // AND & delta
{
if (! ArgsGetImmediateValue( pNext, & nAddressRHS ))
{
ArgsGetRegisterValue( pNext, & nAddressRHS );
}
pPrev->nVal1 &= nAddressRHS;
pPrev->bType |= TYPE_VALUE; // signal already up to date
nParamLen = 2;
}
if (pArg->eToken == TOKEN_PIPE) // OR | delta
{
if (! ArgsGetImmediateValue( pNext, & nAddressRHS ))
{
ArgsGetRegisterValue( pNext, & nAddressRHS );
}
pPrev->nVal1 |= nAddressRHS;
pPrev->bType |= TYPE_VALUE; // signal already up to date
nParamLen = 2;
}
if (pArg->eToken == TOKEN_CARET) // XOR ^ delta
{
if (! ArgsGetImmediateValue( pNext, & nAddressRHS ))
{
ArgsGetRegisterValue( pNext, & nAddressRHS );
}
pPrev->nVal1 ^= nAddressRHS;
pPrev->bType |= TYPE_VALUE; // signal already up to date
nParamLen = 2;
}
if (pArg->eToken == TOKEN_PLUS) // PLUS + delta
{
if (! ArgsGetImmediateValue( pNext, & nAddressRHS ))
{
ArgsGetRegisterValue( pNext, & nAddressRHS );
}
pPrev->nVal1 += nAddressRHS;
pPrev->bType |= TYPE_VALUE; // signal already up to date
nParamLen = 2;
}
if (pArg->eToken == TOKEN_MINUS) // MINUS - delta
{
if (! ArgsGetImmediateValue( pNext, & nAddressRHS ))
{
ArgsGetRegisterValue( pNext, & nAddressRHS );
}
pPrev->nVal1 -= nAddressRHS;
pPrev->bType |= TYPE_VALUE; // signal already up to date
nParamLen = 2;
}
if (pArg->eToken == TOKEN_PERCENT) // PERCENT % delta
{
if (! ArgsGetImmediateValue( pNext, & nAddressRHS ))
{
ArgsGetRegisterValue( pNext, & nAddressRHS );
}
pPrev->nVal1 %= nAddressRHS;
pPrev->bType |= TYPE_VALUE; // signal already up to date
nParamLen = 2;
}
if (pArg->eToken == TOKEN_FSLASH) // FORWARD SLASH / delta
{
if (! ArgsGetImmediateValue( pNext, & nAddressRHS ))
{
ArgsGetRegisterValue( pNext, & nAddressRHS );
}
pPrev->nVal1 /= nAddressRHS;
pPrev->bType |= TYPE_VALUE; // signal already up to date
nParamLen = 2;
}
if (pArg->eToken == TOKEN_EQUAL) // EQUAL = assign
{
pPrev->nVal1 = nAddressRHS;
pPrev->bType |= TYPE_VALUE; // signal already up to date
nParamLen = 0; // need token for Smart BreakPoints
}
if (pArg->eToken == TOKEN_HASH) // HASH # immediate
{
_Arg_Shift( iArg + nParamLen, nArgs, iArg );
nArg--;
pArg->nVal1 = nAddressRHS;
pArg->bSymbol = false;
pArg->bType = TYPE_VALUE | TYPE_ADDRESS | TYPE_NO_REG | TYPE_NO_SYM;
nParamLen = 0;
}
if (pArg->eToken == TOKEN_LESS_THAN) // <
{
nParamLen = 0;
}
if (pArg->eToken == TOKEN_GREATER_THAN) // >
{
nParamLen = 0;
}
if (pArg->eToken == TOKEN_EXCLAMATION) // NOT_EQUAL !
{
if (! ArgsGetImmediateValue( pNext, & nAddressRHS ))
{
if (! ArgsGetRegisterValue( pNext, & nAddressRHS ))
{
nAddressRHS = nAddressVal;
}
}
pArg->nVal1 = ~nAddressRHS;
pArg->bType |= TYPE_VALUE; // signal already up to date
// Don't remove, since "SYM ! symbol" needs token to remove symbol
}
if (nParamLen)
{
_Arg_Shift( iArg + nParamLen, nArgs, iArg );
nArg -= nParamLen;
iArg = 0; // reset args, to handle multiple operators
}
}
else
return ARG_SYNTAX_ERROR;
}
else // not an operator, try (1) address, (2) symbol lookup
{
nAddressArg = (WORD)(_tcstoul( pSrc, &pEnd2, BASE) & _6502_END_MEM_ADDRESS);
if (! (pArg->bType & TYPE_NO_REG))
{
ArgsGetRegisterValue( pArg, & nAddressArg );
}
nAddressVal = nAddressArg;
bool bFound = false;
if (! (pArg->bType & TYPE_NO_SYM))
{
bFound = FindAddressFromSymbol( pSrc, & nAddressSym );
if (bFound)
{
nAddressVal = nAddressSym;
pArg->bSymbol = true;
}
}
if (! (pArg->bType & TYPE_VALUE)) // already up to date?
pArg->nVal1 = nAddressVal;
pArg->bType |= TYPE_ADDRESS;
}
iArg++;
}
return nArg;
}
// Text Util ______________________________________________________________________________________
//===========================================================================
const char * ParserFindToken( const char *pSrc, const TokenTable_t *aTokens, const int nTokens, ArgToken_e * pToken_ )
{
const TokenTable_t *pToken= aTokens;
const TCHAR *pName = NULL;
for (int iToken = 0; iToken < nTokens; iToken++ )
{
pName = & (pToken->sToken);
if (*pSrc == *pName)
{
if ( pToken_)
{
*pToken_ = (ArgToken_e) iToken;
}
return pSrc;
}
pToken++;
}
return NULL;
}
//===========================================================================
const TCHAR * FindTokenOrAlphaNumeric ( const TCHAR *pSrc, const TokenTable_t *aTokens, const int nTokens, ArgToken_e * pToken_ )
{
if (pToken_)
*pToken_ = NO_TOKEN;
const TCHAR *pEnd = pSrc;
if (pSrc && (*pSrc))
{
if (isalnum( *pSrc ))
{
if (pToken_)
*pToken_ = TOKEN_ALPHANUMERIC;
}
else
{
pEnd = ParserFindToken( pSrc, aTokens, nTokens, pToken_ );
if (pEnd)
pEnd = pSrc + 1; // _tcslen( pToken );
else
pEnd = pSrc;
}
}
return pEnd;
}
//===========================================================================
void TextConvertTabsToSpaces( TCHAR *pDeTabified_, LPCTSTR pText, const int nDstSize, int nTabStop )
{
int nLen = _tcslen( pText );
int TAB_SPACING = 8;
int TAB_SPACING_1 = 16;
int TAB_SPACING_2 = 21;
if (nTabStop)
TAB_SPACING = nTabStop;
LPCTSTR pSrc = pText;
LPTSTR pDst = pDeTabified_;
int iTab = 0; // number of tabs seen
int nTab = 0; // gap left to next tab
int nGap = 0; // actual gap
int nCur = 0; // current cursor position
while (pSrc && *pSrc && (nCur < nDstSize))
{
if (*pSrc == CHAR_TAB)
{
if (nTabStop)
{
nTab = nCur % TAB_SPACING;
nGap = (TAB_SPACING - nTab);
}
else
{
if (nCur <= TAB_SPACING_1)
{
nGap = (TAB_SPACING_1 - nCur);
}
else
if (nCur <= TAB_SPACING_2)
{
nGap = (TAB_SPACING_2 - nCur);
}
else
{
nTab = nCur % TAB_SPACING;
nGap = (TAB_SPACING - nTab);
}
}
if ((nCur + nGap) >= nDstSize)
break;
for( int iSpc = 0; iSpc < nGap; iSpc++ )
{
*pDst++ = CHAR_SPACE;
}
nCur += nGap;
}
else
if ((*pSrc == CHAR_LF) || (*pSrc == CHAR_CR))
{
*pDst++ = 0; // *pSrc;
nCur++;
}
else
{
*pDst++ = *pSrc;
nCur++;
}
pSrc++;
}
*pDst = 0;
}
// @return Length of new string
//===========================================================================
int RemoveWhiteSpaceReverse ( TCHAR *pSrc )
{
int nLen = _tcslen( pSrc );
char *pDst = pSrc + nLen;
while (nLen--)
{
pDst--;
if (*pDst == CHAR_SPACE)
{
*pDst = 0;
}
else
{
break;
}
}
return nLen;
}
//===========================================================================
/*
inline
const TCHAR* SkipEOL ( const TCHAR *pSrc )
{
while (pSrc && ((*pSrc == CHAR_LF) || (*pSrc == CHAR_CR)))
{
pSrc++;
}
return pSrc;
}
*/
//===========================================================================
/*
inline
const TCHAR* SkipUntilChar ( const TCHAR *pSrc, const TCHAR nDelim )
{
while (pSrc && (*pSrc))
{
if (*pSrc == nDelim)
break;
pSrc++;
}
return pSrc;
}
*/
//===========================================================================
/*
inline
const TCHAR* SkipUntilEOL ( const TCHAR *pSrc )
{
while (pSrc && (*pSrc))
{
if ((*pSrc == CHAR_LF) || (*pSrc == CHAR_CR))
{
break;
}
pSrc++;
}
return pSrc;
}
*/
//===========================================================================
/*
inline
const TCHAR* SkipUntilTab ( const TCHAR *pSrc )
{
while (pSrc && (*pSrc))
{
if (*pSrc == CHAR_TAB)
{
break;
}
pSrc++;
}
return pSrc;
}
*/
//===========================================================================
/*
const TCHAR* SkipUntilToken ( const TCHAR *pSrc, const TokenTable_t *aTokens, const int nTokens, ArgToken_e *pToken_ )
{
if ( pToken_)
*pToken_ = NO_TOKEN;
while (pSrc && (*pSrc))
{
// Common case is TOKEN_ALPHANUMERIC, so continue until we don't have one
if (ParserFindToken( pSrc, aTokens, pToken_ ))
return pSrc;
pSrc++;
}
return pSrc;
}
*/
//===========================================================================
/*
inline
const TCHAR* SkipUntilWhiteSpace ( const TCHAR *pSrc )
{
while (pSrc && (*pSrc))
{
if ((*pSrc == CHAR_SPACE) || (*pSrc == CHAR_TAB))
{
break;
}
pSrc++;
}
return pSrc;
}
*/
// @param pStart Start of line.
//===========================================================================
/*
inline
const TCHAR *SkipUntilWhiteSpaceReverse ( const TCHAR *pSrc, const TCHAR *pStart )
{
while (pSrc && (pSrc > pStart))
{
if ((*pSrc == CHAR_SPACE) || (*pSrc == CHAR_TAB))
{
break;
}
pSrc--;
}
return pSrc;
}
*/
//===========================================================================
/*
inline
const TCHAR* SkipWhiteSpace ( const TCHAR *pSrc )
{
while (pSrc && ((*pSrc == CHAR_SPACE) || (*pSrc == CHAR_TAB)))
{
pSrc++;
}
return pSrc;
}
*/
// @param pStart Start of line.
//===========================================================================
/*
inline
const TCHAR *SkipWhiteSpaceReverse ( const TCHAR *pSrc, const TCHAR *pStart )
{
while (pSrc && ((*pSrc == CHAR_SPACE) || (*pSrc == CHAR_TAB)) && (pSrc > pStart))
{
pSrc--;
}
return pSrc;
}
*/
// EOF