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; }
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()); }
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; }
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 *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(); }
void CDockScreenStack::IncData (const CString &sAttrib, ICCItem *pValue, ICCItem **retpResult) // IncData // // Increments data { CCodeChain &CC = g_pUniverse->GetCC(); if (IsEmpty()) { if (retpResult) *retpResult = CC.CreateNil(); return; } // If pValue is NULL, we default to 1. We add ref no matter what so that // we can discard unconditionally. if (pValue == NULL) pValue = CC.CreateInteger(1); else pValue->Reference(); // If the entry is currently blank, then we just take the increment. ICCItem *pOriginal = GetData(sAttrib); ICCItem *pResult = NULL; if (pOriginal->IsNil()) pResult = pValue->Reference(); // Otherwise, we need to get the data value else { if (pOriginal->IsDouble() || pValue->IsDouble()) pResult = CC.CreateDouble(pOriginal->GetDoubleValue() + pValue->GetDoubleValue()); else pResult = CC.CreateInteger(pOriginal->GetIntegerValue() + pValue->GetIntegerValue()); } pOriginal->Discard(&CC); // Store SetData(sAttrib, pResult); // Done if (retpResult) *retpResult = pResult; else pResult->Discard(&CC); pValue->Discard(&CC); }
ICCItem *fnSwitch (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnSwitch // // Switch control function // // (switch exp1 case1 exp2 case2 ... default) { CCodeChain *pCC = pCtx->pCC; ICCItem *pTest; ICCItem *pThen; ICCItem *pResult; int iArgPos = 0; while (iArgPos+1 < pArguments->GetCount()) { // Get the arguments pTest = pArguments->GetElement(iArgPos); pThen = pArguments->GetElement(iArgPos+1); // Evaluate the expression pResult = pCC->Eval(pCtx, pTest); if (pResult->IsError()) return pResult; // If the result is not Nil, then evaluate the Then expression if (!pResult->IsNil()) { pResult->Discard(pCC); return pCC->Eval(pCtx, pThen); } // Otherwise, continue with the loop pResult->Discard(pCC); iArgPos += 2; } // Do we have a default case? if (iArgPos < pArguments->GetCount()) { ICCItem *pElse = pArguments->GetElement(iArgPos); return pCC->Eval(pCtx, pElse); } // Otherwise, we return Nil return pCC->CreateNil(); }
void CCSymbolTable::SetIntegerValue (CCodeChain &CC, const CString &sKey, int iValue) // SetIntegerValue // // Sets an integer value { ICCItem *pKey = CC.CreateString(sKey); ICCItem *pValue = CC.CreateInteger(iValue); AddEntry(&CC, pKey, pValue); pKey->Discard(&CC); pValue->Discard(&CC); }
void CCSymbolTable::SetStringValue (CCodeChain &CC, const CString &sKey, const CString &sValue) // SetStringValue // // Sets a string value { ICCItem *pKey = CC.CreateString(sKey); ICCItem *pValue = CC.CreateString(sValue); AddEntry(&CC, pKey, pValue); pKey->Discard(&CC); pValue->Discard(&CC); }
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 *fnIf (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnIf // // If control function // // (if exp then else) { CCodeChain *pCC = pCtx->pCC; ICCItem *pTest; ICCItem *pThen; ICCItem *pElse; ICCItem *pResult; // Get the arguments pTest = pArguments->GetElement(0); if (pTest == NULL) return pCC->CreateError(CONSTLIT("Conditional expression expected"), pCC->CreateNil()); pThen = pArguments->GetElement(1); if (pThen == NULL) return pCC->CreateError(CONSTLIT("Then expression expected"), pCC->CreateNil()); pElse = pArguments->GetElement(2); // Evaluate the test expression pResult = pCC->Eval(pCtx, pTest); if (pResult->IsError()) return pResult; // If the result is not true, evaluate the else expression if (pResult->IsNil()) { if (pElse) { pResult->Discard(pCC); return pCC->Eval(pCtx, pElse); } else return pResult; } // Otherwise, evaluate the then expression pResult->Discard(pCC); return pCC->Eval(pCtx, pThen); }
ICCItem *CreateListFromImage (CCodeChain &CC, const CObjectImageArray &Image, int iRotation) // CreateListFromImage // // Creates an imageDesc from an image { ICCItem *pResult = CC.CreateLinkedList(); if (pResult->IsError()) return pResult; CCLinkedList *pList = (CCLinkedList *)pResult; // Add the bitmap UNID ICCItem *pValue = CC.CreateInteger(Image.GetBitmapUNID()); pList->Append(&CC, pValue, NULL); pValue->Discard(&CC); // Get the rect RECT rcRect = Image.GetImageRect(0, iRotation); // Add the x coordinate pValue = CC.CreateInteger(rcRect.left); pList->Append(&CC, pValue, NULL); pValue->Discard(&CC); // Add the y coordinate pValue = CC.CreateInteger(rcRect.top); pList->Append(&CC, pValue, NULL); pValue->Discard(&CC); // Add width pValue = CC.CreateInteger(RectWidth(rcRect)); pList->Append(&CC, pValue, NULL); pValue->Discard(&CC); // Add height pValue = CC.CreateInteger(RectHeight(rcRect)); pList->Append(&CC, pValue, NULL); pValue->Discard(&CC); // 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 *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(); }
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 *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 *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 *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; }
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 *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 *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 *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)); }
void CCAtomTable::DestroyItem (CCodeChain *pCC) // DestroyItem // // Destroy this item { int i; // Release all the entries for (i = 0; i < m_Table.GetCount(); i++) { int iKey, iValue; ICCItem *pItem; m_Table.GetEntry(i, &iKey, &iValue); pItem = (ICCItem *)iValue; pItem->Discard(pCC); } // Remove all symbols m_Table.RemoveAll(); // Destroy this item pCC->DestroyAtomTable(this); }
ICCItem *CCAtomTable::AddEntry (CCodeChain *pCC, ICCItem *pAtom, ICCItem *pEntry) // AddEntry // // Adds an entry to the symbol table and returns // True for success. { ICCItem *pPrevEntry = NULL; int iOldEntry; BOOL bAdded; if (m_Table.ReplaceEntry(pAtom->GetIntegerValue(), (int)pEntry->Reference(), TRUE, &bAdded, &iOldEntry) != NOERROR) return pCC->CreateMemoryError(); // If we have a previous entry, decrement its refcount since we're // throwing it away pPrevEntry = (ICCItem *)iOldEntry; if (!bAdded && pPrevEntry) pPrevEntry->Discard(pCC); SetModified(); return pCC->CreateTrue(); }
void CCSymbolTable::DestroyItem (CCodeChain *pCC) // DestroyItem // // Destroy this item { int i; // Release our parent reference if (m_pParent) m_pParent->Discard(pCC); // Release all the entries for (i = 0; i < m_Symbols.GetCount(); i++) { CObject *pValue = m_Symbols.GetValue(i); ICCItem *pItem = (ICCItem *)pValue; pItem->Discard(pCC); } // Remove all symbols m_Symbols.RemoveAll(); // Destroy this item pCC->DestroySymbolTable(this); }
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 *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 *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 *CreateListFromBinary (CCodeChain &CC, const CString &sClass, 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; // Add a class, if provided if (!sClass.IsBlank()) pList->AppendString(CC, sClass); // Add binary bytes in DWORD chunks. 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); pInt->Discard(&CC); } return pResult; }