ecere/com/templates: Tweaks to avoid 'AT' class being left declared
[sdk] / ecere / src / com / instance.ec
index e057737..4b43127 100644 (file)
@@ -1,12 +1,25 @@
+#define _Noreturn
+
 namespace com;
 
-// #define DISABLE_MEMMGR
+#if defined(__ANDROID__)
+ #define DISABLE_MEMMGR
+#endif
+
+#if defined(__EMSCRIPTEN__)
+ #define DISABLE_MEMMGR
+ #define _NOMUTEX
+#endif
 
 import "BinaryTree"
 import "OldList"
 import "String"
 import "dataTypes"
 
+//#define JUST_CHECK_LEAKS
+//#define JUST_CHECK_BOUNDARIES
+
+
 #if defined(ECERE_BOOTSTRAP) || defined(ECERE_STATIC)
 #define dllexport
 #if !defined(ECERE_BOOTSTRAP)
@@ -16,8 +29,20 @@ import "dataTypes"
 
 #undef __BLOCKS__
 
-#if !defined(ECERE_BOOTSTRAP)
+#if defined(ECERE_BOOTSTRAP)
+ #define _NOMUTEX
+#endif
+
+#if !defined(_NOMUTEX)
 import "Mutex"
+#else
+#if defined(MEMINFO)
+int GetCurrentThreadID() { return 0; }
+#endif
+#endif
+
+#if defined(__EMSCRIPTEN__)
+#define GetCurrentThreadID()  0
 #endif
 
 // #define MEMINFO
@@ -27,12 +52,21 @@ import "Mutex"
  #define REDZONE   256
 #endif
 */
-#ifndef REDZONE
+
+#if defined(JUST_CHECK_LEAKS) || !defined(REDZONE)
+#undef REDZONE
 #define REDZONE 0
 #endif
 
+
+#ifdef _DEBUG
+// #define MEMTRACKING
+#endif
+
 #ifdef MEMINFO
+#if !defined(_NOMUTEX)
 import "Thread"
+#endif
 static define MAX_MEMORY_LOC = 40;
 static define MAX_STACK_FRAMES = 1000;
 
@@ -80,7 +114,7 @@ private:
 
 #if defined(__ANDROID__)
 
-default const char * AndroidInterface_GetLibLocation();
+default const char * AndroidInterface_GetLibLocation(Module m);
 
 #include <android/log.h>
 #include <android/native_activity.h>
@@ -111,6 +145,7 @@ dllexport int isblank(int c);
 #endif
 bool Instance_LocateModule(const char * name, const char * fileName);
 void Instance_COM_Initialize(int argc, char ** argv, char ** parsedCommand, int * argcPtr, const char *** argvPtr);
+void System_SetArgs(int argc, char ** argv, int * argcPtr, const char *** argvPtr);
 void * Instance_Module_Load(const char * libLocation, const char * name, void ** Load, void ** Unload);
 void Instance_Module_Free(void * library);
 #if defined(_DEBUG)
@@ -178,7 +213,9 @@ public dllexport void MemoryGuard_PushLoc(const char * loc)
 {
 #ifdef MEMINFO
    MemStack stack;
+#if !defined(_NOMUTEX)
    memMutex.Wait();
+#endif
    stack = (MemStack)memStacks.Find(GetCurrentThreadID());
    if(!stack)
    {
@@ -188,22 +225,28 @@ public dllexport void MemoryGuard_PushLoc(const char * loc)
    }
    if(stack.pos < MAX_STACK_FRAMES)
       stack.frames[stack.pos++] = loc;
+#if !defined(_NOMUTEX)
    memMutex.Release();
 #endif
+#endif
 }
 
 public dllexport void MemoryGuard_PopLoc()
 {
 #ifdef MEMINFO
    MemStack stack;
+#if !defined(_NOMUTEX)
    memMutex.Wait();
+#endif
    stack = (MemStack)memStacks.Find(GetCurrentThreadID());
    if(stack && stack.pos > 0)
    {
       stack.pos--;
    }
+#if !defined(_NOMUTEX)
    memMutex.Release();
 #endif
+#endif
 }
 
 #ifdef ECERE_STATIC
@@ -344,7 +387,7 @@ public:
    ClassTemplateArgument * templateArgs;
    Class templateClass;
    OldList templatized;
-   int numParams;
+   int numParams;       // TOTAL number of params including all base classes; use templateParams.count for this level
    bool isInstanceClass;
    bool byValueSystemClass;
 
@@ -669,7 +712,7 @@ static class MemInfo : BTNode //struct
          printf("Object of class %s\n", _class);
       printf("   Allocation Stack:\n");
       for(c = 0; c<MAX_MEMORY_LOC; c++)
-#if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__)
+#if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__) || defined(_M_X64) || defined(_WIN64) || defined(__LP64__) || defined(__LLP64__)
          if(allocLoc[c] && allocLoc[c] != (void *)0xabababababababab)
 #else
          if(allocLoc[c] && allocLoc[c] != (void *)0xabababab)
@@ -702,15 +745,20 @@ static uint TOTAL_MEM = 0;
 static uint OUTSIDE_MEM = 0;
 #endif
 
+#if !defined(_NOMUTEX)
 #if !defined(ECERE_BOOTSTRAP)
 static Mutex memMutex { };
 #endif
+#endif
 
 private class MemBlock : struct
 {
    MemBlock prev, next;
    MemPart part;
    uint size;
+#if !defined(MEMINFO) && defined(MEMTRACKING)
+   Class _class;
+#endif
 };
 
 private class MemPart : struct
@@ -1017,6 +1065,7 @@ private struct BlockPool
 
    void Remove(MemBlock block)
    {
+      MemPart part = block.part;
       /*if(blockSize == 28)
          printf("BlockPool::Remove (%d)\n", blockSize);*/
       if(block.prev)
@@ -1038,14 +1087,13 @@ private struct BlockPool
          printf("Setting new free block: part = %x\n", block.part);
       }*/
 
-      block.part.blocksUsed--;
+      part.blocksUsed--;
       numBlocks--;
-      block.part.pool->usedSpace -= block.size;
+      part.pool->usedSpace -= block.size;
 
-      if(!block.part.blocksUsed && numBlocks && totalSize > numBlocks + numBlocks / 2)
+      if(!part.blocksUsed && numBlocks && totalSize > numBlocks + numBlocks / 2)
       {
          MemBlock next = free, prev = null;
-         MemPart part = block.part;
          free = null;
          totalSize -= part.size;
          /*if(blockSize == 28)
@@ -1140,6 +1188,7 @@ static uint log1_5i(uint number)
          break;
       current = current * 3 / 2;
       if(current == 1) current = 2;
+      if(current & 7) current += 8 - (current & 7);
    }
    return pos;
 }
@@ -1152,6 +1201,7 @@ static uint pow1_5(uint number)
    {
       current = current * 3 / 2;
       if(current == 1) current = 2;
+      if(current & 7) current += 8 - (current & 7);
    }
    return (uint)current;
 }
@@ -1167,6 +1217,7 @@ static uint pow1_5i(uint number)
          return (uint)current;
       current = current * 3 / 2;
       if(current == 1) current = 2;
+      if(current & 7) current += 8 - (current & 7);
    }
    return (uint)current;
 }
@@ -1227,6 +1278,9 @@ static void * _mymalloc(unsigned int size)
          block = pools[p].Add();
          if(block)
          {
+#if defined(MEMTRACKING)
+            block._class = null;
+#endif
             block.size = size;
             pools[p].usedSpace += size;
          }
@@ -1239,6 +1293,9 @@ static void * _mymalloc(unsigned int size)
             TOTAL_MEM += sizeof(class MemBlock) + size;
             OUTSIDE_MEM += sizeof(class MemBlock) + size;
             block.part = null;
+#if defined(MEMTRACKING)
+            block._class = null;
+#endif
             block.size = size;
          }
       }
@@ -1266,11 +1323,20 @@ static void _myfree(void * pointer)
          printf("WARNING! pool is -1\n");
       else   */
       if(pool)
+      {
+#ifdef _DEBUG
+         memset(pointer, 0xec, block.size);
+#endif
          pool->Remove(block);
+      }
       else
       {
          TOTAL_MEM -= sizeof(class MemBlock) + block.size;
          OUTSIDE_MEM -= sizeof(class MemBlock) + block.size;
+
+#ifdef _DEBUG
+         memset(block, 0xec, sizeof(class MemBlock) + block.size);
+#endif
          free(block);
       }
    }
@@ -1407,7 +1473,7 @@ static void * _malloc(unsigned int size)
    void * pointer;
 
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(_NOMUTEX)
    memMutex.Wait();
 #endif
 
@@ -1434,7 +1500,9 @@ static void * _malloc(unsigned int size)
                printf("      %s\n", stack.frames[c]);
 
          memoryErrorsCount++;
+#if !defined(_NOMUTEX)
          memMutex.Release();
+#endif
          return null;
       }
 
@@ -1449,7 +1517,7 @@ static void * _malloc(unsigned int size)
    }
 #endif
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(_NOMUTEX)
    memMutex.Release();
 #endif
 
@@ -1472,7 +1540,7 @@ static void * _calloc(int n, unsigned int size)
 #else
    void * pointer;
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(_NOMUTEX)
    memMutex.Wait();
 #endif
 
@@ -1497,7 +1565,9 @@ static void * _calloc(int n, unsigned int size)
             if(stack.frames[c])
                printf("      %s\n", stack.frames[c]);
          memoryErrorsCount++;
+#if !defined(_NOMUTEX)
          memMutex.Release();
+#endif
          return null;
       }
 
@@ -1514,7 +1584,7 @@ static void * _calloc(int n, unsigned int size)
    }
 #endif
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(_NOMUTEX)
    memMutex.Release();
 #endif
 
@@ -1538,7 +1608,7 @@ static void * _realloc(void * pointer, unsigned int size)
 #else
    if(!size) { _free(pointer); return null; }
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(_NOMUTEX)
    memMutex.Wait();
 #endif
 
@@ -1580,7 +1650,9 @@ static void * _realloc(void * pointer, unsigned int size)
          if(stack.frames[c])
             printf("      %s\n", stack.frames[c]);
       memoryErrorsCount++;
+#if !defined(_NOMUTEX)
       memMutex.Release();
+#endif
       return null;
    }
    memset(pointer, 0xAB, REDZONE);
@@ -1588,6 +1660,12 @@ static void * _realloc(void * pointer, unsigned int size)
 
    if(block)
    {
+#if defined(JUST_CHECK_LEAKS) || defined(JUST_CHECK_BOUNDARIES)
+      memcpy((byte *)pointer + REDZONE, (byte *)block.key, Min(block.size, size));
+      free((byte *)block.key - REDZONE);
+      memBlocks.Remove(block);
+      free(block);
+#else
       if(block.freed)
       {
          memcpy((byte *)pointer + REDZONE, block.oldmem, Min(block.size, size));
@@ -1605,6 +1683,7 @@ static void * _realloc(void * pointer, unsigned int size)
          memset((byte *)block.key - REDZONE, 0xEC, block.size + REDZONE * 2);
          block.freed = true;
       }
+#endif
    }
 
    if(!recurse && !stack.recurse)
@@ -1621,7 +1700,7 @@ static void * _realloc(void * pointer, unsigned int size)
    pointer = realloc(pointer, size);
 #endif
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(_NOMUTEX)
    memMutex.Release();
 #endif
    return pointer ? ((byte *)pointer + REDZONE) : null;
@@ -1642,7 +1721,7 @@ static void * _crealloc(void * pointer, unsigned int size)
 #else
    if(!size) { _free(pointer); return null; }
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(_NOMUTEX)
    memMutex.Wait();
 #endif
 
@@ -1684,7 +1763,9 @@ static void * _crealloc(void * pointer, unsigned int size)
          if(stack.frames[c])
             printf("      %s\n", stack.frames[c]);
       memoryErrorsCount++;
+#if !defined(_NOMUTEX)
       memMutex.Release();
+#endif
       return null;
    }
    memset(pointer, 0xAB, REDZONE);
@@ -1692,6 +1773,12 @@ static void * _crealloc(void * pointer, unsigned int size)
 
    if(block)
    {
+#if defined(JUST_CHECK_LEAKS) || defined(JUST_CHECK_BOUNDARIES)
+      memcpy((byte *)pointer + REDZONE, (byte *)block.key, Min(block.size, size));
+      free((byte *)block.key - REDZONE);
+      memBlocks.Remove(block);
+      free(block);
+#else
       if(block.freed)
       {
          memcpy((byte *)pointer + REDZONE, block.oldmem, Min(block.size, size));
@@ -1709,6 +1796,7 @@ static void * _crealloc(void * pointer, unsigned int size)
          memset((byte *)block.key - REDZONE, 0xEC, block.size + REDZONE * 2);
          block.freed = true;
       }
+#endif
    }
 
    if(!recurse && !stack.recurse)
@@ -1725,7 +1813,7 @@ static void * _crealloc(void * pointer, unsigned int size)
    pointer = crealloc(pointer, size);
 #endif
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(_NOMUTEX)
    memMutex.Release();
 #endif
    return pointer ? ((byte *)pointer + REDZONE) : null;
@@ -1739,7 +1827,7 @@ static void _free(void * pointer)
 #if defined(DISABLE_MEMMGR) && !defined(MEMINFO)
       free(pointer);
 #else
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(_NOMUTEX)
       if(memMutex != pointer) memMutex.Wait();
 #endif
 
@@ -1826,6 +1914,11 @@ static void _free(void * pointer)
             }
 
             block.freed = true;
+#if defined(JUST_CHECK_LEAKS) || defined(JUST_CHECK_BOUNDARIES)
+            free((byte *)block.key - REDZONE);
+            memBlocks.Remove(block);
+            free(block);
+#else
             block.oldmem = (byte *)malloc(block.size + REDZONE * 2);
             if(block.oldmem)
             {
@@ -1835,6 +1928,7 @@ static void _free(void * pointer)
             memset((byte *)block.key - REDZONE, 0xEC, block.size + REDZONE * 2);
 
             memcpy(block.freeLoc, stack.frames + stack.pos - Min(stack.pos, MAX_MEMORY_LOC), Min(stack.pos, MAX_MEMORY_LOC) * sizeof(char *));
+#endif
          }
          stack.recurse = false;
       }
@@ -1843,7 +1937,7 @@ static void _free(void * pointer)
       free(pointer);
 #endif
 
-#if !defined(ECERE_BOOTSTRAP)
+#if !defined(_NOMUTEX)
       if(memMutex != pointer) memMutex.Release();
 #endif
 
@@ -1995,7 +2089,7 @@ static void FixDerivativesBase(Class base, Class mod)
 {
    OldLink derivative;
 
-   ComputeClassParameters(base, strchr(base.name, '<'), null);
+   ComputeClassParameters(base, strchr(base.name, '<'), null, base.templateClass != mod);
 
    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
    {
@@ -2050,8 +2144,12 @@ static void FixDerivativesBase(Class base, Class mod)
       // _class.memberID = _class.startMemberID = (base && (type == normalClass || type == noHeadClass || type == structClass)) ? base.memberID : 0;
 
       if(type == normalClass || type == noHeadClass)
+      {
          // Use 'memberOffset' for nohead class as the members get added without padding
          _class.offset = (base && (base.templateClass ? (type == normalClass ? base.templateClass.structSize : base.templateClass.memberOffset) : (type == normalClass ? base.structSize : base.memberOffset)) && base.type != systemClass) ? (base.templateClass ? base.templateClass.structSize : base.structSize) : ((type == noHeadClass) ? 0 : sizeof(class Instance));
+         if(_class.structAlignment && (_class.offset % _class.structAlignment))
+            _class.offset += _class.structAlignment - _class.offset % _class.structAlignment;
+      }
       else
          _class.offset = 0; // Force set to 0
 
@@ -2267,7 +2365,7 @@ static void FixDerivativesBase(Class base, Class mod)
          //const char * templateParams = strchr(template.name, '<');
          template.base = base.base;
          template._vTbl = base._vTbl;
-         //ComputeClassParameters(template, templateParams, null);
+         //ComputeClassParameters(template, templateParams, null, true);
 
          template.data = base.data;
          template.offset = base.offset;
@@ -2349,7 +2447,7 @@ public dllexport Class eSystem_RegisterClass(ClassType type, const char * name,
       Class _class = null;
       const char * dataTypeString = null;
       Class enumBase = null;
-      Class base = (baseName && baseName[0]) ? eSystem_FindClass(module, baseName) : null;
+      Class base = (baseName && baseName[0]) ? System_FindClass(module, baseName, true) : null;
       Class prevBase = null;
 
       if(base && !base.internalDecl && (base.type == noHeadClass || base.type == structClass || base.type == normalClass))
@@ -2464,13 +2562,13 @@ public dllexport Class eSystem_RegisterClass(ClassType type, const char * name,
       offsetClass = base ? base.sizeClass : (type == noHeadClass ? 0 : 0 /*sizeof(class Class)*/);
       totalSizeClass = offsetClass + sizeClass;
 
-      _class = eSystem_FindClass(module, name);
+      _class = System_FindClass(module, name, true);
       if(!_class)
       {
          const char * colons = RSearchString(name, "::", strlen(name), true, false);
          if(colons && colons)
          {
-            _class = eSystem_FindClass(module, colons + 2);
+            _class = System_FindClass(module, colons + 2, true);
             if(_class)
             {
                if(_class.internalDecl)
@@ -2514,7 +2612,8 @@ public dllexport Class eSystem_RegisterClass(ClassType type, const char * name,
          }
          {
             NameSpace * ns = _class.nameSpace;
-            while(ns->parent &&
+            while(ns != nameSpace &&
+               ns->parent &&
                !ns->classes.first &&
                !ns->functions.first &&
                !ns->defines.first &&
@@ -2596,13 +2695,13 @@ public dllexport Class eSystem_RegisterClass(ClassType type, const char * name,
                Class templateBase;
                strcpy(templateClassName, baseName);
                *strchr(templateClassName, '<') = '\0';
-               templateBase = eSystem_FindClass(module, templateClassName);
+               templateBase = System_FindClass(module, templateClassName, true);
                if(!templateBase)
                {
                   templateBase = eSystem_RegisterClass(0, templateClassName, null, 0,0, null, null, module, declMode, publicAccess);
                   templateBase.internalDecl = true;
                }
-               base = eSystem_FindClass(module, baseName);
+               base = System_FindClass(module, baseName, true);
             }
             else
             {
@@ -2728,7 +2827,8 @@ public dllexport Class eSystem_RegisterClass(ClassType type, const char * name,
                !strcmp(name, "LineStyle") ||
                !strcmp(name, "FillStyle") ||
                !strcmp(name, "FontObject") ||
-               !strcmp(name, "SymbolStyle"))
+               !strcmp(name, "FontObject") ||
+               !strcmp(name, "ecere::sys::Thread"))
             {
                _class.offset = force32Bits ? 24 : 12;
             }
@@ -2778,7 +2878,7 @@ public dllexport Class eSystem_RegisterClass(ClassType type, const char * name,
          }
          else if(type == bitClass || type == enumClass || type == unitClass)
          {
-            Class dataTypeClass = eSystem_FindClass(_class.module, dataTypeString);
+            Class dataTypeClass = System_FindClass(_class.module, dataTypeString, true);
             if(dataTypeClass)
                _class.typeSize = dataTypeClass.typeSize;
             _class.structSize = 0;
@@ -2888,6 +2988,7 @@ static void FreeTemplateArg(Class template, ClassTemplateParameter param, int id
    {
       case type:
          delete (void *)template.templateArgs[id].dataTypeString;
+         template.templateArgs[id].dataTypeClass = null;
          break;
       case identifier:
          delete (void *)template.templateArgs[id].memberString;
@@ -2922,6 +3023,7 @@ static void FreeTemplateArgs(Class template)
                {
                   case type:
                      delete (void *)template.templateArgs[id].dataTypeString;
+                     template.templateArgs[id].dataTypeClass = null;
                      break;
                   case identifier:
                      delete (void *)template.templateArgs[id].memberString;
@@ -2947,12 +3049,9 @@ static void FreeTemplate(Class template)
       if(link)
          template.nameSpace->classes.Delete((BTNode)link);
    }
-   FreeTemplateArgs(template);
 
-   delete (void *)template.fullName;
-   delete (void *)template.name;
-   delete (void *)template.templateArgs;
-   delete (void *)template.dataTypeString;
+   FreeTemplatesDerivatives(template);
+   FreeTemplateArgs(template);
 
    while((deriv = template.derivatives.first))
    {
@@ -2960,6 +3059,11 @@ static void FreeTemplate(Class template)
       template.derivatives.Delete(deriv);
    }
 
+   delete (void *)template.fullName;
+   delete (void *)template.name;
+   delete template.templateArgs;
+   delete (void *)template.dataTypeString;
+
    if(template.module)
       template.module.classes.Delete(template);
    else
@@ -2976,8 +3080,6 @@ static void FreeTemplates(Class _class)
    }
 
    FreeTemplateArgs(_class);
-   //if(_class.templateArgs)
-      //printf("Deleting  Template args for %s\n", _class.name);
    delete _class.templateArgs;
    delete (void *)_class.dataTypeString;
 
@@ -3018,9 +3120,6 @@ public dllexport void eClass_Unregister(Class _class)
 
    FreeTemplates(_class);
 
-   FreeTemplateArgs(_class);
-   delete _class.templateArgs;
-
    while((template = _class.templatized.first))
    {
       FreeTemplate(template.data);
@@ -3242,25 +3341,20 @@ public int64 _strtoi64(const char * string, const char ** endString, int base)
       else if(ch >= 'A' && ch <= 'Z')
          ch -= ('A'- 10);
       else
-      {
-         if(endString)
-            *endString = string + c;
          // Invalid character
          break;
-      }
       if(ch < base)
       {
          value *= base;
          value += ch;
       }
       else
-      {
-         if(endString)
-            *endString = string + c;
          // Invalid character
          break;
-      }
    }
+   if(endString)
+      *endString = string + c;
+
    return sign*value;
 }
 
@@ -3297,30 +3391,29 @@ public uint64 _strtoui64(const char * string, const char ** endString, int base)
       else if(ch >= 'A' && ch <= 'Z')
          ch -= ('A' - 10);
       else
-      {
-         if(endString)
-            *endString = string + c;
          // Invalid character
          break;
-      }
       if(ch < base)
       {
          value *= base;
          value += ch;
       }
       else
-      {
-         if(endString)
-            *endString = string + c;
          // Invalid character
          break;
-      }
    }
+   if(endString)
+      *endString = string + c;
    return sign*value;
 }
 
 public dllexport Class eSystem_FindClass(Module module, const char * name)
 {
+   return System_FindClass(module, name, false);
+}
+
+Class System_FindClass(Module module, const char * name, bool registerTemplatesInternalDecl)
+{
    if(name && module)
    {
       BTNamedLink link;
@@ -3385,7 +3478,7 @@ public dllexport Class eSystem_FindClass(Module module, const char * name)
 
                module.classes.Add(templatedClass);
 
-               ComputeClassParameters(templatedClass, templateParams, module);
+               ComputeClassParameters(templatedClass, templateParams, module, registerTemplatesInternalDecl);
 
                _class.templatized.Add(OldLink { data = templatedClass });
             }
@@ -3401,7 +3494,7 @@ static void CopyTemplateArg(ClassTemplateParameter param, ClassTemplateArgument
    switch(param.type)
    {
       case type:
-         arg.dataTypeString = CopyString(arg.dataTypeString);
+            arg.dataTypeString = CopyString(arg.dataTypeString);
          break;
       case expression:
 
@@ -3412,7 +3505,7 @@ static void CopyTemplateArg(ClassTemplateParameter param, ClassTemplateArgument
    }
 }
 
-static void ComputeClassParameters(Class templatedClass, const char * templateParams, Module findModule)
+static void ComputeClassParameters(Class templatedClass, const char * templateParams, Module findModule, bool registerInternalDecl)
 {
    char ch;
    const char * nextParamStart = templateParams ? (templateParams + 1) : null;
@@ -3618,14 +3711,28 @@ static void ComputeClassParameters(Class templatedClass, const char * templatePa
             {
                case type:
                   argument.dataTypeString = CopyString(value);
-                  argument.dataTypeClass = eSystem_FindClass(_class.module, value);
-                  if(!argument.dataTypeClass) argument.dataTypeClass = eSystem_FindClass(_class.module.application, value);
-                  if(!argument.dataTypeClass) argument.dataTypeClass = eSystem_FindClass(findModule, value);
+                  argument.dataTypeClass = System_FindClass(findModule, value, registerInternalDecl);
+                  if(!argument.dataTypeClass)
+                     argument.dataTypeClass = System_FindClass(_class.module, value, registerInternalDecl);
+                  if(!argument.dataTypeClass)
+                     argument.dataTypeClass = System_FindClass(_class.module.application, value, registerInternalDecl);
+                  if(registerInternalDecl && !argument.dataTypeClass)
+                  {
+                     ClassTemplateParameter param;
+                     for(param = templatedClass.templateParams.first; param; param = param.next)
+                        if(!strcmp(param.name, value))
+                           break;
+                     if(!param)
+                     {
+                        argument.dataTypeClass = eSystem_RegisterClass(0, value, null, 0,0, null, null, _class.module, publicAccess, publicAccess);
+                        argument.dataTypeClass.internalDecl = true;
+                     }
+                  }
                   break;
                case expression:
                {
-                  Class expClass = eSystem_FindClass(_class.module, curParam.dataTypeString);
-                  if(!expClass) expClass = eSystem_FindClass(_class.module.application, curParam.dataTypeString);
+                  Class expClass = System_FindClass(_class.module, curParam.dataTypeString, true);
+                  if(!expClass) expClass = System_FindClass(_class.module.application, curParam.dataTypeString, true);
                   if(expClass)
                   {
                      //if(expClass.type ==
@@ -3718,11 +3825,11 @@ static void ComputeClassParameters(Class templatedClass, const char * templatePa
             CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
             if(param.type == type && param.defaultArg.dataTypeString)
             {
-               templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
+               templatedClass.templateArgs[curParamID].dataTypeClass = System_FindClass(findModule, param.defaultArg.dataTypeString, true);
                if(!templatedClass.templateArgs[curParamID].dataTypeClass)
-                  templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
+                  templatedClass.templateArgs[curParamID].dataTypeClass = System_FindClass(templatedClass.module, param.defaultArg.dataTypeString, true);
                if(!templatedClass.templateArgs[curParamID].dataTypeClass)
-                  templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
+                  templatedClass.templateArgs[curParamID].dataTypeClass = System_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString, true);
             }
          }
          curParamID++;
@@ -3764,6 +3871,7 @@ static void ComputeClassParameters(Class templatedClass, const char * templatePa
                         {
                            int id = p;
                            Class sClass;
+                           // NOTE: This struct 'arg' here is only to build up templateString
                            ClassTemplateArgument arg;
                            for(sClass = expClass.base; sClass; sClass = sClass.base) id += sClass.templateParams.count;
                            arg = expClass.templateArgs[id];
@@ -3775,8 +3883,7 @@ static void ComputeClassParameters(Class templatedClass, const char * templatePa
                               {
                                  if(cParam.type == type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
                                  {
-                                    arg.dataTypeString = templatedClass.templateArgs[p].dataTypeString;
-                                    arg.dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
+                                    arg = templatedClass.templateArgs[p];
                                     break;
                                  }
                               }
@@ -3846,9 +3953,11 @@ static void ComputeClassParameters(Class templatedClass, const char * templatePa
                      FreeTemplateArg(templatedClass, param, c);
 
                      arg->dataTypeString = CopyString(templateString);
-                     arg->dataTypeClass = eSystem_FindClass(templatedClass.module, templateString);
+                     arg->dataTypeClass = System_FindClass(findModule, templateString, true);
                      if(!arg->dataTypeClass)
-                        arg->dataTypeClass = eSystem_FindClass(templatedClass.module.application, templateString);
+                        arg->dataTypeClass = System_FindClass(templatedClass.module, templateString, true);
+                     if(!arg->dataTypeClass)
+                        arg->dataTypeClass = System_FindClass(templatedClass.module.application, templateString, true);
                   }
                   else
                   {
@@ -3861,6 +3970,7 @@ static void ComputeClassParameters(Class templatedClass, const char * templatePa
                         {
                            FreeTemplateArg(templatedClass, param, c);
 
+                           // TRICKY: This copies from equivalent parameters
                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
                            CopyTemplateArg(cParam, arg);
@@ -3898,11 +4008,11 @@ static void ComputeClassParameters(Class templatedClass, const char * templatePa
                CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
                if(param.type == type && param.defaultArg.dataTypeString)
                {
-                  templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
+                  templatedClass.templateArgs[curParamID].dataTypeClass = System_FindClass(findModule, param.defaultArg.dataTypeString, true);
                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
-                     templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
+                     templatedClass.templateArgs[curParamID].dataTypeClass = System_FindClass(templatedClass.module, param.defaultArg.dataTypeString, true);
                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
-                     templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
+                     templatedClass.templateArgs[curParamID].dataTypeClass = System_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString, true);
                }
             }
             curParamID++;
@@ -4000,12 +4110,12 @@ static void ComputeClassParameters(Class templatedClass, const char * templatePa
                         id++;
                      }
                   }
-                  memberClass = eSystem_FindClass(templatedClass.module, className);
                   // TESTING: Added this here...
+                  memberClass = System_FindClass(findModule, className, true);
                   if(!memberClass)
-                     memberClass = eSystem_FindClass(findModule, className);
+                     memberClass = System_FindClass(templatedClass.module, className, true);
                   if(!memberClass)
-                     memberClass = eSystem_FindClass(templatedClass.module.application, className);
+                     memberClass = System_FindClass(templatedClass.module.application, className, true);
                }
 
                if(memberClass)
@@ -4181,7 +4291,7 @@ public dllexport Method eClass_AddMethod(Class _class, const char * name, const
                if(method.vid >= _class.vTblSize)
                   printf("error: virtual methods overriding failure\n");
                else
-                  _class._vTbl[method.vid] = function ? function : (void *)DefaultFunction;
+                  _class._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
                for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
                {
                   Class derivClass = deriv.data;
@@ -4222,7 +4332,7 @@ public dllexport Method eClass_AddMethod(Class _class, const char * name, const
          Method method
          {
             name = CopyString(name),
-            function = function ? function : DefaultFunction;
+            function = function ? function : null; //DefaultFunction;
             _class = _class;
             dataTypeString = CopyString(type);
             memberAccess = declMode;
@@ -4250,7 +4360,7 @@ public dllexport Method eClass_AddVirtualMethod(Class _class, const char * name,
                if(method.vid >= _class.vTblSize)
                   printf("error: virtual methods overriding failure\n");
                else
-                  _class._vTbl[method.vid] = function ? function : (void *)DefaultFunction;
+                  _class._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
             }
             else
                base = null;
@@ -4263,7 +4373,7 @@ public dllexport Method eClass_AddVirtualMethod(Class _class, const char * name,
          Method method
          {
             name = CopyString(name);
-            function = function ? function : DefaultFunction;
+            function = function ? function : null; //DefaultFunction;
             type = virtualMethod;
             _class = _class;
             vid = _class.vTblSize++;
@@ -4272,11 +4382,11 @@ public dllexport Method eClass_AddVirtualMethod(Class _class, const char * name,
          };
          _class.methods.Add((BTNode)method);
          _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
-         _class._vTbl[method.vid] = function ? function : (void *)DefaultFunction;
+         _class._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
 
          // TODO: Fix derived classes
          if(_class.derivatives.first || _class.templatized.first)
-            FixDerivativeVirtualMethod(_class, name, method.vid, function ? function : (void *)DefaultFunction, type);
+            FixDerivativeVirtualMethod(_class, name, method.vid, function ? function : null /*(void *)DefaultFunction*/, type);
          return method;
       }
    }
@@ -4548,7 +4658,9 @@ public dllexport void * eInstance_New(Class _class)
 #ifdef MEMINFO
 
 #undef malloc
+#if !defined(_NOMUTEX)
    memMutex.Wait();
+#endif
       //allocateClass = _class;
       allocateClass = malloc(strlen(_class.name)+1);
       allocateInternal = _class.module == __thisModule;
@@ -4574,18 +4686,32 @@ public dllexport void * eInstance_New(Class _class)
                size *= 3;
          }
          instance = _calloc(1, size);
+         if(!instance && size)
+            printf("Failed to allocate memory instantiating %s object!\n", _class.name);
+         else if(!size)
+            printf("Warning: 0 size instantiating %s object!\n", _class.name);
       }
 #ifdef MEMINFO
       allocateClass = null;
+#if !defined(_NOMUTEX)
    memMutex.Release();
 #endif
-      if(_class.type == normalClass)
+#endif
+
+#if !defined(MEMINFO) && defined(MEMTRACKING)
+      {
+         MemBlock block = (MemBlock)((byte *)instance - sizeof(class MemBlock));
+         block._class = _class;
+      }
+#endif
+
+      if(instance && _class.type == normalClass)
       {
          instance._class = _class;
          // Copy the virtual table initially
          instance._vTbl = _class._vTbl;
       }
-      if(!ConstructInstance(instance, _class, null))
+      if(instance && !ConstructInstance(instance, _class, null))
       {
          _free(instance);
          instance = null;
@@ -4724,7 +4850,7 @@ public dllexport void eInstance_Delete(Instance instance)
       bool ownVtbl;
 
 #ifdef MEMINFO
-#if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__)
+#if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__) || defined(_M_X64) || defined(_WIN64) || defined(__LP64__) || defined(__LLP64__)
       if(instance._class == (void *)0xecececececececec)
 #else
       if(instance._class == (void *)0xecececec)
@@ -5134,7 +5260,7 @@ public dllexport void eInstance_SetMethod(Instance instance, const char * name,
                memcpy(instance._vTbl, instance._class._vTbl,
                   sizeof(int(*)()) * instance._class.vTblSize);
             }
-            instance._vTbl[method.vid] = function ? function : (void *)DefaultFunction;
+            instance._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
          }
       }
    }
@@ -5219,7 +5345,7 @@ public dllexport DataMember eClass_AddDataMember(Class _class, const char * name
                }
             }
 
-            if(pointerAlignment) alignment = sizeof(void *);
+            if(pointerAlignment) alignment = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
 
             if(pointerAlignment && _class.structAlignment <= 4)
                _class.pointerAlignment = 1;
@@ -5228,6 +5354,11 @@ public dllexport DataMember eClass_AddDataMember(Class _class, const char * name
 
             _class.structAlignment = Max(_class.structAlignment, alignment);
 
+            if(_class.offset % alignment)
+            {
+               _class.structSize += alignment - (_class.offset % alignment);
+               _class.offset += alignment - (_class.offset % alignment);
+            }
             if(_class.memberOffset % alignment)
                _class.memberOffset += alignment - (_class.memberOffset % alignment);
          }
@@ -5261,7 +5392,9 @@ public dllexport DataMember eMember_AddDataMember(DataMember member, const char
       if(alignment)
       {
          bool pointerAlignment = alignment == 0xF000F000;
-         if(pointerAlignment) alignment = sizeof(void *);
+         bool force64Bits = false; //(member._class.module.application.isGUIApp & 2) ? true : false;
+         bool force32Bits = false; //(member._class.module.application.isGUIApp & 4) ? true : false;
+         if(pointerAlignment) alignment = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
 
          if(pointerAlignment && member.structAlignment <= 4)
             member.pointerAlignment = 1;
@@ -5465,7 +5598,7 @@ static Module Module_Load(Module fromModule, const char * name, AccessMode impor
       {
          const char * libLocation = null;
 #if defined(__ANDROID__)
-         libLocation = AndroidInterface_GetLibLocation();
+         libLocation = AndroidInterface_GetLibLocation(fromModule.application);
 #endif
          library = Instance_Module_Load(libLocation, name, &Load, &Unload);
       }
@@ -5548,7 +5681,7 @@ static Module Module_Load(Module fromModule, const char * name, AccessMode impor
       }
       incref module;
    }
-#if defined(_DEBUG)
+#if defined(_DEBUG) && !defined(__ANDROID__)
    InternalModuleLoadBreakpoint();
 #endif
    return module;
@@ -5866,7 +5999,7 @@ static int64 GetEnumSize(Class _class)
 #define strnicmp strncasecmp
 #endif
 
-#if defined(ECERE_BOOTSTRAP) || (defined(__GNUC__) && !defined(__DJGPP__) && !defined(__WIN32__))
+#if defined(ECERE_BOOTSTRAP) || (defined(__GNUC__) && !defined(__DJGPP__) && !defined(__WIN32__) && !defined(__EMSCRIPTEN__))
 #undef strlwr
 #undef strupr
 default dllexport char * strlwr(char *string)
@@ -6243,7 +6376,7 @@ public bool LocateModule(const char * name, const char * fileName)
 }
 
 /*
-#if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__)
+#if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__) || defined(_M_X64) || defined(_WIN64) || defined(__LP64__) || defined(__LLP64__)
 #define _64BIT 1
 #else
 #define _64BIT 0
@@ -6458,7 +6591,7 @@ static void LoadCOM(Module module)
 
    // --- Stdio ---
    eSystem_RegisterFunction("sprintf", "int sprintf(char *, const char *, ...)", sprintf, module, baseSystemAccess);
-   eSystem_RegisterFunction("snprintf", "int sprintf(char *, uintsize, const char *, ...)", snprintf, module, baseSystemAccess);
+   eSystem_RegisterFunction("snprintf", "int snprintf(char *, uintsize, const char *, ...)", snprintf, module, baseSystemAccess);
    eSystem_RegisterFunction("printf", "int printf(const char *, ...)", printf, module, baseSystemAccess);
    eSystem_RegisterFunction("vsprintf", "int vsprintf(char*, const char*, __builtin_va_list)", vsprintf, module, baseSystemAccess);
    eSystem_RegisterFunction("vsnprintf", "int vsnprintf(char*, uintsize, const char*, __builtin_va_list)", vsnprintf, module, baseSystemAccess);
@@ -6486,8 +6619,11 @@ public dllexport Application __ecere_COM_Initialize(bool guiApp, int argc, char
 
 #ifdef __ANDROID__
    // Clean up global variables
+#if !defined(DISABLE_MEMMGR)
    memoryInitialized = false;
    pools = null;
+#endif
+
 #ifdef MEMINFO
    memset(&memStacks, 0, sizeof(BinaryTree));
    memoryErrorsCount = 0;
@@ -6525,6 +6661,11 @@ public dllexport Application __ecere_COM_Initialize(bool guiApp, int argc, char
    return app;
 }
 
+public dllexport void eSystem_SetArgs(Application app, int argc, char * argv[])
+{
+   System_SetArgs(argc, argv, &app.argc, &app.argv);
+}
+
 public dllexport ClassTemplateParameter eClass_AddTemplateParameter(Class _class, const char * name, TemplateParameterType type, const void * info, ClassTemplateArgument defaultArg)
 {
    if(_class && name)
@@ -6542,6 +6683,15 @@ public dllexport ClassTemplateParameter eClass_AddTemplateParameter(Class _class
          type = type;
          (type == identifier) ? info : CopyString(info);
       };
+
+      {
+         Class c = eSystem_FindClass(_class.module, name);
+         if(c && c.internalDecl)
+         {
+            c.module.classes.Remove(c);
+            eClass_Unregister(c);
+         }
+      }
       if(defaultArg != null)
       {
          param.defaultArg = defaultArg;
@@ -6885,7 +7035,33 @@ public int ISO8859_1toUTF8(const char * source, char * dest, int max)
       unichar ch = ((byte *)source)[c];
       switch(ch)
       {
-         case 150: ch = (unichar)0x2012; break;
+         case 128: ch = (unichar)0x20AC; break;
+         case 130: ch = (unichar)0x201A; break;
+         case 131: ch = (unichar)0x0192; break;
+         case 132: ch = (unichar)0x201E; break;
+         case 133: ch = (unichar)0x2026; break;
+         case 134: ch = (unichar)0x2020; break;
+         case 135: ch = (unichar)0x2021; break;
+         case 136: ch = (unichar)0x02C6; break;
+         case 137: ch = (unichar)0x2030; break;
+         case 138: ch = (unichar)0x0160; break;
+         case 139: ch = (unichar)0x2039; break;
+         case 140: ch = (unichar)0x0152; break;
+         case 142: ch = (unichar)0x017D; break;
+         case 145: ch = (unichar)0x2018; break;
+         case 146: ch = (unichar)0x2019; break;
+         case 147: ch = (unichar)0x201C; break;
+         case 148: ch = (unichar)0x201D; break;
+         case 149: ch = (unichar)0x2022; break;
+         case 150: ch = (unichar)0x2013; break;
+         case 151: ch = (unichar)0x2014; break;
+         case 152: ch = (unichar)0x02DC; break;
+         case 153: ch = (unichar)0x2122; break;
+         case 154: ch = (unichar)0x0161; break;
+         case 155: ch = (unichar)0x203A; break;
+         case 156: ch = (unichar)0x0153; break;
+         case 158: ch = (unichar)0x017E; break;
+         case 159: ch = (unichar)0x0178; break;
       }
       if(ch < 0x80)
       {
@@ -7223,3 +7399,86 @@ public uint16 * UTF8toUTF16(const char * source, int * wordCount)
 }
 
 namespace com;
+
+#if !defined(MEMINFO) && defined(MEMTRACKING)
+import "Map"
+
+Map<Class, int> blocksByClass { };
+Map<Class, uintsize> sizeByClass { };
+#endif
+
+public void queryMemInfo(char * string)
+{
+#if !defined(MEMINFO) && defined(MEMTRACKING) && !defined(DISABLE_MEMMGR)
+   char s[1024];
+   int p;
+   uint numBlocks = 0;
+   uintsize totalMemUsed = 0;
+   sprintf(s, "Total System Memory Usage: %.02f\n", TOTAL_MEM / 1048576.0f);
+   strcat(string, s);
+
+   for(p = 0; pools && p < NUM_POOLS; p++)
+   {
+      BlockPool * pool = &pools[p];
+      if(pool->totalSize)
+      {
+         numBlocks += pool->totalSize;
+         sprintf(s, "%8d bytes: %d blocks in %d parts (%.02f mb used; taking up %.02f mb space)\n",
+            pool->blockSize, pool->numBlocks, pool->numParts, pool->usedSpace / 1048576.0f, pool->totalSize * pool->blockSpace / 1048576.0f);
+         totalMemUsed += pool->usedSpace;
+         strcat(string, s);
+      }
+   }
+
+
+   blocksByClass.Free();
+   sizeByClass.Free();
+#if !defined(_NOMUTEX)
+   memMutex.Wait();
+#endif
+   for(p = 0; pools && p < NUM_POOLS; p++)
+   {
+      BlockPool * pool = &pools[p];
+      MemBlock block;
+      for(block = pool->first; block; block = block.next)
+      {
+         Class c = block._class;
+         blocksByClass[c]++;
+         sizeByClass[c] += block.size;
+      }
+   }
+#if !defined(_NOMUTEX)
+   memMutex.Release();
+#endif
+
+   //for(c : blocksByClass)
+   {
+      MapIterator<Class, int> it { map = blocksByClass };
+      while(it.Next())
+      {
+         int c = it.data;
+         Class _class = it.key; //&c;
+         uintsize size = sizeByClass[_class];
+         float totalSize = (float) size / 1048576.0f;
+         if(totalSize > 1)
+         {
+            sprintf(s, "%s (%d bytes): %d instances (%.02f mb used)\n", _class ? _class.name : "(none)", (int)size, c, totalSize);
+            strcat(string, s);
+         }
+      }
+   }
+
+   sprintf(s, "Non-pooled memory: %.02f\n", OUTSIDE_MEM / 1048576.0f);
+   strcat(string, s);
+   sprintf(s, "Total Memory in use: %.02f\n", (float)(totalMemUsed + OUTSIDE_MEM) / 1048576.0f);
+   strcat(string, s);
+
+   sprintf(s, "Total Blocks Count: %d (%.02f mb overhead)\n", numBlocks, (float)sizeof(struct MemBlock) * numBlocks / 1048576.0f);
+   strcat(string, s);
+#ifdef MEMORYGUARD
+   sprintf(s, "MemoryGuard: %d blocks (%.02f mb RedZone, %.02f mb MemInfo)\n", memBlocks.count,
+      numBlocks * 2 * REDZONE / 1048576.0f, sizeof(struct MemInfo) * memBlocks.count / 1048576.0f);
+   strcat(string, s);
+#endif
+#endif
+}