📄 commandssupport.cpp
字号:
/************************************************************************************
Copyright (c) 2000 Aaron O'Neil
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1) Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2) Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3) Redistributions in binary form must reproduce the above copyright notice on
program startup. Additional credits for program modification are acceptable
but original copyright and credits must be visible at startup.
4) You may charge a reasonable copying fee for any distribution of Mud Master.
You may charge any fee you choose for support of Mud Master. You may not
charge a fee for Mud Master itself.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**************************************************************************************/
#include "StdAfx.h"
#include "Commands.h"
#include "Extern.h"
#include "MudWindow.h"
#include "DebugStack.h"
// Creates a backup of a file. Just adds ".bak" to the filename.
void BackupFile(const char *pszPath)
{
CString strMessage("Failed to make a backup file.");
CString strSource(pszPath);
CString strTarget(pszPath);
CFile fileSource, fileTarget;
int nBytes;
char *pBuf;
strTarget += ".bak";
if (!fileSource.Open(strSource,CFile::modeRead))
{
PrintMessage(strMessage+" Unable to open the original file.");
return;
}
if (!fileTarget.Open(strTarget,CFile::modeWrite|CFile::modeCreate))
{
fileSource.Close();
PrintMessage(strMessage+" Unable to create a new file.");
return;
}
pBuf = new char[5000];
if (!pBuf)
{
fileSource.Close();
fileTarget.Close();
PrintMessage(strMessage);
delete [] pBuf;
return;
}
nBytes = fileSource.GetLength();
while(nBytes > 0)
{
if (!fileSource.Read(pBuf,min(nBytes,5000)))
{
delete [] pBuf;
fileSource.Close();
fileTarget.Close();
PrintMessage(strMessage);
return;
}
fileTarget.Write(pBuf,min(nBytes,5000));
nBytes -= min(nBytes,5000);
}
delete [] pBuf;
fileSource.Close();
fileTarget.Close();
}
//////////////////////////
// If Functions
//
BOOL EvaluateLine(const char *pszLine)
{
CString strLine(pszLine);
int nLen = strLine.GetLength();
int nIndex = 0;
int nLeftIndex;
BOOL bInQuote = FALSE;
while(nIndex < nLen)
{
if (!bInQuote && strLine.GetAt(nIndex) == ')')
{
// Found an closing paren operator, need to evaluate
// the statemnet inside it.
nLeftIndex = LeftToToken(strLine,nIndex,"(");
// The left index could only be zero is a matching left
// paren was not found.
if (nLeftIndex == 0)
{
if (_config.bDebugMessages)
{
PrintMessage(CString("Missing opening paren: ")+pszLine,TRUE,TRUE);
_debugStack.DumpStack(_config.nDebugDepth);
}
return(FALSE);
}
CString strStatement(strLine.Mid(nLeftIndex,nIndex-nLeftIndex));
if (!EvaluateStatement(strStatement))
return(FALSE);
// Replace what was in the parens with something that evaluates
// to TRUE.
strLine = strLine.Left(nLeftIndex-1) + CString("1") + strLine.Right(nLen-nIndex-2);
nLen = strLine.GetLength();
nIndex = 0;
continue;
}
if (strLine.GetAt(nIndex) == '\\' && nIndex+1 < nLen && strLine.GetAt(nIndex+1) == '"')
{
nIndex += 2;
continue;
}
if (strLine.GetAt(nIndex) == '"')
if (bInQuote)
bInQuote = FALSE;
else
bInQuote = TRUE;
nIndex++;
}
return(EvaluateStatement(strLine));
}
BOOL EvaluateStatement(const char *pszStatement)
{
// Remove all the spaces from the string.
CString strStatement(pszStatement);
int nLen = strStatement.GetLength();
int nIndex = 0;
int nLeftIndex, nRightIndex;
CString strCondition;
BOOL bInQuote = FALSE;
while(nIndex < nLen)
{
if (!bInQuote && strStatement.GetAt(nIndex) == '&' && nIndex+1 < nLen && strStatement.GetAt(nIndex) == '&')
{
// Found an && operator.
nLeftIndex = LeftToToken(strStatement,nIndex,"&&");
nRightIndex = RightToToken(strStatement,nIndex+1,"&&");
if (!EvaluateCondition(strStatement.Mid(nLeftIndex,nIndex-nLeftIndex)) ||
!EvaluateCondition(strStatement.Mid(nIndex+2,nRightIndex-nIndex)))
return(FALSE);
// Remove those 2 statements and replace with a statement that
// will evaluate to true.
strStatement = strStatement.Left(nLeftIndex) + CString("1") + strStatement.Right(nLen-nRightIndex-1);
nLen = strStatement.GetLength();
nIndex = 0;
continue;
}
if (strStatement.GetAt(nIndex) == '\\' && nIndex+1 < nLen && strStatement.GetAt(nIndex+1) == '"')
{
nIndex += 2;
continue;
}
if (strStatement.GetAt(nIndex) == '"')
if (bInQuote)
bInQuote = FALSE;
else
bInQuote = TRUE;
nIndex++;
}
// Look for ||
nIndex = 0;
bInQuote = FALSE;
while(nIndex < nLen)
{
if (!bInQuote && strStatement.GetAt(nIndex) == '|' && nIndex+1 < nLen && strStatement.GetAt(nIndex) == '|')
{
// Found an && operator.
nLeftIndex = LeftToToken(strStatement,nIndex,"||");
nRightIndex = RightToToken(strStatement,nIndex+1,"||");
if (!EvaluateCondition(strStatement.Mid(nLeftIndex,nIndex-nLeftIndex)) &&
!EvaluateCondition(strStatement.Mid(nIndex+2,nRightIndex-nIndex)))
return(FALSE);
// Remove those 2 statements and replace with a statement that
// will evaluate to true.
strStatement = strStatement.Left(nLeftIndex) + CString("1") + strStatement.Right(nLen-nRightIndex-1);
nLen = strStatement.GetLength();
nIndex = 0;
continue;
}
if (strStatement.GetAt(nIndex) == '\\' && nIndex+1 < nLen && strStatement.GetAt(nIndex+1) == '"')
{
nIndex += 2;
continue;
}
if (strStatement.GetAt(nIndex) == '"')
if (bInQuote)
bInQuote = FALSE;
else
bInQuote = TRUE;
nIndex++;
}
return(EvaluateCondition(strStatement));
}
int LeftToToken(const char *pszText, int nStart, const char *pszToken)
{
BOOL bInQuote = FALSE;
int nTokenLen = strlen(pszToken);
int nMaxPrev = nTokenLen - 1;
while(nStart > -1)
{
if (*(pszText+nStart) == '"' && nStart > 0 && *(pszText+nStart-1) == '\\')
{
nStart -= 2;
continue;
}
if (*(pszText+nStart) == '"')
{
if (bInQuote)
bInQuote = FALSE;
else
bInQuote = TRUE;
nStart--;
continue;
}
if (bInQuote)
{
nStart--;
continue;
}
if (nStart-nMaxPrev > -1 && !memcmp(pszText+(nStart-nMaxPrev),pszToken,nTokenLen))
return(nStart+1);
nStart--;
}
// If fell out of the loop it is because we reached the start of
// the buffer, return index 0.
return(0);
}
int RightToToken(const char *pszText, int nStart, const char *pszToken)
{
BOOL bInQuote = FALSE;
int nLen = strlen(pszText);
int nTokenLen = strlen(pszToken);
int nMaxPrev = nTokenLen - 1;
while(nStart < nLen)
{
if (*(pszText+nStart) == '\\' && nStart+1 < nLen && *(pszText+nStart+1) == '"')
{
nStart += 2;
continue;
}
if (*(pszText+nStart) == '"')
{
if (bInQuote)
bInQuote = FALSE;
else
bInQuote = TRUE;
nStart++;
continue;
}
if (bInQuote)
{
nStart++;
continue;
}
if (nStart+nMaxPrev < nLen && !memcmp(pszText+nStart,pszToken,nTokenLen))
return(nStart-1);
nStart++;
}
return(nLen-1);
}
BOOL EvaluateCondition(const char *pszCondition)
{
// Expecting something in the form of: "Arithon"=="Arithon"
// or 1 > 2, etc...
CString strCond(pszCondition);
strCond.TrimRight();
strCond.TrimLeft();
// After trimming the first character must either be a quote for
// a string or a number. If it isn't, return FALSE.
if (!isdigit(strCond[0]) && strCond[0] != '"' && strCond[0] != '-')
{
if (_config.bDebugMessages && _config.bShowMismatches)
{
PrintMessage(CString("Error in condition (strings must use quotes): ")+pszCondition,TRUE,TRUE);
_debugStack.DumpStack(_config.nDebugDepth);
}
return(FALSE);
}
// If this is a string condition handle it differently. This
// will be a bit more code but I think it will go a little faster
// if I just do it all separately.
if (strCond[0] == '"')
{
CString strLeft;
int nLen = strCond.GetLength();
int nIndex = 1;
while(nIndex < nLen)
{
// If we find a backslash, and the next char is a quote,
// then this is an embedded quoation, want to keep it.
if (strCond.GetAt(nIndex) == _config.chEscape && nIndex+1 < nLen && strCond.GetAt(nIndex+1) == '"')
{
strLeft += '"';
nIndex += 2;
continue;
}
// If we find the closing quote then break out of loop.
if (strCond.GetAt(nIndex) == '"')
break;
strLeft += strCond.GetAt(nIndex);
nIndex++;
}
// If already at the end then it is an invalid condition.
if (nIndex >= nLen-1)
{
if (_config.bDebugMessages)
{
PrintMessage(CString("Invalid conditional: ")+pszCondition,TRUE,TRUE);
_debugStack.DumpStack(_config.nDebugDepth);
}
return(FALSE);
}
// Walk the string to the next quote character and we should
// have our operator.
CString strOperator;
nIndex++;
while(nIndex < nLen)
{
if (strCond.GetAt(nIndex) == '"')
break;
strOperator += strCond.GetAt(nIndex);
nIndex++;
}
// Same deal, if at end of line then it is an incomplete
// condition.
nIndex++;
if (nIndex >= nLen)
{
if (_config.bDebugMessages && _config.bShowMismatches)
{
PrintMessage(CString("Error in condition (strings must use quotes): ")+pszCondition,TRUE,TRUE);
_debugStack.DumpStack(_config.nDebugDepth);
}
return(FALSE);
}
strOperator.TrimLeft();
strOperator.TrimRight();
if (strOperator.IsEmpty())
{
if (_config.bDebugMessages)
{
PrintMessage(CString("Condition missing operator: ")+pszCondition,TRUE,TRUE);
_debugStack.DumpStack(_config.nDebugDepth);
}
return(FALSE);
}
// Now pick up the right side of the condition.
CString strRight;
while(nIndex < nLen)
{
// If we find a backslash, and the next char is a quote,
// then this is an embedded quoation, want to keep it.
if (strCond.GetAt(nIndex) == _config.chEscape && nIndex+1 < nLen && strCond.GetAt(nIndex+1) == '"')
{
strRight += '"';
nIndex += 2;
continue;
}
// If we find the closing quote then break out of loop.
if (strCond.GetAt(nIndex) == '"')
break;
strRight += strCond.GetAt(nIndex);
nIndex++;
}
// Do the comparison.
if (strOperator == "=" || strOperator == "==")
return(strLeft == strRight);
else
if (strOperator == "!=")
return(strLeft != strRight);
else
if (strOperator == ">")
return(strLeft > strRight);
else
if (strOperator == "<")
return(strLeft < strRight);
else
if (strOperator == ">=")
return(strLeft >= strRight);
else
if (strOperator == "<=")
return(strLeft <= strRight);
else
{
if (_config.bDebugMessages)
{
PrintMessage(CString("Invalid operator: ")+pszCondition,TRUE,TRUE);
_debugStack.DumpStack(_config.nDebugDepth);
}
return(FALSE);
}
}
// Must be a number condition.
double nLeft = atof(strCond);
int nIndex = 0;
int nLen = strCond.GetLength();
while(nIndex < nLen && (strCond.GetAt(nIndex) == ' ' || isdigit(strCond.GetAt(nIndex)) || strCond.GetAt(nIndex) == '-'))
nIndex++;
// Walk the string to the next space or digit, should then have
// our operator
CString strOperator;
while(nIndex < nLen)
{
if (strCond.GetAt(nIndex) == ' ' || strCond.GetAt(nIndex) == '-' || isalnum(strCond.GetAt(nIndex)))
break;
strOperator += strCond.GetAt(nIndex);
nIndex++;
}
// If there is not an operator, evalute the number.
if (strOperator.IsEmpty())
return((int)nLeft);
// Eat spaces on right of operator.
while(nIndex < nLen && !isalnum(strCond.GetAt(nIndex)) && strCond.GetAt(nIndex) != '-')
nIndex++;
// Operator found but nothing on right of it.
if (nIndex >= nLen)
{
if (_config.bDebugMessages)
{
PrintMessage(CString("Invalid conditional: ")+pszCondition,TRUE,TRUE);
_debugStack.DumpStack(_config.nDebugDepth);
}
return(FALSE);
}
// Right side of operator is text.
if (isalpha(strCond.GetAt(nIndex)))
{
if (_config.bDebugMessages && _config.bShowMismatches)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -