// *************************************************************************** // 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"); }
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; } }
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; }