void CListWrapper::PaintImageAtCursor (CG16bitImage &Dest, int x, int y) // PaintImageAtCursor // // Paints the image for the current element { if (!IsCursorValid()) return; ICCItem *pItem = m_pList->GetElement(m_iCursor); if (pItem->GetCount() <= ICON_INDEX) return; ICCItem *pIcon = pItem->GetElement(ICON_INDEX); if (pIcon->GetCount() < IMAGE_ELEMENTS) return; CG16bitImage *pImage = g_pUniverse->GetLibraryBitmap(pIcon->GetElement(IMAGE_UNID_INDEX)->GetIntegerValue()); if (pImage == NULL) return; Dest.ColorTransBlt(pIcon->GetElement(IMAGE_X_INDEX)->GetIntegerValue(), pIcon->GetElement(IMAGE_Y_INDEX)->GetIntegerValue(), ICON_WIDTH, ICON_HEIGHT, 255, *pImage, x, y); }
ICCItem *fnSubst (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnSubst // // Substitutes string parameters // // (subst string arg1 arg2 ... argn) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("s*")); if (pArgs->IsError()) return pArgs; CString sPattern = pArgs->GetElement(0)->GetStringValue(); // Do the substitution char szResult[4096]; char *pPos = sPattern.GetASCIIZPointer(); char *pDest = szResult; char *pEndDest = szResult + sizeof(szResult) - 1; while (*pPos != '\0' && pDest < pEndDest) { if (*pPos == '%') { pPos++; int iArg = strParseInt(pPos, 0, &pPos, NULL); if (iArg > 0) { CString sParam = pArgs->GetElement(iArg)->GetStringValue(); char *pParam = sParam.GetASCIIZPointer(); while (*pParam != '\0' && pDest < pEndDest) *pDest++ = *pParam++; pPos++; } else { if (*pPos == '%') *pDest++ = *pPos++; } } else *pDest++ = *pPos++; } // Done *pDest = '\0'; pArgs->Discard(pCC); return pCC->CreateString(CString(szResult)); }
ICCItem *fnAtmCreate (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnAtmCreate // // Creates a new atom table // // (atmAtomTable ((atom1 entry1) (atom2 entry2) ... (atomn entryn))) -> atmtable { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pAtomTable; ICCItem *pList; int i; // Evaluate the argument pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("l")); if (pArgs->IsError()) return pArgs; // Create the table pAtomTable = pCC->CreateAtomTable(); if (pAtomTable->IsError()) return pAtomTable; // Add each entry pList = pArgs->Head(pCC); for (i = 0; i < pList->GetCount(); i++) { ICCItem *pPair = pList->GetElement(i); ICCItem *pResult; // Make sure we have two elements if (pPair->GetCount() != 2) { pAtomTable->Discard(pCC); return pCC->CreateError(CONSTLIT("Invalid format for atom table entry:"), pPair); } // Get the atom and the entry pResult = pAtomTable->AddEntry(pCC, pPair->GetElement(0), pPair->GetElement(1)); if (pResult->IsError()) { pAtomTable->Discard(pCC); return pResult; } pResult->Discard(pCC); } // Done pArgs->Discard(pCC); return pAtomTable; }
ICCItem *fnRandom (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnRandom // // (random from to) -> number // (random list) -> random item in list { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pResult; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("*")); if (pArgs->IsError()) return pArgs; // Do stuff based on parameters if (pArgs->GetCount() == 2) { int iOp1 = pArgs->GetElement(0)->GetIntegerValue(); int iOp2 = pArgs->GetElement(1)->GetIntegerValue(); pArgs->Discard(pCC); pResult = pCC->CreateInteger(mathRandom(iOp1, iOp2)); } else if (pArgs->GetCount() == 1) { ICCItem *pList = pArgs->GetElement(0); if (pList->IsNil()) pResult = pCC->CreateNil(); else if (pList->GetCount() == 0) pResult = pCC->CreateNil(); else pResult = pList->GetElement(mathRandom(0, pList->GetCount()-1))->Reference(); pArgs->Discard(pCC); } else { pResult = pCC->CreateNil(); pArgs->Discard(pCC); } // Done return pResult; }
ICCItem *fnStrCapitalize (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnStrCapitalize // // Capitalizes the string // // (strCapitalize string) -> string { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("s")); if (pArgs->IsError()) return pArgs; CString sString = pArgs->GetElement(0)->GetStringValue(); pArgs->Discard(pCC); // Done sString.Capitalize(CString::capFirstLetter); return pCC->CreateString(sString); }
ICCItem *fnAppend (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData) // fnAppend // // Appends two or more elements together { int i, j; CCodeChain *pCC = pCtx->pCC; // Create a new list to store the result in ICCItem *pResult = pCC->CreateLinkedList(); if (pResult->IsError()) return pResult; CCLinkedList *pList = (CCLinkedList *)pResult; // Loop over all arguments and add to result list for (i = 0; i < pArgs->GetCount(); i++) { ICCItem *pItem = pArgs->GetElement(i); for (j = 0; j < pItem->GetCount(); j++) pList->Append(pCC, pItem->GetElement(j), NULL); } // Done return pResult; }
ICCItem *fnCat (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnCat // // Concatenates the given strings // // (cat string1 string2 ... stringn) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pResult; CString sResult; int i; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("*")); if (pArgs->IsError()) return pArgs; // Append each of the items for (i = 0; i < pArgs->GetCount(); i++) sResult.Append(pArgs->GetElement(i)->GetStringValue()); pResult = pCC->CreateString(sResult); // Done pArgs->Discard(pCC); return pResult; }
ICCItem *fnEval (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnEval // // Evaluates an expression // // (eval exp) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pResult; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("v")); if (pArgs->IsError()) return pArgs; pResult = pCC->Eval(pCtx, pArgs->GetElement(0)); // Done pArgs->Discard(pCC); return pResult; }
ICCItem *fnShuffle (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData) // fnShuffle // // Shuffles a list randomly { int i; CCodeChain *pCC = pCtx->pCC; if (pArgs->GetElement(0)->IsNil()) return pCC->CreateNil(); // Create a destination list ICCItem *pResult = pCC->CreateLinkedList(); if (pResult->IsError()) return pResult; CCLinkedList *pList = (CCLinkedList *)pResult; // Copy the list ICCItem *pSource = pArgs->GetElement(0); for (i = 0; i < pSource->GetCount(); i++) pList->Append(pCC, pSource->GetElement(i), NULL); // Shuffle the new list pList->Shuffle(pCC); // Done return pResult; }
ICCItem *fnVector (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnVector // // Vector functions // // (vecSetElement vector index element) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; CCVector *pVector; BOOL bOk; // Evaluate the arguments pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("vii")); if (pArgs->IsError()) return pArgs; // Get the vector pVector = dynamic_cast<CCVector *>(pArgs->GetElement(0)); if (pVector == NULL) { ICCItem *pError = pCC->CreateError(CONSTLIT("Vector expected:"), pArgs->GetElement(0));; pArgs->Discard(pCC); return pError; } // Set the element bOk = pVector->SetElement(pArgs->GetElement(1)->GetIntegerValue(), pArgs->GetElement(2)->GetIntegerValue()); if (!bOk) { pArgs->Discard(pCC); return pCC->CreateError(CONSTLIT("Unable to set vector element"), NULL); } // Done pArgs->Discard(pCC); return pCC->CreateTrue(); }
ICCItem *fnItem (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnItem // // Returns nth entry in a list (0-based) // // (item list nth) -> item { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pResult; ICCItem *pList; int iIndex; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("li")); if (pArgs->IsError()) return pArgs; // The first argument is the list pList = pArgs->Head(pCC); iIndex = pArgs->GetElement(1)->GetIntegerValue(); pResult = pList->GetElement(iIndex); if (pResult == NULL) pResult = pCC->CreateNil(); else pResult = pResult->Reference(); // Done pArgs->Discard(pCC); return pResult; }
CString CListWrapper::GetDescAtCursor (void) // GetDescAtCursor // // Returns the description of the list element { if (IsCursorValid()) { ICCItem *pItem = m_pList->GetElement(m_iCursor); if (DESC_INDEX < pItem->GetCount()) return pItem->GetElement(DESC_INDEX)->GetStringValue(); } return NULL_STR; }
CString CListWrapper::GetTitleAtCursor (void) // GetTitleAtCursor // // Returns the title of the list element { if (IsCursorValid()) { ICCItem *pItem = m_pList->GetElement(m_iCursor); if (TITLE_INDEX < pItem->GetCount()) return pItem->GetElement(TITLE_INDEX)->GetStringValue(); } return NULL_STR; }
ICCItem *fnFind (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData) // fnFind // // Finds a target in a source { int i; CCodeChain *pCC = pCtx->pCC; // Get the source and target ICCItem *pSource = pArgs->GetElement(0); ICCItem *pTarget = pArgs->GetElement(1); // If this is a list, then look for the target in the list and // return the item position in the list int iPos; if (pSource->IsList()) { iPos = -1; for (i = 0; i < pSource->GetCount(); i++) { ICCItem *pItem = pSource->GetElement(i); if (HelperCompareItems(pItem, pTarget) == 0) { iPos = i; break; } } } // Otherwise, look for the target string in the source string else { iPos = strFind(pSource->GetStringValue(), pTarget->GetStringValue()); } // Done if (iPos == -1) return pCC->CreateNil(); else return pCC->CreateInteger(iPos); }
ICCItem *fnSeededRandom (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData) // fnSeededRandom // // (seededRandom seed from to) -> number // (seededRandom seed list) -> random item in list { CCodeChain *pCC = pCtx->pCC; ICCItem *pResult; int iSeed = pArgs->GetElement(0)->GetIntegerValue(); // Do stuff based on parameters if (pArgs->GetCount() == 3) { int iOp1 = pArgs->GetElement(1)->GetIntegerValue(); int iOp2 = pArgs->GetElement(2)->GetIntegerValue(); pResult = pCC->CreateInteger(mathSeededRandom(iSeed, iOp1, iOp2)); } else if (pArgs->GetCount() == 2) { ICCItem *pList = pArgs->GetElement(1); if (pList->IsNil()) pResult = pCC->CreateNil(); else if (pList->GetCount() == 0) pResult = pCC->CreateNil(); else pResult = pList->GetElement(mathSeededRandom(iSeed, 0, pList->GetCount()-1))->Reference(); } else pResult = pCC->CreateNil(); // Done return pResult; }
ICCItem *fnFilter (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData) // fnFilter // // Filters a list based on a boolean expression. // // (filter list var exp) -> list { int i; CCodeChain *pCC = pCtx->pCC; if (pArgs->GetElement(0)->IsNil()) return pCC->CreateNil(); // Args ICCItem *pSource = pArgs->GetElement(0); ICCItem *pVar = pArgs->GetElement(1); ICCItem *pBody = pArgs->GetElement(2); // Create a destination list ICCItem *pResult = pCC->CreateLinkedList(); if (pResult->IsError()) return pResult; CCLinkedList *pList = (CCLinkedList *)pResult; // Setup the locals. We start by creating a local symbol table ICCItem *pLocalSymbols = pCC->CreateSymbolTable(); if (pLocalSymbols->IsError()) { pResult->Discard(pCC); return pLocalSymbols; } // Associate the enumaration variable ICCItem *pError = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil()); if (pError->IsError()) { pLocalSymbols->Discard(pCC); pResult->Discard(pCC); return pError; } pError->Discard(pCC); // Setup the context if (pCtx->pLocalSymbols) pLocalSymbols->SetParent(pCtx->pLocalSymbols); else pLocalSymbols->SetParent(pCtx->pLexicalSymbols); ICCItem *pOldSymbols = pCtx->pLocalSymbols; pCtx->pLocalSymbols = pLocalSymbols; // Get the offset of the variable so we don't have to // search for it all the time int iVarOffset = pLocalSymbols->FindOffset(pCC, pVar); // Loop over all elements of the list for (i = 0; i < pSource->GetCount(); i++) { ICCItem *pItem = pSource->GetElement(i); // Set the element pLocalSymbols->AddByOffset(pCC, iVarOffset, pItem); // Eval ICCItem *pSelect = pCC->Eval(pCtx, pBody); if (pSelect->IsError()) { pResult->Discard(pCC); pResult = pSelect; break; } // If the evaluation is not Nil, then we include the // item in the result if (!pSelect->IsNil()) pList->Append(pCC, pItem, NULL); pSelect->Discard(pCC); } // Clean up pCtx->pLocalSymbols = pOldSymbols; pLocalSymbols->Discard(pCC); // Done if (pResult->GetCount() > 0) return pResult; else { pResult->Discard(pCC); return pCC->CreateNil(); } }
void CShieldClass::FireOnShieldDamage (CItemCtx &ItemCtx, SDamageCtx &Ctx) // FireOnShieldDamage // // Fire OnShieldDamage { SEventHandlerDesc Event; if (FindEventHandlerShieldClass(evtOnShieldDamage, &Event)) { // Setup arguments CCodeChainCtx CCCtx; CCCtx.SaveAndDefineSourceVar(ItemCtx.GetSource()); CCCtx.SaveAndDefineItemVar(ItemCtx); CCCtx.DefineInteger(CONSTLIT("aArmorSeg"), Ctx.iSectHit); CCCtx.DefineSpaceObject(CONSTLIT("aCause"), Ctx.pCause); CCCtx.DefineSpaceObject(CONSTLIT("aAttacker"), Ctx.Attacker.GetObj()); CCCtx.DefineSpaceObject(CONSTLIT("aOrderGiver"), (Ctx.Attacker.GetObj() ? Ctx.Attacker.GetObj()->GetOrderGiver(Ctx.Attacker.GetCause()) : NULL)); CCCtx.DefineVector(CONSTLIT("aHitPos"), Ctx.vHitPos); CCCtx.DefineInteger(CONSTLIT("aHitDir"), Ctx.iDirection); CCCtx.DefineInteger(CONSTLIT("aDamageHP"), Ctx.iDamage); CCCtx.DefineString(CONSTLIT("aDamageType"), GetDamageShortName(Ctx.Damage.GetDamageType())); CCCtx.DefineItemType(CONSTLIT("aWeaponType"), Ctx.pDesc->GetWeaponType()); CCCtx.DefineInteger(CONSTLIT("aShieldHP"), Ctx.iHPLeft); CCCtx.DefineInteger(CONSTLIT("aShieldDamageHP"), Ctx.iShieldDamage); CCCtx.DefineInteger(CONSTLIT("aArmorDamageHP"), Ctx.iDamage - Ctx.iAbsorb); if (Ctx.bReflect) { CCCtx.DefineString(CONSTLIT("aShieldReflect"), STR_SHIELD_REFLECT); CCCtx.DefineInteger(CONSTLIT("aOriginalShieldDamageHP"), Ctx.iOriginalShieldDamage); CCCtx.DefineInteger(CONSTLIT("aOriginalArmorDamageHP"), Ctx.iDamage - Ctx.iOriginalAbsorb); } else { CCCtx.DefineNil(CONSTLIT("aShieldReflect")); CCCtx.DefineInteger(CONSTLIT("aOriginalShieldDamageHP"), Ctx.iShieldDamage); CCCtx.DefineInteger(CONSTLIT("aOriginalArmorDamageHP"), Ctx.iDamage - Ctx.iAbsorb); } ICCItem *pResult = CCCtx.Run(Event); // If we return Nil, then nothing if (pResult->IsNil()) NULL; // If an error, report it else if (pResult->IsError()) ItemCtx.GetSource()->ReportEventError(ON_SHIELD_DAMAGE_EVENT, pResult); // If we return a list, then modify variables else if (pResult->IsList()) { // A single value means we modified the damage to armor if (pResult->GetCount() == 1) { if (strEquals(pResult->GetElement(0)->GetStringValue(), STR_SHIELD_REFLECT)) { Ctx.bReflect = true; Ctx.iAbsorb = Ctx.iDamage; Ctx.iShieldDamage = 0; } else { Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(0)->GetIntegerValue(), Ctx.iHPLeft)); if (Ctx.bReflect) { Ctx.bReflect = false; Ctx.iAbsorb = Ctx.iOriginalAbsorb; } } } // Two values mean we modified both damage to armor and shield damage else if (pResult->GetCount() == 2) { Ctx.bReflect = false; Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(0)->GetIntegerValue(), Ctx.iHPLeft)); Ctx.iAbsorb = Max(0, Ctx.iDamage - Max(0, pResult->GetElement(1)->GetIntegerValue())); } // Otherwise, we deal with reflection else { Ctx.bReflect = strEquals(pResult->GetElement(0)->GetStringValue(), STR_SHIELD_REFLECT); Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(1)->GetIntegerValue(), Ctx.iHPLeft)); Ctx.iAbsorb = Max(0, Ctx.iDamage - Max(0, pResult->GetElement(2)->GetIntegerValue())); } } CCCtx.Discard(pResult); } }
ICCItem *fnApply (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnApply // // Applies the given parameter list to the lambda expression // // (apply exp arg1 arg2 ... argn list) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pResult; ICCItem *pFunction; ICCItem *pLast; CCLinkedList *pList; int i; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("v*")); if (pArgs->IsError()) return pArgs; // We better have at least two arguments if (pArgs->GetCount() < 2) { pArgs->Discard(pCC); return pCC->CreateError(CONSTLIT("apply needs a function and a list of arguments."), NULL); } // The last argument better be a list pLast = pArgs->GetElement(pArgs->GetCount() - 1); if (!pLast->IsList()) { pArgs->Discard(pCC); return pCC->CreateError(CONSTLIT("Last argument for apply must be a list."), NULL); } // The first argument is the function pFunction = pArgs->Head(pCC); // Create a new list to store the arguments in pResult = pCC->CreateLinkedList(); if (pResult->IsError()) { pArgs->Discard(pCC); return pResult; } pList = (CCLinkedList *)pResult; // Add each of the arguments except the last for (i = 1; i < pArgs->GetCount() - 1; i++) { pList->Append(pCC, pArgs->GetElement(i), &pResult); if (pResult->IsError()) { pList->Discard(pCC); pArgs->Discard(pCC); return pResult; } pResult->Discard(pCC); } // Add each of the elements of the last list for (i = 0; i < pLast->GetCount(); i++) { pList->Append(pCC, pLast->GetElement(i), &pResult); if (pResult->IsError()) { pList->Discard(pCC); pArgs->Discard(pCC); return pResult; } pResult->Discard(pCC); } // Set the literal flag to indicate that the arguments should // not be evaluated. pList->SetQuoted(); // Execute the function if (pFunction->IsFunction()) pResult = pFunction->Execute(pCtx, pList); else pResult = pFunction->Reference(); pList->Discard(pCC); // Done pArgs->Discard(pCC); return pResult; }
ICCItem *fnEquality (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnEquality // // Equality and inequality // // (eq exp1 exp2 ... expn) // (> exp1 exp2 ... expn) // (>= exp1 exp2 ... expn) // (< exp1 exp2 ... expn) // (<= exp1 exp2 ... expn) { CCodeChain *pCC = pCtx->pCC; ICCItem *pResult; ICCItem *pExp; ICCItem *pPrev = NULL; ICCItem *pArgs; int i; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("*")); if (pArgs->IsError()) return pArgs; // Loop over all arguments for (i = 0; i < pArgs->GetCount(); i++) { pExp = pArgs->GetElement(i); if (pExp->IsError()) { pExp->Reference(); pArgs->Discard(pCC); return pExp; } if (pPrev) { int iResult = HelperCompareItems(pPrev, pExp); BOOL bOk; switch (dwData) { case FN_EQUALITY_EQ: { bOk = (iResult == 0); break; } case FN_EQUALITY_LESSER: { bOk = (iResult < 0); break; } case FN_EQUALITY_LESSER_EQ: { bOk = (iResult <= 0); break; } case FN_EQUALITY_GREATER: { bOk = (iResult > 0); break; } case FN_EQUALITY_GREATER_EQ: { bOk = (iResult >= 0); break; } default: ASSERT(FALSE); } // If we don't have a match, return if (!bOk) { pArgs->Discard(pCC); return pCC->CreateNil(); } } // Remember the previous element so that we can compare pPrev = pExp; } // If we get here, then all items are ok pArgs->Discard(pCC); pResult = pCC->CreateTrue(); // Done return pResult; }
ICCItem *fnEnum (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnEnum // // Enumerates the elements of a list // // (enum list item-var exp) // (enumwhile list condition item-var exp) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pResult; ICCItem *pVar; ICCItem *pBody; ICCItem *pList; ICCItem *pCondition; ICCItem *pLocalSymbols; ICCItem *pOldSymbols; ICCItem *pError; int i, iVarOffset; // Evaluate the arguments and validate them if (dwData == FN_ENUM_WHILE) { pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("vuqu")); if (pArgs->IsError()) return pArgs; pList = pArgs->GetElement(0); pCondition = pArgs->GetElement(1); pVar = pArgs->GetElement(2); pBody = pArgs->GetElement(3); } else { pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("vqu")); if (pArgs->IsError()) return pArgs; pList = pArgs->GetElement(0); pCondition = NULL; pVar = pArgs->GetElement(1); pBody = pArgs->GetElement(2); } // Setup the locals. We start by creating a local symbol table pLocalSymbols = pCC->CreateSymbolTable(); if (pLocalSymbols->IsError()) { pArgs->Discard(pCC); return pLocalSymbols; } // Associate the enumaration variable pError = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil()); if (pError->IsError()) { pArgs->Discard(pCC); return pError; } pError->Discard(pCC); // Setup the context if (pCtx->pLocalSymbols) pLocalSymbols->SetParent(pCtx->pLocalSymbols); else pLocalSymbols->SetParent(pCtx->pLexicalSymbols); pOldSymbols = pCtx->pLocalSymbols; pCtx->pLocalSymbols = pLocalSymbols; // Start with a default result pResult = pCC->CreateNil(); // Get the offset of the variable so we don't have to // search for it all the time iVarOffset = pLocalSymbols->FindOffset(pCC, pVar); // Loop over all elements of the list for (i = 0; i < pList->GetCount(); i++) { // Check the condition if (pCondition) { ICCItem *pEval; // Evaluate the condition pEval = pCC->Eval(pCtx, pCondition); if (pEval->IsError()) { pResult->Discard(pCC); pResult = pEval; break; } // If the condition is Nil, then we're done if (pEval->IsNil()) { pEval->Discard(pCC); break; } } ICCItem *pItem = pList->GetElement(i); // Clean up the previous result pResult->Discard(pCC); // Set the element pLocalSymbols->AddByOffset(pCC, iVarOffset, pItem); // Eval pResult = pCC->Eval(pCtx, pBody); if (pResult->IsError()) break; } // Clean up pCtx->pLocalSymbols = pOldSymbols; pLocalSymbols->Discard(pCC); // Done pArgs->Discard(pCC); return pResult; }
bool CWeaponFireDesc::FireOnDamageShields (SDamageCtx &Ctx, int iDevice) // FireOnDamageShields // // Fire OnDamageShields event. Returns TRUE if we should skip further shields damage { SEventHandlerDesc Event; if (FindEventHandler(evtOnDamageShields, &Event)) { // Setup arguments CCodeChainCtx CCCtx; CItemListManipulator ItemList(Ctx.pObj->GetItemList()); CShip *pShip = Ctx.pObj->AsShip(); if (pShip) pShip->SetCursorAtDevice(ItemList, iDevice); CCCtx.SaveAndDefineSourceVar(Ctx.pObj); CCCtx.DefineInteger(CONSTLIT("aArmorSeg"), Ctx.iSectHit); CCCtx.DefineInteger(CONSTLIT("aDevice"), iDevice); CCCtx.DefineItem(CONSTLIT("aDeviceItem"), ItemList.GetItemAtCursor()); CCCtx.DefineSpaceObject(CONSTLIT("aCause"), Ctx.pCause); CCCtx.DefineSpaceObject(CONSTLIT("aAttacker"), Ctx.Attacker.GetObj()); CCCtx.DefineSpaceObject(CONSTLIT("aOrderGiver"), (Ctx.Attacker.GetObj() ? Ctx.Attacker.GetObj()->GetOrderGiver(Ctx.Attacker.GetCause()) : NULL)); CCCtx.DefineVector(CONSTLIT("aHitPos"), Ctx.vHitPos); CCCtx.DefineInteger(CONSTLIT("aHitDir"), Ctx.iDirection); CCCtx.DefineInteger(CONSTLIT("aDamageHP"), Ctx.iDamage); CCCtx.DefineString(CONSTLIT("aDamageType"), GetDamageShortName(Ctx.Damage.GetDamageType())); CCCtx.DefineItemType(CONSTLIT("aWeaponType"), Ctx.pDesc->GetWeaponType()); CCCtx.DefineInteger(CONSTLIT("aShieldHP"), Ctx.iHPLeft); CCCtx.DefineInteger(CONSTLIT("aShieldDamageHP"), Ctx.iShieldDamage); CCCtx.DefineInteger(CONSTLIT("aArmorDamageHP"), Ctx.iDamage - Ctx.iAbsorb); if (Ctx.bReflect) { CCCtx.DefineString(CONSTLIT("aShieldReflect"), STR_SHIELD_REFLECT); CCCtx.DefineInteger(CONSTLIT("aOriginalShieldDamageHP"), Ctx.iOriginalShieldDamage); CCCtx.DefineInteger(CONSTLIT("aOriginalArmorDamageHP"), Ctx.iDamage - Ctx.iOriginalAbsorb); } else { CCCtx.DefineNil(CONSTLIT("aShieldReflect")); CCCtx.DefineInteger(CONSTLIT("aOriginalShieldDamageHP"), Ctx.iShieldDamage); CCCtx.DefineInteger(CONSTLIT("aOriginalArmorDamageHP"), Ctx.iDamage - Ctx.iAbsorb); } ICCItem *pResult = CCCtx.Run(Event); // If we return Nil, then we continue processing bool bResult; if (pResult->IsNil()) bResult = false; // If this is an integer, we pass damage to armor else if (pResult->IsInteger()) { Ctx.iDamage = pResult->GetIntegerValue(); bResult = true; } // If we return a list, then modify variables else if (pResult->IsList()) { // A single value means we modified the damage to armor if (pResult->GetCount() == 1) { if (strEquals(pResult->GetElement(0)->GetStringValue(), STR_SHIELD_REFLECT)) { Ctx.bReflect = true; Ctx.iAbsorb = Ctx.iDamage; Ctx.iShieldDamage = 0; } else { Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(0)->GetIntegerValue(), Ctx.iHPLeft)); if (Ctx.bReflect) { Ctx.bReflect = false; Ctx.iAbsorb = Ctx.iOriginalAbsorb; } } } // Two values mean we modified both damage to armor and shield damage else if (pResult->GetCount() == 2) { Ctx.bReflect = false; Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(0)->GetIntegerValue(), Ctx.iHPLeft)); Ctx.iAbsorb = Max(0, Ctx.iDamage - Max(0, pResult->GetElement(1)->GetIntegerValue())); } // Otherwise, we deal with reflection else { Ctx.bReflect = strEquals(pResult->GetElement(0)->GetStringValue(), STR_SHIELD_REFLECT); Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(1)->GetIntegerValue(), Ctx.iHPLeft)); Ctx.iAbsorb = Max(0, Ctx.iDamage - Max(0, pResult->GetElement(2)->GetIntegerValue())); } // Proceed with processing bResult = false; } // If this is the string "reflect" then we reflect else if (strEquals(pResult->GetStringValue(), STR_SHIELD_REFLECT)) { Ctx.bReflect = true; Ctx.iAbsorb = Ctx.iDamage; Ctx.iShieldDamage = 0; bResult = false; } // Otherwise, error else { Ctx.pObj->ReportEventError(ON_DAMAGE_OVERLAY_EVENT, pResult); bResult = true; } CCCtx.Discard(pResult); return bResult; } else return false; }
ICCItem *fnBlock (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnBlock // // Evaluates a list of expressions // // (block (locals ...) exp1 exp2 ... expn) // (errblock (error locals ...) exp1 exp2 ... expn onerror) { CCodeChain *pCC = pCtx->pCC; ICCItem *pResult; ICCItem *pLocals; ICCItem *pExp; ICCItem *pLocalSymbols; ICCItem *pVar; ICCItem *pOldSymbols; int i; // The first argument must be a list of locals pLocals = pArguments->Head(pCC); if (pLocals == NULL || !pLocals->IsList()) return pCC->CreateError(CONSTLIT("Locals list expected:"), pLocals); // If this is an error block then we must have at least one local if (dwData == FN_BLOCK_ERRBLOCK && pLocals->GetCount() == 0) return pCC->CreateError(CONSTLIT("errblock must have an 'error' local variable"), NULL); // Now loop over the remaining arguments, evaluating each in turn pExp = pArguments->GetElement(1); // If there are no expressions, then we just return Nil if (pExp == NULL) return pCC->CreateNil(); // Setup the locals. We start by creating a local symbol table pLocalSymbols = pCC->CreateSymbolTable(); if (pLocalSymbols->IsError()) return pLocalSymbols; pLocalSymbols->SetLocalFrame(); // Loop over each item and associate it for (i = 0; i < pLocals->GetCount(); i++) { ICCItem *pItem; pVar = pLocals->GetElement(i); pItem = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil()); if (pItem->IsError()) { pLocalSymbols->Discard(pCC); return pItem; } pItem->Discard(pCC); } // Setup the context if (pCtx->pLocalSymbols) pLocalSymbols->SetParent(pCtx->pLocalSymbols); else pLocalSymbols->SetParent(pCtx->pLexicalSymbols); pOldSymbols = pCtx->pLocalSymbols; pCtx->pLocalSymbols = pLocalSymbols; // Start with a default result pResult = pCC->CreateNil(); // Loop (starting with the second arg) for (i = 1; i < pArguments->GetCount(); i++) { pExp = pArguments->GetElement(i); // If this is an error block and this is the last expression, // then it must be error condition and we don't want to // execute it. if (i+1 == pArguments->GetCount() && dwData == FN_BLOCK_ERRBLOCK) break; // Evaluate the expression pResult->Discard(pCC); pResult = pCC->Eval(pCtx, pExp); // If we got an error, handle it if (pResult->IsError()) { // If this is an error block, then find the last expression // and evaluate it. if (dwData == FN_BLOCK_ERRBLOCK) { ICCItem *pItem; // Set the first local variable to be the error result pVar = pLocals->Head(pCC); pItem = pLocalSymbols->AddEntry(pCC, pVar, pResult); pItem->Discard(pCC); pResult->Discard(pCC); // Find the last expression pExp = pArguments->GetElement(pArguments->GetCount() - 1); // Evaluate it pResult = pCC->Eval(pCtx, pExp); } // Regardless, leave the block and return the result break; } } // Clean up pCtx->pLocalSymbols = pOldSymbols; pLocalSymbols->Discard(pCC); // Done return pResult; }
ICCItem *fnItemInfo (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnItemInfo // // Returns info about a single item // // (isatom item) -> True/Nil // (iserror item) -> True/Nil // (isfunction item) -> True/Nil { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pResult; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("v")); if (pArgs->IsError()) return pArgs; // Do the right thing switch (dwData) { case FN_ITEMINFO_ISERROR: { if (pArgs->Head(pCC)->IsError()) pResult = pCC->CreateTrue(); else pResult = pCC->CreateNil(); break; } case FN_ITEMINFO_ISATOM: { if (pArgs->Head(pCC)->IsAtom()) pResult = pCC->CreateTrue(); else pResult = pCC->CreateNil(); break; } case FN_ITEMINFO_ISINT: { pResult = pCC->CreateBool(pArgs->Head(pCC)->IsInteger() ? true : false); break; } case FN_ITEMINFO_ISFUNCTION: { if (pArgs->Head(pCC)->IsFunction()) pResult = pCC->CreateTrue(); else pResult = pCC->CreateNil(); break; } case FN_ITEMINFO_ASINT: { pResult = pCC->CreateInteger(pArgs->Head(pCC)->GetIntegerValue()); break; } case FN_ITEMINFO_HELP: { CString sHelp = pArgs->GetElement(0)->GetHelp(); if (sHelp.IsBlank()) pResult = pCC->CreateNil(); else pResult = pCC->CreateString(sHelp); break; } default: ASSERT(FALSE); return NULL; } // Done pArgs->Discard(pCC); return pResult; }
ICCItem *fnAtmTable (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnAtmTable // // Various atom table manipulations // // (atmAddEntry symTable symbol entry) -> entry // (atmDeleteEntry symTable symbol) -> True // (atmLookup symTable symbol) -> entry { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pSymTable; ICCItem *pSymbol; ICCItem *pResult; // Evaluate the arguments and validate them if (dwData == FN_ATMTABLE_ADDENTRY) pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("xiv")); else if (dwData == FN_ATMTABLE_LIST) pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("x")); else pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("xi")); if (pArgs->IsError()) return pArgs; // Get the args pSymTable = pArgs->Head(pCC); // Do the right thing switch (dwData) { case FN_ATMTABLE_ADDENTRY: { ICCItem *pEntry; pSymbol = pArgs->GetElement(1); pEntry = pArgs->GetElement(2); pResult = pSymTable->AddEntry(pCC, pSymbol, pEntry); // If we succeeded, return the entry if (!pResult->IsError()) { pResult->Discard(pCC); pResult = pEntry->Reference(); } break; } case FN_ATMTABLE_DELETEENTRY: { pResult = pCC->CreateNil(); break; } case FN_ATMTABLE_LIST: { pResult = pSymTable->ListSymbols(pCC); break; } case FN_ATMTABLE_LOOKUP: { pSymbol = pArgs->GetElement(1); pResult = pSymTable->Lookup(pCC, pSymbol); break; } default: ASSERT(FALSE); return NULL; } // Done pArgs->Discard(pCC); return pResult; }
ICCItem *fnLinkedList (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnLinkedList // // Handles linked-list specific functions // // (lnkAppend linked-list item) -> list // (lnkRemove linked-list index) -> list // (lnkRemoveNil linked-list) -> list // (lnkReplace linked-list index item) -> list // // HACK: This function has different behavior depending on the first // argument. If the first argument is a variable holding a linked list, // then the variable contents will be changed. If the variable holds Nil, // then the variable contents are not changed. In all cases, the caller // should structure the call as: (setq ListVar (lnkAppend ListVar ...)) // in order to handle all cases. { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pList; CCLinkedList *pLinkedList; ICCItem *pResult; // Evaluate the arguments if (dwData == FN_LINKEDLIST_APPEND) pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("lv")); else if (dwData == FN_LINKEDLIST_REMOVE_NIL) pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("l")); else pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("liv")); if (pArgs->IsError()) return pArgs; // Get the linked list pList = pArgs->GetElement(0); if (pList->GetClass()->GetObjID() == OBJID_CCLINKEDLIST) pLinkedList = (CCLinkedList *)pList->Reference(); else if (pList->IsNil()) { pList = pCC->CreateLinkedList(); if (pList->IsError()) { pArgs->Discard(pCC); return pList; } pLinkedList = (CCLinkedList *)pList; } else { pArgs->Discard(pCC); return pCC->CreateError(CONSTLIT("Linked-list expected:"), NULL); } // Do the right thing switch (dwData) { case FN_LINKEDLIST_APPEND: { ICCItem *pItem = pArgs->GetElement(1); ICCItem *pError; pLinkedList->Append(pCC, pItem, &pError); if (pError->IsError()) { pLinkedList->Discard(pCC); pResult = pError; } else { pError->Discard(pCC); pResult = pLinkedList; } break; } case FN_LINKEDLIST_REMOVE: { int iIndex = pArgs->GetElement(1)->GetIntegerValue(); // Make sure we're in range if (iIndex < 0 || iIndex >= pLinkedList->GetCount()) { pLinkedList->Discard(pCC); pResult = pCC->CreateError(CONSTLIT("Index out of range:"), pArgs->GetElement(1)); } else { pLinkedList->RemoveElement(pCC, iIndex); pResult = pLinkedList; } break; } case FN_LINKEDLIST_REMOVE_NIL: { // Iterate over all elements and remove any elements that are Nil int iIndex = 0; while (iIndex < pLinkedList->GetCount()) { if (pLinkedList->GetElement(iIndex)->IsNil()) pLinkedList->RemoveElement(pCC, iIndex); else iIndex++; } // Done pResult = pLinkedList; break; } case FN_LINKEDLIST_REPLACE: { int iIndex = pArgs->GetElement(1)->GetIntegerValue(); ICCItem *pItem = pArgs->GetElement(2); // Make sure we're in range if (iIndex < 0 || iIndex >= pLinkedList->GetCount()) { pLinkedList->Discard(pCC); pResult = pCC->CreateError(CONSTLIT("Index out of range:"), pArgs->GetElement(1)); } else { pLinkedList->ReplaceElement(pCC, iIndex, pItem); pResult = pLinkedList; } break; } default: ASSERT(FALSE); return NULL; } // Done pArgs->Discard(pCC); return pResult; }
ICCItem *fnMathList (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData) // fnMathList // // Simple integer functions // // (add x1 x2 ... xn) -> z // (max x1 x2 ... xn) -> z // (min x1 x2 ... xn) -> z // (multiply x1 x2 .. .xn) -> z { int i; CCodeChain *pCC = pCtx->pCC; // Get the list ICCItem *pList; if (pArgs->GetElement(0)->IsList()) { pList = pArgs->GetElement(0); if (pList->GetCount() < 1) return pCC->CreateNil(); } else pList = pArgs; // Do the computation switch (dwData) { case FN_MATH_ADD: { int iResult = pList->GetElement(0)->GetIntegerValue(); for (i = 1; i < pList->GetCount(); i++) iResult += pList->GetElement(i)->GetIntegerValue(); return pCC->CreateInteger(iResult); } case FN_MATH_MULTIPLY: { int iResult = pList->GetElement(0)->GetIntegerValue(); for (i = 1; i < pList->GetCount(); i++) iResult *= pList->GetElement(i)->GetIntegerValue(); return pCC->CreateInteger(iResult); } case FN_MATH_MAX: { int iResult = pList->GetElement(0)->GetIntegerValue(); for (i = 1; i < pList->GetCount(); i++) { int iVal = pList->GetElement(i)->GetIntegerValue(); if (iVal > iResult) iResult = iVal; } return pCC->CreateInteger(iResult); } case FN_MATH_MIN: { int iResult = pList->GetElement(0)->GetIntegerValue(); for (i = 1; i < pList->GetCount(); i++) { int iVal = pList->GetElement(i)->GetIntegerValue(); if (iVal < iResult) iResult = iVal; } return pCC->CreateInteger(iResult); } default: ASSERT(false); return pCC->CreateNil(); } }
ICCItem *fnSet (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnSet // // Bind an identifier to some value // // (set var exp) // (setq var exp) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pVar; ICCItem *pValue; int iFrame, iOffset; ICCItem *pSymTable; // Evaluate the arguments and validate them if (dwData == FN_SET_SET) pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("sv")); else pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("qv")); if (pArgs->IsError()) return pArgs; // First is the variable; next is the value pVar = pArgs->GetElement(0); pValue = pArgs->GetElement(1); // Figure out which symbol table to start with if (pCtx->pLocalSymbols) pSymTable = pCtx->pLocalSymbols; else pSymTable = pCtx->pLexicalSymbols; // If this variable has already been bound, then use a short-cut if (pVar->GetBinding(&iFrame, &iOffset)) { while (iFrame > 0) { pSymTable = pSymTable->GetParent(); iFrame--; } pSymTable->AddByOffset(pCC, iOffset, pValue); } else { ICCItem *pError; pError = pSymTable->AddEntry(pCC, pVar, pValue); // Check for error if (pError->IsError()) { pArgs->Discard(pCC); return pError; } pError->Discard(pCC); } // Keep a reference to the value, so we can return it pValue->Reference(); // Done with these pArgs->Discard(pCC); // Done return pValue; }
CLanguageDataBlock::ETranslateResult CLanguageDataBlock::Translate (CSpaceObject *pObj, const CString &sID, TArray<CString> *retText, CString *retsText) const // Translate // // Translates an entry to either a string or an array of strings. { int i; // If we can't find this ID then we can't translate SEntry *pEntry = m_Data.GetAt(sID); if (pEntry == NULL) return resultNotFound; // If we don't want the text back then all we need to do is return that we // have the text. if (retText == NULL && retsText == NULL) return resultFound; // If we don't need to run code then we just return the string. if (pEntry->pCode == NULL) { if (retsText) { *retsText = ::ComposePlayerNameString(pEntry->sText, g_pUniverse->GetPlayerName(), g_pUniverse->GetPlayerGenome()); return resultString; } else return resultFound; } // Otherwise we have to run some code CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(pObj); Ctx.DefineString(CONSTLIT("aTextID"), sID); ICCItem *pResult = Ctx.Run(pEntry->pCode); // LATER:Event ETranslateResult iResult; // Nil if (pResult->IsNil()) iResult = resultNotFound; // List of strings else if (pResult->GetCount() > 1) { if (retText) { CString sPlayerName = g_pUniverse->GetPlayerName(); GenomeTypes iPlayerGenome = g_pUniverse->GetPlayerGenome(); retText->DeleteAll(); retText->InsertEmpty(pResult->GetCount()); for (i = 0; i < pResult->GetCount(); i++) retText->GetAt(i) = ::ComposePlayerNameString(pResult->GetElement(i)->GetStringValue(), sPlayerName, iPlayerGenome); iResult = resultArray; } else iResult = resultFound; } // String else { if (retsText) { *retsText = ::ComposePlayerNameString(pResult->GetStringValue(), g_pUniverse->GetPlayerName(), g_pUniverse->GetPlayerGenome()); iResult = resultString; } else iResult = resultFound; } // Done Ctx.Discard(pResult); return iResult; }
ICCItem *fnForLoop (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnForLoop // // Evaluates an expression for a given number of iterations // Iterates from "from" to "to" inclusive. // // (for var from to exp) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pResult; ICCItem *pVar; ICCItem *pBody; ICCItem *pLocalSymbols; ICCItem *pOldSymbols; ICCItem *pError; int i, iFrom, iTo, iVarOffset; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("qiiu")); if (pArgs->IsError()) return pArgs; pVar = pArgs->GetElement(0); iFrom = pArgs->GetElement(1)->GetIntegerValue(); iTo = pArgs->GetElement(2)->GetIntegerValue(); pBody = pArgs->GetElement(3); // Setup the locals. We start by creating a local symbol table pLocalSymbols = pCC->CreateSymbolTable(); if (pLocalSymbols->IsError()) { pArgs->Discard(pCC); return pLocalSymbols; } // Associate the enumaration variable pError = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil()); if (pError->IsError()) { pArgs->Discard(pCC); return pError; } pError->Discard(pCC); // Setup the context if (pCtx->pLocalSymbols) pLocalSymbols->SetParent(pCtx->pLocalSymbols); else pLocalSymbols->SetParent(pCtx->pLexicalSymbols); pOldSymbols = pCtx->pLocalSymbols; pCtx->pLocalSymbols = pLocalSymbols; // Start with a default result pResult = pCC->CreateNil(); // Get the offset of the variable so we don't have to // search for it all the time iVarOffset = pLocalSymbols->FindOffset(pCC, pVar); // Loop over all elements of the list for (i = iFrom; i <= iTo; i++) { ICCItem *pItem = pCC->CreateInteger(i); // Clean up the previous result pResult->Discard(pCC); // Set the element pLocalSymbols->AddByOffset(pCC, iVarOffset, pItem); pItem->Discard(pCC); // Eval pResult = pCC->Eval(pCtx, pBody); if (pResult->IsError()) break; } // Clean up pCtx->pLocalSymbols = pOldSymbols; pLocalSymbols->Discard(pCC); // Done pArgs->Discard(pCC); return pResult; }
ICCItem *fnMathOld (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnMathOld // // Simple integer arithmetic // // (divide int1 int2) // (modulo int1 int2) // (subtract int1 int2) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; int iResult, iOp1, iOp2; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("ii")); if (pArgs->IsError()) return pArgs; // Convert to integers iOp1 = pArgs->GetElement(0)->GetIntegerValue(); iOp2 = pArgs->GetElement(1)->GetIntegerValue(); // Done with arguments pArgs->Discard(pCC); // Compute switch (dwData) { case FN_MATH_SUBTRACT: iResult = iOp1 - iOp2; break; case FN_MATH_DIVIDE: if (iOp2 != 0) iResult = iOp1 / iOp2; else return pCC->CreateError(CONSTLIT("Division by zero"), pArguments); break; case FN_MATH_MODULUS: if (iOp2 != 0) iResult = iOp1 % iOp2; else return pCC->CreateError(CONSTLIT("Division by zero"), pArguments); break; case FN_MATH_POWER: iResult = mathPower(iOp1, iOp2); break; default: ASSERT(FALSE); } // Done return pCC->CreateInteger(iResult); }