ALERROR CCodeChain::RegisterPrimitive (PRIMITIVEPROCDEF *pDef, IPrimitiveImpl *pImpl) // RegisterPrimitive // // Registers a primitive function implemented in C { ICCItem *pError; ICCItem *pDefinition; // Create a primitive definition pDefinition = CreatePrimitive(pDef, pImpl); if (pDefinition->IsError()) { pDefinition->Discard(this); return ERR_FAIL; } // Add to global symbol table pError = m_pGlobalSymbols->AddEntry(this, pDefinition, pDefinition); if (pError->IsError()) { pError->Discard(this); return ERR_FAIL; } // Don't need these anymore; AddEntry keeps a reference pError->Discard(this); pDefinition->Discard(this); return NOERROR; }
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 *CCAtomTable::StreamItem (CCodeChain *pCC, IWriteStream *pStream) // StreamItem // // Stream the sub-class specific data { ALERROR error; int iCount; int i; // Write out the count iCount = m_Table.GetCount(); error = pStream->Write((char *)&iCount, sizeof(iCount), NULL); if (error) return pCC->CreateSystemError(error); // Write out each of the items in the list for (i = 0; i < iCount; i++) { int iValue, iKey; ICCItem *pItem; ICCItem *pKey; ICCItem *pError; m_Table.GetEntry(i, &iKey, &iValue); pItem = (ICCItem *)iValue; // Write out the key pKey = pCC->CreateInteger(iKey); if (pKey->IsError()) return pKey; pError = pCC->StreamItem(pKey, pStream); pKey->Discard(pCC); if (pError->IsError()) return pError; pError->Discard(pCC); // Write out the value pError = pCC->StreamItem(pItem, pStream); if (pError->IsError()) return pError; pError->Discard(pCC); // Note that there is no need to discard pItem // since we did not increase its refcount } return pCC->CreateTrue(); }
ICCItem *CCSymbolTable::StreamItem (CCodeChain *pCC, IWriteStream *pStream) // StreamItem // // Stream the sub-class specific data { ALERROR error; int iCount; int i; // Write out the count iCount = m_Symbols.GetCount(); if (error = pStream->Write((char *)&iCount, sizeof(iCount), NULL)) return pCC->CreateSystemError(error); // Write out each of the items in the list for (i = 0; i < iCount; i++) { CString sKey = m_Symbols.GetKey(i); CObject *pValue = m_Symbols.GetValue(i); ICCItem *pItem = (ICCItem *)pValue; ICCItem *pKey; ICCItem *pError; // Write out the key pKey = pCC->CreateString(sKey); if (pKey->IsError()) return pKey; pError = pCC->StreamItem(pKey, pStream); pKey->Discard(pCC); if (pError->IsError()) return pError; pError->Discard(pCC); // Write out the value pError = pCC->StreamItem(pItem, pStream); if (pError->IsError()) return pError; pError->Discard(pCC); // Note that there is no need to discard pItem // since we did not increase its refcount } return pCC->CreateTrue(); }
ICCItem *CCodeChain::CreateFilledVector(double dScalar, TArray<int> vShape) // CreateFilledVector // // Creates a vector filled with the given scalar { int i; int iSize = 0; CCVector *pVector; ICCItem *pError; ICCItem *pItem; for (i = 0; i < vShape.GetCount(); i++) { if (i == 0) iSize = vShape[0]; else iSize = iSize*vShape[i]; }; pItem = m_VectorPool.CreateItem(this); if (pItem->IsError()) return pItem; pItem->Reset(); pVector = dynamic_cast<CCVector *>(pItem); pVector->SetContext(this); pVector->SetShape(this, vShape); pError = pVector->SetDataArraySize(this, iSize); if (pError->IsError()) { delete pVector; return pError; } TArray<double> vContentArray = pVector->GetDataArray(); for (i = 0; i < iSize; i++) { vContentArray[i] = dScalar; }; pVector->SetArrayData(this, vContentArray); pError->Discard(this); // Done return pVector->Reference(); }
ICCItem *CCPrimitive::Execute (CEvalContext *pCtx, ICCItem *pArgs) // Execute // // Executes the function and returns a result { bool bCustomArgEval = ((m_dwFlags & PPFLAG_CUSTOM_ARG_EVAL) ? true : false); // Evaluate args, if necessary ICCItem *pEvalArgs; if (!bCustomArgEval) { pEvalArgs = pCtx->pCC->EvaluateArgs(pCtx, pArgs, m_sArgPattern); if (pEvalArgs->IsError()) return pEvalArgs; } else pEvalArgs = pArgs; // Invoke the function ICCItem *pResult; bool bReportError = false; try { pResult = m_pfFunction(pCtx, pEvalArgs, m_dwData); } catch (...) { bReportError = true; } // Report error if (bReportError) { CString sArgs; try { sArgs = pEvalArgs->Print(pCtx->pCC); } catch (...) { sArgs = CONSTLIT("[invalid arg item]"); } CString sError = strPatternSubst(CONSTLIT("Exception in %s; arg = %s"), m_sName, sArgs); pResult = pCtx->pCC->CreateError(sError, pEvalArgs); kernelDebugLogMessage(sError.GetASCIIZPointer()); } // Done if (!bCustomArgEval) pEvalArgs->Discard(pCtx->pCC); return pResult; }
ICCItem *CLWindowManager::CreateLWindow (CLWindowOptions *pOptions, CLSizeOptions *pSize, ICCItem *pController) // CLWindowManager // // Create a new window { CLWindow *pNewWindow; ICCItem *pError; pNewWindow = new CLWindow(this); if (pNewWindow == NULL) return m_pCC->CreateMemoryError(); // Initialize pError = pNewWindow->CreateItem(m_pCC, pOptions, pSize, pController); if (pError->IsError()) return pError; pError->Discard(m_pCC); // Add the window to the window manager's list m_WindowList.AppendObject(pNewWindow, NULL); return pNewWindow->Reference(); }
CString CreateDataFieldFromItemList (const TArray<CItem> &List) // CreateDataFieldFromItemList // // Creates a data field string from a list of items { int i; CCodeChain &CC = g_pUniverse->GetCC(); CMemoryWriteStream Output(10000); if (Output.Create() != NOERROR) return NULL_STR; Output.Write("='(", 3); for (i = 0; i < List.GetCount(); i++) { ICCItem *pItem = List[i].WriteToCCItem(CC); if (pItem->IsError()) { pItem->Discard(&CC); return NULL_STR; } CString sItem = pItem->Print(&CC); Output.Write(sItem.GetASCIIZPointer(), sItem.GetLength()); Output.Write(" ", 1); pItem->Discard(&CC); } Output.Write(")", 1); Output.Close(); return CString(Output.GetPointer(), Output.GetLength()); }
int CArmorClass::FireGetMaxHP (CItemCtx &ItemCtx, int iMaxHP) const // FireGetMaxHP // // Fire GetMaxHP event { SEventHandlerDesc Event; if (FindEventHandlerArmorClass(evtGetMaxHP, &Event)) { // Setup arguments CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(ItemCtx.GetSource()); Ctx.SaveAndDefineItemVar(ItemCtx); Ctx.DefineInteger(CONSTLIT("aMaxHP"), iMaxHP); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) ItemCtx.GetSource()->ReportEventError(GET_MAX_HP_EVENT, pResult); else if (!pResult->IsNil()) iMaxHP = Max(0, pResult->GetIntegerValue()); Ctx.Discard(pResult); } return iMaxHP; }
ICCItem *fnCount (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnCount // // Returns the number of elements in the list // // (count list) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pResult; ICCItem *pList; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("l")); if (pArgs->IsError()) return pArgs; // The first argument is the list pList = pArgs->Head(pCC); pResult = pCC->CreateInteger(pList->GetCount()); // Done pArgs->Discard(pCC); return pResult; }
ICCItem *CMission::FireOnReward (ICCItem *pData) // FireOnReward // // Fire <OnReward> // // Callers are responsible for discarding the result, if not NULL. { SEventHandlerDesc Event; if (FindEventHandler(EVENT_ON_REWARD, &Event)) { CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(this); Ctx.SaveAndDefineDataVar(pData); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) { ReportEventError(EVENT_ON_REWARD, pResult); Ctx.Discard(pResult); return NULL; } return pResult; } return NULL; }
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 *CCLambda::Clone (CCodeChain *pCC) // Clone // // Clone this item { ICCItem *pNew; CCLambda *pClone; pNew = pCC->CreateLambda(NULL, FALSE); if (pNew->IsError()) return pNew; pClone = dynamic_cast<CCLambda *>(pNew); pClone->CloneItem(this); if (m_pArgList) pClone->m_pArgList = m_pArgList->Reference(); else pClone->m_pArgList = NULL; if (m_pCode) pClone->m_pCode = m_pCode->Reference(); else pClone->m_pCode = NULL; return pClone; }
ICCItem *CCodeChain::CreateVectorOld (int iSize) // CreateVectorOld // // Creates a vector of the given number of elements { CCVectorOld *pVector; ICCItem *pError; pVector = new CCVectorOld(this); if (pVector == NULL) return CreateMemoryError(); pError = pVector->SetSize(this, iSize); if (pError->IsError()) { delete pVector; return pError; } pError->Discard(this); // Done return pVector->Reference(); }
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 *CCodeChain::StreamItem (ICCItem *pItem, IWriteStream *pStream) // StreamItem // // Save the item to an open stream { ALERROR error; DWORD dwClass; ICCItem *pError; // Save out the object class dwClass = pItem->GetClass()->GetObjID(); if (error = pStream->Write((char *)&dwClass, sizeof(dwClass), NULL)) return CreateSystemError(error); // Let the object save itself pError = pItem->Stream(this, pStream); if (pError->IsError()) return pError; pError->Discard(this); // Done return CreateTrue(); }
ICCItem *CreateListFromBinary (CCodeChain &CC, void const *pvSource, int iLengthBytes) // CreateListFromBinary // // Creates a code chain list from a block of memory { ICCItem *pResult = CC.CreateLinkedList(); if (pResult->IsError()) return pResult; CCLinkedList *pList = (CCLinkedList *)pResult; // CItem is two DWORD long DWORD *pSource = (DWORD *)pvSource; int iCount = AlignUp(iLengthBytes, sizeof(DWORD)) / sizeof(DWORD); for (int i = 0; i < iCount; i++) { ICCItem *pInt = CC.CreateInteger(*pSource++); pList->Append(&CC, pInt, NULL); pInt->Discard(&CC); } return pResult; }
ICCItem *CCodeChain::LookupGlobal (const CString &sGlobal, LPVOID pExternalCtx) // LookupGlobal // // Returns the binding for this item { CEvalContext EvalCtx; ICCItem *pItem; ICCItem *pResult; // Set up the context EvalCtx.pCC = this; EvalCtx.pLexicalSymbols = m_pGlobalSymbols; EvalCtx.pLocalSymbols = NULL; EvalCtx.pExternalCtx = pExternalCtx; // Create a variable pItem = CreateString(sGlobal); if (pItem->IsError()) return pItem; pResult = Lookup(&EvalCtx, pItem); pItem->Discard(this); return pResult; }
ICCItem *fnLambda (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnLambda // // Lambda expression // // (lambda (args...) code) { CCodeChain *pCC = pCtx->pCC; ICCItem *pItem; CCLambda *pLambda; // Create a lambda expression based on this list pItem = pCC->CreateLambda(pArguments, TRUE); if (pItem->IsError()) return pItem; pLambda = dynamic_cast<CCLambda *>(pItem); // Done return pLambda; }
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; }
ALERROR CCodeChain::DefineGlobal (const CString &sVar, ICCItem *pValue) // DefineGlobal // // Defines a global variable programmatically { ALERROR error; // Create a string item ICCItem *pVar = CreateString(sVar); // Add the symbol ICCItem *pError; pError = m_pGlobalSymbols->AddEntry(this, pVar, pValue); pVar->Discard(this); // Check for error if (pError->IsError()) error = ERR_FAIL; else error = NOERROR; pError->Discard(this); return error; }
ICCItem *CCLambda::StreamItem (CCodeChain *pCC, IWriteStream *pStream) // StreamItem // // Stream the sub-class specific data { ICCItem *pError; // If we don't have both of these, then it is because we're trying // to save an uninitialized lambda structure ASSERT(m_pArgList); ASSERT(m_pCode); // Write out the argument list pError = pCC->StreamItem(m_pArgList, pStream); if (pError->IsError()) return pError; pError->Discard(pCC); // Write out the code return pCC->StreamItem(m_pCode, pStream); }
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); }
int CShieldClass::FireGetMaxHP (CInstalledDevice *pDevice, CSpaceObject *pSource, int iMaxHP) const // FireGetMaxHP // // Fire GetMaxHP event { SEventHandlerDesc Event; if (FindEventHandlerShieldClass(evtGetMaxHP, &Event)) { ASSERT(pSource); ASSERT(pDevice); CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(pSource); Ctx.SaveAndDefineItemVar(pSource->GetItemForDevice(pDevice)); Ctx.DefineInteger(CONSTLIT("aMaxHP"), iMaxHP); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) pSource->ReportEventError(GET_MAX_HP_EVENT, pResult); else if (!pResult->IsNil()) iMaxHP = Max(0, pResult->GetIntegerValue()); Ctx.Discard(pResult); } return iMaxHP; }
ICCItem *fnVecCreate (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnVecCreate // // Creates a new vector of a given size // // (vecVector size) -> vector // // All elements of the vector are initialized to 0 { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pVector; // Evaluate the argument pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("i")); if (pArgs->IsError()) return pArgs; // Create the table pVector = pCC->CreateVector(pArgs->Head(pCC)->GetIntegerValue()); // Done pArgs->Discard(pCC); return pVector; }
bool IDockScreenDisplay::EvalBool (const CString &sCode, bool *retbResult, CString *retsError) // EvalBool // // Evaluates the given string { CCodeChainCtx Ctx; Ctx.SetScreen(m_pDockScreen); Ctx.SaveAndDefineSourceVar(m_pLocation); Ctx.SaveAndDefineDataVar(m_pData); char *pPos = sCode.GetPointer(); ICCItem *pExp = Ctx.Link(sCode, 1, NULL); ICCItem *pResult = Ctx.Run(pExp); // LATER:Event Ctx.Discard(pExp); if (pResult->IsError()) { *retsError = pResult->GetStringValue(); Ctx.Discard(pResult); return false; } *retbResult = !pResult->IsNil(); Ctx.Discard(pResult); return true; }
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; }
COverlayType *CDeviceClass::FireGetOverlayType (CItemCtx &ItemCtx) const // FireGetOverlayType // // Fire GetOverlayType event { SEventHandlerDesc Event; if (FindEventHandlerDeviceClass(evtGetOverlayType, &Event)) { // Setup arguments CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(ItemCtx.GetSource()); Ctx.SaveAndDefineItemVar(ItemCtx); ICCItem *pResult = Ctx.Run(Event); DWORD dwUNID = 0; if (pResult->IsError()) ItemCtx.GetSource()->ReportEventError(GET_OVERLAY_TYPE_EVENT, pResult); else if (!pResult->IsNil()) dwUNID = pResult->GetIntegerValue(); Ctx.Discard(pResult); // Done return COverlayType::AsType(g_pUniverse->FindDesignType(dwUNID)); } else return GetOverlayType(); }
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 *CMission::FireOnDeclined (void) // FireOnDeclined // // Fire <OnDeclined>. We return the result of the event, which might contain // instructions for the mission screen. // // Callers are responsible for discarding the result, if not NULL. { SEventHandlerDesc Event; if (FindEventHandler(EVENT_ON_DECLINED, &Event)) { CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(this); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) { ReportEventError(EVENT_ON_DECLINED, pResult); Ctx.Discard(pResult); return NULL; } return pResult; } return NULL; }