// ***************************************************************************
// Function:    For
// Description: Our '/for' command
// Usage:       /for v# <start> <to|downto> <end>
// ***************************************************************************
VOID For(PSPAWNINFO pChar, PCHAR szLine)
{
    bRunNextCommand = TRUE;
    CHAR ArgLoop[MAX_STRING] = {0};
    CHAR ArgStart[MAX_STRING] = {0};
    CHAR ArgDirection[MAX_STRING] = {0};
    CHAR ArgEnd[MAX_STRING] = {0};

    GetArg(ArgLoop,szLine,1);
    GetArg(ArgStart,szLine,2);
    GetArg(ArgDirection,szLine,3);
    GetArg(ArgEnd,szLine,4);
    _strlwr(ArgDirection);

    PDATAVAR pVar = FindMQ2DataVariable(ArgLoop);
    if (!pVar)
    {
        FatalError("/for loop using invalid variable");
        return;
    }
    if (pVar->Var.Type!=pIntType)
    {
        FatalError("/for loops must use an int variable");
        return;
    }
    if ((ArgStart[0] == 0) || (ArgDirection[0] == 0) || (ArgEnd[0] == 0) || ((strcmp(ArgDirection,"to")) && (strcmp(ArgDirection,"downto")))) {
        FatalError("Usage: /for <variable> <start> <to|downto> <end> [step x]");
        return;
    }
    if (!gMacroBlock) {
        MacroError("Can only use /for during a macro.");
        return;
    }

    if (!pVar->Var.Type->FromString(pVar->Var.VarPtr,ArgStart))
    {
        FatalError("/for loop could not assign value '%s' to variable",ArgStart);
        return;
    }

}
// ***************************************************************************
// Function:    Next
// Description: Our '/next' command
// Usage:       /next v#
// ***************************************************************************
VOID Next(PSPAWNINFO pChar, PCHAR szLine)
{
    bRunNextCommand = TRUE;
    CHAR szComp[MAX_STRING] = {0};
    CHAR ForLine[MAX_STRING] = {0};
    CHAR szNext[MAX_STRING] = {0};
    PMACROBLOCK pMacroLine = gMacroBlock;
    LONG StepSize = 1;
    GetArg(szNext,szLine,1);

    PDATAVAR pVar = FindMQ2DataVariable(szNext);
    if (!pVar)
    {
        FatalError("/next using invalid variable");
        return;
    }
    if (pVar->Var.Type!=pIntType)
    {
        FatalError("/for loops must use an int variable");
        return;
    }

    if (!gMacroBlock) {
        MacroError("Can only use /next during a macro.");
        return;
    }
    sprintf(szComp,"/for %s ",pVar->szName);
    while (pMacroLine->pPrev) {
        strcpy(ForLine,pMacroLine->Line);
        if (!strnicmp(ForLine,"Sub ",4)) {
            FatalError("/next without matching /for");
            return;
        }
        if (strnicmp(ForLine,"/for ",5)) {
            pMacroLine = pMacroLine->pPrev;
            continue;
        }
        if (!strnicmp(ParseMacroParameter(pChar,ForLine),szComp,strlen(szComp))) {
            if (!gMacroBlock) {
                // PMP bailed on us, we need to exit...
                return;
            }
            CHAR szTemp[MAX_STRING] = {0};
            DWORD VarNum = atoi(szLine+1);
            LONG Loop;
            if (strstr(_strlwr(strcpy(szTemp,ForLine)),"step")) {
                PCHAR pTemp = strstr(szTemp,"step")+4;
                while ( (pTemp[0]!=0) && (pTemp[0]!=' ') && (pTemp[0]!='\t')) pTemp++;
                if (pTemp[0]!=0) StepSize = atoi(pTemp);
            }

            pVar = FindMQ2DataVariable(szNext);
            if (!pVar)
            {
                FatalError("/next without badly matching /for");
                return;
            }

            if (strstr(_strlwr(strcpy(szTemp,ForLine)),"downto")) 
            {
                Loop = atoi(strstr(szTemp,"downto")+7);
                DebugSpewNoFile("Next - End of loop %d downto %d", pVar->Var.Int, Loop);
                pVar->Var.Int-=StepSize;
                if (pVar->Var.Int >= Loop) 
                    gMacroBlock = pMacroLine;
            } 
            else 
            {
                Loop = atoi(strstr(szTemp,"to")+3);
                DebugSpewNoFile("Next - End of loop %d to %d", pVar->Var.Int, Loop);
                pVar->Var.Int+=StepSize;
                if (pVar->Var.Int <= Loop) 
                    gMacroBlock = pMacroLine;
            }
            return;
        }
        pMacroLine = pMacroLine->pPrev;
    }

    FatalError("/next without matching /for");
}
예제 #3
0
BOOL ParseMQ2DataPortion(PCHAR szOriginal, MQ2TYPEVAR &Result)
{
	Result.Type = 0;
	Result.DWord = 0;
	// Find [] before a . or null
	PCHAR pPos = &szOriginal[0];
	PCHAR pStart = pPos;
	CHAR Index[MAX_STRING] = { 0 };
	PCHAR pIndex = &Index[0];
	BOOL Quote = FALSE;
	while (1)
	{
		if (*pPos == 0)
		{
			// end completely. process
			if (pStart == pPos)
			{
				if (!Result.Type)
				{
					MQ2DataError("Nothing to parse");
					return FALSE;
				}
				//Result.Type->ToString(Result.VarPtr,szCurrent);
				return TRUE;
			}
			else
			{
				if (!Result.Type)
				{
					if (PMQ2DATAITEM DataItem = FindMQ2Data(pStart))
					{
						if (!DataItem->Function(pIndex, Result))
						{
							return FALSE;
						}
					}
					else if (PDATAVAR DataVar = FindMQ2DataVariable(pStart))
					{
						if (pIndex[0])
						{
							if (DataVar->Var.Type == pArrayType)
							{
								if (!((CDataArray*)DataVar->Var.Ptr)->GetElement(pIndex, Result))
								{
									return FALSE;
								}
							}
						}
						else
							Result = DataVar->Var;
					}
					else
					{
						//MQ2DataError("No such Top-Level Object '%s'",pStart);
						return FALSE;
					}
				}
				else
				{
					if (!Result.Type->GetMember(Result.VarPtr, pStart, pIndex, Result))
					{
						if (!Result.Type->FindMember(pStart) && !Result.Type->InheritedMember(pStart))
						{
							MQ2DataError("No such '%s' member '%s'", Result.Type->GetName(), pStart);
						}
						return FALSE;
					}
				}
			}
			//Result.Type->ToString(Result.VarPtr,szCurrent);

			// done processing
			return TRUE;
		}
		if (*pPos == '(')
		{
			*pPos = 0;
			if (pStart == pPos)
			{
				if (!Result.Type)
				{
					MQ2DataError("Encountered typecast without object to cast");
					return FALSE;
				}
				//Result.Type->ToString(Result.VarPtr,szCurrent);
				return TRUE;
			}
			else
			{
				if (!Result.Type)
				{
					if (PMQ2DATAITEM DataItem = FindMQ2Data(pStart))
					{
						if (!DataItem->Function(pIndex, Result))
						{
							return FALSE;
						}
					}
					else if (PDATAVAR DataVar = FindMQ2DataVariable(pStart))
					{
						if (pIndex[0])
						{
							if (DataVar->Var.Type == pArrayType)
							{
								if (!((CDataArray*)DataVar->Var.Ptr)->GetElement(pIndex, Result))
								{
									return FALSE;
								}
							}
						}
						else
							Result = DataVar->Var;
					}
					else
					{
						//MQ2DataError("No such Top-Level Object '%s'",pStart);
						return FALSE;
					}

				}
				else
				{
					if (!Result.Type->GetMember(Result.VarPtr, pStart, pIndex, Result))
					{
						if (!Result.Type->FindMember(pStart) && !Result.Type->InheritedMember(pStart))
						{
							MQ2DataError("No such '%s' member '%s'", Result.Type->GetName(), pStart);
						}
						return FALSE;
					}
				}
			}
			if (!Result.Type)
			{
				// error
				return FALSE;
			}
			*pPos = 0;
			++pPos;
			PCHAR pType = pPos;
			while (*pPos != ')')
			{
				if (!*pPos)
				{
					// error
					MQ2DataError("Encountered unmatched parenthesis");
					return FALSE;
				}
				++pPos;
			}
			*pPos = 0;
			MQ2Type *pNewType = FindMQ2DataType(pType);
			if (!pNewType)
			{
				// error
				MQ2DataError("Unknown type '%s'", pType);
				return FALSE;
			}
			if (pNewType == pTypeType)
			{
				Result.Ptr = Result.Type;
				Result.Type = pTypeType;
			}
			else
				Result.Type = pNewType;

			if (pPos[1] == '.')
			{
				++pPos;
				pStart = &pPos[1];
			}
			else if (!pPos[1])
			{
				//Result.Type->ToString(Result.VarPtr,szCurrent);
				return TRUE;
			}
			else
			{
				MQ2DataError("Invalid character found after typecast ')%s'", &pPos[1]);
				return FALSE;
			}
		}
		else
			if (*pPos == '[')
			{
				// index
				*pPos = 0;
				++pPos;

				Quote = false;
				BOOL BeginParam = true;
				while (1)
				{
					if (*pPos == 0)
					{
						MQ2DataError("Unmatched bracket or invalid character following bracket found in index: '%s'", pIndex);
						return FALSE;
					}

					if (BeginParam)
					{
						BeginParam = false;
						if (*pPos == '\"')
						{
							Quote = true;
							++pPos;
							continue;
						}
					}
					if (Quote)
					{
						if (*pPos == '\"')
						{
							if (pPos[1] == ']' || pPos[1] == ',')
							{
								Quote = false;
								++pPos;
								continue;
							}
						}
					}
					else
					{
						if (*pPos == ']')
						{
							if (pPos[1] == '.' || pPos[1] == '(' || pPos[1] == 0)
								break;// valid end
						}
						else if (*pPos == ',')
							BeginParam = true;
					}
					*pIndex = *pPos;
					++pIndex;
					++pPos;
				}

				*pIndex = 0;
				pIndex = &Index[0];
				*pPos = 0;
			}
			else
				if (*pPos == '.')
				{
					// end of this one, but more to come!
					*pPos = 0;
					if (pStart == pPos)
					{
						if (!Result.Type)
						{
							MQ2DataError("Encountered member access without object");
							return FALSE;
						}
						//Result.Type->ToString(Result.VarPtr,szCurrent);
						return TRUE;
					}
					else
					{
						if (!Result.Type)
						{
							if (PMQ2DATAITEM DataItem = FindMQ2Data(pStart))
							{
								if (!DataItem->Function(pIndex, Result))
								{
									return FALSE;
								}
							}
							else if (PDATAVAR DataVar = FindMQ2DataVariable(pStart))
							{
								if (pIndex[0])
								{
									if (DataVar->Var.Type == pArrayType)
									{
										if (!((CDataArray*)DataVar->Var.Ptr)->GetElement(pIndex, Result))
										{
											return FALSE;
										}
									}
								}
								else
									Result = DataVar->Var;
							}
							else
							{
								//MQ2DataError("No such Top-Level Object '%s'",pStart);
								return FALSE;
							}

						}
						else
						{
							if (!Result.Type->GetMember(Result.VarPtr, pStart, pIndex, Result))
							{
								if (!Result.Type->FindMember(pStart) && !Result.Type->InheritedMember(pStart))
								{
									MQ2DataError("No such '%s' member '%s'", Result.Type->GetName(), pStart);
								}
								return FALSE;
							}
						}
					}
					pStart = &pPos[1];
					Index[0] = 0;
				}
		++pPos;
	}

}
예제 #4
0
bool EvaluateDataExpression(MQ2TYPEVAR& Result, PCHAR pStart, PCHAR pIndex, bool function_allowed = false)
{
	if (!Result.Type)
	{
		if (!gWarning) {//if they have warnings turned on in the macro, we will disregard checking the map
			if (gUndeclaredVars.find(pStart) != gUndeclaredVars.end())
				return false;//its a undefined variable no point in moving on further.
		}
		if (PMQ2DATAITEM DataItem = FindMQ2Data(pStart))
		{
			if (!DataItem->Function(pIndex, Result))
			{
				return false;
			}
		}
		else if (PDATAVAR DataVar = FindMQ2DataVariable(pStart))
		{
			if (pIndex[0])
			{
				if (DataVar->Var.Type == pArrayType)
				{
					if (!((CDataArray*)DataVar->Var.Ptr)->GetElement(pIndex, Result))
					{
						return false;
					}
				}
			}
			else
				Result = DataVar->Var;
		}
		else if (function_allowed && function_exists(pStart))
		{
			if (!call_function(pStart, pIndex))
				return false;
			strcpy_s(DataTypeTemp, gMacroStack->Return);
			Result.Ptr = &DataTypeTemp[0];
			Result.Type = pStringType;
		}
		else
		{
			if (gMacroBlock) {
				if (gWarning) {
					DumpWarning(pStart,gMacroBlock->CurrIndex);
				}
				gUndeclaredVars[pStart] = gMacroBlock->CurrIndex;
			}
			return false;
		}
	}
	else
	{
		int result = FindMacroDataMember(Result.Type, Result, pStart, pIndex);
		if (result < 0)
		{
			MQ2DataError("No such '%s' member '%s'", Result.Type->GetName(), pStart);
		}
		if (result <= 0)
			return false;
	}
	return true;
}