From 8c812cb44896b85e4dac41d6bb6a2684c6dedd34 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 4 May 2025 10:16:49 +0100 Subject: [PATCH 01/41] initial commit This change makes the memory manager work again for detecting leaks, the built in one kept coming into de-ref and other bugs so this is the start of a refactor to get it working. --- Engine/source/app/mainLoop.cpp | 34 - Engine/source/main/main.cpp | 11 +- Engine/source/platform/platformMemory.cpp | 1758 ++--------------- Engine/source/platform/platformMemory.h | 37 +- Engine/source/ts/assimp/assimpAppMaterial.cpp | 11 + Engine/source/ts/assimp/assimpAppMaterial.h | 12 + Engine/source/ts/assimp/assimpAppMesh.cpp | 12 + Engine/source/ts/assimp/assimpAppNode.cpp | 13 + Engine/source/ts/assimp/assimpAppNode.h | 12 + Engine/source/ts/assimp/assimpAppSequence.h | 12 + Engine/source/ts/assimp/assimpShapeLoader.cpp | 11 + 11 files changed, 258 insertions(+), 1665 deletions(-) diff --git a/Engine/source/app/mainLoop.cpp b/Engine/source/app/mainLoop.cpp index 2acb64845..0d3c77c41 100644 --- a/Engine/source/app/mainLoop.cpp +++ b/Engine/source/app/mainLoop.cpp @@ -114,29 +114,6 @@ namespace engineAPI } - -// The following are some tricks to make the memory leak checker run after global -// dtors have executed by placing some code in the termination segments. - -#if defined( TORQUE_DEBUG ) && !defined( TORQUE_DISABLE_MEMORY_MANAGER ) - - #ifdef TORQUE_COMPILER_VISUALC - # pragma data_seg( ".CRT$XTU" ) - - static void* sCheckMemBeforeTermination = &Memory::ensureAllFreed; - - # pragma data_seg() - #elif defined( TORQUE_COMPILER_GCC ) - - __attribute__ ( ( destructor ) ) static void _ensureAllFreed() - { - Memory::ensureAllFreed(); - } - - #endif - -#endif - // Process a time event and update all sub-processes void processTimeEvent(S32 elapsedTime) { @@ -216,10 +193,6 @@ void StandardMainLoop::init() gStartupTimer = PlatformTimer::create(); #endif - #ifdef TORQUE_DEBUG_GUARD - Memory::flagCurrentAllocs( Memory::FLAG_Global ); - #endif - Platform::setMathControlStateKnown(); // Asserts should be created FIRST @@ -327,10 +300,6 @@ void StandardMainLoop::init() // Hook in for UDP notification Net::getPacketReceiveEvent().notify(GNet, &NetInterface::processPacketReceiveEvent); - - #ifdef TORQUE_DEBUG_GUARD - Memory::flagCurrentAllocs( Memory::FLAG_Static ); - #endif } void StandardMainLoop::shutdown() @@ -378,9 +347,6 @@ void StandardMainLoop::shutdown() // asserts should be destroyed LAST PlatformAssert::destroy(); -#if defined( TORQUE_DEBUG ) && !defined( TORQUE_DISABLE_MEMORY_MANAGER ) - Memory::validate(); -#endif } void StandardMainLoop::preShutdown() diff --git a/Engine/source/main/main.cpp b/Engine/source/main/main.cpp index dc2e19c19..826f14d16 100644 --- a/Engine/source/main/main.cpp +++ b/Engine/source/main/main.cpp @@ -205,6 +205,7 @@ int main(int argc, const char **argv) #include "platform/platform.h" #include "app/mainLoop.h" #include "T3D/gameFunctions.h" +#include "platform/platformMemory.h" #if defined(WIN32) || defined(_WIN32) //tell switchable graphics supported systems that they need to use the beefier GPU @@ -230,8 +231,9 @@ S32 TorqueMain(S32 argc, const char **argv) // argv = argvFake; // } - // Memory::enableLogging("testMem.log"); - // Memory::setBreakAlloc(104717); +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) + Memory::init(); +#endif // Initialize the subsystems. StandardMainLoop::init(); @@ -254,6 +256,11 @@ S32 TorqueMain(S32 argc, const char **argv) if( StandardMainLoop::requiresRestart() ) Platform::restartInstance(); + +#if defined( TORQUE_DEBUG ) && !defined( TORQUE_DISABLE_MEMORY_MANAGER ) + Memory::shutdown(); +#endif + // Return. return StandardMainLoop::getReturnStatus(); } diff --git a/Engine/source/platform/platformMemory.cpp b/Engine/source/platform/platformMemory.cpp index f10113308..33d0a1336 100644 --- a/Engine/source/platform/platformMemory.cpp +++ b/Engine/source/platform/platformMemory.cpp @@ -30,6 +30,14 @@ #include "platform/threads/mutex.h" #include "core/module.h" +#ifdef _WIN32 +#include +#include +#pragma comment(lib, "Dbghelp.lib") +#else +#include +#endif + // If profile paths are enabled, disable profiling of the // memory manager as that would cause a cyclic dependency // through the string table's allocation stuff used by the @@ -45,7 +53,7 @@ #endif #ifdef TORQUE_MULTITHREAD -void * gMemMutex = NULL; +void* gMemMutex = NULL; #endif //-------------------------------------- Make sure we don't have the define set @@ -53,1663 +61,213 @@ void * gMemMutex = NULL; #undef new #endif -enum MemConstants : U32 -{ - Allocated = BIT(0), - Array = BIT(1), - DebugFlag = BIT(2), - Reallocated = BIT(3), /// This flag is set if the memory has been allocated, then 'realloc' is called - GlobalFlag = BIT(4), - StaticFlag = BIT(5), - AllocatedGuard = 0xCEDEFEDE, - FreeGuard = 0x5555FFFF, - MaxAllocationAmount = 0xFFFFFFFF, - TreeNodeAllocCount = 2048, -}; - -inline U32 flagToBit( Memory::EFlag flag ) -{ - using namespace Memory; - - U32 bit = 0; - switch( flag ) - { - case FLAG_Debug: bit = DebugFlag; break; - case FLAG_Global: bit = GlobalFlag; break; - case FLAG_Static: bit = StaticFlag; break; - } - return bit; -} - -enum RedBlackTokens { - Red = 0, - Black = 1 -}; - -static U32 MinPageSize = 8 * 1024 * 1024; - -#if !defined(TORQUE_SHIPPING) && defined(TORQUE_DEBUG_GUARD) -#define LOG_PAGE_ALLOCS -#endif - -U32 gNewNewTotal = 0; -U32 gImageAlloc = 0; - //--------------------------------------------------------------------------- namespace Memory { - -ConsoleFunctionGroupBegin( Memory, "Memory manager utility functions."); - -struct FreeHeader; - -/// Red/Black Tree Node - used to store queues of free blocks -struct TreeNode -{ - U32 size; - TreeNode *parent; - TreeNode *left; - TreeNode *right; - U32 color; - FreeHeader *queueHead; - FreeHeader *queueTail; - U32 unused; -}; - -struct Header -{ - // doubly linked list of allocated and free blocks - - // contiguous in memory. -#ifdef TORQUE_DEBUG_GUARD - U32 preguard[4]; -#endif - Header *next; - Header *prev; - dsize_t size; - U32 flags; -#ifdef TORQUE_DEBUG_GUARD - #ifdef TORQUE_ENABLE_PROFILE_PATH - U32 unused[5]; - #else - U32 unused[4]; - #endif - U32 postguard[4]; -#endif -}; - -struct AllocatedHeader -{ -#ifdef TORQUE_DEBUG_GUARD - U32 preguard[4]; -#endif - Header *next; - Header *prev; - dsize_t size; - U32 flags; - -#ifdef TORQUE_DEBUG_GUARD - // an allocated header will only have this stuff if TORQUE_DEBUG_GUARD - U32 line; - U32 allocNum; - const char *fileName; - #ifdef TORQUE_ENABLE_PROFILE_PATH - const char * profilePath; - #endif - U32 realSize; - U32 postguard[4]; -#endif - - void* getUserPtr() - { - return ( this + 1 ); - } -}; - -struct FreeHeader -{ -#ifdef TORQUE_DEBUG_GUARD - U32 preguard[4]; -#endif - Header *next; - Header *prev; - dsize_t size; - U32 flags; - -// since a free header has at least one cache line (16 bytes) -// we can tag some more stuff on: - - FreeHeader *nextQueue; // of the same size - FreeHeader *prevQueue; // doubly linked - TreeNode *treeNode; // which tree node we're coming off of. - U32 guard; -#ifdef TORQUE_DEBUG_GUARD - #ifdef TORQUE_ENABLE_PROFILE_PATH - U32 unused; - #endif - U32 postguard[4]; -#endif -}; - -struct PageRecord -{ - dsize_t allocSize; - PageRecord *prevPage; - Header *headerList; // if headerList is NULL, this is a treeNode page - void *basePtr; - U32 unused[4]; // even out the record to 32 bytes... - // so if we're on a 32-byte cache-line comp, the tree nodes - // will cache better -}; - -PageRecord *gPageList = NULL; -TreeNode nil; -TreeNode *NIL = &nil; -TreeNode *gFreeTreeRoot = &nil; -TreeNode *gTreeFreeList = NULL; - -U32 gInsertCount = 0; -U32 gRemoveCount = 0; -U32 gBreakAlloc = 0xFFFFFFFF; -U32 gCurrAlloc = 0; -char gLogFilename[256] = "memlog.txt"; -bool gEnableLogging = false; -bool gNeverLogLeaks = 0; -bool gAlwaysLogLeaks = 0; -U32 gBytesAllocated = 0; -U32 gBlocksAllocated = 0; -U32 gPageBytesAllocated = 0; - -struct HeapIterator -{ - PageRecord* mCurrentPage; - Header* mCurrentHeader; - bool mAllocatedOnly; - - HeapIterator( bool allocatedOnly = true ) - : mCurrentPage( gPageList ), - mCurrentHeader( NULL ), - mAllocatedOnly( allocatedOnly ) - { - if( mCurrentPage ) - { - mCurrentHeader = mCurrentPage->headerList; - while( !mCurrentHeader && mCurrentPage ) - { - mCurrentPage = mCurrentPage->prevPage; - mCurrentHeader = mCurrentPage->headerList; - } - - if( mCurrentHeader && mAllocatedOnly && !( mCurrentHeader->flags & Allocated ) ) - ++ ( *this ); // Advance to first allocated record. - } - } - - bool isValid() const - { - return ( mCurrentHeader != NULL ); - } - HeapIterator& operator ++() - { - do - { - if( !mCurrentHeader ) - { - if( mCurrentPage ) - mCurrentPage = mCurrentPage->prevPage; - - if( !mCurrentPage ) - break; - mCurrentHeader = mCurrentPage->headerList; - } - else - mCurrentHeader = mCurrentHeader->next; - } - while( !mCurrentHeader || ( mAllocatedOnly && !( mCurrentHeader->flags & Allocated ) ) ); - - return *this; - } - operator Header*() const - { - return mCurrentHeader; - } - Header* operator *() const - { - return mCurrentHeader; - } - Header* operator ->() const - { - return mCurrentHeader; - } -}; - -#ifdef TORQUE_DEBUG_GUARD - -static bool checkGuard(Header *header, bool alloc) -{ - U32 guardVal = alloc ? AllocatedGuard : FreeGuard; - for(U32 i = 0; i < 4; i++) - if(header->preguard[i] != guardVal || header->postguard[i] != guardVal) - { - Platform::debugBreak(); - return false; - } - - return true; -} - #if !defined(TORQUE_DISABLE_MEMORY_MANAGER) -static void setGuard(Header *header, bool alloc) -{ - U32 guardVal = alloc ? AllocatedGuard : FreeGuard; - for(U32 i = 0; i < 4; i++) - header->preguard[i] = header->postguard[i] = guardVal; -} -#endif // !defined(TORQUE_DISABLE_MEMORY_MANAGER) -#endif // TORQUE_DEBUG_GUARD -static void memoryError() -{ - // free all the pages - PageRecord *walk = gPageList; - while(walk) { - PageRecord *prev = walk->prevPage; - dRealFree(walk); - walk = prev; - } - AssertFatal(false, "Error allocating memory! Shutting down."); - Platform::AlertOK("Torque Memory Error", "Error allocating memory. Shutting down.\n"); - Platform::forceShutdown(-1); -} + static const U32 MaxAllocs = 10240; + static MemInfo allocList[MaxAllocs]; + static U32 allocCount = 0; + static U32 currentAllocId = 0; + static bool initialized = false; + char gLogFilename[256] = "memlog.txt"; + bool gStackTrace = false; -PageRecord *allocPage(dsize_t pageSize) -{ - pageSize += sizeof(PageRecord); - void* base = dRealMalloc(pageSize); - if (base == NULL) - memoryError(); - - PageRecord *rec = (PageRecord *) base; - rec->basePtr = (void *) (rec + 1); - rec->allocSize = pageSize; - rec->prevPage = gPageList; - gPageList = rec; - rec->headerList = NULL; - return rec; -} - -TreeNode *allocTreeNode() -{ - if(!gTreeFreeList) + void init() { - PageRecord *newPage = allocPage(TreeNodeAllocCount * sizeof(TreeNode)); - TreeNode *walk = (TreeNode *) newPage->basePtr; - U32 i; - gTreeFreeList = walk; - for(i = 0; i < TreeNodeAllocCount - 1; i++, walk++) - walk->parent = walk + 1; - walk->parent = NULL; - } - TreeNode *ret = gTreeFreeList; - gTreeFreeList = ret->parent; - return ret; -} + if (initialized) return; + std::memset(allocList, 0, sizeof(allocList)); + allocCount = 0; + currentAllocId = 0; + initialized = true; -void freeTreeNode(TreeNode *tn) -{ - tn->parent = gTreeFreeList; - gTreeFreeList = tn; -} - - -static U32 validateTreeRecurse(TreeNode *tree) -{ - if(tree == NIL) - return 1; - // check my left tree - S32 lcount, rcount, nc = 0; - - if(tree->color == Red) - { - if(tree->left->color == Red || tree->right->color == Red) - Platform::debugBreak(); - } - else - nc = 1; - - FreeHeader *walk = tree->queueHead; - if(!walk) - Platform::debugBreak(); - - FreeHeader *prev = NULL; - while(walk) - { - if(walk->prevQueue != prev) - Platform::debugBreak(); - if(walk->treeNode != tree) - Platform::debugBreak(); - if(walk->size != tree->size) - Platform::debugBreak(); - if(!walk->nextQueue && walk != tree->queueTail) - Platform::debugBreak(); - prev = walk; - walk = walk->nextQueue; } - lcount = validateTreeRecurse(tree->left); - rcount = validateTreeRecurse(tree->right); - if(lcount != rcount) - Platform::debugBreak(); - return lcount + nc; -} - -static void validateParentageRecurse(TreeNode *tree) -{ - if(tree->left != NIL) + void shutdown() { - if(tree->left->parent != tree) - Platform::debugBreak(); + if (!initialized) return; - if(tree->left->size > tree->size) - Platform::debugBreak(); - validateParentageRecurse(tree->left); - } - if(tree->right != NIL) - { - if(tree->right->parent != tree) - Platform::debugBreak(); - - if(tree->right->size < tree->size) - Platform::debugBreak(); - validateParentageRecurse(tree->right); - } -} - -static void validateTree() -{ - if(gFreeTreeRoot == NIL) - return; - validateParentageRecurse(gFreeTreeRoot); - validateTreeRecurse(gFreeTreeRoot); -} - -void validate() -{ -#ifdef TORQUE_MULTITHREAD - if(!gMemMutex) - gMemMutex = Mutex::createMutex(); - - Mutex::lockMutex(gMemMutex); -#endif - - - // first validate the free tree: - validateTree(); - // now validate all blocks: - for(PageRecord *list = gPageList; list; list = list->prevPage) - { - Header *prev = NULL; - for(Header *walk = list->headerList; walk; walk = walk->next) - { -#ifdef TORQUE_DEBUG_GUARD - checkGuard(walk, walk->flags & Allocated); -#endif - if(walk->prev != prev) - Platform::debugBreak(); - prev = walk; - if(walk->next && ((const char *)(walk->next) != (const char *)(walk) + sizeof(Header) + walk->size)) - Platform::debugBreak(); - } - } - -#ifdef TORQUE_MULTITHREAD - Mutex::unlockMutex(gMemMutex); -#endif -} - -#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) -static void rotateLeft(TreeNode *hdr) -{ - TreeNode *temp = hdr->right; - hdr->right = temp->left; - if(temp->left != NIL) - temp->left->parent = hdr; - temp->parent = hdr->parent; - if(temp->parent == NIL) - gFreeTreeRoot = temp; - else if(hdr == hdr->parent->left) - hdr->parent->left = temp; - else - hdr->parent->right = temp; - temp->left = hdr; - hdr->parent = temp; -} -#endif - -#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) -static void rotateRight(TreeNode *hdr) -{ - TreeNode *temp = hdr->left; - hdr->left = temp->right; - if(temp->right != NIL) - temp->right->parent = hdr; - temp->parent = hdr->parent; - if(temp->parent == NIL) - gFreeTreeRoot = temp; - else if(hdr == hdr->parent->left) - hdr->parent->left = temp; - else - hdr->parent->right = temp; - temp->right = hdr; - hdr->parent = temp; -} -#endif - -#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) -static void treeInsert(FreeHeader *fhdr) -{ -#ifdef TORQUE_DEBUG_GUARD - checkGuard((Header *) fhdr, true); // check to see that it's got allocated guards - setGuard((Header *) fhdr, false); -#endif - //gInsertCount++; - - TreeNode *newParent = NIL; - TreeNode *walk = gFreeTreeRoot; - while(walk != NIL) - { - newParent = walk; - if(fhdr->size < walk->size) - walk = walk->left; - else if(fhdr->size > walk->size) - walk = walk->right; - else // tag it on the end of the queue... - { - // insert it on this header... - walk->queueTail->nextQueue = fhdr; - fhdr->prevQueue = walk->queueTail; - walk->queueTail = fhdr; - fhdr->nextQueue = NULL; - fhdr->treeNode = walk; + FILE* log = std::fopen(gLogFilename, "w"); + if (!log) return; - } - } - TreeNode *hdr = allocTreeNode(); - hdr->size = fhdr->size; - hdr->queueHead = hdr->queueTail = fhdr; - fhdr->nextQueue = fhdr->prevQueue = NULL; - fhdr->treeNode = hdr; - hdr->left = NIL; - hdr->right = NIL; - - hdr->parent = newParent; - - if(newParent == NIL) - gFreeTreeRoot = hdr; - else if(hdr->size < newParent->size) - newParent->left = hdr; - else - newParent->right = hdr; - - // do red/black rotations - hdr->color = Red; - while(hdr != gFreeTreeRoot && (hdr->parent->color == Red)) - { - TreeNode *parent = hdr->parent; - TreeNode *pparent = hdr->parent->parent; - - if(parent == pparent->left) + std::fprintf(log, "\n--- Memory Leak Report ---\n"); + for (U32 i = 0; i < allocCount; ++i) { - TreeNode *temp = pparent->right; - if(temp->color == Red) + if (allocList[i].ptr != nullptr) { - parent->color = Black; - temp->color = Black; - pparent->color = Red; - hdr = pparent; - } - else - { - if(hdr == parent->right) + std::fprintf(log, "Leak: %p (%zu bytes) from %s:%u [id=%u]\n", + allocList[i].ptr, allocList[i].size, + allocList[i].file ? allocList[i].file : "(null)", allocList[i].line, + allocList[i].allocId); + if (gStackTrace) { - hdr = parent; - rotateLeft(hdr); - parent = hdr->parent; - pparent = hdr->parent->parent; - } - parent->color = Black; - pparent->color = Red; - rotateRight(pparent); - } - } - else - { - TreeNode *temp = pparent->left; - if(temp->color == Red) - { - parent->color = Black; - temp->color = Black; - pparent->color = Red; - hdr = pparent; - } - else - { - if(hdr == parent->left) - { - hdr = parent; - rotateRight(hdr); - parent = hdr->parent; - pparent = hdr->parent->parent; - } - parent->color = Black; - pparent->color = Red; - rotateLeft(pparent); - } - } - } - gFreeTreeRoot->color = Black; - //validateTree(); -} -#endif +#ifdef _WIN32 + SYMBOL_INFO* symbol = (SYMBOL_INFO*)malloc(sizeof(SYMBOL_INFO) + 256); + symbol->MaxNameLen = 255; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); -#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) -static void treeRemove(FreeHeader *hdr) -{ -#ifdef TORQUE_DEBUG_GUARD - checkGuard((Header *) hdr, false); - setGuard((Header *) hdr, true); -#endif - //validateTree(); - //gRemoveCount++; + HANDLE process = GetCurrentProcess(); + SymInitialize(process, NULL, TRUE); - FreeHeader *prev = hdr->prevQueue; - FreeHeader *next = hdr->nextQueue; - - if(prev) - prev->nextQueue = next; - else - hdr->treeNode->queueHead = next; - - if(next) - next->prevQueue = prev; - else - hdr->treeNode->queueTail = prev; - - if(prev || next) - return; - - TreeNode *z = hdr->treeNode; - - nil.color = Black; - - TreeNode *y, *x; - if(z->left == NIL || z->right == NIL) - y = z; - else - { - y = z->right; - while(y->left != NIL) - y = y->left; - } - if(y->left != NIL) - x = y->left; - else - x = y->right; - - x->parent = y->parent; - if(y->parent == NIL) - gFreeTreeRoot = x; - else if(y == y->parent->left) - y->parent->left = x; - else - y->parent->right = x; - - U32 yColor = y->color; - if(y != z) - { - // copy y's important fields into z (since we're going to free y) - if(z->parent->left == z) - z->parent->left = y; - else if(z->parent->right == z) - z->parent->right = y; - y->left = z->left; - y->right = z->right; - if(y->left != NIL) - y->left->parent = y; - if(y->right != NIL) - y->right->parent = y; - y->parent = z->parent; - if(z->parent == NIL) - gFreeTreeRoot = y; - y->color = z->color; - if(x->parent == z) - x->parent = y; - //validateTree(); - } - freeTreeNode(z); - - if(yColor == Black) - { - while(x != gFreeTreeRoot && x->color == Black) - { - TreeNode *w; - if(x == x->parent->left) - { - w = x->parent->right; - if(w->color == Red) - { - w->color = Black; - x->parent->color = Red; - rotateLeft(x->parent); - w = x->parent->right; - } - if(w->left->color == Black && w->right->color == Black) - { - w->color = Red; - x = x->parent; - } - else - { - if(w->right->color == Black) + for (int j = 0; j < allocList[i].backtraceSize; ++j) { - w->left->color = Black; - rotateRight(w); - w = x->parent->right; + DWORD64 addr = (DWORD64)(allocList[i].backtracePtrs[j]); + if (SymFromAddr(process, addr, 0, symbol)) + { + std::fprintf(log, " [%d] %s - 0x%0llX\n", j, symbol->Name, symbol->Address); + } + else + { + std::fprintf(log, " [%d] ??? - 0x%0llX\n", j, addr); + } } - w->color = x->parent->color; - x->parent->color = Black; - w->right->color = Black; - rotateLeft(x->parent); - x = gFreeTreeRoot; - } - } - else - { - w = x->parent->left; - if(w->color == Red) - { - w->color = Black; - x->parent->color = Red; - rotateRight(x->parent); - w = x->parent->left; - } - if(w->left->color == Black && w->right->color == Black) - { - w->color = Red; - x = x->parent; - } - else - { - if(w->left->color == Black) + + std::free(symbol); +#else + char** symbols = backtrace_symbols(allocList[i].backtracePtrs, allocList[i].backtraceSize); + for (int j = 0; j < allocList[i].backtraceSize; ++j) { - w->right->color = Black; - rotateLeft(w); - w = x->parent->left; + std::fprintf(log, " [%d] %s\n", j, symbols[j]); } - w->color = x->parent->color; - x->parent->color = Black; - w->left->color = Black; - rotateRight(x->parent); - x = gFreeTreeRoot; + std::free(symbols); +#endif } } } - x->color = Black; + std::fclose(log); + initialized = false; } - //validateTree(); -} -#endif -#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) -static FreeHeader *treeFindSmallestGreaterThan(dsize_t size) -{ - TreeNode *bestMatch = NIL; - TreeNode *walk = gFreeTreeRoot; - while(walk != NIL) + void checkPtr(void* ptr) { - if(size == walk->size) - return walk->queueHead; - else if(size > walk->size) - walk = walk->right; - else // size < walk->size + for (U32 i = 0; i < allocCount; ++i) + if (allocList[i].ptr == ptr) + return; + + Platform::debugBreak(); + } + + static void* alloc(dsize_t size, bool array, const char* fileName, U32 line) + { + if (size == 0) + return nullptr; + + void* ptr = std::malloc(size); + if (!ptr) + return nullptr; + + if (!initialized || allocCount >= MaxAllocs) + return ptr; + + MemInfo& info = allocList[allocCount++]; + info.ptr = ptr; + info.size = size; + info.file = fileName ? fileName : "unknown"; + info.line = line; + info.allocId = currentAllocId++; + info.flagged = false; + + if (gStackTrace) { - bestMatch = walk; - walk = walk->left; +#ifdef _WIN32 + info.backtraceSize = CaptureStackBackTrace(0, 16, info.backtracePtrs, nullptr); +#else + info.backtraceSize = backtrace(info.backtracePtrs, MaxBacktraceDepth); +#endif } + + return ptr; } - //validateTree(); - if(bestMatch != NIL) - return bestMatch->queueHead; - return NULL; -} -#endif - -/// Trigger a breakpoint if ptr is not a valid heap pointer or if its memory guards -/// have been destroyed (only if TORQUE_DEBUG_GUARD is enabled). -/// -/// @note This function does not allow interior pointers! - -void checkPtr( void* ptr ) -{ - for( HeapIterator iter; iter.isValid(); ++ iter ) + static void free(void* ptr, bool array) { - AllocatedHeader* header = ( AllocatedHeader* ) *iter; - if( header->getUserPtr() == ptr ) + if (!ptr || !initialized) + return; + + + for (U32 i = 0; i < allocCount; ++i) { -#ifdef TORQUE_DEBUG_GUARD - char buffer[ 1024 ]; - if( !checkGuard( *iter, true ) ) + if (allocList[i].ptr == ptr) { - dSprintf( buffer, sizeof( buffer ), "0x%x is a valid heap pointer but has its guards corrupted", ptr ); - Platform::outputDebugString( buffer ); + std::free(ptr); + allocList[i] = allocList[allocCount - 1]; + allocList[--allocCount] = {}; return; } - //dSprintf( buffer, sizeof( buffer ), "0x%x is a valid heap pointer", ptr ); - //Platform::outputDebugString( buffer ); -#endif - return; } + + // Unknown pointer, still free it. + std::free(ptr); } - char buffer[ 1024 ]; - dSprintf( buffer, sizeof( buffer ), "0x%x is not a valid heap pointer", ptr ); - Platform::outputDebugString( buffer ); - - Platform::debugBreak(); -} - -/// Dump info on all memory blocks that are still allocated. -/// @note Only works if TORQUE_DISABLE_MEMORY_MANAGER is not defined; otherwise this is a NOP. - -void ensureAllFreed() -{ -#ifndef TORQUE_DISABLE_MEMORY_MANAGER - - U32 numLeaks = 0; - U32 bytesLeaked = 0; - - for( HeapIterator iter; iter.isValid(); ++ iter ) + static void* realloc(void* oldPtr, dsize_t newSize, const char* fileName, U32 line) { - AllocatedHeader* header = ( AllocatedHeader* ) *iter; - if( !( header->flags & GlobalFlag ) ) + if (!initialized) + return std::realloc(oldPtr, newSize); // fallback if not tracking + + if (newSize == 0) { - // Note: can't spill profile paths here since they by - // now are all invalid (they're on the now freed string table) - -#ifdef TORQUE_DEBUG_GUARD - Platform::outputDebugString( "MEMORY LEAKED: 0x%x %i %s %s:%i = %i (%i)", - header->getUserPtr(), - header->allocNum, - ( header->flags & StaticFlag ? "(static)" : "" ), - header->fileName, header->line, header->realSize, header->size ); - numLeaks ++; - bytesLeaked += header->size; -#endif + free(oldPtr, false); + return nullptr; } - } - if( numLeaks ) - Platform::outputDebugString( "NUM LEAKS: %i (%i bytes)", numLeaks, bytesLeaked ); -#endif -} + if (oldPtr == nullptr) + return alloc(newSize, false, fileName, line); -struct MemDumpLog -{ - U32 size; - U32 count; - U32 depthTotal; - U32 maxDepth; - U32 minDepth; -}; -void logDumpTraverse(MemDumpLog *sizes, TreeNode *header, U32 depth) -{ - if(header == NIL) - return; - MemDumpLog *mySize = sizes; - while(mySize->size < header->size) - mySize++; + void* newPtr = std::realloc(oldPtr, newSize); + if (!newPtr) + return nullptr; - U32 cnt = 0; - for(FreeHeader *walk = header->queueHead; walk; walk = walk->nextQueue) - cnt++; - mySize->count += cnt; - mySize->depthTotal += depth * cnt; - mySize->maxDepth = depth > mySize->maxDepth ? depth : mySize->maxDepth; - mySize->minDepth = depth < mySize->minDepth ? depth : mySize->minDepth; - logDumpTraverse(sizes, header->left, depth + 1); - logDumpTraverse(sizes, header->right, depth + 1); -} -#ifdef TORQUE_DEBUG -DefineEngineFunction( validateMemory, void, ( ),, - "@brief Used to validate memory space for the game.\n\n" - "@ingroup Debugging" ) -{ - validate(); -} -#endif - -DefineEngineFunction( freeMemoryDump, void, ( ),, - "@brief Dumps some useful statistics regarding free memory.\n\n" - "Dumps an analysis of \'free chunks\' of memory. " - "Does not print how much memory is free.\n\n" - "@ingroup Debugging" ) -{ - U32 startSize = 16; - MemDumpLog memSizes[20]; - U32 i; - for(i = 0; i < 20; i++) - { - memSizes[i].size = startSize << i; - memSizes[i].count = 0; - memSizes[i].depthTotal = 0; - memSizes[i].maxDepth = 0; - memSizes[i].minDepth = 1000; - } - memSizes[19].size = MaxAllocationAmount; - logDumpTraverse(memSizes, gFreeTreeRoot, 1); - MemDumpLog fullMem; - fullMem.count = 0; - fullMem.depthTotal = 0; - fullMem.maxDepth = 0; - fullMem.minDepth = 1000; - - for(i = 0; i < 20; i++) - { - if(memSizes[i].count) - Con::printf("Size: %d - Free blocks: %d Max Depth: %d Min Depth: %d Average Depth: %g", - memSizes[i].size, memSizes[i].count, memSizes[i].maxDepth, memSizes[i].minDepth, - F32(memSizes[i].depthTotal) / F32(memSizes[i].count)); - - fullMem.count += memSizes[i].count; - fullMem.depthTotal += memSizes[i].depthTotal; - fullMem.maxDepth = memSizes[i].maxDepth > fullMem.maxDepth ? memSizes[i].maxDepth : fullMem.maxDepth; - fullMem.minDepth = memSizes[i].minDepth < fullMem.minDepth ? memSizes[i].minDepth : fullMem.minDepth; - } - Con::printf("Total free blocks: %d Max Depth: %d Min Depth: %d Average Depth: %g", - fullMem.count, fullMem.maxDepth, fullMem.minDepth, F32(fullMem.depthTotal) / F32(fullMem.count)); -} - -#ifdef TORQUE_DEBUG_GUARD - -void flagCurrentAllocs( EFlag flag ) -{ -#ifdef TORQUE_ENABLE_PROFILE_PATH - if (gProfiler && !gProfiler->isEnabled()) - { - gProfiler->enable(true); - // warm it up - //gProfiler->dumpToConsole(); - } -#endif - - U32 bit = flagToBit( flag ); - for( HeapIterator iter; iter.isValid(); ++ iter ) - iter->flags |= bit; -} - -DefineEngineFunction(flagCurrentAllocs, void, (),, - "@brief Flags all current memory allocations.\n\n" - "Flags all current memory allocations for exclusion in subsequent calls to dumpUnflaggedAllocs(). " - "Helpful in detecting memory leaks and analyzing memory usage.\n\n" - "@ingroup Debugging" ) -{ - flagCurrentAllocs(); -} - -void dumpUnflaggedAllocs(const char *file, EFlag flag) -{ - countUnflaggedAllocs(file, NULL, flag); -} - -S32 countUnflaggedAllocs(const char * filename, S32 *outUnflaggedRealloc, EFlag flag) -{ - S32 unflaggedAllocCount = 0; - S32 unflaggedReAllocCount = 0; - - FileStream fws; - bool useFile = filename && *filename; - if (useFile) - useFile = fws.open(filename, Torque::FS::File::Write); - char buffer[1024]; - - U32 bit = flagToBit( flag ); - - PageRecord* walk; - for (walk = gPageList; walk; walk = walk->prevPage) - { - for(Header *probe = walk->headerList; probe; probe = probe->next) + // Update existing record + for (U32 i = 0; i < allocCount; ++i) { - if (probe->flags & Allocated) + if (allocList[i].ptr == oldPtr) { - AllocatedHeader* pah = (AllocatedHeader*)probe; - if (!(pah->flags & bit)) - { - // If you want to extract further information from an unflagged - // memory allocation, do the following: - // U8 *foo = (U8 *)pah; - // foo += sizeof(Header); - // FooObject *obj = (FooObject *)foo; - dSprintf(buffer, 1023, "%s%s\t%d\t%d\t%d\r\n", - pah->flags & Reallocated ? "[R] " : "", - pah->fileName != NULL ? pah->fileName : "Undetermined", - pah->line, pah->realSize, pah->allocNum); - - if( pah->flags & Reallocated ) - unflaggedReAllocCount++; - else - unflaggedAllocCount++; - - if (useFile) - { - fws.write(dStrlen(buffer), buffer); - fws.write(2, "\r\n"); - } - else - { - if( pah->flags & Reallocated ) - Con::warnf(buffer); - else - Con::errorf(buffer); - } - -#ifdef TORQUE_ENABLE_PROFILE_PATH - static char line[4096]; - dSprintf(line, sizeof(line), " %s\r\nreal size=%d", - pah->profilePath ? pah->profilePath : "unknown", - pah->realSize); - - if (useFile) - { - fws.write(dStrlen(line), line); - fws.write(2, "\r\n"); - } - else - { - if( pah->flags & Reallocated ) - Con::warnf(line); - else - Con::errorf(line); - } -#endif - - } + allocList[i].ptr = newPtr; + allocList[i].size = newSize; + allocList[i].file = fileName; + allocList[i].line = line; + allocList[i].allocId = currentAllocId++; + return newPtr; } } - } - if (useFile) - fws.close(); - - if( outUnflaggedRealloc != NULL ) - *outUnflaggedRealloc = unflaggedReAllocCount; - - return unflaggedAllocCount; -} - -DefineEngineFunction(dumpUnflaggedAllocs, void, ( const char* fileName ), ( "" ), - "@brief Dumps all unflagged memory allocations.\n\n" - "Dumps all memory allocations that were made after a call to flagCurrentAllocs(). " - "Helpful when used with flagCurrentAllocs() for detecting memory leaks and analyzing general memory usage.\n\n" - "@param fileName Optional file path and location to dump all memory allocations not flagged by flagCurrentAllocs(). " - "If left blank, data will be dumped to the console.\n\n" - "@tsexample\n" - "dumpMemSnapshot(); // dumps info to console\n" - "dumpMemSnapshot( \"C:/Torque/profilerlog1.txt\" ); // dumps info to file\n" - "@endtsexample\n\n" - "@note Available in debug builds only. " - "In torqueConfig.h, TORQUE_DISABLE_MEMORY_MANAGER must be undefined to use this function.\n\n" - "@ingroup Debugging" ) -{ - dumpUnflaggedAllocs(fileName); -} - -static void initLog() -{ - static const char* sInitString = " --- INIT MEMORY LOG (ACTION): (FILE) (LINE) (SIZE) (ALLOCNUMBER) ---\r\n"; - - FileStream fws; - fws.open(gLogFilename, Torque::FS::File::Write); - fws.write(dStrlen(sInitString), sInitString); - fws.close(); -} - -#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) -static void logAlloc(const AllocatedHeader* hdr, S32 memSize) -{ - FileStream fws; - fws.open(gLogFilename, Torque::FS::File::ReadWrite); - fws.setPosition(fws.getStreamSize()); - - char buffer[1024]; - dSprintf(buffer, 1023, "alloc: %s %d %d %d\r\n", - hdr->fileName != NULL ? hdr->fileName : "Undetermined", - hdr->line, memSize, hdr->allocNum); - fws.write(dStrlen(buffer), buffer); - fws.close(); -} -#endif - -#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) -static void logRealloc(const AllocatedHeader* hdr, S32 memSize) -{ - FileStream fws; - fws.open(gLogFilename, Torque::FS::File::ReadWrite); - fws.setPosition(fws.getStreamSize()); - - char buffer[1024]; - dSprintf(buffer, 1023, "realloc: %s %d %d %d\r\n", - hdr->fileName != NULL ? hdr->fileName : "Undetermined", - hdr->line, memSize, hdr->allocNum); - fws.write(dStrlen(buffer), buffer); - fws.close(); -} -#endif - -#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) -static void logFree(const AllocatedHeader* hdr) -{ - FileStream fws; - fws.open(gLogFilename, Torque::FS::File::ReadWrite); - fws.setPosition(fws.getStreamSize()); - - char buffer[1024]; - dSprintf(buffer, 1023, "free: %s %d %d\r\n", - hdr->fileName != NULL ? hdr->fileName : "Undetermined", - hdr->line, hdr->allocNum); - fws.write(dStrlen(buffer), buffer); - fws.close(); -} -#endif // !defined(TORQUE_DISABLE_MEMORY_MANAGER) - -#endif - -void enableLogging(const char* fileName) -{ - dStrcpy(gLogFilename, fileName, 256); - if (!gEnableLogging) - { - gEnableLogging = true; -#ifdef TORQUE_DEBUG_GUARD - initLog(); -#endif - } -} - -void disableLogging() -{ - gLogFilename[0] = '\0'; - gEnableLogging = false; -} - -// CodeReview - this is never called so commented out to save warning. -// Do we want to re-enable it? Might be nice to get leak tracking on -// exit...or maybe that is just a problematical feature we shouldn't -// worry about. -//static void shutdown() -//{ -//#ifdef TORQUE_MULTITHREAD -// Mutex::destroyMutex(gMemMutex); -// gMemMutex = NULL; -//#endif -// -//#ifdef TORQUE_DEBUG_GUARD -// -// // write out leaks and such -// const U32 maxNumLeaks = 1024; -// U32 numLeaks = 0; -// -// AllocatedHeader* pLeaks[maxNumLeaks]; -// for (PageRecord * walk = gPageList; walk; walk = walk->prevPage) -// for(Header *probe = walk->headerList; probe; probe = probe->next) -// if ((probe->flags & Allocated) && ((AllocatedHeader *)probe)->fileName != NULL) -// pLeaks[numLeaks++] = (AllocatedHeader *) probe; -// -// if (numLeaks && !gNeverLogLeaks) -// { -// if (gAlwaysLogLeaks || Platform::AlertOKCancel("Memory Status", "Memory leaks detected. Write to memoryLeaks.log?") == true) -// { -// char buffer[1024]; -// FileStream logFile; -// logFile.open("memoryLeaks.log", Torque::FS::File::Write); -// -// for (U32 i = 0; i < numLeaks; i++) -// { -// dSprintf(buffer, 1023, "Leak in %s: %d (%d)\r\n", pLeaks[i]->fileName, pLeaks[i]->line, pLeaks[i]->allocNum); -// logFile.write(dStrlen(buffer), buffer); -// } -// logFile.close(); -// } -// } -//#endif -// -// // then free all the memory pages -// for (PageRecord * walk = gPageList; walk; ) -// { -// PageRecord *prev = walk->prevPage; -// dRealFree(walk); -// walk = prev; -// } -//} - -#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) -static Header *allocMemPage(dsize_t pageSize) -{ - pageSize += sizeof(Header); - if(pageSize < MinPageSize) - pageSize = MinPageSize; - PageRecord *base = allocPage(pageSize); - - Header* rec = (Header*)base->basePtr; - base->headerList = rec; - - rec->size = pageSize - sizeof(Header); - rec->next = NULL; - rec->prev = NULL; - rec->flags = 0; -#ifdef TORQUE_DEBUG_GUARD - setGuard(rec, true); -#endif - -#ifdef LOG_PAGE_ALLOCS - gPageBytesAllocated += pageSize; - // total bytes allocated so far will be 0 when TORQUE_DEBUG_GUARD is disabled, so convert that into more meaningful string - const U32 StrSize = 256; - char strBytesAllocated[StrSize]; - if (gBytesAllocated > 0) - dSprintf(strBytesAllocated, sizeof(strBytesAllocated), "%i", gBytesAllocated); - else - dStrncpy(strBytesAllocated,"unknown - enable TORQUE_DEBUG_GUARD", StrSize); - -#ifndef TORQUE_MULTITHREAD // May deadlock. - // NOTE: This code may be called within Con::_printf, and if that is the case - // this will infinitly recurse. This is the reason for the code in Con::_printf - // that sets Con::active to false. -patw - if (Con::isActive()) - Con::errorf("PlatformMemory: allocating new page, total bytes allocated so far: %s (total bytes in all pages=%i)",strBytesAllocated,gPageBytesAllocated); -#endif -#endif - return rec; -} -#endif - -#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) -static void checkUnusedAlloc(FreeHeader *header, U32 size) -{ - //validate(); - if(header->size >= size + sizeof(Header) + 16) - { - U8 *basePtr = (U8 *) header; - basePtr += sizeof(Header); - FreeHeader *newHeader = (FreeHeader *) (basePtr + size); - newHeader->next = header->next; - newHeader->prev = (Header *) header; - header->next = (Header *) newHeader; - if(newHeader->next) - newHeader->next->prev = (Header *) newHeader; - newHeader->flags = 0; - newHeader->size = header->size - size - sizeof(Header); - header->size = size; -#ifdef TORQUE_DEBUG_GUARD - setGuard((Header *) newHeader, true); -#endif - treeInsert(newHeader); - } -} -#endif - -#if defined(TORQUE_MULTITHREAD) && !defined(TORQUE_DISABLE_MEMORY_MANAGER) -static bool gReentrantGuard = false; -#endif - -#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) -static void* alloc(dsize_t size, bool array, const char* fileName, const U32 line) -{ - AssertFatal(size < MaxAllocationAmount, "Memory::alloc - tried to allocate > MaxAllocationAmount!"); - -#ifdef TORQUE_MULTITHREAD - if(!gMemMutex && !gReentrantGuard) - { - gReentrantGuard = true; - gMemMutex = Mutex::createMutex(); - gReentrantGuard = false; - } - - if(!gReentrantGuard) - Mutex::lockMutex(gMemMutex); - -#endif - - AssertFatal(size < MaxAllocationAmount, "Size error."); - //validate(); - if (size == 0) - { -#ifdef TORQUE_MULTITHREAD - if(!gReentrantGuard) - Mutex::unlockMutex(gMemMutex); -#endif - return NULL; - } - -#ifndef TORQUE_ENABLE_PROFILE_PATH - // Note: will cause crash if profile path is on - PROFILE_START(MemoryAlloc); -#endif - -#ifdef TORQUE_DEBUG_GUARD - // if we're guarding, round up to the nearest DWORD - size = ((size + 3) & ~0x3); -#else - // round up size to nearest 16 byte boundary (cache lines and all...) - size = ((size + 15) & ~0xF); -#endif - - FreeHeader *header = treeFindSmallestGreaterThan(size); - if(header) - treeRemove(header); - else - header = (FreeHeader *) allocMemPage(size); - - // ok, see if there's enough room in the block to make another block - // for this to happen it has to have enough room for a header - // and 16 more bytes. - - U8 *basePtr = (U8 *) header; - basePtr += sizeof(Header); - - checkUnusedAlloc(header, size); - - AllocatedHeader *retHeader = (AllocatedHeader *) header; - retHeader->flags = array ? (Allocated | Array) : Allocated; - -#ifdef TORQUE_DEBUG_GUARD - retHeader->line = line; - retHeader->fileName = fileName; - retHeader->allocNum = gCurrAlloc; - retHeader->realSize = size; -#ifdef TORQUE_ENABLE_PROFILE_PATH - retHeader->profilePath = gProfiler ? gProfiler->getProfilePath() : "pre"; -#endif - gBytesAllocated += size; - gBlocksAllocated ++; - //static U32 skip = 0; - //if ((++skip % 1000) == 0) - // Con::printf("new=%i, newnew=%i, imagenew=%i",gBytesAllocated,gNewNewTotal,gImageAlloc); - if (gEnableLogging) - logAlloc(retHeader, size); -#endif - if(gCurrAlloc == gBreakAlloc && gBreakAlloc != 0xFFFFFFFF) - Platform::debugBreak(); - gCurrAlloc++; -#ifndef TORQUE_ENABLE_PROFILE_PATH - PROFILE_END(); -#endif - //validate(); - -#ifdef TORQUE_DEBUG - // fill the block with the fill value. although this is done in free(), that won't fill - // newly allocated MM memory (which hasn't been freed yet). We use a different fill value - // to diffentiate filled freed memory from filled new memory; this may aid debugging. - #ifndef TORQUE_ENABLE_PROFILE_PATH - PROFILE_START(stompMem1); - #endif - dMemset(basePtr, 0xCF, size); - #ifndef TORQUE_ENABLE_PROFILE_PATH - PROFILE_END(); - #endif -#endif - - if(gCurrAlloc == gBreakAlloc && gBreakAlloc != 0xFFFFFFFF) - Platform::debugBreak(); - - gCurrAlloc++; - -#ifdef TORQUE_MULTITHREAD - if(!gReentrantGuard) - Mutex::unlockMutex(gMemMutex); -#endif - - return basePtr; -} -#endif - -#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) -static void free(void* mem, bool array) -{ - // validate(); - - if (!mem) - return; - -#ifdef TORQUE_MULTITHREAD - if(!gMemMutex) - gMemMutex = Mutex::createMutex(); - - if( mem != gMemMutex ) - Mutex::lockMutex(gMemMutex); - else - gMemMutex = NULL; -#endif - - PROFILE_START(MemoryFree); - AllocatedHeader *hdr = ((AllocatedHeader *)mem) - 1; - - AssertFatal(hdr->flags & Allocated, avar("Not an allocated block!")); - AssertFatal(((bool)((hdr->flags & Array)==Array))==array, avar("Array alloc mismatch. ")); - - gBlocksAllocated --; -#ifdef TORQUE_DEBUG_GUARD - gBytesAllocated -= hdr->realSize; - if (gEnableLogging) - logFree(hdr); -#endif - - hdr->flags = 0; - - // fill the block with the fill value - -#ifdef TORQUE_DEBUG - #ifndef TORQUE_ENABLE_PROFILE_PATH - PROFILE_START(stompMem2); - #endif - dMemset(mem, 0xCE, hdr->size); - #ifndef TORQUE_ENABLE_PROFILE_PATH - PROFILE_END(); - #endif -#endif - - // see if we can merge hdr with the block after it. - - Header* next = hdr->next; - if (next && next->flags == 0) - { - treeRemove((FreeHeader *) next); - hdr->size += next->size + sizeof(Header); - hdr->next = next->next; - if(next->next) - next->next->prev = (Header *) hdr; - } - - // see if we can merge hdr with the block before it. - Header* prev = hdr->prev; - - if (prev && prev->flags == 0) - { - treeRemove((FreeHeader *) prev); - prev->size += hdr->size + sizeof(Header); - prev->next = hdr->next; - if (hdr->next) - hdr->next->prev = prev; - - hdr = (AllocatedHeader *) prev; - } - - // throw this puppy into the tree! - treeInsert((FreeHeader *) hdr); - PROFILE_END(); - -// validate(); - -#ifdef TORQUE_MULTITHREAD - Mutex::unlockMutex(gMemMutex); -#endif -} -#endif - -#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) -static void* realloc(void* mem, dsize_t size, const char* fileName, const U32 line) -{ - //validate(); - if (!size) { - free(mem, false); - return NULL; - } - if(!mem) - return alloc(size, false, fileName, line); - -#ifdef TORQUE_MULTITHREAD - if(!gMemMutex) - gMemMutex = Mutex::createMutex(); - - Mutex::lockMutex(gMemMutex); -#endif - - AllocatedHeader* hdr = ((AllocatedHeader *)mem) - 1; -#ifdef TORQUE_DEBUG_GUARD - checkGuard( ( Header* ) hdr, true ); -#endif - - AssertFatal((hdr->flags & Allocated) == Allocated, "Bad block flags."); - - size = (size + 0xF) & ~0xF; - - U32 oldSize = hdr->size; - if(oldSize == size) - { -#ifdef TORQUE_MULTITHREAD - Mutex::unlockMutex(gMemMutex); -#endif - return mem; - } - PROFILE_START(MemoryRealloc); - - FreeHeader *next = (FreeHeader *) hdr->next; - -#ifdef TORQUE_DEBUG_GUARD - // adjust header size and allocated bytes size - hdr->realSize += size - oldSize; - gBytesAllocated += size - oldSize; - if (gEnableLogging) - logRealloc(hdr, size); - - // Add reallocated flag, note header changes will not persist if the realloc - // decides tofree, and then perform a fresh allocation for the memory. The flag will - // be manually set again after this takes place, down at the bottom of this fxn. - hdr->flags |= Reallocated; - - // Note on Above ^ - // A more useful/robust implementation can be accomplished by storing an additional - // AllocatedHeader* in DEBUG_GUARD builds inside the AllocatedHeader structure - // itself to create a sort of reallocation history. This will be, essentially, - // a allocation header stack for each allocation. Each time the memory is reallocated - // it should use dRealMalloc (IMPORTANT!!) to allocate a AllocatedHeader* and chain - // it to the reallocation history chain, and the dump output changed to display - // reallocation history. It is also important to clean up this chain during 'free' - // using dRealFree (Since memory for the chain was allocated via dRealMalloc). - // - // See patw for details. -#endif - if (next && !(next->flags & Allocated) && next->size + hdr->size + sizeof(Header) >= size) - { - // we can merge with the next dude. - treeRemove(next); - hdr->size += sizeof(Header) + next->size; - hdr->next = next->next; - if(next->next) - next->next->prev = (Header *) hdr; - - checkUnusedAlloc((FreeHeader *) hdr, size); - //validate(); - PROFILE_END(); -#ifdef TORQUE_MULTITHREAD - Mutex::unlockMutex(gMemMutex); -#endif - return mem; - } - else if(size < oldSize) - { - checkUnusedAlloc((FreeHeader *) hdr, size); - PROFILE_END(); -#ifdef TORQUE_MULTITHREAD - Mutex::unlockMutex(gMemMutex); -#endif - return mem; - } -#ifdef TORQUE_DEBUG_GUARD - // undo above adjustment because we're going though alloc instead - hdr->realSize -= size - oldSize; - gBytesAllocated -= size - oldSize; -#endif - void* ret = alloc(size, false, fileName, line); - dMemcpy(ret, mem, oldSize); - free(mem, false); - PROFILE_END(); - - // Re-enable the 'Reallocated' flag so that this allocation can be ignored by - // a non-strict run of the flag/dumpunflagged. - hdr = ((AllocatedHeader *)ret) - 1; - hdr->flags |= Reallocated; - -#ifdef TORQUE_MULTITHREAD - Mutex::unlockMutex(gMemMutex); -#endif - return ret; -} -#endif - -dsize_t getMemoryUsed() -{ - U32 size = 0; - - PageRecord* walk; - for (walk = gPageList; walk; walk = walk->prevPage) { - for(Header *probe = walk->headerList; probe; probe = probe->next) - if (probe->flags & Allocated) { - size += probe->size; - } - } - - return size; -} - -#ifdef TORQUE_DEBUG_GUARD -DefineEngineFunction( dumpAlloc, void, ( S32 allocNum ),, - "@brief Dumps information about the given allocated memory block.\n\n" - "@param allocNum Memory block to dump information about." - "@note Available in debug builds only. " - "In torqueConfig.h, TORQUE_DISABLE_MEMORY_MANAGER must be undefined to use this function.\n\n" - "@ingroup Debugging") -{ - PageRecord* walk; - for( walk = gPageList; walk; walk = walk->prevPage ) - for( Header* probe = walk->headerList; probe; probe = probe->next ) - if( probe->flags & Allocated ) + // Not found — see if newPtr is already being tracked + for (U32 i = 0; i < allocCount; ++i) + { + if (allocList[i].ptr == newPtr) { - AllocatedHeader* pah = ( AllocatedHeader* ) probe; - if( pah->allocNum == allocNum ) - { - Con::printf( "file: %s\n" - "line: %i\n" - "size: %i\n" - "allocNum: %i\n" - "reallocated: %s", - pah->fileName != NULL ? pah->fileName : "Undetermined", - pah->line, - pah->realSize, - pah->allocNum, - pah->flags & Reallocated ? "yes" : "no" - ); - - // Dump the profile path, if we have one. - - #ifdef TORQUE_ENABLE_PROFILE_PATH - if( pah->profilePath && pah->profilePath[ 0 ] ) - Con::printf( "profilepath: %s", pah->profilePath ); - #endif - } - } -} + allocList[i].size = newSize; + allocList[i].file = fileName; + allocList[i].line = line; + allocList[i].allocId = currentAllocId++; -DefineEngineFunction( dumpMemSnapshot, void, ( const char* fileName ),, - "@brief Dumps a snapshot of current memory to a file.\n\n" - "The total memory used will also be output to the console.\n" - "This function will attempt to create the file if it does not already exist.\n" - "@param fileName Name and path of file to save profiling stats to. Must use forward slashes (/)\n" - "@tsexample\n" - "dumpMemSnapshot( \"C:/Torque/ProfilerLogs/profilerlog1.txt\" );\n" - "@endtsexample\n\n" - "@note Available in debug builds only. " - "In torqueConfig.h, TORQUE_DISABLE_MEMORY_MANAGER must be undefined to use this function.\n\n" - "@ingroup Debugging") -{ - FileStream fws; - fws.open(fileName, Torque::FS::File::Write); - char buffer[ 2048 ]; - - PageRecord* walk; - for (walk = gPageList; walk; walk = walk->prevPage) { - for(Header *probe = walk->headerList; probe; probe = probe->next) - if (probe->flags & Allocated) { - AllocatedHeader* pah = (AllocatedHeader*)probe; - - dSprintf( buffer, sizeof( buffer ), "%s%s\t%d\t%d\t%d\r\n", - pah->flags & Reallocated ? "[R] " : "", - pah->fileName != NULL ? pah->fileName : "Undetermined", - pah->line, pah->realSize, pah->allocNum); - fws.write(dStrlen(buffer), buffer); - - // Dump the profile path, if we have one. - - #ifdef TORQUE_ENABLE_PROFILE_PATH - if( pah->profilePath ) - { - dSprintf( buffer, sizeof( buffer ), "%s\r\n\r\n", pah->profilePath ); - fws.write( dStrlen( buffer ), buffer ); - } - #endif + return newPtr; } + } + + // Still not found — treat as a new allocation + if (allocCount < MaxAllocs) + { + MemInfo& info = allocList[allocCount++]; + info = {}; + info.ptr = newPtr; + info.size = newSize; + info.file = fileName; + info.line = line; + info.allocId = currentAllocId++; + } + return newPtr; } - Con::errorf("total memory used: %d",getMemoryUsed()); - fws.close(); -} #endif - -dsize_t getMemoryAllocated() -{ - return 0; } - -void getMemoryInfo( void* ptr, Info& info ) -{ - #ifndef TORQUE_DISABLE_MEMORY_MANAGER - - AllocatedHeader* header = ( ( AllocatedHeader* ) ptr ) - 1; - - info.mAllocSize = header->size; - #ifdef TORQUE_DEBUG_GUARD - info.mAllocNumber = header->allocNum; - info.mLineNumber = header->line; - info.mFileName = header->fileName; - #endif - info.mIsArray = header->flags & Array; - info.mIsGlobal = header->flags & GlobalFlag; - info.mIsStatic = header->flags & StaticFlag; - - #endif -} - -void setBreakAlloc(U32 breakAlloc) -{ - gBreakAlloc = breakAlloc; -} - -ConsoleFunctionGroupEnd( Memory ); - -} // namespace Memory - -void setMinimumAllocUnit(U32 allocUnit) -{ - AssertFatal(isPow2(allocUnit) && allocUnit > (2 << 20), - "Error, allocunit must be a power of two, and greater than 2 megs"); - - MinPageSize = allocUnit; -} - //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- @@ -1763,16 +321,6 @@ void* dRealloc_r(void* in_pResize, dsize_t in_size, const char* fileName, const return Memory::realloc(in_pResize, in_size, fileName, line); } -AFTER_MODULE_INIT( Sim ) -{ - Con::addVariable( "$Memory::numBlocksAllocated", TypeS32, &Memory::gBlocksAllocated, - "Total number of memory blocks currently allocated.\n\n" - "@ingroup Debugging" ); - Con::addVariable( "$Memory::numBytesAllocated", TypeS32, &Memory::gBytesAllocated, - "Total number of bytes currently allocated.\n\n" - "@ingroup Debugging" ); -} - #else // Don't manage our own memory diff --git a/Engine/source/platform/platformMemory.h b/Engine/source/platform/platformMemory.h index 96db06584..06b5e2fd2 100644 --- a/Engine/source/platform/platformMemory.h +++ b/Engine/source/platform/platformMemory.h @@ -27,33 +27,22 @@ namespace Memory { - enum EFlag + struct MemInfo { - FLAG_Debug, - FLAG_Global, - FLAG_Static + void* ptr; + dsize_t size; + const char* file; + U32 line; + U32 allocId; + bool flagged; + + void* backtracePtrs[16]; + int backtraceSize; }; - struct Info - { - U32 mAllocNumber; - U32 mAllocSize; - const char* mFileName; - U32 mLineNumber; - bool mIsArray; - bool mIsGlobal; - bool mIsStatic; - }; - - void checkPtr( void* ptr ); - void flagCurrentAllocs( EFlag flag = FLAG_Debug ); - void ensureAllFreed(); - void dumpUnflaggedAllocs(const char *file, EFlag flag = FLAG_Debug ); - S32 countUnflaggedAllocs(const char *file, S32 *outUnflaggedRealloc = NULL, EFlag flag = FLAG_Debug ); - dsize_t getMemoryUsed(); - dsize_t getMemoryAllocated(); - void getMemoryInfo( void* ptr, Info& info ); - void validate(); + void init(); + void shutdown(); + void checkPtr(void* ptr); } #endif // _TORQUE_PLATFORM_PLATFORMMEMORY_H_ diff --git a/Engine/source/ts/assimp/assimpAppMaterial.cpp b/Engine/source/ts/assimp/assimpAppMaterial.cpp index cf62d6cbb..5a45dc741 100644 --- a/Engine/source/ts/assimp/assimpAppMaterial.cpp +++ b/Engine/source/ts/assimp/assimpAppMaterial.cpp @@ -29,12 +29,23 @@ #include "ts/tsMaterialList.h" #include "core/stream/fileStream.h" +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) +#ifdef new +#undef new +#endif +#endif + // assimp include files. #include #include #include #include +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) +# define _new new(__FILE__, __LINE__) +# define new _new +#endif + U32 AssimpAppMaterial::sDefaultMatNumber = 0; String AppMaterial::cleanString(const String& str) diff --git a/Engine/source/ts/assimp/assimpAppMaterial.h b/Engine/source/ts/assimp/assimpAppMaterial.h index 0e973aaeb..4b80b5430 100644 --- a/Engine/source/ts/assimp/assimpAppMaterial.h +++ b/Engine/source/ts/assimp/assimpAppMaterial.h @@ -26,8 +26,20 @@ #ifndef _APPMATERIAL_H_ #include "ts/loader/appMaterial.h" #endif + +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) +#ifdef new +#undef new +#endif +#endif + #include +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) +# define _new new(__FILE__, __LINE__) +# define new _new +#endif + class Material; class AssimpAppMaterial : public AppMaterial diff --git a/Engine/source/ts/assimp/assimpAppMesh.cpp b/Engine/source/ts/assimp/assimpAppMesh.cpp index bd116869a..0eb015473 100644 --- a/Engine/source/ts/assimp/assimpAppMesh.cpp +++ b/Engine/source/ts/assimp/assimpAppMesh.cpp @@ -24,12 +24,24 @@ #include "ts/collada/colladaExtensions.h" #include "ts/assimp/assimpAppMesh.h" + +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) +#ifdef new +#undef new +#endif +#endif + // assimp include files. #include #include #include #include +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) +# define _new new(__FILE__, __LINE__) +# define new _new +#endif + bool AssimpAppMesh::fixedSizeEnabled = false; S32 AssimpAppMesh::fixedSize = 2; diff --git a/Engine/source/ts/assimp/assimpAppNode.cpp b/Engine/source/ts/assimp/assimpAppNode.cpp index ac1802468..62d1ad5a3 100644 --- a/Engine/source/ts/assimp/assimpAppNode.cpp +++ b/Engine/source/ts/assimp/assimpAppNode.cpp @@ -25,12 +25,25 @@ #include "ts/assimp/assimpAppNode.h" #include "ts/assimp/assimpAppMesh.h" + +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) +#ifdef new +#undef new +#endif +#endif + // assimp include files. #include #include #include #include +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) +# define _new new(__FILE__, __LINE__) +# define new _new +#endif + + aiAnimation* AssimpAppNode::sActiveSequence = NULL; F32 AssimpAppNode::sTimeMultiplier = 1.0f; diff --git a/Engine/source/ts/assimp/assimpAppNode.h b/Engine/source/ts/assimp/assimpAppNode.h index db5e18a81..311b42d93 100644 --- a/Engine/source/ts/assimp/assimpAppNode.h +++ b/Engine/source/ts/assimp/assimpAppNode.h @@ -33,11 +33,23 @@ #include "ts/collada/colladaExtensions.h" #endif + +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) +#ifdef new +#undef new +#endif +#endif + #ifndef AI_TYPES_H_INC #include #endif #include +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) +# define _new new(__FILE__, __LINE__) +# define new _new +#endif + class AssimpAppMesh; class AssimpAppNode : public AppNode diff --git a/Engine/source/ts/assimp/assimpAppSequence.h b/Engine/source/ts/assimp/assimpAppSequence.h index 1c4ac16dd..5468e1ce0 100644 --- a/Engine/source/ts/assimp/assimpAppSequence.h +++ b/Engine/source/ts/assimp/assimpAppSequence.h @@ -18,8 +18,20 @@ #include "ts/loader/appSequence.h" #endif +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) +#ifdef new +#undef new +#endif +#endif + #include +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) +# define _new new(__FILE__, __LINE__) +# define new _new +#endif + + class AssimpAppSequence : public AppSequence { String mSequenceName; diff --git a/Engine/source/ts/assimp/assimpShapeLoader.cpp b/Engine/source/ts/assimp/assimpShapeLoader.cpp index 19162ac82..c261f11cd 100644 --- a/Engine/source/ts/assimp/assimpShapeLoader.cpp +++ b/Engine/source/ts/assimp/assimpShapeLoader.cpp @@ -51,6 +51,11 @@ #include "gfx/bitmap/gBitmap.h" #include "gui/controls/guiTreeViewCtrl.h" +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) +#ifdef new +#undef new +#endif +#endif // assimp include files. #include #include @@ -59,6 +64,12 @@ #include #include +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) +# define _new new(__FILE__, __LINE__) +# define new _new +#endif + + MODULE_BEGIN( AssimpShapeLoader ) MODULE_INIT_AFTER( ShapeLoader ) MODULE_INIT From 8f856dd7cdc167e716d929ec6974a2177128d3a6 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 4 May 2025 10:34:43 +0100 Subject: [PATCH 02/41] build fixes missed by copy over --- Engine/source/console/simObject.cpp | 12 +++++------- Engine/source/platform/platformMemory.cpp | 15 +++++++++++++++ Engine/source/platform/platformMemory.h | 1 + .../source/scene/zones/sceneZoneSpaceManager.cpp | 2 +- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/Engine/source/console/simObject.cpp b/Engine/source/console/simObject.cpp index 6039393ef..cabafe466 100644 --- a/Engine/source/console/simObject.cpp +++ b/Engine/source/console/simObject.cpp @@ -3536,15 +3536,13 @@ DefineEngineMethod( SimObject, getDebugInfo, ArrayObject*, (),, array->push_back( "Flag|CanSave", object->getCanSave() ? "true" : "false" ); #ifndef TORQUE_DISABLE_MEMORY_MANAGER - Memory::Info memInfo; + Memory::MemInfo memInfo; Memory::getMemoryInfo( object, memInfo ); - array->push_back( "Memory|AllocNumber", String::ToString( memInfo.mAllocNumber ) ); - array->push_back( "Memory|AllocSize", String::ToString( memInfo.mAllocSize ) ); - array->push_back( "Memory|AllocFile", memInfo.mFileName ); - array->push_back( "Memory|AllocLine", String::ToString( memInfo.mLineNumber ) ); - array->push_back( "Memory|IsGlobal", memInfo.mIsGlobal ? "true" : "false" ); - array->push_back( "Memory|IsStatic", memInfo.mIsStatic ? "true" : "false" ); + array->push_back( "Memory|AllocNumber", String::ToString( memInfo.allocId) ); + array->push_back( "Memory|AllocSize", String::ToString( (U32)memInfo.size) ); + array->push_back( "Memory|AllocFile", memInfo.file); + array->push_back( "Memory|AllocLine", String::ToString( memInfo.line) ); #endif return array; diff --git a/Engine/source/platform/platformMemory.cpp b/Engine/source/platform/platformMemory.cpp index 33d0a1336..8bd120c1c 100644 --- a/Engine/source/platform/platformMemory.cpp +++ b/Engine/source/platform/platformMemory.cpp @@ -204,6 +204,21 @@ namespace Memory std::free(ptr); } + void getMemoryInfo(void* ptr, MemInfo& info) + { + if (!ptr || !initialized) + return; + + for (U32 i = 0; i < allocCount; ++i) + { + if (allocList[i].ptr == ptr) + { + info = allocList[i]; + return; + } + } + } + static void* realloc(void* oldPtr, dsize_t newSize, const char* fileName, U32 line) { if (!initialized) diff --git a/Engine/source/platform/platformMemory.h b/Engine/source/platform/platformMemory.h index 06b5e2fd2..2b56af18b 100644 --- a/Engine/source/platform/platformMemory.h +++ b/Engine/source/platform/platformMemory.h @@ -42,6 +42,7 @@ namespace Memory void init(); void shutdown(); + void getMemoryInfo(void* ptr, MemInfo& info); void checkPtr(void* ptr); } diff --git a/Engine/source/scene/zones/sceneZoneSpaceManager.cpp b/Engine/source/scene/zones/sceneZoneSpaceManager.cpp index 84f733d03..b610d1724 100644 --- a/Engine/source/scene/zones/sceneZoneSpaceManager.cpp +++ b/Engine/source/scene/zones/sceneZoneSpaceManager.cpp @@ -922,7 +922,7 @@ void SceneZoneSpaceManager::verifyState() AssertFatal( mObjectZoneLists.containsBinItem(object->mZoneListHandle, zoneId), "SceneZoneSpaceManager::verifyState - Object doesn't have zone in list!"); #ifndef TORQUE_DISABLE_MEMORY_MANAGER - Memory::checkPtr( ref->object ); + Memory::checkPtr( object ); #endif } } From 15ff3824690ac624e9ec86dbb2c2149552a41711 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 4 May 2025 12:54:01 +0100 Subject: [PATCH 03/41] plugging found leaks LEAK from G:\GameDev\GithubRepo\Torque3D\Engine\source\console/consoleObject.h:686 - leak around props remaining after the const_cast free it up LEAK around sound asset - assetEnumNameConcat was creating a leak. --- Engine/source/T3D/assets/SoundAsset.h | 7 ++++++- Engine/source/console/consoleObject.h | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Engine/source/T3D/assets/SoundAsset.h b/Engine/source/T3D/assets/SoundAsset.h index f867e0e4f..8692e96f4 100644 --- a/Engine/source/T3D/assets/SoundAsset.h +++ b/Engine/source/T3D/assets/SoundAsset.h @@ -516,7 +516,12 @@ if (m##name##AssetId[index] != StringTable->EmptyString())\ else Con::warnf("Warning: %s::LOAD_SOUNDASSET_ARRAY(%s[%i])-%s", mClassName, m##name##AssetId[index], index, ImageAsset::getAssetErrstrn(assetState).c_str());\ } -#define assetEnumNameConcat(x,suff)(new std::string( x + std::string(#suff)))->c_str() +#define assetEnumNameConcat(x, suff) ([](const char* base) { \ + String result = String(base) + #suff; \ + char* ret = Con::getReturnBuffer(result.length() + 1); \ + dStrcpy(ret, result.c_str(), result.length() + 1); \ + return ret; \ + })(x) #define INITPERSISTFIELD_SOUNDASSET_ENUMED(name, enumType, maxValue, consoleClass, docs) \ for (U32 i = 0; i < maxValue; i++)\ diff --git a/Engine/source/console/consoleObject.h b/Engine/source/console/consoleObject.h index b4daf6613..9995dc2aa 100644 --- a/Engine/source/console/consoleObject.h +++ b/Engine/source/console/consoleObject.h @@ -705,7 +705,9 @@ public: smPropertyTable = _smPropertyTable; const_cast(mTypeInfo)->mPropertyTable = &_smPropertyTable; - + + // After we hand it off, immediately delete if safe: + delete[] props; // Let the base finish up. AbstractClassRep::init(); } From 1050cad3728c4bfe787452d99d0619c63d0cfdd3 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 4 May 2025 18:23:51 +0100 Subject: [PATCH 04/41] Update platformMemory.cpp add date and time to output logfile --- Engine/source/platform/platformMemory.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Engine/source/platform/platformMemory.cpp b/Engine/source/platform/platformMemory.cpp index 8bd120c1c..6bc2b0447 100644 --- a/Engine/source/platform/platformMemory.cpp +++ b/Engine/source/platform/platformMemory.cpp @@ -37,6 +37,7 @@ #else #include #endif +#include // If profile paths are enabled, disable profiling of the // memory manager as that would cause a cyclic dependency @@ -73,7 +74,7 @@ namespace Memory static U32 allocCount = 0; static U32 currentAllocId = 0; static bool initialized = false; - char gLogFilename[256] = "memlog.txt"; + char gLogFilename[256] = { 0 }; bool gStackTrace = false; void init() @@ -84,6 +85,10 @@ namespace Memory currentAllocId = 0; initialized = true; + // Generate timestamped log filename + std::time_t now = std::time(nullptr); + std::tm* localTime = std::localtime(&now); + std::strftime(gLogFilename, sizeof(gLogFilename), "memlog_%Y-%m-%d_%H-%M-%S.txt", localTime); } void shutdown() From b0eb3875c98153029907fde1701929771088dafb Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 5 May 2025 08:17:45 +0100 Subject: [PATCH 05/41] changes from az Output now collates issues together into 1 entry for each leak point tDictionary leak --- Engine/source/core/util/tDictionary.h | 28 +++---- Engine/source/platform/platformMemory.cpp | 93 +++++++++++++++++++---- Tools/CMake/torqueConfig.h.in | 2 + 3 files changed, 95 insertions(+), 28 deletions(-) diff --git a/Engine/source/core/util/tDictionary.h b/Engine/source/core/util/tDictionary.h index 4af0d6037..6c8c7d21f 100644 --- a/Engine/source/core/util/tDictionary.h +++ b/Engine/source/core/util/tDictionary.h @@ -193,7 +193,7 @@ private: { Node* mNext; Pair mPair; - Node(): mNext(0) {} + Node(): mNext(nullptr) {} Node(Pair p,Node* n) : mNext(n), mPair(p) @@ -226,8 +226,8 @@ public: _Iterator() { - mHashTable = 0; - mLink = 0; + mHashTable = nullptr; + mLink = nullptr; } _Iterator(M* table,E* ptr) @@ -320,7 +320,7 @@ public: template HashTable::HashTable() : mNodeAllocator(512) { mTableSize = 0; - mTable = 0; + mTable = nullptr; mSize = 0; } @@ -328,7 +328,7 @@ template HashTable::HashTable(const Has { mSize = 0; mTableSize = 0; - mTable = 0; + mTable = nullptr; *this = p; } @@ -357,7 +357,7 @@ typename HashTable::Node* HashTable::_next(U32 index) cons for (; index < mTableSize; index++) if (Node* node = mTable[index]) return node; - return 0; + return nullptr; } template @@ -402,7 +402,7 @@ void HashTable::_destroy() mNodeAllocator.freeBlocks(); delete[] mTable; - mTable = NULL; + mTable = nullptr; } @@ -509,7 +509,7 @@ typename HashTable::Iterator HashTable::insertEqual(const template void HashTable::erase(const Key& key) { - if (mTable==NULL) + if (mTable == nullptr) return; Node** prev = &mTable[_index(key)]; for (Node* itr = *prev; itr; prev = &itr->mNext, itr = itr->mNext) @@ -529,7 +529,7 @@ void HashTable::erase(const Key& key) template void HashTable::erase(Iterator node) { - if (mTable==NULL) + if (mTable == nullptr) return; Node** prev = &mTable[_index(node->key)]; for (Node* itr = *prev; itr; prev = &itr->mNext, itr = itr->mNext) @@ -547,7 +547,7 @@ void HashTable::erase(Iterator node) template void HashTable::erase(const Key & key, const Value & value) { - if (mTable==NULL) + if (mTable == nullptr) return; Node** prev = &mTable[_index(key)]; for (Node* itr = *prev; itr; prev = &itr->mNext, itr = itr->mNext) @@ -591,7 +591,7 @@ typename HashTable::Iterator HashTable::find(const Key& ke for (Node* itr = mTable[_index(key)]; itr; itr = itr->mNext) if ( KeyCmp::equals( itr->mPair.key, key ) ) return Iterator(this,itr); - return Iterator(this,0); + return Iterator(this, nullptr); } template @@ -605,7 +605,7 @@ typename HashTable::ConstIterator HashTable::find(const Ke return ConstIterator(this,itr); } } - return ConstIterator(this,0); + return ConstIterator(this, nullptr); } template @@ -659,13 +659,13 @@ inline typename HashTable::ConstIterator HashTable::begin( template inline typename HashTable::Iterator HashTable::end() { - return Iterator(this,0); + return Iterator(this, nullptr); } template inline typename HashTable::ConstIterator HashTable::end() const { - return ConstIterator(this,0); + return ConstIterator(this, nullptr); } diff --git a/Engine/source/platform/platformMemory.cpp b/Engine/source/platform/platformMemory.cpp index 6bc2b0447..fe732db52 100644 --- a/Engine/source/platform/platformMemory.cpp +++ b/Engine/source/platform/platformMemory.cpp @@ -38,6 +38,7 @@ #include #endif #include +#include // If profile paths are enabled, disable profiling of the // memory manager as that would cause a cyclic dependency @@ -75,7 +76,16 @@ namespace Memory static U32 currentAllocId = 0; static bool initialized = false; char gLogFilename[256] = { 0 }; - bool gStackTrace = false; + bool gStackTrace = true; + bool gFromScript = false; + + struct memReport + { + std::string report; + bool skip; + U32 count = 1; + U32 total = 0; + } memLog[MaxAllocs]; void init() { @@ -100,16 +110,27 @@ namespace Memory return; std::fprintf(log, "\n--- Memory Leak Report ---\n"); - for (U32 i = 0; i < allocCount; ++i) + + U32 start = 0; + U32 stop = allocCount; + if (gFromScript) //filter out the bits from console { - if (allocList[i].ptr != nullptr) + start = 6; + stop = allocCount - 8; + } + for (U32 curRep = start; curRep < stop; ++curRep) + { + if (allocList[curRep].ptr != nullptr) { - std::fprintf(log, "Leak: %p (%zu bytes) from %s:%u [id=%u]\n", - allocList[i].ptr, allocList[i].size, - allocList[i].file ? allocList[i].file : "(null)", allocList[i].line, - allocList[i].allocId); + char entry[512] = ""; + std::sprintf(entry, "from %s:%u\n", allocList[curRep].file ? allocList[curRep].file : "(null)", allocList[curRep].line); + + memLog[curRep].skip = false; + std::string report = entry; + if (gStackTrace) { + char stack[512] = ""; #ifdef _WIN32 SYMBOL_INFO* symbol = (SYMBOL_INFO*)malloc(sizeof(SYMBOL_INFO) + 256); symbol->MaxNameLen = 255; @@ -118,31 +139,67 @@ namespace Memory HANDLE process = GetCurrentProcess(); SymInitialize(process, NULL, TRUE); - for (int j = 0; j < allocList[i].backtraceSize; ++j) + for (int curStack = 0; curStack < allocList[curRep].backtraceSize; ++curStack) { - DWORD64 addr = (DWORD64)(allocList[i].backtracePtrs[j]); + DWORD64 addr = (DWORD64)(allocList[curRep].backtracePtrs[curStack]); if (SymFromAddr(process, addr, 0, symbol)) { - std::fprintf(log, " [%d] %s - 0x%0llX\n", j, symbol->Name, symbol->Address); + std::sprintf(stack, " [%d] %s - 0x%0llX\n", curStack, symbol->Name, symbol->Address); } else { - std::fprintf(log, " [%d] ??? - 0x%0llX\n", j, addr); + std::sprintf(stack, " [%d] ??? - 0x%0llX\n", curStack, addr); } + report += stack; } std::free(symbol); #else - char** symbols = backtrace_symbols(allocList[i].backtracePtrs, allocList[i].backtraceSize); - for (int j = 0; j < allocList[i].backtraceSize; ++j) + char** symbols = backtrace_symbols(allocList[curRep].backtracePtrs, allocList[i].backtraceSize); + for (int curStack = 0; curStack < allocList[curRep].backtraceSize; ++curStack) { - std::fprintf(log, " [%d] %s\n", j, symbols[j]); + std::sprintf(stack, " [%d] %s\n", curStack, symbols[curStack]); + report += stack; } std::free(symbols); #endif } + + if (report.find("getDocsLink") != std::string::npos) + { + //known issue. one off allocation + memLog[curRep].skip = true; + } + + for (U32 oldRep = start; oldRep < curRep; ++oldRep) + { + if (!memLog[oldRep].skip && (memLog[oldRep].report.find(report) != std::string::npos)) + { + //inc origional + memLog[oldRep].count++; + memLog[oldRep].total += allocList[curRep].size; + //skip dupe report + memLog[curRep].skip = true; + } + } + if (!memLog[curRep].skip) + { + memLog[curRep].report = report; + memLog[curRep].count = 1; + memLog[curRep].total = allocList[curRep].size; + } } } + + for (U32 ntry = start; ntry < stop; ++ntry) + { + if (!memLog[ntry].skip) + { + std::fprintf(log, "Leak-count[%i]total[%i]:%s", memLog[ntry].count, memLog[ntry].total, memLog[ntry].report.c_str()); + memLog[ntry].report.clear(); + } + } + std::fclose(log); initialized = false; } @@ -341,6 +398,14 @@ void* dRealloc_r(void* in_pResize, dsize_t in_size, const char* fileName, const return Memory::realloc(in_pResize, in_size, fileName, line); } +DefineEngineFunction(LeakTrace, void, (bool start, bool stackTrace), (true, true), "start/stop tracing leaks") +{ + if (Memory::initialized) Memory::shutdown(); + if (start) Memory::init(); + Memory::gFromScript = true; + Memory::gStackTrace = stackTrace; +} + #else // Don't manage our own memory diff --git a/Tools/CMake/torqueConfig.h.in b/Tools/CMake/torqueConfig.h.in index 717c05eb1..a0bbc70a8 100644 --- a/Tools/CMake/torqueConfig.h.in +++ b/Tools/CMake/torqueConfig.h.in @@ -54,7 +54,9 @@ #cmakedefine TORQUE_MULTITHREAD /// Define me if you want to disable Torque memory manager. +#ifndef TORQUE_ENABLE_ASSERTS #cmakedefine TORQUE_DISABLE_MEMORY_MANAGER +#endif /// Define me if you want to disable the virtual mount system. #cmakedefine TORQUE_DISABLE_VIRTUAL_MOUNT_SYSTEM From e2c4f88fafeab5c4dd9628bab3168ce317eea2a7 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 5 May 2025 11:06:20 +0100 Subject: [PATCH 06/41] plugging moar leaks Namespace Leaks: these leaks would have been freed on app kill but they were still contaminating the log so free em. Con::shutdown: gGlobablVars again another leak that would of been freed on app kill AssetManager onRemove should be clearing its lists Scripting language needs a free for its strings these destructors free after the rule is executed so the data is cached internally and then freed. This may be needed for other types in the union (should not be used on nodes just raw data) --- Engine/source/assets/assetManager.cpp | 10 + Engine/source/console/console.cpp | 1 + Engine/source/console/consoleInternal.cpp | 6 + Engine/source/console/torquescript/CMDgram.y | 4 + .../source/console/torquescript/cmdgram.cpp | 708 ++++++++++-------- .../source/console/torquescript/compiler.cpp | 4 +- 6 files changed, 401 insertions(+), 332 deletions(-) diff --git a/Engine/source/assets/assetManager.cpp b/Engine/source/assets/assetManager.cpp index e2c6d1133..d400de2fb 100644 --- a/Engine/source/assets/assetManager.cpp +++ b/Engine/source/assets/assetManager.cpp @@ -119,6 +119,16 @@ void AssetManager::onRemove() mAssetTagsManifest->deleteObject(); } + for (auto itr = mDeclaredAssets.begin(); itr != mDeclaredAssets.end(); ++itr) + { + delete itr->value; + } + mDeclaredAssets.clear(); + + // Clear dependency graphs + mAssetDependsOn.clear(); + mAssetIsDependedOn.clear(); + // Call parent. Parent::onRemove(); } diff --git a/Engine/source/console/console.cpp b/Engine/source/console/console.cpp index 863626b62..f56051e7e 100644 --- a/Engine/source/console/console.cpp +++ b/Engine/source/console/console.cpp @@ -440,6 +440,7 @@ void shutdown() Namespace::shutdown(); AbstractClassRep::shutdown(); Compiler::freeConsoleParserList(); + gGlobalVars.reset(); } bool isActive() diff --git a/Engine/source/console/consoleInternal.cpp b/Engine/source/console/consoleInternal.cpp index 8c04ee830..aff6f433d 100644 --- a/Engine/source/console/consoleInternal.cpp +++ b/Engine/source/console/consoleInternal.cpp @@ -924,6 +924,12 @@ void Namespace::shutdown() for (Namespace *walk = mNamespaceList; walk; walk = walk->mNext) walk->~Namespace(); + + gNamespaceCache.clear(); + + mNamespaceList = nullptr; + mGlobalNamespace = nullptr; + mAllocator.freeBlocks(); } void Namespace::trashCache() diff --git a/Engine/source/console/torquescript/CMDgram.y b/Engine/source/console/torquescript/CMDgram.y index 9e1b30543..643cd65a9 100644 --- a/Engine/source/console/torquescript/CMDgram.y +++ b/Engine/source/console/torquescript/CMDgram.y @@ -102,6 +102,10 @@ struct Token IfStmtNode* ifnode; } + +%destructor { dFree($$.value); } +%destructor { dFree($$.value); } + %type parent_block %type case_block %type switch_stmt diff --git a/Engine/source/console/torquescript/cmdgram.cpp b/Engine/source/console/torquescript/cmdgram.cpp index d6d877da2..0a8dba10c 100644 --- a/Engine/source/console/torquescript/cmdgram.cpp +++ b/Engine/source/console/torquescript/cmdgram.cpp @@ -694,23 +694,23 @@ static const yytype_int8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_int16 yyrline[] = { - 0, 166, 166, 172, 173, 178, 180, 182, 187, 192, - 194, 200, 201, 206, 207, 208, 209, 210, 211, 212, - 214, 216, 218, 220, 222, 224, 226, 231, 233, 239, - 240, 245, 247, 252, 257, 259, 261, 263, 265, 267, - 273, 274, 280, 281, 287, 288, 294, 295, 297, 299, - 304, 306, 311, 313, 318, 320, 325, 327, 329, 334, - 336, 341, 343, 348, 350, 355, 357, 359, 361, 363, - 365, 367, 369, 374, 376, 381, 386, 388, 390, 392, - 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, - 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, - 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, - 454, 456, 458, 460, 462, 484, 486, 491, 493, 498, - 500, 505, 507, 509, 511, 513, 515, 517, 519, 521, - 523, 525, 527, 532, 534, 536, 538, 540, 542, 544, - 546, 548, 550, 555, 557, 559, 569, 571, 577, 578, - 583, 585, 591, 592, 597, 599, 604, 606, 608, 610, - 612, 617, 619 + 0, 170, 170, 176, 177, 182, 184, 186, 191, 196, + 198, 204, 205, 210, 211, 212, 213, 214, 215, 216, + 218, 220, 222, 224, 226, 228, 230, 235, 237, 243, + 244, 249, 251, 256, 261, 263, 265, 267, 269, 271, + 277, 278, 284, 285, 291, 292, 298, 299, 301, 303, + 308, 310, 315, 317, 322, 324, 329, 331, 333, 338, + 340, 345, 347, 352, 354, 359, 361, 363, 365, 367, + 369, 371, 373, 378, 380, 385, 390, 392, 394, 396, + 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, + 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, + 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, + 458, 460, 462, 464, 466, 488, 490, 495, 497, 502, + 504, 509, 511, 513, 515, 517, 519, 521, 523, 525, + 527, 529, 531, 536, 538, 540, 542, 544, 546, 548, + 550, 552, 554, 559, 561, 563, 573, 575, 581, 582, + 587, 589, 595, 596, 601, 603, 608, 610, 612, 614, + 616, 621, 623 }; #endif @@ -1904,7 +1904,53 @@ yydestruct (const char *yymsg, YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YY_USE (yykind); + switch (yykind) + { + case YYSYMBOL_TTAG: /* TTAG */ +#line 106 "CMDgram.y" + { dFree(((*yyvaluep).s).value); } +#line 1913 "CMDgram.c" + break; + + case YYSYMBOL_VAR: /* VAR */ +#line 106 "CMDgram.y" + { dFree(((*yyvaluep).s).value); } +#line 1919 "CMDgram.c" + break; + + case YYSYMBOL_IDENT: /* IDENT */ +#line 106 "CMDgram.y" + { dFree(((*yyvaluep).s).value); } +#line 1925 "CMDgram.c" + break; + + case YYSYMBOL_DOCBLOCK: /* DOCBLOCK */ +#line 107 "CMDgram.y" + { dFree(((*yyvaluep).str).value); } +#line 1931 "CMDgram.c" + break; + + case YYSYMBOL_STRATOM: /* STRATOM */ +#line 107 "CMDgram.y" + { dFree(((*yyvaluep).str).value); } +#line 1937 "CMDgram.c" + break; + + case YYSYMBOL_TAGATOM: /* TAGATOM */ +#line 107 "CMDgram.y" + { dFree(((*yyvaluep).str).value); } +#line 1943 "CMDgram.c" + break; + + case YYSYMBOL_parent_block: /* parent_block */ +#line 106 "CMDgram.y" + { dFree(((*yyvaluep).s).value); } +#line 1949 "CMDgram.c" + break; + + default: + break; + } YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -2192,937 +2238,937 @@ yyreduce: switch (yyn) { case 2: /* start: decl_list */ -#line 167 "CMDgram.y" +#line 171 "CMDgram.y" { } -#line 2198 "CMDgram.c" +#line 2244 "CMDgram.c" break; case 3: /* decl_list: %empty */ -#line 172 "CMDgram.y" +#line 176 "CMDgram.y" { (yyval.stmt) = nil; } -#line 2204 "CMDgram.c" +#line 2250 "CMDgram.c" break; case 4: /* decl_list: decl_list decl */ -#line 174 "CMDgram.y" +#line 178 "CMDgram.y" { if(!Script::gStatementList) { Script::gStatementList = (yyvsp[0].stmt); } else { Script::gStatementList->append((yyvsp[0].stmt)); } } -#line 2210 "CMDgram.c" +#line 2256 "CMDgram.c" break; case 5: /* decl: stmt */ -#line 179 "CMDgram.y" +#line 183 "CMDgram.y" { (yyval.stmt) = (yyvsp[0].stmt); } -#line 2216 "CMDgram.c" +#line 2262 "CMDgram.c" break; case 6: /* decl: fn_decl_stmt */ -#line 181 "CMDgram.y" +#line 185 "CMDgram.y" { (yyval.stmt) = (yyvsp[0].stmt); } -#line 2222 "CMDgram.c" +#line 2268 "CMDgram.c" break; case 7: /* decl: package_decl */ -#line 183 "CMDgram.y" +#line 187 "CMDgram.y" { (yyval.stmt) = (yyvsp[0].stmt); } -#line 2228 "CMDgram.c" +#line 2274 "CMDgram.c" break; case 8: /* package_decl: rwPACKAGE IDENT '{' fn_decl_list '}' ';' */ -#line 188 "CMDgram.y" +#line 192 "CMDgram.y" { (yyval.stmt) = (yyvsp[-2].stmt); for(StmtNode *walk = ((yyvsp[-2].stmt));walk;walk = walk->getNext() ) walk->setPackage((yyvsp[-4].s).value); } -#line 2234 "CMDgram.c" +#line 2280 "CMDgram.c" break; case 9: /* fn_decl_list: fn_decl_stmt */ -#line 193 "CMDgram.y" +#line 197 "CMDgram.y" { (yyval.stmt) = (yyvsp[0].stmt); } -#line 2240 "CMDgram.c" +#line 2286 "CMDgram.c" break; case 10: /* fn_decl_list: fn_decl_list fn_decl_stmt */ -#line 195 "CMDgram.y" +#line 199 "CMDgram.y" { (yyval.stmt) = (yyvsp[-1].stmt); ((yyvsp[-1].stmt))->append((yyvsp[0].stmt)); } -#line 2246 "CMDgram.c" +#line 2292 "CMDgram.c" break; case 11: /* statement_list: %empty */ -#line 200 "CMDgram.y" +#line 204 "CMDgram.y" { (yyval.stmt) = nil; } -#line 2252 "CMDgram.c" +#line 2298 "CMDgram.c" break; case 12: /* statement_list: statement_list stmt */ -#line 202 "CMDgram.y" +#line 206 "CMDgram.y" { if(!(yyvsp[-1].stmt)) { (yyval.stmt) = (yyvsp[0].stmt); } else { ((yyvsp[-1].stmt))->append((yyvsp[0].stmt)); (yyval.stmt) = (yyvsp[-1].stmt); } } -#line 2258 "CMDgram.c" +#line 2304 "CMDgram.c" break; case 19: /* stmt: rwBREAK ';' */ -#line 213 "CMDgram.y" +#line 217 "CMDgram.y" { (yyval.stmt) = BreakStmtNode::alloc( (yyvsp[-1].i).lineNumber ); } -#line 2264 "CMDgram.c" +#line 2310 "CMDgram.c" break; case 20: /* stmt: rwCONTINUE ';' */ -#line 215 "CMDgram.y" +#line 219 "CMDgram.y" { (yyval.stmt) = ContinueStmtNode::alloc( (yyvsp[-1].i).lineNumber ); } -#line 2270 "CMDgram.c" +#line 2316 "CMDgram.c" break; case 21: /* stmt: rwRETURN ';' */ -#line 217 "CMDgram.y" +#line 221 "CMDgram.y" { (yyval.stmt) = ReturnStmtNode::alloc( (yyvsp[-1].i).lineNumber, NULL ); } -#line 2276 "CMDgram.c" +#line 2322 "CMDgram.c" break; case 22: /* stmt: rwRETURN expr ';' */ -#line 219 "CMDgram.y" +#line 223 "CMDgram.y" { (yyval.stmt) = ReturnStmtNode::alloc( (yyvsp[-2].i).lineNumber, (yyvsp[-1].expr) ); } -#line 2282 "CMDgram.c" +#line 2328 "CMDgram.c" break; case 23: /* stmt: expression_stmt ';' */ -#line 221 "CMDgram.y" +#line 225 "CMDgram.y" { (yyval.stmt) = (yyvsp[-1].stmt); } -#line 2288 "CMDgram.c" +#line 2334 "CMDgram.c" break; case 24: /* stmt: TTAG '=' expr ';' */ -#line 223 "CMDgram.y" +#line 227 "CMDgram.y" { (yyval.stmt) = TTagSetStmtNode::alloc( (yyvsp[-3].s).lineNumber, (yyvsp[-3].s).value, (yyvsp[-1].expr), NULL ); } -#line 2294 "CMDgram.c" +#line 2340 "CMDgram.c" break; case 25: /* stmt: TTAG '=' expr ',' expr ';' */ -#line 225 "CMDgram.y" +#line 229 "CMDgram.y" { (yyval.stmt) = TTagSetStmtNode::alloc( (yyvsp[-5].s).lineNumber, (yyvsp[-5].s).value, (yyvsp[-3].expr), (yyvsp[-1].expr) ); } -#line 2300 "CMDgram.c" +#line 2346 "CMDgram.c" break; case 26: /* stmt: DOCBLOCK */ -#line 227 "CMDgram.y" +#line 231 "CMDgram.y" { (yyval.stmt) = StrConstNode::alloc( (yyvsp[0].str).lineNumber, (yyvsp[0].str).value, false, true ); } -#line 2306 "CMDgram.c" +#line 2352 "CMDgram.c" break; case 27: /* fn_decl_stmt: rwDEFINE IDENT '(' var_list_decl ')' '{' statement_list '}' */ -#line 232 "CMDgram.y" +#line 236 "CMDgram.y" { (yyval.stmt) = FunctionDeclStmtNode::alloc( (yyvsp[-7].i).lineNumber, (yyvsp[-6].s).value, NULL, (yyvsp[-4].var), (yyvsp[-1].stmt) ); } -#line 2312 "CMDgram.c" +#line 2358 "CMDgram.c" break; case 28: /* fn_decl_stmt: rwDEFINE IDENT opCOLONCOLON IDENT '(' var_list_decl ')' '{' statement_list '}' */ -#line 234 "CMDgram.y" +#line 238 "CMDgram.y" { (yyval.stmt) = FunctionDeclStmtNode::alloc( (yyvsp[-9].i).lineNumber, (yyvsp[-6].s).value, (yyvsp[-8].s).value, (yyvsp[-4].var), (yyvsp[-1].stmt) ); } -#line 2318 "CMDgram.c" +#line 2364 "CMDgram.c" break; case 29: /* var_list_decl: %empty */ -#line 239 "CMDgram.y" +#line 243 "CMDgram.y" { (yyval.var) = NULL; } -#line 2324 "CMDgram.c" +#line 2370 "CMDgram.c" break; case 30: /* var_list_decl: var_list */ -#line 241 "CMDgram.y" +#line 245 "CMDgram.y" { (yyval.var) = (yyvsp[0].var); } -#line 2330 "CMDgram.c" +#line 2376 "CMDgram.c" break; case 31: /* var_list: VAR */ -#line 246 "CMDgram.y" +#line 250 "CMDgram.y" { (yyval.var) = VarNode::alloc( (yyvsp[0].s).lineNumber, (yyvsp[0].s).value, NULL ); } -#line 2336 "CMDgram.c" +#line 2382 "CMDgram.c" break; case 32: /* var_list: var_list ',' VAR */ -#line 248 "CMDgram.y" +#line 252 "CMDgram.y" { (yyval.var) = (yyvsp[-2].var); ((StmtNode*)((yyvsp[-2].var)))->append((StmtNode*)VarNode::alloc( (yyvsp[0].s).lineNumber, (yyvsp[0].s).value, NULL ) ); } -#line 2342 "CMDgram.c" +#line 2388 "CMDgram.c" break; case 33: /* datablock_decl: rwDATABLOCK class_name_expr '(' expr parent_block ')' '{' slot_assign_list_opt '}' ';' */ -#line 253 "CMDgram.y" +#line 257 "CMDgram.y" { (yyval.stmt) = ObjectDeclNode::alloc( (yyvsp[-9].i).lineNumber, (yyvsp[-8].expr), (yyvsp[-6].expr), NULL, (yyvsp[-5].s).value, (yyvsp[-2].slist), NULL, true, false, false); } -#line 2348 "CMDgram.c" +#line 2394 "CMDgram.c" break; case 34: /* object_decl: rwDECLARE class_name_expr '(' object_name parent_block object_args ')' '{' object_declare_block '}' */ -#line 258 "CMDgram.y" +#line 262 "CMDgram.y" { (yyval.od) = ObjectDeclNode::alloc( (yyvsp[-9].i).lineNumber, (yyvsp[-8].expr), (yyvsp[-6].expr), (yyvsp[-4].expr), (yyvsp[-5].s).value, (yyvsp[-1].odcl).slots, (yyvsp[-1].odcl).decls, false, false, false); } -#line 2354 "CMDgram.c" +#line 2400 "CMDgram.c" break; case 35: /* object_decl: rwDECLARE class_name_expr '(' object_name parent_block object_args ')' */ -#line 260 "CMDgram.y" +#line 264 "CMDgram.y" { (yyval.od) = ObjectDeclNode::alloc( (yyvsp[-6].i).lineNumber, (yyvsp[-5].expr), (yyvsp[-3].expr), (yyvsp[-1].expr), (yyvsp[-2].s).value, NULL, NULL, false, false, false); } -#line 2360 "CMDgram.c" +#line 2406 "CMDgram.c" break; case 36: /* object_decl: rwDECLARE class_name_expr '(' '[' object_name ']' parent_block object_args ')' '{' object_declare_block '}' */ -#line 262 "CMDgram.y" +#line 266 "CMDgram.y" { (yyval.od) = ObjectDeclNode::alloc( (yyvsp[-11].i).lineNumber, (yyvsp[-10].expr), (yyvsp[-7].expr), (yyvsp[-4].expr), (yyvsp[-5].s).value, (yyvsp[-1].odcl).slots, (yyvsp[-1].odcl).decls, false, true, false); } -#line 2366 "CMDgram.c" +#line 2412 "CMDgram.c" break; case 37: /* object_decl: rwDECLARE class_name_expr '(' '[' object_name ']' parent_block object_args ')' */ -#line 264 "CMDgram.y" +#line 268 "CMDgram.y" { (yyval.od) = ObjectDeclNode::alloc( (yyvsp[-8].i).lineNumber, (yyvsp[-7].expr), (yyvsp[-4].expr), (yyvsp[-1].expr), (yyvsp[-2].s).value, NULL, NULL, false, true, false); } -#line 2372 "CMDgram.c" +#line 2418 "CMDgram.c" break; case 38: /* object_decl: rwDECLARESINGLETON class_name_expr '(' object_name parent_block object_args ')' '{' object_declare_block '}' */ -#line 266 "CMDgram.y" +#line 270 "CMDgram.y" { (yyval.od) = ObjectDeclNode::alloc( (yyvsp[-9].i).lineNumber, (yyvsp[-8].expr), (yyvsp[-6].expr), (yyvsp[-4].expr), (yyvsp[-5].s).value, (yyvsp[-1].odcl).slots, (yyvsp[-1].odcl).decls, false, false, true); } -#line 2378 "CMDgram.c" +#line 2424 "CMDgram.c" break; case 39: /* object_decl: rwDECLARESINGLETON class_name_expr '(' object_name parent_block object_args ')' */ -#line 268 "CMDgram.y" +#line 272 "CMDgram.y" { (yyval.od) = ObjectDeclNode::alloc( (yyvsp[-6].i).lineNumber, (yyvsp[-5].expr), (yyvsp[-3].expr), (yyvsp[-1].expr), (yyvsp[-2].s).value, NULL, NULL, false, false, true); } -#line 2384 "CMDgram.c" +#line 2430 "CMDgram.c" break; case 40: /* parent_block: %empty */ -#line 273 "CMDgram.y" +#line 277 "CMDgram.y" { (yyval.s).value = NULL; } -#line 2390 "CMDgram.c" +#line 2436 "CMDgram.c" break; case 41: /* parent_block: ':' IDENT */ -#line 275 "CMDgram.y" +#line 279 "CMDgram.y" { (yyval.s) = (yyvsp[0].s); } -#line 2396 "CMDgram.c" +#line 2442 "CMDgram.c" break; case 42: /* object_name: %empty */ -#line 280 "CMDgram.y" +#line 284 "CMDgram.y" { (yyval.expr) = StrConstNode::alloc( CodeBlock::smCurrentParser->getCurrentLine(), "", false); } -#line 2402 "CMDgram.c" +#line 2448 "CMDgram.c" break; case 43: /* object_name: expr */ -#line 282 "CMDgram.y" +#line 286 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 2408 "CMDgram.c" +#line 2454 "CMDgram.c" break; case 44: /* object_args: %empty */ -#line 287 "CMDgram.y" +#line 291 "CMDgram.y" { (yyval.expr) = NULL; } -#line 2414 "CMDgram.c" +#line 2460 "CMDgram.c" break; case 45: /* object_args: ',' expr_list */ -#line 289 "CMDgram.y" +#line 293 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 2420 "CMDgram.c" +#line 2466 "CMDgram.c" break; case 46: /* object_declare_block: %empty */ -#line 294 "CMDgram.y" +#line 298 "CMDgram.y" { (yyval.odcl).slots = NULL; (yyval.odcl).decls = NULL; } -#line 2426 "CMDgram.c" +#line 2472 "CMDgram.c" break; case 47: /* object_declare_block: slot_assign_list */ -#line 296 "CMDgram.y" +#line 300 "CMDgram.y" { (yyval.odcl).slots = (yyvsp[0].slist); (yyval.odcl).decls = NULL; } -#line 2432 "CMDgram.c" +#line 2478 "CMDgram.c" break; case 48: /* object_declare_block: object_decl_list */ -#line 298 "CMDgram.y" +#line 302 "CMDgram.y" { (yyval.odcl).slots = NULL; (yyval.odcl).decls = (yyvsp[0].od); } -#line 2438 "CMDgram.c" +#line 2484 "CMDgram.c" break; case 49: /* object_declare_block: slot_assign_list object_decl_list */ -#line 300 "CMDgram.y" +#line 304 "CMDgram.y" { (yyval.odcl).slots = (yyvsp[-1].slist); (yyval.odcl).decls = (yyvsp[0].od); } -#line 2444 "CMDgram.c" +#line 2490 "CMDgram.c" break; case 50: /* object_decl_list: object_decl ';' */ -#line 305 "CMDgram.y" +#line 309 "CMDgram.y" { (yyval.od) = (yyvsp[-1].od); } -#line 2450 "CMDgram.c" +#line 2496 "CMDgram.c" break; case 51: /* object_decl_list: object_decl_list object_decl ';' */ -#line 307 "CMDgram.y" +#line 311 "CMDgram.y" { (yyvsp[-2].od)->append((yyvsp[-1].od)); (yyval.od) = (yyvsp[-2].od); } -#line 2456 "CMDgram.c" +#line 2502 "CMDgram.c" break; case 52: /* stmt_block: '{' statement_list '}' */ -#line 312 "CMDgram.y" +#line 316 "CMDgram.y" { (yyval.stmt) = (yyvsp[-1].stmt); } -#line 2462 "CMDgram.c" +#line 2508 "CMDgram.c" break; case 53: /* stmt_block: stmt */ -#line 314 "CMDgram.y" +#line 318 "CMDgram.y" { (yyval.stmt) = (yyvsp[0].stmt); } -#line 2468 "CMDgram.c" +#line 2514 "CMDgram.c" break; case 54: /* switch_stmt: rwSWITCH '(' expr ')' '{' case_block '}' */ -#line 319 "CMDgram.y" +#line 323 "CMDgram.y" { (yyval.stmt) = (yyvsp[-1].ifnode); (yyvsp[-1].ifnode)->propagateSwitchExpr((yyvsp[-4].expr), false); } -#line 2474 "CMDgram.c" +#line 2520 "CMDgram.c" break; case 55: /* switch_stmt: rwSWITCHSTR '(' expr ')' '{' case_block '}' */ -#line 321 "CMDgram.y" +#line 325 "CMDgram.y" { (yyval.stmt) = (yyvsp[-1].ifnode); (yyvsp[-1].ifnode)->propagateSwitchExpr((yyvsp[-4].expr), true); } -#line 2480 "CMDgram.c" +#line 2526 "CMDgram.c" break; case 56: /* case_block: rwCASE case_expr ':' statement_list */ -#line 326 "CMDgram.y" +#line 330 "CMDgram.y" { (yyval.ifnode) = IfStmtNode::alloc( (yyvsp[-3].i).lineNumber, (yyvsp[-2].expr), (yyvsp[0].stmt), NULL, false); } -#line 2486 "CMDgram.c" +#line 2532 "CMDgram.c" break; case 57: /* case_block: rwCASE case_expr ':' statement_list rwDEFAULT ':' statement_list */ -#line 328 "CMDgram.y" +#line 332 "CMDgram.y" { (yyval.ifnode) = IfStmtNode::alloc( (yyvsp[-6].i).lineNumber, (yyvsp[-5].expr), (yyvsp[-3].stmt), (yyvsp[0].stmt), false); } -#line 2492 "CMDgram.c" +#line 2538 "CMDgram.c" break; case 58: /* case_block: rwCASE case_expr ':' statement_list case_block */ -#line 330 "CMDgram.y" +#line 334 "CMDgram.y" { (yyval.ifnode) = IfStmtNode::alloc( (yyvsp[-4].i).lineNumber, (yyvsp[-3].expr), (yyvsp[-1].stmt), (yyvsp[0].ifnode), true); } -#line 2498 "CMDgram.c" +#line 2544 "CMDgram.c" break; case 59: /* case_expr: expr */ -#line 335 "CMDgram.y" +#line 339 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr);} -#line 2504 "CMDgram.c" +#line 2550 "CMDgram.c" break; case 60: /* case_expr: case_expr rwCASEOR expr */ -#line 337 "CMDgram.y" +#line 341 "CMDgram.y" { ((yyvsp[-2].expr))->append((yyvsp[0].expr)); (yyval.expr)=(yyvsp[-2].expr); } -#line 2510 "CMDgram.c" +#line 2556 "CMDgram.c" break; case 61: /* if_stmt: rwIF '(' expr ')' stmt_block */ -#line 342 "CMDgram.y" +#line 346 "CMDgram.y" { (yyval.stmt) = IfStmtNode::alloc((yyvsp[-4].i).lineNumber, (yyvsp[-2].expr), (yyvsp[0].stmt), NULL, false); } -#line 2516 "CMDgram.c" +#line 2562 "CMDgram.c" break; case 62: /* if_stmt: rwIF '(' expr ')' stmt_block rwELSE stmt_block */ -#line 344 "CMDgram.y" +#line 348 "CMDgram.y" { (yyval.stmt) = IfStmtNode::alloc((yyvsp[-6].i).lineNumber, (yyvsp[-4].expr), (yyvsp[-2].stmt), (yyvsp[0].stmt), false); } -#line 2522 "CMDgram.c" +#line 2568 "CMDgram.c" break; case 63: /* while_stmt: rwWHILE '(' expr ')' stmt_block */ -#line 349 "CMDgram.y" +#line 353 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-4].i).lineNumber, nil, (yyvsp[-2].expr), nil, (yyvsp[0].stmt), false); } -#line 2528 "CMDgram.c" +#line 2574 "CMDgram.c" break; case 64: /* while_stmt: rwDO stmt_block rwWHILE '(' expr ')' */ -#line 351 "CMDgram.y" +#line 355 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-3].i).lineNumber, nil, (yyvsp[-1].expr), nil, (yyvsp[-4].stmt), true); } -#line 2534 "CMDgram.c" +#line 2580 "CMDgram.c" break; case 65: /* for_stmt: rwFOR '(' expr ';' expr ';' expr ')' stmt_block */ -#line 356 "CMDgram.y" +#line 360 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-8].i).lineNumber, (yyvsp[-6].expr), (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].stmt), false); } -#line 2540 "CMDgram.c" +#line 2586 "CMDgram.c" break; case 66: /* for_stmt: rwFOR '(' expr ';' expr ';' ')' stmt_block */ -#line 358 "CMDgram.y" +#line 362 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-7].i).lineNumber, (yyvsp[-5].expr), (yyvsp[-3].expr), NULL, (yyvsp[0].stmt), false); } -#line 2546 "CMDgram.c" +#line 2592 "CMDgram.c" break; case 67: /* for_stmt: rwFOR '(' expr ';' ';' expr ')' stmt_block */ -#line 360 "CMDgram.y" +#line 364 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-7].i).lineNumber, (yyvsp[-5].expr), NULL, (yyvsp[-2].expr), (yyvsp[0].stmt), false); } -#line 2552 "CMDgram.c" +#line 2598 "CMDgram.c" break; case 68: /* for_stmt: rwFOR '(' expr ';' ';' ')' stmt_block */ -#line 362 "CMDgram.y" +#line 366 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-6].i).lineNumber, (yyvsp[-4].expr), NULL, NULL, (yyvsp[0].stmt), false); } -#line 2558 "CMDgram.c" +#line 2604 "CMDgram.c" break; case 69: /* for_stmt: rwFOR '(' ';' expr ';' expr ')' stmt_block */ -#line 364 "CMDgram.y" +#line 368 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-7].i).lineNumber, NULL, (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].stmt), false); } -#line 2564 "CMDgram.c" +#line 2610 "CMDgram.c" break; case 70: /* for_stmt: rwFOR '(' ';' expr ';' ')' stmt_block */ -#line 366 "CMDgram.y" +#line 370 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-6].i).lineNumber, NULL, (yyvsp[-3].expr), NULL, (yyvsp[0].stmt), false); } -#line 2570 "CMDgram.c" +#line 2616 "CMDgram.c" break; case 71: /* for_stmt: rwFOR '(' ';' ';' expr ')' stmt_block */ -#line 368 "CMDgram.y" +#line 372 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-6].i).lineNumber, NULL, NULL, (yyvsp[-2].expr), (yyvsp[0].stmt), false); } -#line 2576 "CMDgram.c" +#line 2622 "CMDgram.c" break; case 72: /* for_stmt: rwFOR '(' ';' ';' ')' stmt_block */ -#line 370 "CMDgram.y" +#line 374 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-5].i).lineNumber, NULL, NULL, NULL, (yyvsp[0].stmt), false); } -#line 2582 "CMDgram.c" +#line 2628 "CMDgram.c" break; case 73: /* foreach_stmt: rwFOREACH '(' VAR rwIN expr ')' stmt_block */ -#line 375 "CMDgram.y" +#line 379 "CMDgram.y" { (yyval.stmt) = IterStmtNode::alloc( (yyvsp[-6].i).lineNumber, (yyvsp[-4].s).value, (yyvsp[-2].expr), (yyvsp[0].stmt), false ); } -#line 2588 "CMDgram.c" +#line 2634 "CMDgram.c" break; case 74: /* foreach_stmt: rwFOREACHSTR '(' VAR rwIN expr ')' stmt_block */ -#line 377 "CMDgram.y" +#line 381 "CMDgram.y" { (yyval.stmt) = IterStmtNode::alloc( (yyvsp[-6].i).lineNumber, (yyvsp[-4].s).value, (yyvsp[-2].expr), (yyvsp[0].stmt), true ); } -#line 2594 "CMDgram.c" +#line 2640 "CMDgram.c" break; case 75: /* expression_stmt: stmt_expr */ -#line 382 "CMDgram.y" +#line 386 "CMDgram.y" { (yyval.stmt) = (yyvsp[0].expr); } -#line 2600 "CMDgram.c" +#line 2646 "CMDgram.c" break; case 76: /* expr: stmt_expr */ -#line 387 "CMDgram.y" +#line 391 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 2606 "CMDgram.c" +#line 2652 "CMDgram.c" break; case 77: /* expr: '(' expr ')' */ -#line 389 "CMDgram.y" +#line 393 "CMDgram.y" { (yyval.expr) = (yyvsp[-1].expr); } -#line 2612 "CMDgram.c" +#line 2658 "CMDgram.c" break; case 78: /* expr: expr '^' expr */ -#line 391 "CMDgram.y" +#line 395 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2618 "CMDgram.c" +#line 2664 "CMDgram.c" break; case 79: /* expr: expr '%' expr */ -#line 393 "CMDgram.y" +#line 397 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2624 "CMDgram.c" +#line 2670 "CMDgram.c" break; case 80: /* expr: expr '&' expr */ -#line 395 "CMDgram.y" +#line 399 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2630 "CMDgram.c" +#line 2676 "CMDgram.c" break; case 81: /* expr: expr '|' expr */ -#line 397 "CMDgram.y" +#line 401 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2636 "CMDgram.c" +#line 2682 "CMDgram.c" break; case 82: /* expr: expr '+' expr */ -#line 399 "CMDgram.y" +#line 403 "CMDgram.y" { (yyval.expr) = FloatBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2642 "CMDgram.c" +#line 2688 "CMDgram.c" break; case 83: /* expr: expr '-' expr */ -#line 401 "CMDgram.y" +#line 405 "CMDgram.y" { (yyval.expr) = FloatBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2648 "CMDgram.c" +#line 2694 "CMDgram.c" break; case 84: /* expr: expr '*' expr */ -#line 403 "CMDgram.y" +#line 407 "CMDgram.y" { (yyval.expr) = FloatBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2654 "CMDgram.c" +#line 2700 "CMDgram.c" break; case 85: /* expr: expr '/' expr */ -#line 405 "CMDgram.y" +#line 409 "CMDgram.y" { (yyval.expr) = FloatBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2660 "CMDgram.c" +#line 2706 "CMDgram.c" break; case 86: /* expr: '-' expr */ -#line 407 "CMDgram.y" +#line 411 "CMDgram.y" { (yyval.expr) = FloatUnaryExprNode::alloc( (yyvsp[-1].i).lineNumber, (yyvsp[-1].i).value, (yyvsp[0].expr)); } -#line 2666 "CMDgram.c" +#line 2712 "CMDgram.c" break; case 87: /* expr: '*' expr */ -#line 409 "CMDgram.y" +#line 413 "CMDgram.y" { (yyval.expr) = TTagDerefNode::alloc( (yyvsp[-1].i).lineNumber, (yyvsp[0].expr) ); } -#line 2672 "CMDgram.c" +#line 2718 "CMDgram.c" break; case 88: /* expr: TTAG */ -#line 411 "CMDgram.y" +#line 415 "CMDgram.y" { (yyval.expr) = TTagExprNode::alloc( (yyvsp[0].s).lineNumber, (yyvsp[0].s).value ); } -#line 2678 "CMDgram.c" +#line 2724 "CMDgram.c" break; case 89: /* expr: expr '?' expr ':' expr */ -#line 413 "CMDgram.y" +#line 417 "CMDgram.y" { (yyval.expr) = ConditionalExprNode::alloc( (yyvsp[-4].expr)->dbgLineNumber, (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2684 "CMDgram.c" +#line 2730 "CMDgram.c" break; case 90: /* expr: expr '<' expr */ -#line 415 "CMDgram.y" +#line 419 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2690 "CMDgram.c" +#line 2736 "CMDgram.c" break; case 91: /* expr: expr '>' expr */ -#line 417 "CMDgram.y" +#line 421 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2696 "CMDgram.c" +#line 2742 "CMDgram.c" break; case 92: /* expr: expr opGE expr */ -#line 419 "CMDgram.y" +#line 423 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2702 "CMDgram.c" +#line 2748 "CMDgram.c" break; case 93: /* expr: expr opLE expr */ -#line 421 "CMDgram.y" +#line 425 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2708 "CMDgram.c" +#line 2754 "CMDgram.c" break; case 94: /* expr: expr opEQ expr */ -#line 423 "CMDgram.y" +#line 427 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2714 "CMDgram.c" +#line 2760 "CMDgram.c" break; case 95: /* expr: expr opNE expr */ -#line 425 "CMDgram.y" +#line 429 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2720 "CMDgram.c" +#line 2766 "CMDgram.c" break; case 96: /* expr: expr opOR expr */ -#line 427 "CMDgram.y" +#line 431 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2726 "CMDgram.c" +#line 2772 "CMDgram.c" break; case 97: /* expr: expr opSHL expr */ -#line 429 "CMDgram.y" +#line 433 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2732 "CMDgram.c" +#line 2778 "CMDgram.c" break; case 98: /* expr: expr opSHR expr */ -#line 431 "CMDgram.y" +#line 435 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2738 "CMDgram.c" +#line 2784 "CMDgram.c" break; case 99: /* expr: expr opAND expr */ -#line 433 "CMDgram.y" +#line 437 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2744 "CMDgram.c" +#line 2790 "CMDgram.c" break; case 100: /* expr: expr opSTREQ expr */ -#line 435 "CMDgram.y" +#line 439 "CMDgram.y" { (yyval.expr) = StreqExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-2].expr), (yyvsp[0].expr), true); } -#line 2750 "CMDgram.c" +#line 2796 "CMDgram.c" break; case 101: /* expr: expr opSTRNE expr */ -#line 437 "CMDgram.y" +#line 441 "CMDgram.y" { (yyval.expr) = StreqExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-2].expr), (yyvsp[0].expr), false); } -#line 2756 "CMDgram.c" +#line 2802 "CMDgram.c" break; case 102: /* expr: expr '@' expr */ -#line 439 "CMDgram.y" +#line 443 "CMDgram.y" { (yyval.expr) = StrcatExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-2].expr), (yyvsp[0].expr), (yyvsp[-1].i).value); } -#line 2762 "CMDgram.c" +#line 2808 "CMDgram.c" break; case 103: /* expr: '!' expr */ -#line 441 "CMDgram.y" +#line 445 "CMDgram.y" { (yyval.expr) = IntUnaryExprNode::alloc((yyvsp[-1].i).lineNumber, (yyvsp[-1].i).value, (yyvsp[0].expr)); } -#line 2768 "CMDgram.c" +#line 2814 "CMDgram.c" break; case 104: /* expr: '~' expr */ -#line 443 "CMDgram.y" +#line 447 "CMDgram.y" { (yyval.expr) = IntUnaryExprNode::alloc((yyvsp[-1].i).lineNumber, (yyvsp[-1].i).value, (yyvsp[0].expr)); } -#line 2774 "CMDgram.c" +#line 2820 "CMDgram.c" break; case 105: /* expr: TAGATOM */ -#line 445 "CMDgram.y" +#line 449 "CMDgram.y" { (yyval.expr) = StrConstNode::alloc( (yyvsp[0].str).lineNumber, (yyvsp[0].str).value, true); } -#line 2780 "CMDgram.c" +#line 2826 "CMDgram.c" break; case 106: /* expr: FLTCONST */ -#line 447 "CMDgram.y" +#line 451 "CMDgram.y" { (yyval.expr) = FloatNode::alloc( (yyvsp[0].f).lineNumber, (yyvsp[0].f).value ); } -#line 2786 "CMDgram.c" +#line 2832 "CMDgram.c" break; case 107: /* expr: INTCONST */ -#line 449 "CMDgram.y" +#line 453 "CMDgram.y" { (yyval.expr) = IntNode::alloc( (yyvsp[0].i).lineNumber, (yyvsp[0].i).value ); } -#line 2792 "CMDgram.c" +#line 2838 "CMDgram.c" break; case 108: /* expr: rwBREAK */ -#line 451 "CMDgram.y" +#line 455 "CMDgram.y" { (yyval.expr) = ConstantNode::alloc( (yyvsp[0].i).lineNumber, StringTable->insert("break")); } -#line 2798 "CMDgram.c" +#line 2844 "CMDgram.c" break; case 109: /* expr: slot_acc */ -#line 453 "CMDgram.y" +#line 457 "CMDgram.y" { (yyval.expr) = SlotAccessNode::alloc( (yyvsp[0].slot).lineNumber, (yyvsp[0].slot).object, (yyvsp[0].slot).array, (yyvsp[0].slot).slotName ); } -#line 2804 "CMDgram.c" +#line 2850 "CMDgram.c" break; case 110: /* expr: intslot_acc */ -#line 455 "CMDgram.y" +#line 459 "CMDgram.y" { (yyval.expr) = InternalSlotAccessNode::alloc( (yyvsp[0].intslot).lineNumber, (yyvsp[0].intslot).object, (yyvsp[0].intslot).slotExpr, (yyvsp[0].intslot).recurse); } -#line 2810 "CMDgram.c" +#line 2856 "CMDgram.c" break; case 111: /* expr: IDENT */ -#line 457 "CMDgram.y" +#line 461 "CMDgram.y" { (yyval.expr) = ConstantNode::alloc( (yyvsp[0].s).lineNumber, (yyvsp[0].s).value ); } -#line 2816 "CMDgram.c" +#line 2862 "CMDgram.c" break; case 112: /* expr: STRATOM */ -#line 459 "CMDgram.y" +#line 463 "CMDgram.y" { (yyval.expr) = StrConstNode::alloc( (yyvsp[0].str).lineNumber, (yyvsp[0].str).value, false); } -#line 2822 "CMDgram.c" +#line 2868 "CMDgram.c" break; case 113: /* expr: VAR */ -#line 461 "CMDgram.y" +#line 465 "CMDgram.y" { (yyval.expr) = (ExprNode*)VarNode::alloc( (yyvsp[0].s).lineNumber, (yyvsp[0].s).value, NULL); } -#line 2828 "CMDgram.c" +#line 2874 "CMDgram.c" break; case 114: /* expr: VAR '[' aidx_expr ']' */ -#line 463 "CMDgram.y" +#line 467 "CMDgram.y" { (yyval.expr) = (ExprNode*)VarNode::alloc( (yyvsp[-3].s).lineNumber, (yyvsp[-3].s).value, (yyvsp[-1].expr) ); } -#line 2834 "CMDgram.c" +#line 2880 "CMDgram.c" break; case 115: /* slot_acc: expr '.' IDENT */ -#line 485 "CMDgram.y" +#line 489 "CMDgram.y" { (yyval.slot).lineNumber = (yyvsp[-2].expr)->dbgLineNumber; (yyval.slot).object = (yyvsp[-2].expr); (yyval.slot).slotName = (yyvsp[0].s).value; (yyval.slot).array = NULL; } -#line 2840 "CMDgram.c" +#line 2886 "CMDgram.c" break; case 116: /* slot_acc: expr '.' IDENT '[' aidx_expr ']' */ -#line 487 "CMDgram.y" +#line 491 "CMDgram.y" { (yyval.slot).lineNumber = (yyvsp[-5].expr)->dbgLineNumber; (yyval.slot).object = (yyvsp[-5].expr); (yyval.slot).slotName = (yyvsp[-3].s).value; (yyval.slot).array = (yyvsp[-1].expr); } -#line 2846 "CMDgram.c" +#line 2892 "CMDgram.c" break; case 117: /* intslot_acc: expr opINTNAME class_name_expr */ -#line 492 "CMDgram.y" +#line 496 "CMDgram.y" { (yyval.intslot).lineNumber = (yyvsp[-2].expr)->dbgLineNumber; (yyval.intslot).object = (yyvsp[-2].expr); (yyval.intslot).slotExpr = (yyvsp[0].expr); (yyval.intslot).recurse = false; } -#line 2852 "CMDgram.c" +#line 2898 "CMDgram.c" break; case 118: /* intslot_acc: expr opINTNAMER class_name_expr */ -#line 494 "CMDgram.y" +#line 498 "CMDgram.y" { (yyval.intslot).lineNumber = (yyvsp[-2].expr)->dbgLineNumber; (yyval.intslot).object = (yyvsp[-2].expr); (yyval.intslot).slotExpr = (yyvsp[0].expr); (yyval.intslot).recurse = true; } -#line 2858 "CMDgram.c" +#line 2904 "CMDgram.c" break; case 119: /* class_name_expr: IDENT */ -#line 499 "CMDgram.y" +#line 503 "CMDgram.y" { (yyval.expr) = ConstantNode::alloc( (yyvsp[0].s).lineNumber, (yyvsp[0].s).value ); } -#line 2864 "CMDgram.c" +#line 2910 "CMDgram.c" break; case 120: /* class_name_expr: '(' expr ')' */ -#line 501 "CMDgram.y" +#line 505 "CMDgram.y" { (yyval.expr) = (yyvsp[-1].expr); } -#line 2870 "CMDgram.c" +#line 2916 "CMDgram.c" break; case 121: /* assign_op_struct: opPLUSPLUS */ -#line 506 "CMDgram.y" +#line 510 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[0].i).lineNumber; (yyval.asn).token = opPLUSPLUS; (yyval.asn).expr = FloatNode::alloc( (yyvsp[0].i).lineNumber, 1 ); } -#line 2876 "CMDgram.c" +#line 2922 "CMDgram.c" break; case 122: /* assign_op_struct: opMINUSMINUS */ -#line 508 "CMDgram.y" +#line 512 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[0].i).lineNumber; (yyval.asn).token = opMINUSMINUS; (yyval.asn).expr = FloatNode::alloc( (yyvsp[0].i).lineNumber, 1 ); } -#line 2882 "CMDgram.c" +#line 2928 "CMDgram.c" break; case 123: /* assign_op_struct: opPLASN expr */ -#line 510 "CMDgram.y" +#line 514 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = '+'; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2888 "CMDgram.c" +#line 2934 "CMDgram.c" break; case 124: /* assign_op_struct: opMIASN expr */ -#line 512 "CMDgram.y" +#line 516 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = '-'; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2894 "CMDgram.c" +#line 2940 "CMDgram.c" break; case 125: /* assign_op_struct: opMLASN expr */ -#line 514 "CMDgram.y" +#line 518 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = '*'; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2900 "CMDgram.c" +#line 2946 "CMDgram.c" break; case 126: /* assign_op_struct: opDVASN expr */ -#line 516 "CMDgram.y" +#line 520 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = '/'; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2906 "CMDgram.c" +#line 2952 "CMDgram.c" break; case 127: /* assign_op_struct: opMODASN expr */ -#line 518 "CMDgram.y" +#line 522 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = '%'; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2912 "CMDgram.c" +#line 2958 "CMDgram.c" break; case 128: /* assign_op_struct: opANDASN expr */ -#line 520 "CMDgram.y" +#line 524 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = '&'; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2918 "CMDgram.c" +#line 2964 "CMDgram.c" break; case 129: /* assign_op_struct: opXORASN expr */ -#line 522 "CMDgram.y" +#line 526 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = '^'; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2924 "CMDgram.c" +#line 2970 "CMDgram.c" break; case 130: /* assign_op_struct: opORASN expr */ -#line 524 "CMDgram.y" +#line 528 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = '|'; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2930 "CMDgram.c" +#line 2976 "CMDgram.c" break; case 131: /* assign_op_struct: opSLASN expr */ -#line 526 "CMDgram.y" +#line 530 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = opSHL; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2936 "CMDgram.c" +#line 2982 "CMDgram.c" break; case 132: /* assign_op_struct: opSRASN expr */ -#line 528 "CMDgram.y" +#line 532 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = opSHR; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2942 "CMDgram.c" +#line 2988 "CMDgram.c" break; case 133: /* stmt_expr: funcall_expr */ -#line 533 "CMDgram.y" +#line 537 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 2948 "CMDgram.c" +#line 2994 "CMDgram.c" break; case 134: /* stmt_expr: assert_expr */ -#line 535 "CMDgram.y" +#line 539 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 2954 "CMDgram.c" +#line 3000 "CMDgram.c" break; case 135: /* stmt_expr: object_decl */ -#line 537 "CMDgram.y" +#line 541 "CMDgram.y" { (yyval.expr) = (yyvsp[0].od); } -#line 2960 "CMDgram.c" +#line 3006 "CMDgram.c" break; case 136: /* stmt_expr: VAR '=' expr */ -#line 539 "CMDgram.y" +#line 543 "CMDgram.y" { (yyval.expr) = AssignExprNode::alloc( (yyvsp[-2].s).lineNumber, (yyvsp[-2].s).value, NULL, (yyvsp[0].expr)); } -#line 2966 "CMDgram.c" +#line 3012 "CMDgram.c" break; case 137: /* stmt_expr: VAR '[' aidx_expr ']' '=' expr */ -#line 541 "CMDgram.y" +#line 545 "CMDgram.y" { (yyval.expr) = AssignExprNode::alloc( (yyvsp[-5].s).lineNumber, (yyvsp[-5].s).value, (yyvsp[-3].expr), (yyvsp[0].expr)); } -#line 2972 "CMDgram.c" +#line 3018 "CMDgram.c" break; case 138: /* stmt_expr: VAR assign_op_struct */ -#line 543 "CMDgram.y" +#line 547 "CMDgram.y" { (yyval.expr) = AssignOpExprNode::alloc( (yyvsp[-1].s).lineNumber, (yyvsp[-1].s).value, NULL, (yyvsp[0].asn).expr, (yyvsp[0].asn).token); } -#line 2978 "CMDgram.c" +#line 3024 "CMDgram.c" break; case 139: /* stmt_expr: VAR '[' aidx_expr ']' assign_op_struct */ -#line 545 "CMDgram.y" +#line 549 "CMDgram.y" { (yyval.expr) = AssignOpExprNode::alloc( (yyvsp[-4].s).lineNumber, (yyvsp[-4].s).value, (yyvsp[-2].expr), (yyvsp[0].asn).expr, (yyvsp[0].asn).token); } -#line 2984 "CMDgram.c" +#line 3030 "CMDgram.c" break; case 140: /* stmt_expr: slot_acc assign_op_struct */ -#line 547 "CMDgram.y" +#line 551 "CMDgram.y" { (yyval.expr) = SlotAssignOpNode::alloc( (yyvsp[-1].slot).lineNumber, (yyvsp[-1].slot).object, (yyvsp[-1].slot).slotName, (yyvsp[-1].slot).array, (yyvsp[0].asn).token, (yyvsp[0].asn).expr); } -#line 2990 "CMDgram.c" +#line 3036 "CMDgram.c" break; case 141: /* stmt_expr: slot_acc '=' expr */ -#line 549 "CMDgram.y" +#line 553 "CMDgram.y" { (yyval.expr) = SlotAssignNode::alloc( (yyvsp[-2].slot).lineNumber, (yyvsp[-2].slot).object, (yyvsp[-2].slot).array, (yyvsp[-2].slot).slotName, (yyvsp[0].expr)); } -#line 2996 "CMDgram.c" +#line 3042 "CMDgram.c" break; case 142: /* stmt_expr: slot_acc '=' '{' expr_list '}' */ -#line 551 "CMDgram.y" +#line 555 "CMDgram.y" { (yyval.expr) = SlotAssignNode::alloc( (yyvsp[-4].slot).lineNumber, (yyvsp[-4].slot).object, (yyvsp[-4].slot).array, (yyvsp[-4].slot).slotName, (yyvsp[-1].expr)); } -#line 3002 "CMDgram.c" +#line 3048 "CMDgram.c" break; case 143: /* funcall_expr: IDENT '(' expr_list_decl ')' */ -#line 556 "CMDgram.y" +#line 560 "CMDgram.y" { (yyval.expr) = FuncCallExprNode::alloc( (yyvsp[-3].s).lineNumber, (yyvsp[-3].s).value, NULL, (yyvsp[-1].expr), false); } -#line 3008 "CMDgram.c" +#line 3054 "CMDgram.c" break; case 144: /* funcall_expr: IDENT opCOLONCOLON IDENT '(' expr_list_decl ')' */ -#line 558 "CMDgram.y" +#line 562 "CMDgram.y" { (yyval.expr) = FuncCallExprNode::alloc( (yyvsp[-5].s).lineNumber, (yyvsp[-3].s).value, (yyvsp[-5].s).value, (yyvsp[-1].expr), false); } -#line 3014 "CMDgram.c" +#line 3060 "CMDgram.c" break; case 145: /* funcall_expr: expr '.' IDENT '(' expr_list_decl ')' */ -#line 560 "CMDgram.y" +#line 564 "CMDgram.y" { (yyvsp[-5].expr)->append((yyvsp[-1].expr)); (yyval.expr) = FuncCallExprNode::alloc( (yyvsp[-5].expr)->dbgLineNumber, (yyvsp[-3].s).value, NULL, (yyvsp[-5].expr), true); } -#line 3020 "CMDgram.c" +#line 3066 "CMDgram.c" break; case 146: /* assert_expr: rwASSERT '(' expr ')' */ -#line 570 "CMDgram.y" +#line 574 "CMDgram.y" { (yyval.expr) = AssertCallExprNode::alloc( (yyvsp[-3].i).lineNumber, (yyvsp[-1].expr), NULL ); } -#line 3026 "CMDgram.c" +#line 3072 "CMDgram.c" break; case 147: /* assert_expr: rwASSERT '(' expr ',' STRATOM ')' */ -#line 572 "CMDgram.y" +#line 576 "CMDgram.y" { (yyval.expr) = AssertCallExprNode::alloc( (yyvsp[-5].i).lineNumber, (yyvsp[-3].expr), (yyvsp[-1].str).value ); } -#line 3032 "CMDgram.c" +#line 3078 "CMDgram.c" break; case 148: /* expr_list_decl: %empty */ -#line 577 "CMDgram.y" +#line 581 "CMDgram.y" { (yyval.expr) = NULL; } -#line 3038 "CMDgram.c" +#line 3084 "CMDgram.c" break; case 149: /* expr_list_decl: expr_list */ -#line 579 "CMDgram.y" +#line 583 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 3044 "CMDgram.c" +#line 3090 "CMDgram.c" break; case 150: /* expr_list: expr */ -#line 584 "CMDgram.y" +#line 588 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 3050 "CMDgram.c" +#line 3096 "CMDgram.c" break; case 151: /* expr_list: expr_list ',' expr */ -#line 586 "CMDgram.y" +#line 590 "CMDgram.y" { ((yyvsp[-2].expr))->append((yyvsp[0].expr)); (yyval.expr) = (yyvsp[-2].expr); } -#line 3056 "CMDgram.c" +#line 3102 "CMDgram.c" break; case 152: /* slot_assign_list_opt: %empty */ -#line 591 "CMDgram.y" +#line 595 "CMDgram.y" { (yyval.slist) = NULL; } -#line 3062 "CMDgram.c" +#line 3108 "CMDgram.c" break; case 153: /* slot_assign_list_opt: slot_assign_list */ -#line 593 "CMDgram.y" +#line 597 "CMDgram.y" { (yyval.slist) = (yyvsp[0].slist); } -#line 3068 "CMDgram.c" +#line 3114 "CMDgram.c" break; case 154: /* slot_assign_list: slot_assign */ -#line 598 "CMDgram.y" +#line 602 "CMDgram.y" { (yyval.slist) = (yyvsp[0].slist); } -#line 3074 "CMDgram.c" +#line 3120 "CMDgram.c" break; case 155: /* slot_assign_list: slot_assign_list slot_assign */ -#line 600 "CMDgram.y" +#line 604 "CMDgram.y" { (yyvsp[-1].slist)->append((yyvsp[0].slist)); (yyval.slist) = (yyvsp[-1].slist); } -#line 3080 "CMDgram.c" +#line 3126 "CMDgram.c" break; case 156: /* slot_assign: IDENT '=' expr ';' */ -#line 605 "CMDgram.y" +#line 609 "CMDgram.y" { (yyval.slist) = SlotAssignNode::alloc( (yyvsp[-3].s).lineNumber, NULL, NULL, (yyvsp[-3].s).value, (yyvsp[-1].expr)); } -#line 3086 "CMDgram.c" +#line 3132 "CMDgram.c" break; case 157: /* slot_assign: TYPEIDENT IDENT '=' expr ';' */ -#line 607 "CMDgram.y" +#line 611 "CMDgram.y" { (yyval.slist) = SlotAssignNode::alloc( (yyvsp[-4].i).lineNumber, NULL, NULL, (yyvsp[-3].s).value, (yyvsp[-1].expr), (yyvsp[-4].i).value); } -#line 3092 "CMDgram.c" +#line 3138 "CMDgram.c" break; case 158: /* slot_assign: rwDATABLOCK '=' expr ';' */ -#line 609 "CMDgram.y" +#line 613 "CMDgram.y" { (yyval.slist) = SlotAssignNode::alloc( (yyvsp[-3].i).lineNumber, NULL, NULL, StringTable->insert("datablock"), (yyvsp[-1].expr)); } -#line 3098 "CMDgram.c" +#line 3144 "CMDgram.c" break; case 159: /* slot_assign: IDENT '[' aidx_expr ']' '=' expr ';' */ -#line 611 "CMDgram.y" +#line 615 "CMDgram.y" { (yyval.slist) = SlotAssignNode::alloc( (yyvsp[-6].s).lineNumber, NULL, (yyvsp[-4].expr), (yyvsp[-6].s).value, (yyvsp[-1].expr)); } -#line 3104 "CMDgram.c" +#line 3150 "CMDgram.c" break; case 160: /* slot_assign: TYPEIDENT IDENT '[' aidx_expr ']' '=' expr ';' */ -#line 613 "CMDgram.y" +#line 617 "CMDgram.y" { (yyval.slist) = SlotAssignNode::alloc( (yyvsp[-7].i).lineNumber, NULL, (yyvsp[-4].expr), (yyvsp[-6].s).value, (yyvsp[-1].expr), (yyvsp[-7].i).value); } -#line 3110 "CMDgram.c" +#line 3156 "CMDgram.c" break; case 161: /* aidx_expr: expr */ -#line 618 "CMDgram.y" +#line 622 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 3116 "CMDgram.c" +#line 3162 "CMDgram.c" break; case 162: /* aidx_expr: aidx_expr ',' expr */ -#line 620 "CMDgram.y" +#line 624 "CMDgram.y" { (yyval.expr) = CommaCatExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 3122 "CMDgram.c" +#line 3168 "CMDgram.c" break; -#line 3126 "CMDgram.c" +#line 3172 "CMDgram.c" default: break; } @@ -3325,7 +3371,7 @@ yyreturnlab: return yyresult; } -#line 622 "CMDgram.y" +#line 626 "CMDgram.y" int @@ -3363,7 +3409,7 @@ yyreport_syntax_error (const yypcontext_t *ctx) output += String::ToString("%5s | %*s", "", loc->first_column, "^"); } - yyerror("%s",output.c_str()); + yyerror("%s", output.c_str()); return ret; } diff --git a/Engine/source/console/torquescript/compiler.cpp b/Engine/source/console/torquescript/compiler.cpp index 817b181c3..890f47e98 100644 --- a/Engine/source/console/torquescript/compiler.cpp +++ b/Engine/source/console/torquescript/compiler.cpp @@ -269,8 +269,10 @@ U32 CompilerStringTable::addFloatString(F64 value) void CompilerStringTable::reset() { - list = NULL; + // Reset list and associated variables + list = nullptr; totalLen = 0; + hashTable.clear(); // Clear the lookup table too } char *CompilerStringTable::build() From 8926d1c32b522c56d9f32e653f2cbb99ba0d89f5 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 5 May 2025 11:12:13 +0100 Subject: [PATCH 07/41] Update assetManager.cpp purgeAssets correctly on tear down of the asset manager --- Engine/source/assets/assetManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Engine/source/assets/assetManager.cpp b/Engine/source/assets/assetManager.cpp index d400de2fb..468192f3d 100644 --- a/Engine/source/assets/assetManager.cpp +++ b/Engine/source/assets/assetManager.cpp @@ -119,6 +119,8 @@ void AssetManager::onRemove() mAssetTagsManifest->deleteObject(); } + purgeAssets(); + for (auto itr = mDeclaredAssets.begin(); itr != mDeclaredAssets.end(); ++itr) { delete itr->value; From d8315267e83987df74133d6f2e2e4f3294fae7bb Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 5 May 2025 17:30:40 +0100 Subject: [PATCH 08/41] clear utf16 cache this stops the unicode global cache from showing in the memleak output --- Engine/source/core/strings/unicode.cpp | 5 +++++ Engine/source/core/strings/unicode.h | 4 +++- Engine/source/main/main.cpp | 3 ++- Engine/source/platformWin32/winWindow.cpp | 2 ++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Engine/source/core/strings/unicode.cpp b/Engine/source/core/strings/unicode.cpp index ad43ad3e1..28fb25323 100644 --- a/Engine/source/core/strings/unicode.cpp +++ b/Engine/source/core/strings/unicode.cpp @@ -289,6 +289,11 @@ UTF8* createUTF8string( const UTF16* unistring) return ret; } +void UTF16ClearCache() +{ + sgUTF16Cache.clear(); +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- diff --git a/Engine/source/core/strings/unicode.h b/Engine/source/core/strings/unicode.h index ec26d1c91..009489630 100644 --- a/Engine/source/core/strings/unicode.h +++ b/Engine/source/core/strings/unicode.h @@ -66,6 +66,8 @@ UTF16* createUTF16string( const UTF8 *unistring); UTF8* createUTF8string( const UTF16 *unistring); +void UTF16ClearCache(); + //----------------------------------------------------------------------------- /// Functions that convert buffers of unicode code points, into a provided buffer. /// - These functions are useful for working on existing buffers. @@ -138,4 +140,4 @@ const UTF8* getNthCodepoint(const UTF8 *unistring, const U32 n); bool chompUTF8BOM( const char *inString, char **outStringPtr ); bool isValidUTF8BOM( U8 bom[4] ); -#endif // _UNICODE_H_ \ No newline at end of file +#endif // _UNICODE_H_ diff --git a/Engine/source/main/main.cpp b/Engine/source/main/main.cpp index 826f14d16..c0699b9a1 100644 --- a/Engine/source/main/main.cpp +++ b/Engine/source/main/main.cpp @@ -231,7 +231,7 @@ S32 TorqueMain(S32 argc, const char **argv) // argv = argvFake; // } -#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) +#if defined( TORQUE_DEBUG ) && !defined(TORQUE_DISABLE_MEMORY_MANAGER) Memory::init(); #endif @@ -257,6 +257,7 @@ S32 TorqueMain(S32 argc, const char **argv) Platform::restartInstance(); + #if defined( TORQUE_DEBUG ) && !defined( TORQUE_DISABLE_MEMORY_MANAGER ) Memory::shutdown(); #endif diff --git a/Engine/source/platformWin32/winWindow.cpp b/Engine/source/platformWin32/winWindow.cpp index 011884ce4..4661140d1 100644 --- a/Engine/source/platformWin32/winWindow.cpp +++ b/Engine/source/platformWin32/winWindow.cpp @@ -317,6 +317,8 @@ void Platform::shutdown() GFXDevice::destroy(); WinConsole::destroy(); + + UTF16ClearCache(); } extern bool LinkConsoleFunctions; From d93f094cf5d8a9de95817622fec535bc1396818d Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 5 May 2025 20:14:03 +0100 Subject: [PATCH 09/41] Update console.cpp move shutdown function to after PathExpandos is defined and clear it to remove it from memlog --- Engine/source/console/console.cpp | 32 ++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/Engine/source/console/console.cpp b/Engine/source/console/console.cpp index f56051e7e..760142b2c 100644 --- a/Engine/source/console/console.cpp +++ b/Engine/source/console/console.cpp @@ -427,21 +427,6 @@ void init() smConsoleInput.notify(postConsoleInput); } -//-------------------------------------- - -void shutdown() -{ - AssertFatal(active == true, "Con::shutdown should only be called once."); - active = false; - - smConsoleInput.remove(postConsoleInput); - - consoleLogFile.close(); - Namespace::shutdown(); - AbstractClassRep::shutdown(); - Compiler::freeConsoleParserList(); - gGlobalVars.reset(); -} bool isActive() { @@ -2111,6 +2096,23 @@ void ensureTrailingSlash(char* pDstPath, const char* pSrcPath, S32 dstSize) pDstPath[trailIndex] = 0; } +//-------------------------------------- + +void shutdown() +{ + AssertFatal(active == true, "Con::shutdown should only be called once."); + active = false; + + smConsoleInput.remove(postConsoleInput); + + consoleLogFile.close(); + Namespace::shutdown(); + AbstractClassRep::shutdown(); + Compiler::freeConsoleParserList(); + gGlobalVars.reset(); + PathExpandos.clear(); +} + //----------------------------------------------------------------------------- StringTableEntry getDSOPath(const char *scriptPath) From 6237703140d0d8fa4c01de2675ffbe97c4b1ab61 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Tue, 6 May 2025 15:17:52 +0100 Subject: [PATCH 10/41] Update platformMemory.cpp stop memleaker from leaking...... yes i see the irony free was being blocked from running when unitialized in shutdown reset our allocList allocCount and currentAllocId so the array can be written to again --- Engine/source/platform/platformMemory.cpp | 43 +++++++++++++++++------ 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/Engine/source/platform/platformMemory.cpp b/Engine/source/platform/platformMemory.cpp index fe732db52..14fd4d02f 100644 --- a/Engine/source/platform/platformMemory.cpp +++ b/Engine/source/platform/platformMemory.cpp @@ -99,6 +99,8 @@ namespace Memory std::time_t now = std::time(nullptr); std::tm* localTime = std::localtime(&now); std::strftime(gLogFilename, sizeof(gLogFilename), "memlog_%Y-%m-%d_%H-%M-%S.txt", localTime); + + //std::atexit(shutdown); } void shutdown() @@ -142,12 +144,22 @@ namespace Memory for (int curStack = 0; curStack < allocList[curRep].backtraceSize; ++curStack) { DWORD64 addr = (DWORD64)(allocList[curRep].backtracePtrs[curStack]); - if (SymFromAddr(process, addr, 0, symbol)) - { - std::sprintf(stack, " [%d] %s - 0x%0llX\n", curStack, symbol->Name, symbol->Address); + DWORD displacement = 0; + IMAGEHLP_LINE64 line; + std::memset(&line, 0, sizeof(IMAGEHLP_LINE64)); + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + + if (SymFromAddr(process, addr, 0, symbol)) { + if (SymGetLineFromAddr64(process, addr, &displacement, &line)) { + std::sprintf(stack, " [%d] %s - %s:%lu (0x%0llX)\n", + curStack, symbol->Name, line.FileName, line.LineNumber, symbol->Address); + } + else { + std::sprintf(stack, " [%d] %s - ???:??? (0x%0llX)\n", + curStack, symbol->Name, symbol->Address); + } } - else - { + else { std::sprintf(stack, " [%d] ??? - 0x%0llX\n", curStack, addr); } report += stack; @@ -165,11 +177,11 @@ namespace Memory #endif } - if (report.find("getDocsLink") != std::string::npos) - { - //known issue. one off allocation - memLog[curRep].skip = true; - } + //if (report.find("getDocsLink") != std::string::npos) + //{ + // //known issue. one off allocation + // memLog[curRep].skip = true; + //} for (U32 oldRep = start; oldRep < curRep; ++oldRep) { @@ -201,6 +213,10 @@ namespace Memory } std::fclose(log); + + std::memset(allocList, 0, sizeof(allocList)); + allocCount = 0; + currentAllocId = 0; initialized = false; } @@ -247,9 +263,14 @@ namespace Memory static void free(void* ptr, bool array) { - if (!ptr || !initialized) + if (!ptr) return; + if (!initialized) + { + std::free(ptr); + return; + } for (U32 i = 0; i < allocCount; ++i) { From bab75a3a46796a1ca84eea1c5562ac9ab4542e7e Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 7 May 2025 17:04:55 +0100 Subject: [PATCH 11/41] clang-tidy complained about std::moves --- Engine/source/console/console.cpp | 34 +++++++++---------- Engine/source/console/consoleInternal.cpp | 4 +-- Engine/source/console/runtime.h | 2 +- Engine/source/console/simEvents.cpp | 4 +-- .../source/console/torquescript/codeBlock.cpp | 2 +- .../source/console/torquescript/runtime.cpp | 2 +- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Engine/source/console/console.cpp b/Engine/source/console/console.cpp index 760142b2c..fec923819 100644 --- a/Engine/source/console/console.cpp +++ b/Engine/source/console/console.cpp @@ -1187,10 +1187,10 @@ ConsoleValue _internalExecute(S32 argc, ConsoleValue argv[]) warnf(ConsoleLogEntry::Script, "%s: Unknown command.", funcName); STR.clearFunctionOffset(); - return std::move(ConsoleValue()); + return (ConsoleValue()); } - return std::move(ent->execute(argc, argv, NULL)); + return (ent->execute(argc, argv, NULL)); } ConsoleValue execute(S32 argc, ConsoleValue argv[]) @@ -1220,7 +1220,7 @@ ConsoleValue execute(S32 argc, const char *argv[]) ConsoleStackFrameSaver stackSaver; stackSaver.save(); StringArrayToConsoleValueWrapper args(argc, argv); - return std::move(execute(args.count(), args)); + return (execute(args.count(), args)); } //------------------------------------------------------------------------------ @@ -1229,12 +1229,12 @@ ConsoleValue execute(S32 argc, const char *argv[]) static ConsoleValue _internalExecute(SimObject *object, S32 argc, ConsoleValue argv[], bool thisCallOnly) { if (object == NULL) - return std::move(ConsoleValue()); + return (ConsoleValue()); if(argc < 2) { STR.clearFunctionOffset(); - return std::move(ConsoleValue()); + return (ConsoleValue()); } // [neo, 10/05/2007 - #3010] @@ -1262,7 +1262,7 @@ static ConsoleValue _internalExecute(SimObject *object, S32 argc, ConsoleValue a { //warnf(ConsoleLogEntry::Script, "%s: undefined for object '%s' - id %d", funcName, object->getName(), object->getId()); STR.clearFunctionOffset(); - return std::move(ConsoleValue()); + return (ConsoleValue()); } const char* oldIdent = dStrdup(argv[1].getString()); @@ -1270,7 +1270,7 @@ static ConsoleValue _internalExecute(SimObject *object, S32 argc, ConsoleValue a // Twiddle %this argument argv[1].setInt(ident); - ConsoleValue ret = std::move(ent->execute(argc, argv, object)); + ConsoleValue ret = (ent->execute(argc, argv, object)); // Twiddle it back argv[1].setString(oldIdent); @@ -1281,7 +1281,7 @@ static ConsoleValue _internalExecute(SimObject *object, S32 argc, ConsoleValue a warnf(ConsoleLogEntry::Script, "Con::execute - %d has no namespace: %s", object->getId(), funcName); STR.clearFunctionOffset(); - return std::move(ConsoleValue()); + return (ConsoleValue()); } ConsoleValue execute(SimObject *object, S32 argc, ConsoleValue argv[], bool thisCallOnly) @@ -1289,7 +1289,7 @@ ConsoleValue execute(SimObject *object, S32 argc, ConsoleValue argv[], bool this if(argc < 2) { STR.clearFunctionOffset(); - return std::move(ConsoleValue()); + return (ConsoleValue()); } ConsoleStackFrameSaver stackSaver; @@ -1299,7 +1299,7 @@ ConsoleValue execute(SimObject *object, S32 argc, ConsoleValue argv[], bool this { if (isMainThread()) { - return std::move(_internalExecute(object, argc, argv, thisCallOnly)); + return (_internalExecute(object, argc, argv, thisCallOnly)); } else { @@ -1311,7 +1311,7 @@ ConsoleValue execute(SimObject *object, S32 argc, ConsoleValue argv[], bool this warnf(ConsoleLogEntry::Script, "Con::execute - %d has no namespace: %s", object->getId(), argv[0].getString()); STR.clearFunctionOffset(); - return std::move(ConsoleValue()); + return (ConsoleValue()); } ConsoleValue execute(SimObject *object, S32 argc, const char *argv[], bool thisCallOnly) @@ -1319,7 +1319,7 @@ ConsoleValue execute(SimObject *object, S32 argc, const char *argv[], bool thisC ConsoleStackFrameSaver stackSaver; stackSaver.save(); StringArrayToConsoleValueWrapper args(argc, argv); - return std::move(execute(object, args.count(), args, thisCallOnly)); + return (execute(object, args.count(), args, thisCallOnly)); } inline ConsoleValue _executef(SimObject *obj, S32 checkArgc, S32 argc, ConsoleValue *argv) @@ -1327,7 +1327,7 @@ inline ConsoleValue _executef(SimObject *obj, S32 checkArgc, S32 argc, ConsoleVa const U32 maxArg = 12; AssertFatal(checkArgc == argc, "Incorrect arg count passed to Con::executef(SimObject*)"); AssertFatal(argc <= maxArg - 1, "Too many args passed to Con::_executef(SimObject*). Please update the function to handle more."); - return std::move(execute(obj, argc, argv)); + return (execute(obj, argc, argv)); } //------------------------------------------------------------------------------ @@ -1336,7 +1336,7 @@ inline ConsoleValue _executef(S32 checkArgc, S32 argc, ConsoleValue *argv) const U32 maxArg = 10; AssertFatal(checkArgc == argc, "Incorrect arg count passed to Con::executef()"); AssertFatal(argc <= maxArg, "Too many args passed to Con::_executef(). Please update the function to handle more."); - return std::move(execute(argc, argv)); + return (execute(argc, argv)); } //------------------------------------------------------------------------------ @@ -2312,10 +2312,10 @@ ConsoleValue _BaseEngineConsoleCallbackHelper::_exec() STR.clearFunctionOffset(); mArgc = mInitialArgc; // reset - return std::move(ConsoleValue()); + return (ConsoleValue()); } - ConsoleValue returnValue = std::move(Con::_internalExecute( mArgc, mArgv )); + ConsoleValue returnValue = (Con::_internalExecute( mArgc, mArgv )); mArgc = mInitialArgc; // reset args return returnValue; } @@ -2324,7 +2324,7 @@ ConsoleValue _BaseEngineConsoleCallbackHelper::_execLater(SimConsoleThreadExecEv { mArgc = mInitialArgc; // reset args Sim::postEvent((SimObject*)Sim::getRootGroup(), evt, Sim::getCurrentTime()); - return std::move(evt->getCB().waitForResult()); + return (evt->getCB().waitForResult()); } //------------------------------------------------------------------------------ diff --git a/Engine/source/console/consoleInternal.cpp b/Engine/source/console/consoleInternal.cpp index aff6f433d..f0f17b604 100644 --- a/Engine/source/console/consoleInternal.cpp +++ b/Engine/source/console/consoleInternal.cpp @@ -1163,7 +1163,7 @@ ConsoleValue Namespace::Entry::execute(S32 argc, ConsoleValue *argv, SimObject * } else { - return std::move(ConsoleValue()); + return (ConsoleValue()); } } @@ -1181,7 +1181,7 @@ ConsoleValue Namespace::Entry::execute(S32 argc, ConsoleValue *argv, SimObject * { Con::warnf(ConsoleLogEntry::Script, "%s::%s - wrong number of arguments. got %d, expected %d to %d", mNamespace->mName, mFunctionName, argc, mMinArgs, mMaxArgs); Con::warnf(ConsoleLogEntry::Script, "usage: %s", mUsage); - return std::move(ConsoleValue()); + return (ConsoleValue()); } ConsoleValue result; diff --git a/Engine/source/console/runtime.h b/Engine/source/console/runtime.h index d10df543c..03d94ea85 100644 --- a/Engine/source/console/runtime.h +++ b/Engine/source/console/runtime.h @@ -17,7 +17,7 @@ namespace Con EvalResult(ConsoleValue&& pValue) { valid = true; - value = (ConsoleValue&&)pValue; + value = std::move(pValue); } EvalResult(String errorMessage) diff --git a/Engine/source/console/simEvents.cpp b/Engine/source/console/simEvents.cpp index c27728580..b02e6fa0d 100644 --- a/Engine/source/console/simEvents.cpp +++ b/Engine/source/console/simEvents.cpp @@ -134,9 +134,9 @@ void SimConsoleThreadExecEvent::process(SimObject* object) if (cb) { if (mOnObject) - cb->handleCallback(std::move(Con::execute(object, mArgc, mArgv))); + cb->handleCallback(Con::execute(object, mArgc, mArgv)); else - cb->handleCallback(std::move(Con::execute(mArgc, mArgv))); + cb->handleCallback(Con::execute(mArgc, mArgv)); } else { diff --git a/Engine/source/console/torquescript/codeBlock.cpp b/Engine/source/console/torquescript/codeBlock.cpp index f7534cc54..5a4bdb30a 100644 --- a/Engine/source/console/torquescript/codeBlock.cpp +++ b/Engine/source/console/torquescript/codeBlock.cpp @@ -668,7 +668,7 @@ Con::EvalResult CodeBlock::compileExec(StringTableEntry fileName, const char *in Con::warnf(ConsoleLogEntry::General, "precompile size mismatch, precompile: %d compile: %d", codeSize, lastIp); // repurpose argc as local register counter for global state - return std::move(exec(0, fileName, NULL, localRegisterCount, 0, noCalls, NULL, setFrame)); + return (exec(0, fileName, NULL, localRegisterCount, 0, noCalls, NULL, setFrame)); } //------------------------------------------------------------------------- diff --git a/Engine/source/console/torquescript/runtime.cpp b/Engine/source/console/torquescript/runtime.cpp index be2d4af91..ddb063699 100644 --- a/Engine/source/console/torquescript/runtime.cpp +++ b/Engine/source/console/torquescript/runtime.cpp @@ -39,7 +39,7 @@ namespace TorqueScript fileName = StringTable->insert(fileName); CodeBlock* newCodeBlock = new CodeBlock(); - return std::move(newCodeBlock->compileExec(fileName, string, false, fileName ? -1 : 0)); + return (newCodeBlock->compileExec(fileName, string, false, fileName ? -1 : 0)); } Con::EvalResult TorqueScriptRuntime::evaluate(const char* script, S32 frame, bool echo, const char* fileName) From ea39c83afdf15437a2531dddfd752b95ab966a43 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 8 May 2025 13:35:55 +0100 Subject: [PATCH 12/41] Update console.h might not fix the leak we were having around callbacks, but it really slows down the upcreep of memory --- Engine/source/console/console.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index b3163e5c5..ef83ed397 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -152,7 +152,7 @@ class ConsoleValue TORQUE_FORCEINLINE bool hasAllocatedData() const { - return (type == ConsoleValueType::cvString || isConsoleType()) && data != NULL; + return (type == ConsoleValueType::cvString || isConsoleType()) && data != NULL; } const char* getConsoleData() const; @@ -182,14 +182,16 @@ class ConsoleValue TORQUE_CASE_FALLTHROUGH; case cvString: s = ref.s; + ref.s = const_cast(StringTable->EmptyString()); break; default: data = ref.data; + break; } - + ref.type = ConsoleValueType::cvSTEntry; ref.data = NULL; - ref.setEmptyString(); + //ref.reset(); } public: @@ -305,9 +307,7 @@ public: } cleanupData(); - type = ConsoleValueType::cvString; - s = (char*)dMalloc(static_cast(len) + 1); s[len] = '\0'; dStrcpy(s, val, static_cast(len) + 1); From ee0cf872a0204e235fdb1494aeccddee8213d77b Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 8 May 2025 20:40:17 +0100 Subject: [PATCH 13/41] moar leak plug attempts --- Engine/source/console/console.h | 101 +++++++++++++++++- Engine/source/console/consoleInternal.cpp | 4 +- Engine/source/console/consoleInternal.h | 2 +- Engine/source/console/consoleObject.cpp | 6 ++ Engine/source/console/simEvents.cpp | 2 +- .../source/console/torquescript/evalState.h | 4 +- 6 files changed, 108 insertions(+), 11 deletions(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index ef83ed397..1b5b47fb0 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -203,17 +203,108 @@ public: ConsoleValue(ConsoleValue&& ref) noexcept { - _move(std::move(ref)); + type = ref.type; + + switch (ref.type) + { + case cvInteger: + i = ref.i; + break; + case cvFloat: + f = ref.f; + break; + case cvSTEntry: + TORQUE_CASE_FALLTHROUGH; + case cvString: + s = ref.s; + ref.s = const_cast(StringTable->EmptyString()); + break; + default: + data = ref.data; + + break; + } + ref.type = ConsoleValueType::cvSTEntry; + ref.data = NULL; } TORQUE_FORCEINLINE ConsoleValue& operator=(ConsoleValue&& ref) noexcept { - _move(std::move(ref)); + type = ref.type; + + switch (ref.type) + { + case cvInteger: + i = ref.i; + break; + case cvFloat: + f = ref.f; + break; + case cvSTEntry: + TORQUE_CASE_FALLTHROUGH; + case cvString: + s = ref.s; + ref.s = const_cast(StringTable->EmptyString()); + break; + default: + data = ref.data; + + break; + } + ref.type = ConsoleValueType::cvSTEntry; + ref.data = NULL; return *this; } - ConsoleValue(const ConsoleValue&) = delete; - ConsoleValue& operator=(const ConsoleValue&) = delete; + ConsoleValue(const ConsoleValue& ref) + { + type = ref.type; + + switch (ref.type) + { + case cvInteger: + i = ref.i; + break; + case cvFloat: + f = ref.f; + break; + case cvSTEntry: + TORQUE_CASE_FALLTHROUGH; + case cvString: + s = ref.s; + break; + default: + data = ref.data; + + break; + } + } + + ConsoleValue& operator=(const ConsoleValue& ref) + { + type = ref.type; + + switch (ref.type) + { + case cvInteger: + i = ref.i; + break; + case cvFloat: + f = ref.f; + break; + case cvSTEntry: + TORQUE_CASE_FALLTHROUGH; + case cvString: + s = ref.s; + break; + default: + data = ref.data; + + break; + } + + return *this; + } TORQUE_FORCEINLINE ~ConsoleValue() { @@ -1022,7 +1113,7 @@ namespace Con ConsoleValue executef(R r, ArgTs ...argTs) { _EngineConsoleExecCallbackHelper callback(r); - return std::move(callback.template call(argTs...)); + return (callback.template call(argTs...)); } /// } }; diff --git a/Engine/source/console/consoleInternal.cpp b/Engine/source/console/consoleInternal.cpp index f0f17b604..454af91ec 100644 --- a/Engine/source/console/consoleInternal.cpp +++ b/Engine/source/console/consoleInternal.cpp @@ -1159,7 +1159,7 @@ ConsoleValue Namespace::Entry::execute(S32 argc, ConsoleValue *argv, SimObject * { if (mFunctionOffset) { - return std::move(mModule->exec(mFunctionOffset, argv[0].getString(), mNamespace, argc, argv, false, mPackage).value); + return (mModule->exec(mFunctionOffset, argv[0].getString(), mNamespace, argc, argv, false, mPackage).value); } else { @@ -1173,7 +1173,7 @@ ConsoleValue Namespace::Entry::execute(S32 argc, ConsoleValue *argv, SimObject * if (mToolOnly && !Con::isCurrentScriptToolScript()) { Con::errorf(ConsoleLogEntry::Script, "%s::%s - attempting to call tools only function from outside of tools", mNamespace->mName, mFunctionName); - return std::move(ConsoleValue()); + return (ConsoleValue()); } #endif diff --git a/Engine/source/console/consoleInternal.h b/Engine/source/console/consoleInternal.h index 6c0c91828..9a32dbe7c 100644 --- a/Engine/source/console/consoleInternal.h +++ b/Engine/source/console/consoleInternal.h @@ -321,7 +321,7 @@ public: void reset(); - inline ConsoleValue getValue() { return std::move(value); } + inline ConsoleValue getValue() { return (value); } inline U32 getIntValue() { diff --git a/Engine/source/console/consoleObject.cpp b/Engine/source/console/consoleObject.cpp index 9156c1da7..eed85cbfa 100644 --- a/Engine/source/console/consoleObject.cpp +++ b/Engine/source/console/consoleObject.cpp @@ -286,6 +286,12 @@ void AbstractClassRep::shutdown() // Release storage allocated to the class table. + for (auto walk = classLinkList; walk; walk = walk->nextClass) + { + walk->mFieldList.clear(); + walk->mFieldList.compact(); // Important: frees the internal buffer + } + for (U32 group = 0; group < NetClassGroupsCount; group++) for(U32 type = 0; type < NetClassTypesCount; type++) if( classTable[ group ][ type ] ) diff --git a/Engine/source/console/simEvents.cpp b/Engine/source/console/simEvents.cpp index b02e6fa0d..47924082e 100644 --- a/Engine/source/console/simEvents.cpp +++ b/Engine/source/console/simEvents.cpp @@ -116,7 +116,7 @@ ConsoleValue SimConsoleThreadExecCallback::waitForResult() { if(sem->acquire(true)) { - return std::move(retVal); + return (retVal); } return ConsoleValue(); diff --git a/Engine/source/console/torquescript/evalState.h b/Engine/source/console/torquescript/evalState.h index cd0d34a13..599af113e 100644 --- a/Engine/source/console/torquescript/evalState.h +++ b/Engine/source/console/torquescript/evalState.h @@ -1,4 +1,4 @@ -#ifndef _EVALSTATE_H +#ifndef _EVALSTATE_H #define _EVALSTATE_H #include "console/consoleInternal.h" @@ -81,7 +81,7 @@ public: currentRegisterArray->values[reg].setStringTableEntry(val); } - TORQUE_FORCEINLINE void moveConsoleValue(S32 reg, ConsoleValue val) + TORQUE_FORCEINLINE void moveConsoleValue(S32 reg, ConsoleValue&& val) { currentRegisterArray->values[reg] = std::move(val); } From 5fc9da789b260669e59e75f525c03dc9d0ac2d9c Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Fri, 9 May 2025 07:57:13 +0100 Subject: [PATCH 14/41] changes from az leak damn near fixed with these changes --- Engine/source/console/console.h | 122 +++++++++++++++++--------------- 1 file changed, 66 insertions(+), 56 deletions(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index 1b5b47fb0..d15cd801c 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -37,6 +37,7 @@ #include "core/util/str.h" #include "core/util/journal/journaledSignal.h" #include "core/stringTable.h" +#include class SimObject; class Namespace; @@ -119,6 +120,7 @@ typedef const char *StringTableEntry; enum ConsoleValueType { + cvNULL = -5, cvInteger = -4, cvFloat = -3, cvString = -2, @@ -152,7 +154,7 @@ class ConsoleValue TORQUE_FORCEINLINE bool hasAllocatedData() const { - return (type == ConsoleValueType::cvString || isConsoleType()) && data != NULL; + return (isConsoleType() && data != NULL); } const char* getConsoleData() const; @@ -164,34 +166,40 @@ class ConsoleValue dFree(data); data = NULL; } + else if (type == ConsoleValueType::cvString) + { + if (s && s[0]) + dFree(s); + } + type = ConsoleValueType::cvNULL; } TORQUE_FORCEINLINE void _move(ConsoleValue&& ref) noexcept { - type = ref.type; - + if (ref.type == ConsoleValueType::cvNULL) + { + std::cout << "Cannot Move a variable twice!"; + return; + } switch (ref.type) { case cvInteger: - i = ref.i; + setInt(ref.i); break; case cvFloat: - f = ref.f; + setFloat(ref.f); break; case cvSTEntry: - TORQUE_CASE_FALLTHROUGH; + setStringTableEntry(ref.s); + break; case cvString: - s = ref.s; - ref.s = const_cast(StringTable->EmptyString()); + setString(ref.s); break; default: - data = ref.data; - + setConsoleData(ref.ct->consoleType, ref.ct->dataPtr, ref.ct->enumTable); break; } - ref.type = ConsoleValueType::cvSTEntry; - ref.data = NULL; - //ref.reset(); + ref.cleanupData(); } public: @@ -203,106 +211,109 @@ public: ConsoleValue(ConsoleValue&& ref) noexcept { - type = ref.type; - + if (ref.type == ConsoleValueType::cvNULL) + { + std::cout << "Cannot Move a variable twice!"; + return; + } switch (ref.type) { case cvInteger: - i = ref.i; + setInt(ref.i); break; case cvFloat: - f = ref.f; + setFloat(ref.f); break; case cvSTEntry: - TORQUE_CASE_FALLTHROUGH; + setStringTableEntry(ref.s); + break; case cvString: - s = ref.s; - ref.s = const_cast(StringTable->EmptyString()); + setString(ref.s); break; default: - data = ref.data; - + setConsoleData(ref.ct->consoleType, ref.ct->dataPtr, ref.ct->enumTable); break; } - ref.type = ConsoleValueType::cvSTEntry; - ref.data = NULL; + ref.cleanupData(); } TORQUE_FORCEINLINE ConsoleValue& operator=(ConsoleValue&& ref) noexcept { - type = ref.type; - + if (ref.type == ConsoleValueType::cvNULL) + { + std::cout << "Cannot Move a variable twice!"; + return *this; + } switch (ref.type) { case cvInteger: - i = ref.i; + setInt(ref.i); break; case cvFloat: - f = ref.f; + setFloat(ref.f); break; case cvSTEntry: - TORQUE_CASE_FALLTHROUGH; + setStringTableEntry(ref.s); + break; case cvString: - s = ref.s; - ref.s = const_cast(StringTable->EmptyString()); + setString(ref.s); break; default: - data = ref.data; - + setConsoleData(ref.ct->consoleType, ref.ct->dataPtr, ref.ct->enumTable); break; } - ref.type = ConsoleValueType::cvSTEntry; - ref.data = NULL; + ref.cleanupData(); return *this; } ConsoleValue(const ConsoleValue& ref) { - type = ref.type; - switch (ref.type) { + case cvNULL: + std::cout << "Ref already cleared!"; + break; case cvInteger: - i = ref.i; + setInt(ref.i); break; case cvFloat: - f = ref.f; + setFloat(ref.f); break; case cvSTEntry: - TORQUE_CASE_FALLTHROUGH; + setStringTableEntry(ref.s); + break; case cvString: - s = ref.s; + setString(ref.s); break; default: - data = ref.data; - + setConsoleData(ref.ct->consoleType, ref.ct->dataPtr, ref.ct->enumTable); break; } } ConsoleValue& operator=(const ConsoleValue& ref) { - type = ref.type; - switch (ref.type) { + case cvNULL: + std::cout << "Ref already cleared!"; + break; case cvInteger: - i = ref.i; + setInt(ref.i); break; case cvFloat: - f = ref.f; + setFloat(ref.f); break; case cvSTEntry: - TORQUE_CASE_FALLTHROUGH; + setStringTableEntry(ref.s); + break; case cvString: - s = ref.s; + setString(ref.s); break; default: - data = ref.data; - + setConsoleData(ref.ct->consoleType, ref.ct->dataPtr, ref.ct->enumTable); break; } - return *this; } @@ -396,12 +407,11 @@ public: setEmptyString(); return; } - cleanupData(); type = ConsoleValueType::cvString; - s = (char*)dMalloc(static_cast(len) + 1); + s = (char*)dMalloc(len + 1); s[len] = '\0'; - dStrcpy(s, val, static_cast(len) + 1); + dStrcpy(s, val, len + 1); } TORQUE_FORCEINLINE void setStringRef(const char* ref, S32 len) @@ -420,7 +430,7 @@ public: TORQUE_FORCEINLINE void setStringTableEntry(StringTableEntry val) { - cleanupData(); + //cleanupData(); type = ConsoleValueType::cvSTEntry; s = const_cast(val); } From 8176145aaa974d50938cf95d432f8f2627661949 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Fri, 9 May 2025 08:47:34 +0100 Subject: [PATCH 15/41] remove more std::move std::move needs to be used with pointers, we werent doing that and so a temp var was being copied onto the heap when it should of stayed on the stack. This caused memory leaks --- Engine/source/console/console.h | 28 ------------------- Engine/source/console/consoleValueStack.h | 4 +-- Engine/source/console/runtime.h | 4 +-- Engine/source/console/script.h | 2 +- .../console/torquescript/compiledEval.cpp | 10 +++---- .../source/console/torquescript/evalState.h | 4 +-- 6 files changed, 12 insertions(+), 40 deletions(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index d15cd801c..c00da4351 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -174,34 +174,6 @@ class ConsoleValue type = ConsoleValueType::cvNULL; } - TORQUE_FORCEINLINE void _move(ConsoleValue&& ref) noexcept - { - if (ref.type == ConsoleValueType::cvNULL) - { - std::cout << "Cannot Move a variable twice!"; - return; - } - switch (ref.type) - { - case cvInteger: - setInt(ref.i); - break; - case cvFloat: - setFloat(ref.f); - break; - case cvSTEntry: - setStringTableEntry(ref.s); - break; - case cvString: - setString(ref.s); - break; - default: - setConsoleData(ref.ct->consoleType, ref.ct->dataPtr, ref.ct->enumTable); - break; - } - ref.cleanupData(); - } - public: ConsoleValue() { diff --git a/Engine/source/console/consoleValueStack.h b/Engine/source/console/consoleValueStack.h index 8b44a652c..529f5f1a9 100644 --- a/Engine/source/console/consoleValueStack.h +++ b/Engine/source/console/consoleValueStack.h @@ -89,10 +89,10 @@ public: stack.pop_back(); } - TORQUE_FORCEINLINE void push(ConsoleValue&& val) + TORQUE_FORCEINLINE void push(ConsoleValue val) { Frame& frame = stack.last(); - frame.values[frame.internalCounter++] = std::move(val); + frame.values[frame.internalCounter++] = (val); } TORQUE_FORCEINLINE void argvc(StringTableEntry fn, S32& argc, ConsoleValue** argv) diff --git a/Engine/source/console/runtime.h b/Engine/source/console/runtime.h index 03d94ea85..cb2a32805 100644 --- a/Engine/source/console/runtime.h +++ b/Engine/source/console/runtime.h @@ -14,10 +14,10 @@ namespace Con public: EvalResult() {} - EvalResult(ConsoleValue&& pValue) + EvalResult(ConsoleValue pValue) { valid = true; - value = std::move(pValue); + value = (pValue); } EvalResult(String errorMessage) diff --git a/Engine/source/console/script.h b/Engine/source/console/script.h index 55653bff2..d6dca7c24 100644 --- a/Engine/source/console/script.h +++ b/Engine/source/console/script.h @@ -16,7 +16,7 @@ namespace Con gLastEvalResult.value.setString(pLastEvalResult.value.getString()); return pLastEvalResult; } - inline EvalResult getLastEvalResult() { return setLastEvalResult(std::move(gLastEvalResult)); }; + inline EvalResult getLastEvalResult() { return setLastEvalResult((gLastEvalResult)); }; bool runStream(Stream* byteCode, const char* fileName); diff --git a/Engine/source/console/torquescript/compiledEval.cpp b/Engine/source/console/torquescript/compiledEval.cpp index 94ddcab80..b9ada8750 100644 --- a/Engine/source/console/torquescript/compiledEval.cpp +++ b/Engine/source/console/torquescript/compiledEval.cpp @@ -612,7 +612,7 @@ Con::EvalResult CodeBlock::exec(U32 ip, const char* functionName, Namespace* thi { S32 reg = code[ip + (2 + 6 + 1 + 1) + i]; ConsoleValue& value = argv[i + 1]; - Script::gEvalState.moveConsoleValue(reg, std::move(value)); + Script::gEvalState.moveConsoleValue(reg, (value)); } ip = ip + fnArgc + (2 + 6 + 1 + 1); curFloatTable = functionFloats; @@ -1214,7 +1214,7 @@ Con::EvalResult CodeBlock::exec(U32 ip, const char* functionName, Namespace* thi case OP_RETURN: { - returnValue = std::move(stack[_STK]); + returnValue = (stack[_STK]); _STK--; // Clear iterator state. @@ -1905,7 +1905,7 @@ Con::EvalResult CodeBlock::exec(U32 ip, const char* functionName, Namespace* thi if (nsEntry->mFunctionOffset) { ConsoleValue returnFromFn = nsEntry->mModule->exec(nsEntry->mFunctionOffset, fnName, nsEntry->mNamespace, callArgc, callArgv, false, nsEntry->mPackage).value; - stack[_STK + 1] = std::move(returnFromFn); + stack[_STK + 1] = (returnFromFn); } else // no body stack[_STK + 1].setEmptyString(); @@ -2040,7 +2040,7 @@ Con::EvalResult CodeBlock::exec(U32 ip, const char* functionName, Namespace* thi break; case OP_PUSH: - gCallStack.push(std::move(stack[_STK--])); + gCallStack.push((stack[_STK--])); break; case OP_PUSH_FRAME: @@ -2303,7 +2303,7 @@ execFinished: AssertFatal(!(_STK < stackStart), "String stack popped too much in script exec"); #endif - return Con::EvalResult(std::move(returnValue)); + return Con::EvalResult((returnValue)); } //------------------------------------------------------------ diff --git a/Engine/source/console/torquescript/evalState.h b/Engine/source/console/torquescript/evalState.h index 599af113e..05c3be335 100644 --- a/Engine/source/console/torquescript/evalState.h +++ b/Engine/source/console/torquescript/evalState.h @@ -81,9 +81,9 @@ public: currentRegisterArray->values[reg].setStringTableEntry(val); } - TORQUE_FORCEINLINE void moveConsoleValue(S32 reg, ConsoleValue&& val) + TORQUE_FORCEINLINE void moveConsoleValue(S32 reg, ConsoleValue val) { - currentRegisterArray->values[reg] = std::move(val); + currentRegisterArray->values[reg] = (val); } void pushFrame(StringTableEntry frameName, Namespace *ns, S32 regCount); From dc16c50e4e23de24e51f28570a5f184d06a79a1e Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Fri, 9 May 2025 09:57:30 +0100 Subject: [PATCH 16/41] Update console.h --- Engine/source/console/console.h | 59 +-------------------------------- 1 file changed, 1 insertion(+), 58 deletions(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index c00da4351..3612bb0bf 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -168,7 +168,7 @@ class ConsoleValue } else if (type == ConsoleValueType::cvString) { - if (s && s[0]) + if (s != StringTable->EmptyString()) dFree(s); } type = ConsoleValueType::cvNULL; @@ -181,63 +181,6 @@ public: s = const_cast(StringTable->EmptyString()); } - ConsoleValue(ConsoleValue&& ref) noexcept - { - if (ref.type == ConsoleValueType::cvNULL) - { - std::cout << "Cannot Move a variable twice!"; - return; - } - switch (ref.type) - { - case cvInteger: - setInt(ref.i); - break; - case cvFloat: - setFloat(ref.f); - break; - case cvSTEntry: - setStringTableEntry(ref.s); - break; - case cvString: - setString(ref.s); - break; - default: - setConsoleData(ref.ct->consoleType, ref.ct->dataPtr, ref.ct->enumTable); - break; - } - ref.cleanupData(); - } - - TORQUE_FORCEINLINE ConsoleValue& operator=(ConsoleValue&& ref) noexcept - { - if (ref.type == ConsoleValueType::cvNULL) - { - std::cout << "Cannot Move a variable twice!"; - return *this; - } - switch (ref.type) - { - case cvInteger: - setInt(ref.i); - break; - case cvFloat: - setFloat(ref.f); - break; - case cvSTEntry: - setStringTableEntry(ref.s); - break; - case cvString: - setString(ref.s); - break; - default: - setConsoleData(ref.ct->consoleType, ref.ct->dataPtr, ref.ct->enumTable); - break; - } - ref.cleanupData(); - return *this; - } - ConsoleValue(const ConsoleValue& ref) { switch (ref.type) From 338eaea78607c7f79cc37f89d552a0a2ed2618c5 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Fri, 9 May 2025 17:06:33 +0100 Subject: [PATCH 17/41] Update console.h az: stringtable insert for stentry --- Engine/source/console/console.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index 3612bb0bf..e5ba8ffe7 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -347,7 +347,7 @@ public: { //cleanupData(); type = ConsoleValueType::cvSTEntry; - s = const_cast(val); + s = const_cast(StringTable->insert(val)); } TORQUE_FORCEINLINE void setEmptyString() From 0690ad912af00421239004b92e761d2a9d93b496 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 10 May 2025 10:12:39 +0100 Subject: [PATCH 18/41] Update ScriptTest.cpp --- Engine/source/testing/ScriptTest.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Engine/source/testing/ScriptTest.cpp b/Engine/source/testing/ScriptTest.cpp index d13d2b6f2..983ac1d0a 100644 --- a/Engine/source/testing/ScriptTest.cpp +++ b/Engine/source/testing/ScriptTest.cpp @@ -32,7 +32,8 @@ inline ConsoleValue RunScript(const char* str) { - return std::move(Con::evaluate(str, false, NULL).value); + auto result = Con::evaluate(str, false, NULL); + return result.value; // ensure lifetime is safe } using ::testing::Matcher; From 0ba8d6102d3c39d49b20028bc9c85de480f34720 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 10 May 2025 13:50:31 +0100 Subject: [PATCH 19/41] Update torqueConfig.h.in --- Tools/CMake/torqueConfig.h.in | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Tools/CMake/torqueConfig.h.in b/Tools/CMake/torqueConfig.h.in index a0bbc70a8..dde50431b 100644 --- a/Tools/CMake/torqueConfig.h.in +++ b/Tools/CMake/torqueConfig.h.in @@ -53,9 +53,12 @@ /// Define me if you want to enable multithreading support. #cmakedefine TORQUE_MULTITHREAD +#cmakedefine TORQUE_DISABLE_MEMORY_MANAGER /// Define me if you want to disable Torque memory manager. #ifndef TORQUE_ENABLE_ASSERTS -#cmakedefine TORQUE_DISABLE_MEMORY_MANAGER +#ifdef TORQUE_DISABLE_MEMORY_MANAGER +#undef TORQUE_DISABLE_MEMORY_MANAGER +#endif #endif /// Define me if you want to disable the virtual mount system. From a993b728810d5e26ce52d7660204e23883de70b2 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 10 May 2025 14:12:41 +0100 Subject: [PATCH 20/41] Update torqueConfig.h.in --- Tools/CMake/torqueConfig.h.in | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Tools/CMake/torqueConfig.h.in b/Tools/CMake/torqueConfig.h.in index dde50431b..717c05eb1 100644 --- a/Tools/CMake/torqueConfig.h.in +++ b/Tools/CMake/torqueConfig.h.in @@ -53,13 +53,8 @@ /// Define me if you want to enable multithreading support. #cmakedefine TORQUE_MULTITHREAD -#cmakedefine TORQUE_DISABLE_MEMORY_MANAGER /// Define me if you want to disable Torque memory manager. -#ifndef TORQUE_ENABLE_ASSERTS -#ifdef TORQUE_DISABLE_MEMORY_MANAGER -#undef TORQUE_DISABLE_MEMORY_MANAGER -#endif -#endif +#cmakedefine TORQUE_DISABLE_MEMORY_MANAGER /// Define me if you want to disable the virtual mount system. #cmakedefine TORQUE_DISABLE_VIRTUAL_MOUNT_SYSTEM From 656a8ac0bd78f8e54a4a5cf2394e5e05aa8ed7c4 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 10 May 2025 14:46:49 +0100 Subject: [PATCH 21/41] Update console.h --- Engine/source/console/console.h | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index e5ba8ffe7..e2a014024 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -161,16 +161,29 @@ class ConsoleValue TORQUE_FORCEINLINE void cleanupData() { - if (hasAllocatedData()) + switch (type) + { + case ConsoleValueType::cvConsoleValueType: + if (ct) + { + delete ct; + ct = nullptr; + } + break; + case ConsoleValueType::cvString: + if (s && s != StringTable->EmptyString()) + dFree(s); + break; + default: + break; + } + + if (data != NULL) { dFree(data); data = NULL; } - else if (type == ConsoleValueType::cvString) - { - if (s != StringTable->EmptyString()) - dFree(s); - } + type = ConsoleValueType::cvNULL; } From cb7dab4052877a3879fc114955aaff72b622bf47 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 10 May 2025 19:37:09 +0100 Subject: [PATCH 22/41] Update console.h --- Engine/source/console/console.h | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index e2a014024..6a1dc7942 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -154,37 +154,18 @@ class ConsoleValue TORQUE_FORCEINLINE bool hasAllocatedData() const { - return (isConsoleType() && data != NULL); + return (type == ConsoleValueType::cvString || isConsoleType()) && data != NULL; } const char* getConsoleData() const; TORQUE_FORCEINLINE void cleanupData() { - switch (type) - { - case ConsoleValueType::cvConsoleValueType: - if (ct) - { - delete ct; - ct = nullptr; - } - break; - case ConsoleValueType::cvString: - if (s && s != StringTable->EmptyString()) - dFree(s); - break; - default: - break; - } - - if (data != NULL) + if (hasAllocatedData()) { dFree(data); data = NULL; } - - type = ConsoleValueType::cvNULL; } public: From 5cc2abc9ae4f87c2a2d15e5842d9244dbfb311fe Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 10 May 2025 21:59:05 +0100 Subject: [PATCH 23/41] update revert console.h to best working version wrap includes around the TORQUE_DISABLE_MEMORY_MANAGER macro in torqueConfig.h.in add check for whether we are in release and make sure TORQUE_DISABLE_MEMORY_MANAGER is defined. --- Engine/source/console/console.h | 8 +++++++- Engine/source/platform/platformMemory.cpp | 14 +++++++++----- Tools/CMake/torqueConfig.h.in | 4 ++++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index 6a1dc7942..e5ba8ffe7 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -154,7 +154,7 @@ class ConsoleValue TORQUE_FORCEINLINE bool hasAllocatedData() const { - return (type == ConsoleValueType::cvString || isConsoleType()) && data != NULL; + return (isConsoleType() && data != NULL); } const char* getConsoleData() const; @@ -166,6 +166,12 @@ class ConsoleValue dFree(data); data = NULL; } + else if (type == ConsoleValueType::cvString) + { + if (s != StringTable->EmptyString()) + dFree(s); + } + type = ConsoleValueType::cvNULL; } public: diff --git a/Engine/source/platform/platformMemory.cpp b/Engine/source/platform/platformMemory.cpp index 14fd4d02f..557482412 100644 --- a/Engine/source/platform/platformMemory.cpp +++ b/Engine/source/platform/platformMemory.cpp @@ -30,6 +30,8 @@ #include "platform/threads/mutex.h" #include "core/module.h" +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) + #ifdef _WIN32 #include #include @@ -40,6 +42,8 @@ #include #include +#endif + // If profile paths are enabled, disable profiling of the // memory manager as that would cause a cyclic dependency // through the string table's allocation stuff used by the @@ -177,11 +181,11 @@ namespace Memory #endif } - //if (report.find("getDocsLink") != std::string::npos) - //{ - // //known issue. one off allocation - // memLog[curRep].skip = true; - //} + if (report.find("getDocsLink") != std::string::npos) + { + //known issue. one off allocation + memLog[curRep].skip = true; + } for (U32 oldRep = start; oldRep < curRep; ++oldRep) { diff --git a/Tools/CMake/torqueConfig.h.in b/Tools/CMake/torqueConfig.h.in index 717c05eb1..b96a7c7d1 100644 --- a/Tools/CMake/torqueConfig.h.in +++ b/Tools/CMake/torqueConfig.h.in @@ -56,6 +56,10 @@ /// Define me if you want to disable Torque memory manager. #cmakedefine TORQUE_DISABLE_MEMORY_MANAGER +#ifdef TORQUE_RELEASE +#define TORQUE_DISABLE_MEMORY_MANAGER +#endif + /// Define me if you want to disable the virtual mount system. #cmakedefine TORQUE_DISABLE_VIRTUAL_MOUNT_SYSTEM From 2b14e5448e5676b7dedcaa0ed1876fe3152d9581 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 11 May 2025 15:53:55 +0100 Subject: [PATCH 24/41] Revert "update" This reverts commit 7ac9c55bf1efa23db674dba4f2c7ada7ca344d7d. --- Engine/source/console/console.h | 8 +------- Engine/source/platform/platformMemory.cpp | 14 +++++--------- Tools/CMake/torqueConfig.h.in | 4 ---- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index e5ba8ffe7..6a1dc7942 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -154,7 +154,7 @@ class ConsoleValue TORQUE_FORCEINLINE bool hasAllocatedData() const { - return (isConsoleType() && data != NULL); + return (type == ConsoleValueType::cvString || isConsoleType()) && data != NULL; } const char* getConsoleData() const; @@ -166,12 +166,6 @@ class ConsoleValue dFree(data); data = NULL; } - else if (type == ConsoleValueType::cvString) - { - if (s != StringTable->EmptyString()) - dFree(s); - } - type = ConsoleValueType::cvNULL; } public: diff --git a/Engine/source/platform/platformMemory.cpp b/Engine/source/platform/platformMemory.cpp index 557482412..14fd4d02f 100644 --- a/Engine/source/platform/platformMemory.cpp +++ b/Engine/source/platform/platformMemory.cpp @@ -30,8 +30,6 @@ #include "platform/threads/mutex.h" #include "core/module.h" -#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) - #ifdef _WIN32 #include #include @@ -42,8 +40,6 @@ #include #include -#endif - // If profile paths are enabled, disable profiling of the // memory manager as that would cause a cyclic dependency // through the string table's allocation stuff used by the @@ -181,11 +177,11 @@ namespace Memory #endif } - if (report.find("getDocsLink") != std::string::npos) - { - //known issue. one off allocation - memLog[curRep].skip = true; - } + //if (report.find("getDocsLink") != std::string::npos) + //{ + // //known issue. one off allocation + // memLog[curRep].skip = true; + //} for (U32 oldRep = start; oldRep < curRep; ++oldRep) { diff --git a/Tools/CMake/torqueConfig.h.in b/Tools/CMake/torqueConfig.h.in index b96a7c7d1..717c05eb1 100644 --- a/Tools/CMake/torqueConfig.h.in +++ b/Tools/CMake/torqueConfig.h.in @@ -56,10 +56,6 @@ /// Define me if you want to disable Torque memory manager. #cmakedefine TORQUE_DISABLE_MEMORY_MANAGER -#ifdef TORQUE_RELEASE -#define TORQUE_DISABLE_MEMORY_MANAGER -#endif - /// Define me if you want to disable the virtual mount system. #cmakedefine TORQUE_DISABLE_VIRTUAL_MOUNT_SYSTEM From 0df6e99a7541a6e8f6850d489528de4ac23172a4 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 11 May 2025 15:53:59 +0100 Subject: [PATCH 25/41] Revert "Update console.h" This reverts commit f10080489995570036e2e5ba762357559a0abd34. --- Engine/source/console/console.h | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index 6a1dc7942..e2a014024 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -154,18 +154,37 @@ class ConsoleValue TORQUE_FORCEINLINE bool hasAllocatedData() const { - return (type == ConsoleValueType::cvString || isConsoleType()) && data != NULL; + return (isConsoleType() && data != NULL); } const char* getConsoleData() const; TORQUE_FORCEINLINE void cleanupData() { - if (hasAllocatedData()) + switch (type) + { + case ConsoleValueType::cvConsoleValueType: + if (ct) + { + delete ct; + ct = nullptr; + } + break; + case ConsoleValueType::cvString: + if (s && s != StringTable->EmptyString()) + dFree(s); + break; + default: + break; + } + + if (data != NULL) { dFree(data); data = NULL; } + + type = ConsoleValueType::cvNULL; } public: From 8fc91bbc1e99ca9fd9e337f9cac7650afeed3c21 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 11 May 2025 15:54:03 +0100 Subject: [PATCH 26/41] Revert "Update console.h" This reverts commit ffac34b2d3eb24ec6a460f2cf77e172543c15772. --- Engine/source/console/console.h | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index e2a014024..e5ba8ffe7 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -161,29 +161,16 @@ class ConsoleValue TORQUE_FORCEINLINE void cleanupData() { - switch (type) - { - case ConsoleValueType::cvConsoleValueType: - if (ct) - { - delete ct; - ct = nullptr; - } - break; - case ConsoleValueType::cvString: - if (s && s != StringTable->EmptyString()) - dFree(s); - break; - default: - break; - } - - if (data != NULL) + if (hasAllocatedData()) { dFree(data); data = NULL; } - + else if (type == ConsoleValueType::cvString) + { + if (s != StringTable->EmptyString()) + dFree(s); + } type = ConsoleValueType::cvNULL; } From 8795a4f3309fe28be797bfbc2cb0bd451e4fb273 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 11 May 2025 15:54:08 +0100 Subject: [PATCH 27/41] Revert "Update torqueConfig.h.in" This reverts commit f624a85ce4c4bb89d9281ddf4f65f5318eab4c01. --- Tools/CMake/torqueConfig.h.in | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Tools/CMake/torqueConfig.h.in b/Tools/CMake/torqueConfig.h.in index 717c05eb1..dde50431b 100644 --- a/Tools/CMake/torqueConfig.h.in +++ b/Tools/CMake/torqueConfig.h.in @@ -53,8 +53,13 @@ /// Define me if you want to enable multithreading support. #cmakedefine TORQUE_MULTITHREAD -/// Define me if you want to disable Torque memory manager. #cmakedefine TORQUE_DISABLE_MEMORY_MANAGER +/// Define me if you want to disable Torque memory manager. +#ifndef TORQUE_ENABLE_ASSERTS +#ifdef TORQUE_DISABLE_MEMORY_MANAGER +#undef TORQUE_DISABLE_MEMORY_MANAGER +#endif +#endif /// Define me if you want to disable the virtual mount system. #cmakedefine TORQUE_DISABLE_VIRTUAL_MOUNT_SYSTEM From f2d4d7103ab59532e73eeeb9f2830e406455578c Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 11 May 2025 15:54:12 +0100 Subject: [PATCH 28/41] Revert "Update torqueConfig.h.in" This reverts commit bf6c8827a1e6863804c32905f20b1df15b74fa1f. --- Tools/CMake/torqueConfig.h.in | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Tools/CMake/torqueConfig.h.in b/Tools/CMake/torqueConfig.h.in index dde50431b..a0bbc70a8 100644 --- a/Tools/CMake/torqueConfig.h.in +++ b/Tools/CMake/torqueConfig.h.in @@ -53,12 +53,9 @@ /// Define me if you want to enable multithreading support. #cmakedefine TORQUE_MULTITHREAD -#cmakedefine TORQUE_DISABLE_MEMORY_MANAGER /// Define me if you want to disable Torque memory manager. #ifndef TORQUE_ENABLE_ASSERTS -#ifdef TORQUE_DISABLE_MEMORY_MANAGER -#undef TORQUE_DISABLE_MEMORY_MANAGER -#endif +#cmakedefine TORQUE_DISABLE_MEMORY_MANAGER #endif /// Define me if you want to disable the virtual mount system. From bdcd60f8afb0d1d3cd994f8c872ec24995f59746 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 11 May 2025 15:54:15 +0100 Subject: [PATCH 29/41] Revert "Update ScriptTest.cpp" This reverts commit 40aa2414ebeb14274aed4d2b77f6847ac0f8b28b. --- Engine/source/testing/ScriptTest.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Engine/source/testing/ScriptTest.cpp b/Engine/source/testing/ScriptTest.cpp index 983ac1d0a..d13d2b6f2 100644 --- a/Engine/source/testing/ScriptTest.cpp +++ b/Engine/source/testing/ScriptTest.cpp @@ -32,8 +32,7 @@ inline ConsoleValue RunScript(const char* str) { - auto result = Con::evaluate(str, false, NULL); - return result.value; // ensure lifetime is safe + return std::move(Con::evaluate(str, false, NULL).value); } using ::testing::Matcher; From 954c3b03db566f9e26b60f7d3bc3a827d6bbb5ee Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 11 May 2025 15:54:20 +0100 Subject: [PATCH 30/41] Revert "Update console.h" This reverts commit 76c17179e695df08466c34bf334c1e819ad59c76. --- Engine/source/console/console.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index e5ba8ffe7..3612bb0bf 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -347,7 +347,7 @@ public: { //cleanupData(); type = ConsoleValueType::cvSTEntry; - s = const_cast(StringTable->insert(val)); + s = const_cast(val); } TORQUE_FORCEINLINE void setEmptyString() From 1ddc7219a5c281a4510cb87658b7027878dfa090 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 11 May 2025 16:29:59 +0100 Subject: [PATCH 31/41] Update console.h --- Engine/source/console/console.h | 34 +++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index 3612bb0bf..ce3c96e14 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -137,13 +137,21 @@ struct ConsoleValueConsoleType class ConsoleValue { +#pragma warning( push ) +#pragma warning( disable : 4201 ) // warning C4201: nonstandard extension used : nameless struct/union union { - F64 f; - S64 i; - char* s; - void* data; - ConsoleValueConsoleType* ct; + struct + { + F64 f; + S64 i; + char* s; + }; + + struct + { + ConsoleValueConsoleType* ct; + }; }; S32 type; @@ -152,21 +160,11 @@ class ConsoleValue char* convertToBuffer() const; - TORQUE_FORCEINLINE bool hasAllocatedData() const - { - return (isConsoleType() && data != NULL); - } - const char* getConsoleData() const; TORQUE_FORCEINLINE void cleanupData() { - if (hasAllocatedData()) - { - dFree(data); - data = NULL; - } - else if (type == ConsoleValueType::cvString) + if (type == ConsoleValueType::cvString) { if (s != StringTable->EmptyString()) dFree(s); @@ -323,8 +321,12 @@ public: return; } cleanupData(); + + U32 oldLen = dStrlen(s); + type = ConsoleValueType::cvString; s = (char*)dMalloc(len + 1); + s[len] = '\0'; dStrcpy(s, val, len + 1); } From c6e0eade04333a22d6df48420d831f435bf7c807 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 11 May 2025 22:57:56 +0100 Subject: [PATCH 32/41] az changes --- Engine/source/console/console.cpp | 2 +- Engine/source/console/console.h | 35 ++++++++++--------------- Engine/source/console/consoleInternal.h | 9 +++---- Engine/source/console/engineDoc.cpp | 2 +- 4 files changed, 19 insertions(+), 29 deletions(-) diff --git a/Engine/source/console/console.cpp b/Engine/source/console/console.cpp index fec923819..015ee7540 100644 --- a/Engine/source/console/console.cpp +++ b/Engine/source/console/console.cpp @@ -71,7 +71,7 @@ char* ConsoleValue::convertToBuffer() const const char* ConsoleValue::getConsoleData() const { - return Con::getData(ct->consoleType, ct->dataPtr, 0, ct->enumTable); + return Con::getData(type, dataPtr, 0, enumTable); } ConsoleDocFragment* ConsoleDocFragment::smFirst; diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index ce3c96e14..dcd9d4531 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -128,15 +128,9 @@ enum ConsoleValueType cvConsoleValueType = 0 }; -struct ConsoleValueConsoleType -{ - S32 consoleType; - void* dataPtr; - EnumTable* enumTable; -}; - class ConsoleValue { +public: #pragma warning( push ) #pragma warning( disable : 4201 ) // warning C4201: nonstandard extension used : nameless struct/union union @@ -150,7 +144,8 @@ class ConsoleValue struct { - ConsoleValueConsoleType* ct; + void* dataPtr; + EnumTable* enumTable; }; }; @@ -164,15 +159,14 @@ class ConsoleValue TORQUE_FORCEINLINE void cleanupData() { - if (type == ConsoleValueType::cvString) + if (type == cvString) { if (s != StringTable->EmptyString()) dFree(s); } + type = ConsoleValueType::cvNULL; } - -public: ConsoleValue() { type = ConsoleValueType::cvSTEntry; @@ -199,7 +193,7 @@ public: setString(ref.s); break; default: - setConsoleData(ref.ct->consoleType, ref.ct->dataPtr, ref.ct->enumTable); + setConsoleData(ref.type, ref.dataPtr, ref.enumTable); break; } } @@ -224,7 +218,7 @@ public: setString(ref.s); break; default: - setConsoleData(ref.ct->consoleType, ref.ct->dataPtr, ref.ct->enumTable); + setConsoleData(ref.type, ref.dataPtr, ref.enumTable); break; } return *this; @@ -322,8 +316,6 @@ public: } cleanupData(); - U32 oldLen = dStrlen(s); - type = ConsoleValueType::cvString; s = (char*)dMalloc(len + 1); @@ -357,12 +349,13 @@ public: setStringTableEntry(StringTable->EmptyString()); } - TORQUE_FORCEINLINE void setConsoleData(S32 consoleType, void* dataPtr, const EnumTable* enumTable) + TORQUE_FORCEINLINE void setConsoleData(S32 inConsoleType, void* inDataPtr, const EnumTable* inEnumTable) { cleanupData(); - type = ConsoleValueType::cvConsoleValueType; - ct = new ConsoleValueConsoleType{ consoleType, dataPtr, const_cast(enumTable) }; - } + type = inConsoleType; + dataPtr = inDataPtr; + enumTable = const_cast(inEnumTable); + }; TORQUE_FORCEINLINE S32 getType() const { @@ -384,11 +377,11 @@ public: return type >= ConsoleValueType::cvConsoleValueType; } - TORQUE_FORCEINLINE ConsoleValueConsoleType* getConsoleType() const + TORQUE_FORCEINLINE S32 getConsoleType() const { if(type >= ConsoleValueType::cvConsoleValueType) { - return ct; + return type; } else { diff --git a/Engine/source/console/consoleInternal.h b/Engine/source/console/consoleInternal.h index 9a32dbe7c..beffb2e2c 100644 --- a/Engine/source/console/consoleInternal.h +++ b/Engine/source/console/consoleInternal.h @@ -349,8 +349,7 @@ public: if (value.isConsoleType()) { const char* dptr = Con::getData(TypeS32, &val, 0); - ConsoleValueConsoleType* cvt = value.getConsoleType(); - Con::setData(cvt->consoleType, cvt->dataPtr, 0, 1, &dptr, cvt->enumTable); + Con::setData(value.type, value.dataPtr, 0, 1, &dptr, value.enumTable); } else { @@ -373,8 +372,7 @@ public: if (value.isConsoleType()) { const char* dptr = Con::getData(TypeF32, &val, 0); - ConsoleValueConsoleType* cvt = value.getConsoleType(); - Con::setData(cvt->consoleType, cvt->dataPtr, 0, 1, &dptr, cvt->enumTable); + Con::setData(value.type, value.dataPtr, 0, 1, &dptr, value.enumTable); } else { @@ -397,8 +395,7 @@ public: if (value.isConsoleType()) { - ConsoleValueConsoleType* cvt = value.getConsoleType(); - Con::setData(cvt->consoleType, cvt->dataPtr, 0, 1, &val, cvt->enumTable); + Con::setData(value.type, value.dataPtr, 0, 1, &val, value.enumTable); } else { diff --git a/Engine/source/console/engineDoc.cpp b/Engine/source/console/engineDoc.cpp index baffb12e6..6dde4ab7c 100644 --- a/Engine/source/console/engineDoc.cpp +++ b/Engine/source/console/engineDoc.cpp @@ -148,7 +148,7 @@ static void dumpVariable( Stream& stream, // Skip variables for which we can't decipher their type. - ConsoleBaseType* type = ConsoleBaseType::getType( entry->value.getConsoleType()->consoleType ); + ConsoleBaseType* type = ConsoleBaseType::getType( entry->value.type ); if( !type ) { Con::errorf( "Can't find type for variable '%s'", entry->name ); From f3046a9c3e5a50371effc339ccf0ac7c4fca52a7 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 11 May 2025 23:02:36 +0100 Subject: [PATCH 33/41] Update ScriptTest.cpp --- Engine/source/testing/ScriptTest.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Engine/source/testing/ScriptTest.cpp b/Engine/source/testing/ScriptTest.cpp index d13d2b6f2..7b99613d3 100644 --- a/Engine/source/testing/ScriptTest.cpp +++ b/Engine/source/testing/ScriptTest.cpp @@ -32,7 +32,8 @@ inline ConsoleValue RunScript(const char* str) { - return std::move(Con::evaluate(str, false, NULL).value); + auto conRes = Con::evaluate(str, false, NULL); + return conRes.value; } using ::testing::Matcher; From e5e3efb30c439ce024182f107a1285b85b255729 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 11 May 2025 23:17:36 +0100 Subject: [PATCH 34/41] Update platformMemory.h --- Engine/source/platform/platformMemory.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Engine/source/platform/platformMemory.h b/Engine/source/platform/platformMemory.h index 2b56af18b..c9b74c750 100644 --- a/Engine/source/platform/platformMemory.h +++ b/Engine/source/platform/platformMemory.h @@ -27,6 +27,7 @@ namespace Memory { +#if !defined(TORQUE_DISABLE_MEMORY_MANAGER) struct MemInfo { void* ptr; @@ -44,6 +45,7 @@ namespace Memory void shutdown(); void getMemoryInfo(void* ptr, MemInfo& info); void checkPtr(void* ptr); +#endif } #endif // _TORQUE_PLATFORM_PLATFORMMEMORY_H_ From b54ed77f7a06bbdc949d3c4cc4e2b184b824ff5d Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 12 May 2025 10:09:52 +0100 Subject: [PATCH 35/41] Update console.h --- Engine/source/console/console.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index dcd9d4531..eec41a6a3 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -175,6 +175,9 @@ public: ConsoleValue(const ConsoleValue& ref) { + type = ConsoleValueType::cvSTEntry; + s = const_cast(StringTable->EmptyString()); + switch (ref.type) { case cvNULL: From 0f819a3af496e536b84bfdd4e628e1f3b9f35bfa Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 12 May 2025 11:56:26 +0100 Subject: [PATCH 36/41] Update EditorGui.ed.tscript clean teardown around editorPluginSet not sure why this is failing at the foreach but editorPluginSet doesnt seem to exist during the teardown of everything and foreach causes a null reference to be fired off. --- .../worldEditor/scripts/EditorGui.ed.tscript | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript b/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript index 714e81b80..87ec21497 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript @@ -317,8 +317,11 @@ function EditorGui::shutdown( %this ) %this.setEditor( "" ); // Call the shutdown callback on the editor plugins. - foreach( %plugin in EditorPluginSet ) - %plugin.onWorldEditorShutdown(); + for ( %i = 0; %i < EditorPluginSet.getCount(); %i++ ) + { + %obj = EditorPluginSet.getObject(%i); + %obj.onWorldEditorShutdown(); + } } /// This is used to add an editor to the Editors menu which @@ -575,9 +578,11 @@ function EditorGui::onWake( %this ) EHWorldEditor.setStateOn( 1 ); // Notify the editor plugins that the editor has started. - - foreach( %plugin in EditorPluginSet ) - %plugin.onEditorWake(); + for ( %i = 0; %i < EditorPluginSet.getCount(); %i++ ) + { + %obj = EditorPluginSet.getObject( %i ); + %obj.onEditorWake(); + } // Push the ActionMaps in the order that we want to have them // before activating an editor plugin, so that if the plugin @@ -616,9 +621,11 @@ function EditorGui::onSleep( %this ) MoveMap.pop(); // Notify the editor plugins that the editor will be closing. - - foreach( %plugin in EditorPluginSet ) - %plugin.onEditorSleep(); + for ( %i = 0; %i < EditorPluginSet.getCount(); %i++ ) + { + %obj = EditorPluginSet.getObject(%i); + %obj.onEditorSleep(); + } if(isObject($Server::CurrentScene)) $Server::CurrentScene.open(); @@ -715,8 +722,12 @@ function EditorGui::onNewLevelLoaded( %this, %levelName ) function EditorMissionCleanup::onRemove( %this ) { EditorGui.levelName = ""; - foreach( %plugin in EditorPluginSet ) - %plugin.onExitMission(); + + for ( %i = 0; %i < EditorPluginSet.getCount(); %i++ ) + { + %obj = EditorPluginSet.getObject(%i); + %obj.onExitMission(); + } } //----------------------------------------------------------------------------- From 04fa9d87f423727461fb89f2d827d2c341eb54ba Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 12 May 2025 12:50:31 +0100 Subject: [PATCH 37/41] Revert "Update EditorGui.ed.tscript" This reverts commit 0f819a3af496e536b84bfdd4e628e1f3b9f35bfa. --- .../worldEditor/scripts/EditorGui.ed.tscript | 31 ++++++------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript b/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript index 87ec21497..714e81b80 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript @@ -317,11 +317,8 @@ function EditorGui::shutdown( %this ) %this.setEditor( "" ); // Call the shutdown callback on the editor plugins. - for ( %i = 0; %i < EditorPluginSet.getCount(); %i++ ) - { - %obj = EditorPluginSet.getObject(%i); - %obj.onWorldEditorShutdown(); - } + foreach( %plugin in EditorPluginSet ) + %plugin.onWorldEditorShutdown(); } /// This is used to add an editor to the Editors menu which @@ -578,11 +575,9 @@ function EditorGui::onWake( %this ) EHWorldEditor.setStateOn( 1 ); // Notify the editor plugins that the editor has started. - for ( %i = 0; %i < EditorPluginSet.getCount(); %i++ ) - { - %obj = EditorPluginSet.getObject( %i ); - %obj.onEditorWake(); - } + + foreach( %plugin in EditorPluginSet ) + %plugin.onEditorWake(); // Push the ActionMaps in the order that we want to have them // before activating an editor plugin, so that if the plugin @@ -621,11 +616,9 @@ function EditorGui::onSleep( %this ) MoveMap.pop(); // Notify the editor plugins that the editor will be closing. - for ( %i = 0; %i < EditorPluginSet.getCount(); %i++ ) - { - %obj = EditorPluginSet.getObject(%i); - %obj.onEditorSleep(); - } + + foreach( %plugin in EditorPluginSet ) + %plugin.onEditorSleep(); if(isObject($Server::CurrentScene)) $Server::CurrentScene.open(); @@ -722,12 +715,8 @@ function EditorGui::onNewLevelLoaded( %this, %levelName ) function EditorMissionCleanup::onRemove( %this ) { EditorGui.levelName = ""; - - for ( %i = 0; %i < EditorPluginSet.getCount(); %i++ ) - { - %obj = EditorPluginSet.getObject(%i); - %obj.onExitMission(); - } + foreach( %plugin in EditorPluginSet ) + %plugin.onExitMission(); } //----------------------------------------------------------------------------- From 41c3f610bec56d567a389d69dae0b890c6fd58d7 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 12 May 2025 12:50:49 +0100 Subject: [PATCH 38/41] remove free from scripting lanugage was causing issues with foreach --- Engine/source/console/torquescript/CMDgram.y | 4 - .../source/console/torquescript/cmdgram.cpp | 706 ++++++++---------- 2 files changed, 330 insertions(+), 380 deletions(-) diff --git a/Engine/source/console/torquescript/CMDgram.y b/Engine/source/console/torquescript/CMDgram.y index 643cd65a9..9e1b30543 100644 --- a/Engine/source/console/torquescript/CMDgram.y +++ b/Engine/source/console/torquescript/CMDgram.y @@ -102,10 +102,6 @@ struct Token IfStmtNode* ifnode; } - -%destructor { dFree($$.value); } -%destructor { dFree($$.value); } - %type parent_block %type case_block %type switch_stmt diff --git a/Engine/source/console/torquescript/cmdgram.cpp b/Engine/source/console/torquescript/cmdgram.cpp index 0a8dba10c..ab15ffc73 100644 --- a/Engine/source/console/torquescript/cmdgram.cpp +++ b/Engine/source/console/torquescript/cmdgram.cpp @@ -694,23 +694,23 @@ static const yytype_int8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_int16 yyrline[] = { - 0, 170, 170, 176, 177, 182, 184, 186, 191, 196, - 198, 204, 205, 210, 211, 212, 213, 214, 215, 216, - 218, 220, 222, 224, 226, 228, 230, 235, 237, 243, - 244, 249, 251, 256, 261, 263, 265, 267, 269, 271, - 277, 278, 284, 285, 291, 292, 298, 299, 301, 303, - 308, 310, 315, 317, 322, 324, 329, 331, 333, 338, - 340, 345, 347, 352, 354, 359, 361, 363, 365, 367, - 369, 371, 373, 378, 380, 385, 390, 392, 394, 396, - 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, - 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, - 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, - 458, 460, 462, 464, 466, 488, 490, 495, 497, 502, - 504, 509, 511, 513, 515, 517, 519, 521, 523, 525, - 527, 529, 531, 536, 538, 540, 542, 544, 546, 548, - 550, 552, 554, 559, 561, 563, 573, 575, 581, 582, - 587, 589, 595, 596, 601, 603, 608, 610, 612, 614, - 616, 621, 623 + 0, 166, 166, 172, 173, 178, 180, 182, 187, 192, + 194, 200, 201, 206, 207, 208, 209, 210, 211, 212, + 214, 216, 218, 220, 222, 224, 226, 231, 233, 239, + 240, 245, 247, 252, 257, 259, 261, 263, 265, 267, + 273, 274, 280, 281, 287, 288, 294, 295, 297, 299, + 304, 306, 311, 313, 318, 320, 325, 327, 329, 334, + 336, 341, 343, 348, 350, 355, 357, 359, 361, 363, + 365, 367, 369, 374, 376, 381, 386, 388, 390, 392, + 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, + 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, + 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, + 454, 456, 458, 460, 462, 484, 486, 491, 493, 498, + 500, 505, 507, 509, 511, 513, 515, 517, 519, 521, + 523, 525, 527, 532, 534, 536, 538, 540, 542, 544, + 546, 548, 550, 555, 557, 559, 569, 571, 577, 578, + 583, 585, 591, 592, 597, 599, 604, 606, 608, 610, + 612, 617, 619 }; #endif @@ -1904,53 +1904,7 @@ yydestruct (const char *yymsg, YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - switch (yykind) - { - case YYSYMBOL_TTAG: /* TTAG */ -#line 106 "CMDgram.y" - { dFree(((*yyvaluep).s).value); } -#line 1913 "CMDgram.c" - break; - - case YYSYMBOL_VAR: /* VAR */ -#line 106 "CMDgram.y" - { dFree(((*yyvaluep).s).value); } -#line 1919 "CMDgram.c" - break; - - case YYSYMBOL_IDENT: /* IDENT */ -#line 106 "CMDgram.y" - { dFree(((*yyvaluep).s).value); } -#line 1925 "CMDgram.c" - break; - - case YYSYMBOL_DOCBLOCK: /* DOCBLOCK */ -#line 107 "CMDgram.y" - { dFree(((*yyvaluep).str).value); } -#line 1931 "CMDgram.c" - break; - - case YYSYMBOL_STRATOM: /* STRATOM */ -#line 107 "CMDgram.y" - { dFree(((*yyvaluep).str).value); } -#line 1937 "CMDgram.c" - break; - - case YYSYMBOL_TAGATOM: /* TAGATOM */ -#line 107 "CMDgram.y" - { dFree(((*yyvaluep).str).value); } -#line 1943 "CMDgram.c" - break; - - case YYSYMBOL_parent_block: /* parent_block */ -#line 106 "CMDgram.y" - { dFree(((*yyvaluep).s).value); } -#line 1949 "CMDgram.c" - break; - - default: - break; - } + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -2238,937 +2192,937 @@ yyreduce: switch (yyn) { case 2: /* start: decl_list */ -#line 171 "CMDgram.y" +#line 167 "CMDgram.y" { } -#line 2244 "CMDgram.c" +#line 2198 "CMDgram.c" break; case 3: /* decl_list: %empty */ -#line 176 "CMDgram.y" +#line 172 "CMDgram.y" { (yyval.stmt) = nil; } -#line 2250 "CMDgram.c" +#line 2204 "CMDgram.c" break; case 4: /* decl_list: decl_list decl */ -#line 178 "CMDgram.y" +#line 174 "CMDgram.y" { if(!Script::gStatementList) { Script::gStatementList = (yyvsp[0].stmt); } else { Script::gStatementList->append((yyvsp[0].stmt)); } } -#line 2256 "CMDgram.c" +#line 2210 "CMDgram.c" break; case 5: /* decl: stmt */ -#line 183 "CMDgram.y" +#line 179 "CMDgram.y" { (yyval.stmt) = (yyvsp[0].stmt); } -#line 2262 "CMDgram.c" +#line 2216 "CMDgram.c" break; case 6: /* decl: fn_decl_stmt */ -#line 185 "CMDgram.y" +#line 181 "CMDgram.y" { (yyval.stmt) = (yyvsp[0].stmt); } -#line 2268 "CMDgram.c" +#line 2222 "CMDgram.c" break; case 7: /* decl: package_decl */ -#line 187 "CMDgram.y" +#line 183 "CMDgram.y" { (yyval.stmt) = (yyvsp[0].stmt); } -#line 2274 "CMDgram.c" +#line 2228 "CMDgram.c" break; case 8: /* package_decl: rwPACKAGE IDENT '{' fn_decl_list '}' ';' */ -#line 192 "CMDgram.y" +#line 188 "CMDgram.y" { (yyval.stmt) = (yyvsp[-2].stmt); for(StmtNode *walk = ((yyvsp[-2].stmt));walk;walk = walk->getNext() ) walk->setPackage((yyvsp[-4].s).value); } -#line 2280 "CMDgram.c" +#line 2234 "CMDgram.c" break; case 9: /* fn_decl_list: fn_decl_stmt */ -#line 197 "CMDgram.y" +#line 193 "CMDgram.y" { (yyval.stmt) = (yyvsp[0].stmt); } -#line 2286 "CMDgram.c" +#line 2240 "CMDgram.c" break; case 10: /* fn_decl_list: fn_decl_list fn_decl_stmt */ -#line 199 "CMDgram.y" +#line 195 "CMDgram.y" { (yyval.stmt) = (yyvsp[-1].stmt); ((yyvsp[-1].stmt))->append((yyvsp[0].stmt)); } -#line 2292 "CMDgram.c" +#line 2246 "CMDgram.c" break; case 11: /* statement_list: %empty */ -#line 204 "CMDgram.y" +#line 200 "CMDgram.y" { (yyval.stmt) = nil; } -#line 2298 "CMDgram.c" +#line 2252 "CMDgram.c" break; case 12: /* statement_list: statement_list stmt */ -#line 206 "CMDgram.y" +#line 202 "CMDgram.y" { if(!(yyvsp[-1].stmt)) { (yyval.stmt) = (yyvsp[0].stmt); } else { ((yyvsp[-1].stmt))->append((yyvsp[0].stmt)); (yyval.stmt) = (yyvsp[-1].stmt); } } -#line 2304 "CMDgram.c" +#line 2258 "CMDgram.c" break; case 19: /* stmt: rwBREAK ';' */ -#line 217 "CMDgram.y" +#line 213 "CMDgram.y" { (yyval.stmt) = BreakStmtNode::alloc( (yyvsp[-1].i).lineNumber ); } -#line 2310 "CMDgram.c" +#line 2264 "CMDgram.c" break; case 20: /* stmt: rwCONTINUE ';' */ -#line 219 "CMDgram.y" +#line 215 "CMDgram.y" { (yyval.stmt) = ContinueStmtNode::alloc( (yyvsp[-1].i).lineNumber ); } -#line 2316 "CMDgram.c" +#line 2270 "CMDgram.c" break; case 21: /* stmt: rwRETURN ';' */ -#line 221 "CMDgram.y" +#line 217 "CMDgram.y" { (yyval.stmt) = ReturnStmtNode::alloc( (yyvsp[-1].i).lineNumber, NULL ); } -#line 2322 "CMDgram.c" +#line 2276 "CMDgram.c" break; case 22: /* stmt: rwRETURN expr ';' */ -#line 223 "CMDgram.y" +#line 219 "CMDgram.y" { (yyval.stmt) = ReturnStmtNode::alloc( (yyvsp[-2].i).lineNumber, (yyvsp[-1].expr) ); } -#line 2328 "CMDgram.c" +#line 2282 "CMDgram.c" break; case 23: /* stmt: expression_stmt ';' */ -#line 225 "CMDgram.y" +#line 221 "CMDgram.y" { (yyval.stmt) = (yyvsp[-1].stmt); } -#line 2334 "CMDgram.c" +#line 2288 "CMDgram.c" break; case 24: /* stmt: TTAG '=' expr ';' */ -#line 227 "CMDgram.y" +#line 223 "CMDgram.y" { (yyval.stmt) = TTagSetStmtNode::alloc( (yyvsp[-3].s).lineNumber, (yyvsp[-3].s).value, (yyvsp[-1].expr), NULL ); } -#line 2340 "CMDgram.c" +#line 2294 "CMDgram.c" break; case 25: /* stmt: TTAG '=' expr ',' expr ';' */ -#line 229 "CMDgram.y" +#line 225 "CMDgram.y" { (yyval.stmt) = TTagSetStmtNode::alloc( (yyvsp[-5].s).lineNumber, (yyvsp[-5].s).value, (yyvsp[-3].expr), (yyvsp[-1].expr) ); } -#line 2346 "CMDgram.c" +#line 2300 "CMDgram.c" break; case 26: /* stmt: DOCBLOCK */ -#line 231 "CMDgram.y" +#line 227 "CMDgram.y" { (yyval.stmt) = StrConstNode::alloc( (yyvsp[0].str).lineNumber, (yyvsp[0].str).value, false, true ); } -#line 2352 "CMDgram.c" +#line 2306 "CMDgram.c" break; case 27: /* fn_decl_stmt: rwDEFINE IDENT '(' var_list_decl ')' '{' statement_list '}' */ -#line 236 "CMDgram.y" +#line 232 "CMDgram.y" { (yyval.stmt) = FunctionDeclStmtNode::alloc( (yyvsp[-7].i).lineNumber, (yyvsp[-6].s).value, NULL, (yyvsp[-4].var), (yyvsp[-1].stmt) ); } -#line 2358 "CMDgram.c" +#line 2312 "CMDgram.c" break; case 28: /* fn_decl_stmt: rwDEFINE IDENT opCOLONCOLON IDENT '(' var_list_decl ')' '{' statement_list '}' */ -#line 238 "CMDgram.y" +#line 234 "CMDgram.y" { (yyval.stmt) = FunctionDeclStmtNode::alloc( (yyvsp[-9].i).lineNumber, (yyvsp[-6].s).value, (yyvsp[-8].s).value, (yyvsp[-4].var), (yyvsp[-1].stmt) ); } -#line 2364 "CMDgram.c" +#line 2318 "CMDgram.c" break; case 29: /* var_list_decl: %empty */ -#line 243 "CMDgram.y" +#line 239 "CMDgram.y" { (yyval.var) = NULL; } -#line 2370 "CMDgram.c" +#line 2324 "CMDgram.c" break; case 30: /* var_list_decl: var_list */ -#line 245 "CMDgram.y" +#line 241 "CMDgram.y" { (yyval.var) = (yyvsp[0].var); } -#line 2376 "CMDgram.c" +#line 2330 "CMDgram.c" break; case 31: /* var_list: VAR */ -#line 250 "CMDgram.y" +#line 246 "CMDgram.y" { (yyval.var) = VarNode::alloc( (yyvsp[0].s).lineNumber, (yyvsp[0].s).value, NULL ); } -#line 2382 "CMDgram.c" +#line 2336 "CMDgram.c" break; case 32: /* var_list: var_list ',' VAR */ -#line 252 "CMDgram.y" +#line 248 "CMDgram.y" { (yyval.var) = (yyvsp[-2].var); ((StmtNode*)((yyvsp[-2].var)))->append((StmtNode*)VarNode::alloc( (yyvsp[0].s).lineNumber, (yyvsp[0].s).value, NULL ) ); } -#line 2388 "CMDgram.c" +#line 2342 "CMDgram.c" break; case 33: /* datablock_decl: rwDATABLOCK class_name_expr '(' expr parent_block ')' '{' slot_assign_list_opt '}' ';' */ -#line 257 "CMDgram.y" +#line 253 "CMDgram.y" { (yyval.stmt) = ObjectDeclNode::alloc( (yyvsp[-9].i).lineNumber, (yyvsp[-8].expr), (yyvsp[-6].expr), NULL, (yyvsp[-5].s).value, (yyvsp[-2].slist), NULL, true, false, false); } -#line 2394 "CMDgram.c" +#line 2348 "CMDgram.c" break; case 34: /* object_decl: rwDECLARE class_name_expr '(' object_name parent_block object_args ')' '{' object_declare_block '}' */ -#line 262 "CMDgram.y" +#line 258 "CMDgram.y" { (yyval.od) = ObjectDeclNode::alloc( (yyvsp[-9].i).lineNumber, (yyvsp[-8].expr), (yyvsp[-6].expr), (yyvsp[-4].expr), (yyvsp[-5].s).value, (yyvsp[-1].odcl).slots, (yyvsp[-1].odcl).decls, false, false, false); } -#line 2400 "CMDgram.c" +#line 2354 "CMDgram.c" break; case 35: /* object_decl: rwDECLARE class_name_expr '(' object_name parent_block object_args ')' */ -#line 264 "CMDgram.y" +#line 260 "CMDgram.y" { (yyval.od) = ObjectDeclNode::alloc( (yyvsp[-6].i).lineNumber, (yyvsp[-5].expr), (yyvsp[-3].expr), (yyvsp[-1].expr), (yyvsp[-2].s).value, NULL, NULL, false, false, false); } -#line 2406 "CMDgram.c" +#line 2360 "CMDgram.c" break; case 36: /* object_decl: rwDECLARE class_name_expr '(' '[' object_name ']' parent_block object_args ')' '{' object_declare_block '}' */ -#line 266 "CMDgram.y" +#line 262 "CMDgram.y" { (yyval.od) = ObjectDeclNode::alloc( (yyvsp[-11].i).lineNumber, (yyvsp[-10].expr), (yyvsp[-7].expr), (yyvsp[-4].expr), (yyvsp[-5].s).value, (yyvsp[-1].odcl).slots, (yyvsp[-1].odcl).decls, false, true, false); } -#line 2412 "CMDgram.c" +#line 2366 "CMDgram.c" break; case 37: /* object_decl: rwDECLARE class_name_expr '(' '[' object_name ']' parent_block object_args ')' */ -#line 268 "CMDgram.y" +#line 264 "CMDgram.y" { (yyval.od) = ObjectDeclNode::alloc( (yyvsp[-8].i).lineNumber, (yyvsp[-7].expr), (yyvsp[-4].expr), (yyvsp[-1].expr), (yyvsp[-2].s).value, NULL, NULL, false, true, false); } -#line 2418 "CMDgram.c" +#line 2372 "CMDgram.c" break; case 38: /* object_decl: rwDECLARESINGLETON class_name_expr '(' object_name parent_block object_args ')' '{' object_declare_block '}' */ -#line 270 "CMDgram.y" +#line 266 "CMDgram.y" { (yyval.od) = ObjectDeclNode::alloc( (yyvsp[-9].i).lineNumber, (yyvsp[-8].expr), (yyvsp[-6].expr), (yyvsp[-4].expr), (yyvsp[-5].s).value, (yyvsp[-1].odcl).slots, (yyvsp[-1].odcl).decls, false, false, true); } -#line 2424 "CMDgram.c" +#line 2378 "CMDgram.c" break; case 39: /* object_decl: rwDECLARESINGLETON class_name_expr '(' object_name parent_block object_args ')' */ -#line 272 "CMDgram.y" +#line 268 "CMDgram.y" { (yyval.od) = ObjectDeclNode::alloc( (yyvsp[-6].i).lineNumber, (yyvsp[-5].expr), (yyvsp[-3].expr), (yyvsp[-1].expr), (yyvsp[-2].s).value, NULL, NULL, false, false, true); } -#line 2430 "CMDgram.c" +#line 2384 "CMDgram.c" break; case 40: /* parent_block: %empty */ -#line 277 "CMDgram.y" +#line 273 "CMDgram.y" { (yyval.s).value = NULL; } -#line 2436 "CMDgram.c" +#line 2390 "CMDgram.c" break; case 41: /* parent_block: ':' IDENT */ -#line 279 "CMDgram.y" +#line 275 "CMDgram.y" { (yyval.s) = (yyvsp[0].s); } -#line 2442 "CMDgram.c" +#line 2396 "CMDgram.c" break; case 42: /* object_name: %empty */ -#line 284 "CMDgram.y" +#line 280 "CMDgram.y" { (yyval.expr) = StrConstNode::alloc( CodeBlock::smCurrentParser->getCurrentLine(), "", false); } -#line 2448 "CMDgram.c" +#line 2402 "CMDgram.c" break; case 43: /* object_name: expr */ -#line 286 "CMDgram.y" +#line 282 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 2454 "CMDgram.c" +#line 2408 "CMDgram.c" break; case 44: /* object_args: %empty */ -#line 291 "CMDgram.y" +#line 287 "CMDgram.y" { (yyval.expr) = NULL; } -#line 2460 "CMDgram.c" +#line 2414 "CMDgram.c" break; case 45: /* object_args: ',' expr_list */ -#line 293 "CMDgram.y" +#line 289 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 2466 "CMDgram.c" +#line 2420 "CMDgram.c" break; case 46: /* object_declare_block: %empty */ -#line 298 "CMDgram.y" +#line 294 "CMDgram.y" { (yyval.odcl).slots = NULL; (yyval.odcl).decls = NULL; } -#line 2472 "CMDgram.c" +#line 2426 "CMDgram.c" break; case 47: /* object_declare_block: slot_assign_list */ -#line 300 "CMDgram.y" +#line 296 "CMDgram.y" { (yyval.odcl).slots = (yyvsp[0].slist); (yyval.odcl).decls = NULL; } -#line 2478 "CMDgram.c" +#line 2432 "CMDgram.c" break; case 48: /* object_declare_block: object_decl_list */ -#line 302 "CMDgram.y" +#line 298 "CMDgram.y" { (yyval.odcl).slots = NULL; (yyval.odcl).decls = (yyvsp[0].od); } -#line 2484 "CMDgram.c" +#line 2438 "CMDgram.c" break; case 49: /* object_declare_block: slot_assign_list object_decl_list */ -#line 304 "CMDgram.y" +#line 300 "CMDgram.y" { (yyval.odcl).slots = (yyvsp[-1].slist); (yyval.odcl).decls = (yyvsp[0].od); } -#line 2490 "CMDgram.c" +#line 2444 "CMDgram.c" break; case 50: /* object_decl_list: object_decl ';' */ -#line 309 "CMDgram.y" +#line 305 "CMDgram.y" { (yyval.od) = (yyvsp[-1].od); } -#line 2496 "CMDgram.c" +#line 2450 "CMDgram.c" break; case 51: /* object_decl_list: object_decl_list object_decl ';' */ -#line 311 "CMDgram.y" +#line 307 "CMDgram.y" { (yyvsp[-2].od)->append((yyvsp[-1].od)); (yyval.od) = (yyvsp[-2].od); } -#line 2502 "CMDgram.c" +#line 2456 "CMDgram.c" break; case 52: /* stmt_block: '{' statement_list '}' */ -#line 316 "CMDgram.y" +#line 312 "CMDgram.y" { (yyval.stmt) = (yyvsp[-1].stmt); } -#line 2508 "CMDgram.c" +#line 2462 "CMDgram.c" break; case 53: /* stmt_block: stmt */ -#line 318 "CMDgram.y" +#line 314 "CMDgram.y" { (yyval.stmt) = (yyvsp[0].stmt); } -#line 2514 "CMDgram.c" +#line 2468 "CMDgram.c" break; case 54: /* switch_stmt: rwSWITCH '(' expr ')' '{' case_block '}' */ -#line 323 "CMDgram.y" +#line 319 "CMDgram.y" { (yyval.stmt) = (yyvsp[-1].ifnode); (yyvsp[-1].ifnode)->propagateSwitchExpr((yyvsp[-4].expr), false); } -#line 2520 "CMDgram.c" +#line 2474 "CMDgram.c" break; case 55: /* switch_stmt: rwSWITCHSTR '(' expr ')' '{' case_block '}' */ -#line 325 "CMDgram.y" +#line 321 "CMDgram.y" { (yyval.stmt) = (yyvsp[-1].ifnode); (yyvsp[-1].ifnode)->propagateSwitchExpr((yyvsp[-4].expr), true); } -#line 2526 "CMDgram.c" +#line 2480 "CMDgram.c" break; case 56: /* case_block: rwCASE case_expr ':' statement_list */ -#line 330 "CMDgram.y" +#line 326 "CMDgram.y" { (yyval.ifnode) = IfStmtNode::alloc( (yyvsp[-3].i).lineNumber, (yyvsp[-2].expr), (yyvsp[0].stmt), NULL, false); } -#line 2532 "CMDgram.c" +#line 2486 "CMDgram.c" break; case 57: /* case_block: rwCASE case_expr ':' statement_list rwDEFAULT ':' statement_list */ -#line 332 "CMDgram.y" +#line 328 "CMDgram.y" { (yyval.ifnode) = IfStmtNode::alloc( (yyvsp[-6].i).lineNumber, (yyvsp[-5].expr), (yyvsp[-3].stmt), (yyvsp[0].stmt), false); } -#line 2538 "CMDgram.c" +#line 2492 "CMDgram.c" break; case 58: /* case_block: rwCASE case_expr ':' statement_list case_block */ -#line 334 "CMDgram.y" +#line 330 "CMDgram.y" { (yyval.ifnode) = IfStmtNode::alloc( (yyvsp[-4].i).lineNumber, (yyvsp[-3].expr), (yyvsp[-1].stmt), (yyvsp[0].ifnode), true); } -#line 2544 "CMDgram.c" +#line 2498 "CMDgram.c" break; case 59: /* case_expr: expr */ -#line 339 "CMDgram.y" +#line 335 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr);} -#line 2550 "CMDgram.c" +#line 2504 "CMDgram.c" break; case 60: /* case_expr: case_expr rwCASEOR expr */ -#line 341 "CMDgram.y" +#line 337 "CMDgram.y" { ((yyvsp[-2].expr))->append((yyvsp[0].expr)); (yyval.expr)=(yyvsp[-2].expr); } -#line 2556 "CMDgram.c" +#line 2510 "CMDgram.c" break; case 61: /* if_stmt: rwIF '(' expr ')' stmt_block */ -#line 346 "CMDgram.y" +#line 342 "CMDgram.y" { (yyval.stmt) = IfStmtNode::alloc((yyvsp[-4].i).lineNumber, (yyvsp[-2].expr), (yyvsp[0].stmt), NULL, false); } -#line 2562 "CMDgram.c" +#line 2516 "CMDgram.c" break; case 62: /* if_stmt: rwIF '(' expr ')' stmt_block rwELSE stmt_block */ -#line 348 "CMDgram.y" +#line 344 "CMDgram.y" { (yyval.stmt) = IfStmtNode::alloc((yyvsp[-6].i).lineNumber, (yyvsp[-4].expr), (yyvsp[-2].stmt), (yyvsp[0].stmt), false); } -#line 2568 "CMDgram.c" +#line 2522 "CMDgram.c" break; case 63: /* while_stmt: rwWHILE '(' expr ')' stmt_block */ -#line 353 "CMDgram.y" +#line 349 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-4].i).lineNumber, nil, (yyvsp[-2].expr), nil, (yyvsp[0].stmt), false); } -#line 2574 "CMDgram.c" +#line 2528 "CMDgram.c" break; case 64: /* while_stmt: rwDO stmt_block rwWHILE '(' expr ')' */ -#line 355 "CMDgram.y" +#line 351 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-3].i).lineNumber, nil, (yyvsp[-1].expr), nil, (yyvsp[-4].stmt), true); } -#line 2580 "CMDgram.c" +#line 2534 "CMDgram.c" break; case 65: /* for_stmt: rwFOR '(' expr ';' expr ';' expr ')' stmt_block */ -#line 360 "CMDgram.y" +#line 356 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-8].i).lineNumber, (yyvsp[-6].expr), (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].stmt), false); } -#line 2586 "CMDgram.c" +#line 2540 "CMDgram.c" break; case 66: /* for_stmt: rwFOR '(' expr ';' expr ';' ')' stmt_block */ -#line 362 "CMDgram.y" +#line 358 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-7].i).lineNumber, (yyvsp[-5].expr), (yyvsp[-3].expr), NULL, (yyvsp[0].stmt), false); } -#line 2592 "CMDgram.c" +#line 2546 "CMDgram.c" break; case 67: /* for_stmt: rwFOR '(' expr ';' ';' expr ')' stmt_block */ -#line 364 "CMDgram.y" +#line 360 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-7].i).lineNumber, (yyvsp[-5].expr), NULL, (yyvsp[-2].expr), (yyvsp[0].stmt), false); } -#line 2598 "CMDgram.c" +#line 2552 "CMDgram.c" break; case 68: /* for_stmt: rwFOR '(' expr ';' ';' ')' stmt_block */ -#line 366 "CMDgram.y" +#line 362 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-6].i).lineNumber, (yyvsp[-4].expr), NULL, NULL, (yyvsp[0].stmt), false); } -#line 2604 "CMDgram.c" +#line 2558 "CMDgram.c" break; case 69: /* for_stmt: rwFOR '(' ';' expr ';' expr ')' stmt_block */ -#line 368 "CMDgram.y" +#line 364 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-7].i).lineNumber, NULL, (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].stmt), false); } -#line 2610 "CMDgram.c" +#line 2564 "CMDgram.c" break; case 70: /* for_stmt: rwFOR '(' ';' expr ';' ')' stmt_block */ -#line 370 "CMDgram.y" +#line 366 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-6].i).lineNumber, NULL, (yyvsp[-3].expr), NULL, (yyvsp[0].stmt), false); } -#line 2616 "CMDgram.c" +#line 2570 "CMDgram.c" break; case 71: /* for_stmt: rwFOR '(' ';' ';' expr ')' stmt_block */ -#line 372 "CMDgram.y" +#line 368 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-6].i).lineNumber, NULL, NULL, (yyvsp[-2].expr), (yyvsp[0].stmt), false); } -#line 2622 "CMDgram.c" +#line 2576 "CMDgram.c" break; case 72: /* for_stmt: rwFOR '(' ';' ';' ')' stmt_block */ -#line 374 "CMDgram.y" +#line 370 "CMDgram.y" { (yyval.stmt) = LoopStmtNode::alloc((yyvsp[-5].i).lineNumber, NULL, NULL, NULL, (yyvsp[0].stmt), false); } -#line 2628 "CMDgram.c" +#line 2582 "CMDgram.c" break; case 73: /* foreach_stmt: rwFOREACH '(' VAR rwIN expr ')' stmt_block */ -#line 379 "CMDgram.y" +#line 375 "CMDgram.y" { (yyval.stmt) = IterStmtNode::alloc( (yyvsp[-6].i).lineNumber, (yyvsp[-4].s).value, (yyvsp[-2].expr), (yyvsp[0].stmt), false ); } -#line 2634 "CMDgram.c" +#line 2588 "CMDgram.c" break; case 74: /* foreach_stmt: rwFOREACHSTR '(' VAR rwIN expr ')' stmt_block */ -#line 381 "CMDgram.y" +#line 377 "CMDgram.y" { (yyval.stmt) = IterStmtNode::alloc( (yyvsp[-6].i).lineNumber, (yyvsp[-4].s).value, (yyvsp[-2].expr), (yyvsp[0].stmt), true ); } -#line 2640 "CMDgram.c" +#line 2594 "CMDgram.c" break; case 75: /* expression_stmt: stmt_expr */ -#line 386 "CMDgram.y" +#line 382 "CMDgram.y" { (yyval.stmt) = (yyvsp[0].expr); } -#line 2646 "CMDgram.c" +#line 2600 "CMDgram.c" break; case 76: /* expr: stmt_expr */ -#line 391 "CMDgram.y" +#line 387 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 2652 "CMDgram.c" +#line 2606 "CMDgram.c" break; case 77: /* expr: '(' expr ')' */ -#line 393 "CMDgram.y" +#line 389 "CMDgram.y" { (yyval.expr) = (yyvsp[-1].expr); } -#line 2658 "CMDgram.c" +#line 2612 "CMDgram.c" break; case 78: /* expr: expr '^' expr */ -#line 395 "CMDgram.y" +#line 391 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2664 "CMDgram.c" +#line 2618 "CMDgram.c" break; case 79: /* expr: expr '%' expr */ -#line 397 "CMDgram.y" +#line 393 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2670 "CMDgram.c" +#line 2624 "CMDgram.c" break; case 80: /* expr: expr '&' expr */ -#line 399 "CMDgram.y" +#line 395 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2676 "CMDgram.c" +#line 2630 "CMDgram.c" break; case 81: /* expr: expr '|' expr */ -#line 401 "CMDgram.y" +#line 397 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2682 "CMDgram.c" +#line 2636 "CMDgram.c" break; case 82: /* expr: expr '+' expr */ -#line 403 "CMDgram.y" +#line 399 "CMDgram.y" { (yyval.expr) = FloatBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2688 "CMDgram.c" +#line 2642 "CMDgram.c" break; case 83: /* expr: expr '-' expr */ -#line 405 "CMDgram.y" +#line 401 "CMDgram.y" { (yyval.expr) = FloatBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2694 "CMDgram.c" +#line 2648 "CMDgram.c" break; case 84: /* expr: expr '*' expr */ -#line 407 "CMDgram.y" +#line 403 "CMDgram.y" { (yyval.expr) = FloatBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2700 "CMDgram.c" +#line 2654 "CMDgram.c" break; case 85: /* expr: expr '/' expr */ -#line 409 "CMDgram.y" +#line 405 "CMDgram.y" { (yyval.expr) = FloatBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2706 "CMDgram.c" +#line 2660 "CMDgram.c" break; case 86: /* expr: '-' expr */ -#line 411 "CMDgram.y" +#line 407 "CMDgram.y" { (yyval.expr) = FloatUnaryExprNode::alloc( (yyvsp[-1].i).lineNumber, (yyvsp[-1].i).value, (yyvsp[0].expr)); } -#line 2712 "CMDgram.c" +#line 2666 "CMDgram.c" break; case 87: /* expr: '*' expr */ -#line 413 "CMDgram.y" +#line 409 "CMDgram.y" { (yyval.expr) = TTagDerefNode::alloc( (yyvsp[-1].i).lineNumber, (yyvsp[0].expr) ); } -#line 2718 "CMDgram.c" +#line 2672 "CMDgram.c" break; case 88: /* expr: TTAG */ -#line 415 "CMDgram.y" +#line 411 "CMDgram.y" { (yyval.expr) = TTagExprNode::alloc( (yyvsp[0].s).lineNumber, (yyvsp[0].s).value ); } -#line 2724 "CMDgram.c" +#line 2678 "CMDgram.c" break; case 89: /* expr: expr '?' expr ':' expr */ -#line 417 "CMDgram.y" +#line 413 "CMDgram.y" { (yyval.expr) = ConditionalExprNode::alloc( (yyvsp[-4].expr)->dbgLineNumber, (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2730 "CMDgram.c" +#line 2684 "CMDgram.c" break; case 90: /* expr: expr '<' expr */ -#line 419 "CMDgram.y" +#line 415 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2736 "CMDgram.c" +#line 2690 "CMDgram.c" break; case 91: /* expr: expr '>' expr */ -#line 421 "CMDgram.y" +#line 417 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2742 "CMDgram.c" +#line 2696 "CMDgram.c" break; case 92: /* expr: expr opGE expr */ -#line 423 "CMDgram.y" +#line 419 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2748 "CMDgram.c" +#line 2702 "CMDgram.c" break; case 93: /* expr: expr opLE expr */ -#line 425 "CMDgram.y" +#line 421 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2754 "CMDgram.c" +#line 2708 "CMDgram.c" break; case 94: /* expr: expr opEQ expr */ -#line 427 "CMDgram.y" +#line 423 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2760 "CMDgram.c" +#line 2714 "CMDgram.c" break; case 95: /* expr: expr opNE expr */ -#line 429 "CMDgram.y" +#line 425 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2766 "CMDgram.c" +#line 2720 "CMDgram.c" break; case 96: /* expr: expr opOR expr */ -#line 431 "CMDgram.y" +#line 427 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2772 "CMDgram.c" +#line 2726 "CMDgram.c" break; case 97: /* expr: expr opSHL expr */ -#line 433 "CMDgram.y" +#line 429 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2778 "CMDgram.c" +#line 2732 "CMDgram.c" break; case 98: /* expr: expr opSHR expr */ -#line 435 "CMDgram.y" +#line 431 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2784 "CMDgram.c" +#line 2738 "CMDgram.c" break; case 99: /* expr: expr opAND expr */ -#line 437 "CMDgram.y" +#line 433 "CMDgram.y" { (yyval.expr) = IntBinaryExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-1].i).value, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 2790 "CMDgram.c" +#line 2744 "CMDgram.c" break; case 100: /* expr: expr opSTREQ expr */ -#line 439 "CMDgram.y" +#line 435 "CMDgram.y" { (yyval.expr) = StreqExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-2].expr), (yyvsp[0].expr), true); } -#line 2796 "CMDgram.c" +#line 2750 "CMDgram.c" break; case 101: /* expr: expr opSTRNE expr */ -#line 441 "CMDgram.y" +#line 437 "CMDgram.y" { (yyval.expr) = StreqExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-2].expr), (yyvsp[0].expr), false); } -#line 2802 "CMDgram.c" +#line 2756 "CMDgram.c" break; case 102: /* expr: expr '@' expr */ -#line 443 "CMDgram.y" +#line 439 "CMDgram.y" { (yyval.expr) = StrcatExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-2].expr), (yyvsp[0].expr), (yyvsp[-1].i).value); } -#line 2808 "CMDgram.c" +#line 2762 "CMDgram.c" break; case 103: /* expr: '!' expr */ -#line 445 "CMDgram.y" +#line 441 "CMDgram.y" { (yyval.expr) = IntUnaryExprNode::alloc((yyvsp[-1].i).lineNumber, (yyvsp[-1].i).value, (yyvsp[0].expr)); } -#line 2814 "CMDgram.c" +#line 2768 "CMDgram.c" break; case 104: /* expr: '~' expr */ -#line 447 "CMDgram.y" +#line 443 "CMDgram.y" { (yyval.expr) = IntUnaryExprNode::alloc((yyvsp[-1].i).lineNumber, (yyvsp[-1].i).value, (yyvsp[0].expr)); } -#line 2820 "CMDgram.c" +#line 2774 "CMDgram.c" break; case 105: /* expr: TAGATOM */ -#line 449 "CMDgram.y" +#line 445 "CMDgram.y" { (yyval.expr) = StrConstNode::alloc( (yyvsp[0].str).lineNumber, (yyvsp[0].str).value, true); } -#line 2826 "CMDgram.c" +#line 2780 "CMDgram.c" break; case 106: /* expr: FLTCONST */ -#line 451 "CMDgram.y" +#line 447 "CMDgram.y" { (yyval.expr) = FloatNode::alloc( (yyvsp[0].f).lineNumber, (yyvsp[0].f).value ); } -#line 2832 "CMDgram.c" +#line 2786 "CMDgram.c" break; case 107: /* expr: INTCONST */ -#line 453 "CMDgram.y" +#line 449 "CMDgram.y" { (yyval.expr) = IntNode::alloc( (yyvsp[0].i).lineNumber, (yyvsp[0].i).value ); } -#line 2838 "CMDgram.c" +#line 2792 "CMDgram.c" break; case 108: /* expr: rwBREAK */ -#line 455 "CMDgram.y" +#line 451 "CMDgram.y" { (yyval.expr) = ConstantNode::alloc( (yyvsp[0].i).lineNumber, StringTable->insert("break")); } -#line 2844 "CMDgram.c" +#line 2798 "CMDgram.c" break; case 109: /* expr: slot_acc */ -#line 457 "CMDgram.y" +#line 453 "CMDgram.y" { (yyval.expr) = SlotAccessNode::alloc( (yyvsp[0].slot).lineNumber, (yyvsp[0].slot).object, (yyvsp[0].slot).array, (yyvsp[0].slot).slotName ); } -#line 2850 "CMDgram.c" +#line 2804 "CMDgram.c" break; case 110: /* expr: intslot_acc */ -#line 459 "CMDgram.y" +#line 455 "CMDgram.y" { (yyval.expr) = InternalSlotAccessNode::alloc( (yyvsp[0].intslot).lineNumber, (yyvsp[0].intslot).object, (yyvsp[0].intslot).slotExpr, (yyvsp[0].intslot).recurse); } -#line 2856 "CMDgram.c" +#line 2810 "CMDgram.c" break; case 111: /* expr: IDENT */ -#line 461 "CMDgram.y" +#line 457 "CMDgram.y" { (yyval.expr) = ConstantNode::alloc( (yyvsp[0].s).lineNumber, (yyvsp[0].s).value ); } -#line 2862 "CMDgram.c" +#line 2816 "CMDgram.c" break; case 112: /* expr: STRATOM */ -#line 463 "CMDgram.y" +#line 459 "CMDgram.y" { (yyval.expr) = StrConstNode::alloc( (yyvsp[0].str).lineNumber, (yyvsp[0].str).value, false); } -#line 2868 "CMDgram.c" +#line 2822 "CMDgram.c" break; case 113: /* expr: VAR */ -#line 465 "CMDgram.y" +#line 461 "CMDgram.y" { (yyval.expr) = (ExprNode*)VarNode::alloc( (yyvsp[0].s).lineNumber, (yyvsp[0].s).value, NULL); } -#line 2874 "CMDgram.c" +#line 2828 "CMDgram.c" break; case 114: /* expr: VAR '[' aidx_expr ']' */ -#line 467 "CMDgram.y" +#line 463 "CMDgram.y" { (yyval.expr) = (ExprNode*)VarNode::alloc( (yyvsp[-3].s).lineNumber, (yyvsp[-3].s).value, (yyvsp[-1].expr) ); } -#line 2880 "CMDgram.c" +#line 2834 "CMDgram.c" break; case 115: /* slot_acc: expr '.' IDENT */ -#line 489 "CMDgram.y" +#line 485 "CMDgram.y" { (yyval.slot).lineNumber = (yyvsp[-2].expr)->dbgLineNumber; (yyval.slot).object = (yyvsp[-2].expr); (yyval.slot).slotName = (yyvsp[0].s).value; (yyval.slot).array = NULL; } -#line 2886 "CMDgram.c" +#line 2840 "CMDgram.c" break; case 116: /* slot_acc: expr '.' IDENT '[' aidx_expr ']' */ -#line 491 "CMDgram.y" +#line 487 "CMDgram.y" { (yyval.slot).lineNumber = (yyvsp[-5].expr)->dbgLineNumber; (yyval.slot).object = (yyvsp[-5].expr); (yyval.slot).slotName = (yyvsp[-3].s).value; (yyval.slot).array = (yyvsp[-1].expr); } -#line 2892 "CMDgram.c" +#line 2846 "CMDgram.c" break; case 117: /* intslot_acc: expr opINTNAME class_name_expr */ -#line 496 "CMDgram.y" +#line 492 "CMDgram.y" { (yyval.intslot).lineNumber = (yyvsp[-2].expr)->dbgLineNumber; (yyval.intslot).object = (yyvsp[-2].expr); (yyval.intslot).slotExpr = (yyvsp[0].expr); (yyval.intslot).recurse = false; } -#line 2898 "CMDgram.c" +#line 2852 "CMDgram.c" break; case 118: /* intslot_acc: expr opINTNAMER class_name_expr */ -#line 498 "CMDgram.y" +#line 494 "CMDgram.y" { (yyval.intslot).lineNumber = (yyvsp[-2].expr)->dbgLineNumber; (yyval.intslot).object = (yyvsp[-2].expr); (yyval.intslot).slotExpr = (yyvsp[0].expr); (yyval.intslot).recurse = true; } -#line 2904 "CMDgram.c" +#line 2858 "CMDgram.c" break; case 119: /* class_name_expr: IDENT */ -#line 503 "CMDgram.y" +#line 499 "CMDgram.y" { (yyval.expr) = ConstantNode::alloc( (yyvsp[0].s).lineNumber, (yyvsp[0].s).value ); } -#line 2910 "CMDgram.c" +#line 2864 "CMDgram.c" break; case 120: /* class_name_expr: '(' expr ')' */ -#line 505 "CMDgram.y" +#line 501 "CMDgram.y" { (yyval.expr) = (yyvsp[-1].expr); } -#line 2916 "CMDgram.c" +#line 2870 "CMDgram.c" break; case 121: /* assign_op_struct: opPLUSPLUS */ -#line 510 "CMDgram.y" +#line 506 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[0].i).lineNumber; (yyval.asn).token = opPLUSPLUS; (yyval.asn).expr = FloatNode::alloc( (yyvsp[0].i).lineNumber, 1 ); } -#line 2922 "CMDgram.c" +#line 2876 "CMDgram.c" break; case 122: /* assign_op_struct: opMINUSMINUS */ -#line 512 "CMDgram.y" +#line 508 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[0].i).lineNumber; (yyval.asn).token = opMINUSMINUS; (yyval.asn).expr = FloatNode::alloc( (yyvsp[0].i).lineNumber, 1 ); } -#line 2928 "CMDgram.c" +#line 2882 "CMDgram.c" break; case 123: /* assign_op_struct: opPLASN expr */ -#line 514 "CMDgram.y" +#line 510 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = '+'; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2934 "CMDgram.c" +#line 2888 "CMDgram.c" break; case 124: /* assign_op_struct: opMIASN expr */ -#line 516 "CMDgram.y" +#line 512 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = '-'; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2940 "CMDgram.c" +#line 2894 "CMDgram.c" break; case 125: /* assign_op_struct: opMLASN expr */ -#line 518 "CMDgram.y" +#line 514 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = '*'; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2946 "CMDgram.c" +#line 2900 "CMDgram.c" break; case 126: /* assign_op_struct: opDVASN expr */ -#line 520 "CMDgram.y" +#line 516 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = '/'; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2952 "CMDgram.c" +#line 2906 "CMDgram.c" break; case 127: /* assign_op_struct: opMODASN expr */ -#line 522 "CMDgram.y" +#line 518 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = '%'; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2958 "CMDgram.c" +#line 2912 "CMDgram.c" break; case 128: /* assign_op_struct: opANDASN expr */ -#line 524 "CMDgram.y" +#line 520 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = '&'; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2964 "CMDgram.c" +#line 2918 "CMDgram.c" break; case 129: /* assign_op_struct: opXORASN expr */ -#line 526 "CMDgram.y" +#line 522 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = '^'; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2970 "CMDgram.c" +#line 2924 "CMDgram.c" break; case 130: /* assign_op_struct: opORASN expr */ -#line 528 "CMDgram.y" +#line 524 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = '|'; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2976 "CMDgram.c" +#line 2930 "CMDgram.c" break; case 131: /* assign_op_struct: opSLASN expr */ -#line 530 "CMDgram.y" +#line 526 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = opSHL; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2982 "CMDgram.c" +#line 2936 "CMDgram.c" break; case 132: /* assign_op_struct: opSRASN expr */ -#line 532 "CMDgram.y" +#line 528 "CMDgram.y" { (yyval.asn).lineNumber = (yyvsp[-1].i).lineNumber; (yyval.asn).token = opSHR; (yyval.asn).expr = (yyvsp[0].expr); } -#line 2988 "CMDgram.c" +#line 2942 "CMDgram.c" break; case 133: /* stmt_expr: funcall_expr */ -#line 537 "CMDgram.y" +#line 533 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 2994 "CMDgram.c" +#line 2948 "CMDgram.c" break; case 134: /* stmt_expr: assert_expr */ -#line 539 "CMDgram.y" +#line 535 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 3000 "CMDgram.c" +#line 2954 "CMDgram.c" break; case 135: /* stmt_expr: object_decl */ -#line 541 "CMDgram.y" +#line 537 "CMDgram.y" { (yyval.expr) = (yyvsp[0].od); } -#line 3006 "CMDgram.c" +#line 2960 "CMDgram.c" break; case 136: /* stmt_expr: VAR '=' expr */ -#line 543 "CMDgram.y" +#line 539 "CMDgram.y" { (yyval.expr) = AssignExprNode::alloc( (yyvsp[-2].s).lineNumber, (yyvsp[-2].s).value, NULL, (yyvsp[0].expr)); } -#line 3012 "CMDgram.c" +#line 2966 "CMDgram.c" break; case 137: /* stmt_expr: VAR '[' aidx_expr ']' '=' expr */ -#line 545 "CMDgram.y" +#line 541 "CMDgram.y" { (yyval.expr) = AssignExprNode::alloc( (yyvsp[-5].s).lineNumber, (yyvsp[-5].s).value, (yyvsp[-3].expr), (yyvsp[0].expr)); } -#line 3018 "CMDgram.c" +#line 2972 "CMDgram.c" break; case 138: /* stmt_expr: VAR assign_op_struct */ -#line 547 "CMDgram.y" +#line 543 "CMDgram.y" { (yyval.expr) = AssignOpExprNode::alloc( (yyvsp[-1].s).lineNumber, (yyvsp[-1].s).value, NULL, (yyvsp[0].asn).expr, (yyvsp[0].asn).token); } -#line 3024 "CMDgram.c" +#line 2978 "CMDgram.c" break; case 139: /* stmt_expr: VAR '[' aidx_expr ']' assign_op_struct */ -#line 549 "CMDgram.y" +#line 545 "CMDgram.y" { (yyval.expr) = AssignOpExprNode::alloc( (yyvsp[-4].s).lineNumber, (yyvsp[-4].s).value, (yyvsp[-2].expr), (yyvsp[0].asn).expr, (yyvsp[0].asn).token); } -#line 3030 "CMDgram.c" +#line 2984 "CMDgram.c" break; case 140: /* stmt_expr: slot_acc assign_op_struct */ -#line 551 "CMDgram.y" +#line 547 "CMDgram.y" { (yyval.expr) = SlotAssignOpNode::alloc( (yyvsp[-1].slot).lineNumber, (yyvsp[-1].slot).object, (yyvsp[-1].slot).slotName, (yyvsp[-1].slot).array, (yyvsp[0].asn).token, (yyvsp[0].asn).expr); } -#line 3036 "CMDgram.c" +#line 2990 "CMDgram.c" break; case 141: /* stmt_expr: slot_acc '=' expr */ -#line 553 "CMDgram.y" +#line 549 "CMDgram.y" { (yyval.expr) = SlotAssignNode::alloc( (yyvsp[-2].slot).lineNumber, (yyvsp[-2].slot).object, (yyvsp[-2].slot).array, (yyvsp[-2].slot).slotName, (yyvsp[0].expr)); } -#line 3042 "CMDgram.c" +#line 2996 "CMDgram.c" break; case 142: /* stmt_expr: slot_acc '=' '{' expr_list '}' */ -#line 555 "CMDgram.y" +#line 551 "CMDgram.y" { (yyval.expr) = SlotAssignNode::alloc( (yyvsp[-4].slot).lineNumber, (yyvsp[-4].slot).object, (yyvsp[-4].slot).array, (yyvsp[-4].slot).slotName, (yyvsp[-1].expr)); } -#line 3048 "CMDgram.c" +#line 3002 "CMDgram.c" break; case 143: /* funcall_expr: IDENT '(' expr_list_decl ')' */ -#line 560 "CMDgram.y" +#line 556 "CMDgram.y" { (yyval.expr) = FuncCallExprNode::alloc( (yyvsp[-3].s).lineNumber, (yyvsp[-3].s).value, NULL, (yyvsp[-1].expr), false); } -#line 3054 "CMDgram.c" +#line 3008 "CMDgram.c" break; case 144: /* funcall_expr: IDENT opCOLONCOLON IDENT '(' expr_list_decl ')' */ -#line 562 "CMDgram.y" +#line 558 "CMDgram.y" { (yyval.expr) = FuncCallExprNode::alloc( (yyvsp[-5].s).lineNumber, (yyvsp[-3].s).value, (yyvsp[-5].s).value, (yyvsp[-1].expr), false); } -#line 3060 "CMDgram.c" +#line 3014 "CMDgram.c" break; case 145: /* funcall_expr: expr '.' IDENT '(' expr_list_decl ')' */ -#line 564 "CMDgram.y" +#line 560 "CMDgram.y" { (yyvsp[-5].expr)->append((yyvsp[-1].expr)); (yyval.expr) = FuncCallExprNode::alloc( (yyvsp[-5].expr)->dbgLineNumber, (yyvsp[-3].s).value, NULL, (yyvsp[-5].expr), true); } -#line 3066 "CMDgram.c" +#line 3020 "CMDgram.c" break; case 146: /* assert_expr: rwASSERT '(' expr ')' */ -#line 574 "CMDgram.y" +#line 570 "CMDgram.y" { (yyval.expr) = AssertCallExprNode::alloc( (yyvsp[-3].i).lineNumber, (yyvsp[-1].expr), NULL ); } -#line 3072 "CMDgram.c" +#line 3026 "CMDgram.c" break; case 147: /* assert_expr: rwASSERT '(' expr ',' STRATOM ')' */ -#line 576 "CMDgram.y" +#line 572 "CMDgram.y" { (yyval.expr) = AssertCallExprNode::alloc( (yyvsp[-5].i).lineNumber, (yyvsp[-3].expr), (yyvsp[-1].str).value ); } -#line 3078 "CMDgram.c" +#line 3032 "CMDgram.c" break; case 148: /* expr_list_decl: %empty */ -#line 581 "CMDgram.y" +#line 577 "CMDgram.y" { (yyval.expr) = NULL; } -#line 3084 "CMDgram.c" +#line 3038 "CMDgram.c" break; case 149: /* expr_list_decl: expr_list */ -#line 583 "CMDgram.y" +#line 579 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 3090 "CMDgram.c" +#line 3044 "CMDgram.c" break; case 150: /* expr_list: expr */ -#line 588 "CMDgram.y" +#line 584 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 3096 "CMDgram.c" +#line 3050 "CMDgram.c" break; case 151: /* expr_list: expr_list ',' expr */ -#line 590 "CMDgram.y" +#line 586 "CMDgram.y" { ((yyvsp[-2].expr))->append((yyvsp[0].expr)); (yyval.expr) = (yyvsp[-2].expr); } -#line 3102 "CMDgram.c" +#line 3056 "CMDgram.c" break; case 152: /* slot_assign_list_opt: %empty */ -#line 595 "CMDgram.y" +#line 591 "CMDgram.y" { (yyval.slist) = NULL; } -#line 3108 "CMDgram.c" +#line 3062 "CMDgram.c" break; case 153: /* slot_assign_list_opt: slot_assign_list */ -#line 597 "CMDgram.y" +#line 593 "CMDgram.y" { (yyval.slist) = (yyvsp[0].slist); } -#line 3114 "CMDgram.c" +#line 3068 "CMDgram.c" break; case 154: /* slot_assign_list: slot_assign */ -#line 602 "CMDgram.y" +#line 598 "CMDgram.y" { (yyval.slist) = (yyvsp[0].slist); } -#line 3120 "CMDgram.c" +#line 3074 "CMDgram.c" break; case 155: /* slot_assign_list: slot_assign_list slot_assign */ -#line 604 "CMDgram.y" +#line 600 "CMDgram.y" { (yyvsp[-1].slist)->append((yyvsp[0].slist)); (yyval.slist) = (yyvsp[-1].slist); } -#line 3126 "CMDgram.c" +#line 3080 "CMDgram.c" break; case 156: /* slot_assign: IDENT '=' expr ';' */ -#line 609 "CMDgram.y" +#line 605 "CMDgram.y" { (yyval.slist) = SlotAssignNode::alloc( (yyvsp[-3].s).lineNumber, NULL, NULL, (yyvsp[-3].s).value, (yyvsp[-1].expr)); } -#line 3132 "CMDgram.c" +#line 3086 "CMDgram.c" break; case 157: /* slot_assign: TYPEIDENT IDENT '=' expr ';' */ -#line 611 "CMDgram.y" +#line 607 "CMDgram.y" { (yyval.slist) = SlotAssignNode::alloc( (yyvsp[-4].i).lineNumber, NULL, NULL, (yyvsp[-3].s).value, (yyvsp[-1].expr), (yyvsp[-4].i).value); } -#line 3138 "CMDgram.c" +#line 3092 "CMDgram.c" break; case 158: /* slot_assign: rwDATABLOCK '=' expr ';' */ -#line 613 "CMDgram.y" +#line 609 "CMDgram.y" { (yyval.slist) = SlotAssignNode::alloc( (yyvsp[-3].i).lineNumber, NULL, NULL, StringTable->insert("datablock"), (yyvsp[-1].expr)); } -#line 3144 "CMDgram.c" +#line 3098 "CMDgram.c" break; case 159: /* slot_assign: IDENT '[' aidx_expr ']' '=' expr ';' */ -#line 615 "CMDgram.y" +#line 611 "CMDgram.y" { (yyval.slist) = SlotAssignNode::alloc( (yyvsp[-6].s).lineNumber, NULL, (yyvsp[-4].expr), (yyvsp[-6].s).value, (yyvsp[-1].expr)); } -#line 3150 "CMDgram.c" +#line 3104 "CMDgram.c" break; case 160: /* slot_assign: TYPEIDENT IDENT '[' aidx_expr ']' '=' expr ';' */ -#line 617 "CMDgram.y" +#line 613 "CMDgram.y" { (yyval.slist) = SlotAssignNode::alloc( (yyvsp[-7].i).lineNumber, NULL, (yyvsp[-4].expr), (yyvsp[-6].s).value, (yyvsp[-1].expr), (yyvsp[-7].i).value); } -#line 3156 "CMDgram.c" +#line 3110 "CMDgram.c" break; case 161: /* aidx_expr: expr */ -#line 622 "CMDgram.y" +#line 618 "CMDgram.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 3162 "CMDgram.c" +#line 3116 "CMDgram.c" break; case 162: /* aidx_expr: aidx_expr ',' expr */ -#line 624 "CMDgram.y" +#line 620 "CMDgram.y" { (yyval.expr) = CommaCatExprNode::alloc( (yyvsp[-2].expr)->dbgLineNumber, (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 3168 "CMDgram.c" +#line 3122 "CMDgram.c" break; -#line 3172 "CMDgram.c" +#line 3126 "CMDgram.c" default: break; } @@ -3371,7 +3325,7 @@ yyreturnlab: return yyresult; } -#line 626 "CMDgram.y" +#line 622 "CMDgram.y" int From 2207ae4a659ca73b12f1dae76acd850d22adc1a3 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 12 May 2025 16:35:08 +0100 Subject: [PATCH 39/41] Update console.h --- Engine/source/console/console.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index eec41a6a3..dda72ec05 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -150,6 +150,7 @@ public: }; S32 type; + U32 bufferLen; static DataChunker sConversionAllocator; @@ -159,24 +160,27 @@ public: TORQUE_FORCEINLINE void cleanupData() { - if (type == cvString) + if (type <= cvString && bufferLen > 0) { - if (s != StringTable->EmptyString()) - dFree(s); + dFree(s); + bufferLen = 0; } + s = const_cast(StringTable->EmptyString()); type = ConsoleValueType::cvNULL; } ConsoleValue() { type = ConsoleValueType::cvSTEntry; s = const_cast(StringTable->EmptyString()); + bufferLen = 0; } ConsoleValue(const ConsoleValue& ref) { type = ConsoleValueType::cvSTEntry; s = const_cast(StringTable->EmptyString()); + bufferLen = 0; switch (ref.type) { @@ -317,11 +321,14 @@ public: setEmptyString(); return; } + cleanupData(); type = ConsoleValueType::cvString; + s = (char*)dMalloc(len + 1); + bufferLen = len + 1; s[len] = '\0'; dStrcpy(s, val, len + 1); } @@ -342,7 +349,7 @@ public: TORQUE_FORCEINLINE void setStringTableEntry(StringTableEntry val) { - //cleanupData(); + cleanupData(); type = ConsoleValueType::cvSTEntry; s = const_cast(val); } From eec4573782382fddbf1757f79558853c599511f7 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 12 May 2025 16:49:08 +0100 Subject: [PATCH 40/41] Update torqueConfig.h.in --- Tools/CMake/torqueConfig.h.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tools/CMake/torqueConfig.h.in b/Tools/CMake/torqueConfig.h.in index a0bbc70a8..11eba5fbe 100644 --- a/Tools/CMake/torqueConfig.h.in +++ b/Tools/CMake/torqueConfig.h.in @@ -54,8 +54,9 @@ #cmakedefine TORQUE_MULTITHREAD /// Define me if you want to disable Torque memory manager. -#ifndef TORQUE_ENABLE_ASSERTS #cmakedefine TORQUE_DISABLE_MEMORY_MANAGER +#ifndef TORQUE_ENABLE_ASSERTS // disable memory manager when in release build. +#define TORQUE_DISABLE_MEMORY_MANAGER #endif /// Define me if you want to disable the virtual mount system. From fb1840ab1d6370cca5136f07b688ae4bcc9512c9 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 12 May 2025 21:17:26 +0100 Subject: [PATCH 41/41] Update console.h --- Engine/source/console/console.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index dda72ec05..beec7ccc8 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -337,7 +337,8 @@ public: { cleanupData(); type = ConsoleValueType::cvString; - s = const_cast(ref); + s = (char*)std::move(ref); + bufferLen = len; } TORQUE_FORCEINLINE void setBool(const bool val) @@ -351,7 +352,8 @@ public: { cleanupData(); type = ConsoleValueType::cvSTEntry; - s = const_cast(val); + s = (char*)std::move(val); + bufferLen = 0; } TORQUE_FORCEINLINE void setEmptyString()