ecere: Initial Emscripten support
[sdk] / ecere / src / com / instance.ec
1 #define _Noreturn
2
3 namespace com;
4
5 // #define DISABLE_MEMMGR
6
7 import "BinaryTree"
8 import "OldList"
9 import "String"
10 import "dataTypes"
11
12 #if defined(ECERE_BOOTSTRAP) || defined(ECERE_STATIC)
13 #define dllexport
14 #if !defined(ECERE_BOOTSTRAP)
15 #define stdcall
16 #endif
17 #endif
18
19 #undef __BLOCKS__
20
21 #if !defined(__EMSCRIPTEN__)
22 #if !defined(ECERE_BOOTSTRAP)
23 import "Mutex"
24 #endif
25 #endif
26
27 #if defined(__EMSCRIPTEN__)
28 #define GetCurrentThreadID()  0
29 #endif
30
31 // #define MEMINFO
32 /*
33 #ifdef MEMINFO
34  #undef REDZONE
35  #define REDZONE   256
36 #endif
37 */
38 #ifndef REDZONE
39 #define REDZONE 0
40 #endif
41
42
43 #ifdef _DEBUG
44 // #define MEMTRACKING
45 #endif
46
47 #ifdef MEMINFO
48 #if !defined(__EMSCRIPTEN__)
49 import "Thread"
50 #endif
51 static define MAX_MEMORY_LOC = 40;
52 static define MAX_STACK_FRAMES = 1000;
53
54 static class MemStack : BTNode
55 {
56    const char * frames[MAX_STACK_FRAMES];
57    int pos;
58    bool recurse;
59 };
60
61 static BinaryTree memStacks { };
62 static uint memoryErrorsCount = 0;
63
64 #endif
65
66 default:
67 #define property _property
68
69 #if defined(DISABLE_MEMMGR)
70
71 #ifndef ECERE_BOOTSTRAP
72 # include <malloc.h>
73 #endif
74
75 #if defined(__WIN32__)
76 #ifdef ECERE_BOOTSTRAP
77 uintsize _msize(void * p);
78 #endif
79
80 #  define msize _msize
81 #else
82 #ifdef ECERE_BOOTSTRAP
83 uintsize malloc_usable_size(void * p);
84 #endif
85
86 #  define msize malloc_usable_size
87 #endif
88
89 #endif
90
91 #include <stdlib.h>
92 #include <stdio.h>
93
94 private:
95
96 #if defined(__ANDROID__)
97
98 default const char * AndroidInterface_GetLibLocation(Module m);
99
100 #include <android/log.h>
101 #include <android/native_activity.h>
102
103 #define printf(...)  ((void)__android_log_print(ANDROID_LOG_VERBOSE, "ecere-app", __VA_ARGS__))
104 #endif
105
106 #undef property
107
108 #undef CompareString
109
110 public define null = ((void *)0);
111
112 dllexport Class eSystem_FindClass(Module module, const char * name);
113 dllexport void * eSystem_Renew(void * memory, unsigned int size);
114 dllexport void * eSystem_Renew0(void * memory, unsigned int size);
115 dllexport void * eSystem_New(unsigned int size);
116 dllexport void * eSystem_New0(unsigned int size);
117 dllexport void eSystem_Delete(void * memory);
118 dllexport void * eInstance_New(Class _class);
119
120 default:
121 extern int __ecereVMethodID_class_OnGetDataFromString;
122
123 // IMPLEMENTATION FOR THESE IN _instance.c:
124 #if defined(__MINGW32__) && !defined(_W64) && __GNUC__ < 4
125 dllexport int isblank(int c);
126 #endif
127 bool Instance_LocateModule(const char * name, const char * fileName);
128 void Instance_COM_Initialize(int argc, char ** argv, char ** parsedCommand, int * argcPtr, const char *** argvPtr);
129 void * Instance_Module_Load(const char * libLocation, const char * name, void ** Load, void ** Unload);
130 void Instance_Module_Free(void * library);
131 #if defined(_DEBUG)
132 void InternalModuleLoadBreakpoint();
133 #endif
134
135 private:
136
137 public class Angle : double;
138
139 public class ::unichar : uint32
140 {
141
142    const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
143    {
144       UTF32toUTF8Len(&this, 1, tempString, 5);
145       return tempString;
146    }
147
148    bool OnGetDataFromString(const char * string)
149    {
150       int nb;
151       this = UTF8GetChar(string, &nb);
152       return true;
153    }
154
155 };
156
157 // Forward declarations to hook on to libec:
158 class ::Type;
159 class ::Instantiation;
160 class ::ClassDefinition;
161
162 public class Property : struct
163 {
164 public:
165    class_fixed
166    class_no_expansion
167    Property prev, next;
168    const char * name;
169    bool isProperty;
170    AccessMode memberAccess;
171    int id;
172    Class _class;
173    const char * dataTypeString;
174    Class dataTypeClass;
175    Type dataType;
176
177    void (*Set)(void *, int);
178    int (*Get)(void *);
179    bool (*IsSet)(void *);
180    void * data;
181    void * symbol;
182    int vid;
183    bool conversion;
184    uint watcherOffset;
185    const char * category;
186    bool compiled;
187    bool selfWatchable, isWatchable;
188 };
189
190 dllexport void eInstance_FireWatchers(Instance instance, Property _property);
191
192 public dllexport void MemoryGuard_PushLoc(const char * loc)
193 {
194 #ifdef MEMINFO
195    MemStack stack;
196 #if !defined(__EMSCRIPTEN__)
197    memMutex.Wait();
198 #endif
199    stack = (MemStack)memStacks.Find(GetCurrentThreadID());
200    if(!stack)
201    {
202       stack = (MemStack)calloc(1, sizeof(class MemStack));
203       stack.key = GetCurrentThreadID();
204       memStacks.Add(stack);
205    }
206    if(stack.pos < MAX_STACK_FRAMES)
207       stack.frames[stack.pos++] = loc;
208 #if !defined(__EMSCRIPTEN__)
209    memMutex.Release();
210 #endif
211 #endif
212 }
213
214 public dllexport void MemoryGuard_PopLoc()
215 {
216 #ifdef MEMINFO
217    MemStack stack;
218 #if !defined(__EMSCRIPTEN__)
219    memMutex.Wait();
220 #endif
221    stack = (MemStack)memStacks.Find(GetCurrentThreadID());
222    if(stack && stack.pos > 0)
223    {
224       stack.pos--;
225    }
226 #if !defined(__EMSCRIPTEN__)
227    memMutex.Release();
228 #endif
229 #endif
230 }
231
232 #ifdef ECERE_STATIC
233
234 #ifdef ECERE_COM_ONLY
235
236 #define COM_LOAD_FUNCTION  __ecereDll_Load_ecereCOM
237 #define COM_UNLOAD_FUNCTION  __ecereDll_Unload_ecereCOM
238
239 #else
240
241 #define COM_LOAD_FUNCTION  __ecereDll_Load_ecere
242 #define COM_UNLOAD_FUNCTION  __ecereDll_Unload_ecere
243
244 #endif
245
246 #else
247
248 #define COM_LOAD_FUNCTION  __ecereDll_Load
249 #define COM_UNLOAD_FUNCTION  __ecereDll_Unload
250
251 #endif
252
253 default:
254
255 #if defined(ECERE_BOOTSTRAP)
256 extern bool COM_LOAD_FUNCTION(Module module);
257 extern bool COM_UNLOAD_FUNCTION(Module module);
258 #else
259 extern bool stdcall COM_LOAD_FUNCTION(Module module);
260 extern bool stdcall COM_UNLOAD_FUNCTION(Module module);
261 #endif
262
263 private:
264
265 public class BTNamedLink : struct
266 {
267    class_fixed
268 public:
269    const char * name;
270    BTNamedLink parent, left, right;
271    int depth;
272    void * data;
273 };
274
275 class SelfWatcher : struct
276 {
277    class_fixed
278    SelfWatcher prev, next;
279    void (*callback)(void *);
280    Property _property;
281 };
282
283 public enum AccessMode
284 {
285    defaultAccess,
286    publicAccess,
287    privateAccess,
288    staticAccess,
289    baseSystemAccess
290 };
291
292 public class SubModule : struct
293 {
294 public:
295    SubModule prev, next;
296    Module module;
297    AccessMode importMode;
298 };
299
300 public enum DataMemberType { normalMember, unionMember, structMember };
301
302 public enum ClassType
303 {
304    normalClass,
305    structClass,
306    bitClass,
307    unitClass,
308    enumClass,
309    noHeadClass,
310    unionClass, // Temporary only in firstPass
311    systemClass = 1000
312 };
313
314 public class Class : struct
315 {
316 public:
317    class_fixed
318    class_no_expansion
319    Class prev, next;
320    const char * name;
321    int offset, structSize;
322    void ** _vTbl;
323    int vTblSize;
324    bool (*Constructor)(void *);
325    void (*Destructor)(void *);
326
327    int offsetClass, sizeClass;
328    Class base;
329    BinaryTree methods;
330    BinaryTree members;
331    BinaryTree prop;
332    OldList membersAndProperties;
333    BinaryTree classProperties;
334    OldList derivatives;
335    int memberID, startMemberID;
336    ClassType type;
337    Module module;
338    NameSpace * nameSpace;
339    const char * dataTypeString;
340    Type dataType;
341    int typeSize;
342    int defaultAlignment;
343    void (*Initialize)();
344    int memberOffset;       // For structs, this includes all base classes structSize. Otherwise it restarts at for each class hierarchy level.
345    OldList selfWatchers;
346    const char * designerClass;
347    bool noExpansion;
348    const char * defaultProperty;
349    bool comRedefinition;
350
351    int count;     // DEBUGGING
352
353    int isRemote;  // TODO: Convert to an enum, can have values 0..3
354    bool internalDecl;
355    void * data;
356    bool computeSize;
357    short structAlignment; short pointerAlignment;
358    int destructionWatchOffset;
359    bool fixed;
360    OldList delayedCPValues;
361    AccessMode inheritanceAccess;
362    const char * fullName;
363    void * symbol;
364    OldList conversions;
365
366    OldList templateParams;
367    ClassTemplateArgument * templateArgs;
368    Class templateClass;
369    OldList templatized;
370    int numParams;
371    bool isInstanceClass;
372    bool byValueSystemClass;
373
374    property const char *
375    {
376       get { return name; }
377       set
378       {
379          Class theClass = eSystem_FindClass(__thisModule, value);
380          /*
381          if(!theClass)
382             theClass = eSystem_FindClass(__thisModule.application, value);
383          */
384          return theClass;
385       }
386    };
387
388    const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
389    {
390       return name;
391    }
392
393    bool OnGetDataFromString(const char * string)
394    {
395       Class theClass;
396       theClass = eSystem_FindClass(__thisModule, string);
397       if(!theClass)
398          theClass = eSystem_FindClass(__thisModule.application, string);
399       this = (void *)theClass;
400       return theClass != null;
401    }
402
403    void OnSerialize(IOChannel channel)
404    {
405       channel.Serialize(fullName);
406    }
407
408    void OnFree()
409    {
410
411    }
412
413    void OnUnserialize(IOChannel channel)
414    {
415       Class theClass;
416       String string;
417       channel.Unserialize(string);
418       theClass = eSystem_FindClass(__thisModule, string);
419       if(!theClass)
420          theClass = eSystem_FindClass(__thisModule.application, string);
421       delete string;
422       this = (void *)theClass;
423    }
424 };
425
426
427 public enum TemplateParameterType { type, identifier, expression };
428 public enum TemplateMemberType { dataMember, method, prop };
429
430 public struct ClassTemplateArgument
431 {
432 public:
433    union
434    {
435       // For type
436       struct
437       {
438          const char * dataTypeString;
439          Class dataTypeClass;
440          // Type dataType;
441       };
442       // For expression
443       DataValue expression;
444
445       // For identifier
446       struct
447       {
448          const char * memberString;
449          union
450          {
451             DataMember member;
452             Property prop;
453             Method method;
454          };
455       };
456    };
457 };
458
459 public class ClassTemplateParameter : struct
460 {
461 class_fixed
462 public:
463    ClassTemplateParameter prev, next;
464    const char * name;
465    TemplateParameterType type;
466    union
467    {
468       // Class baseClass;                 // For type
469       const char * dataTypeString;           // For expression
470       TemplateMemberType memberType;   // For identifier
471    };
472    ClassTemplateArgument defaultArg;
473    void * param;  // To attach to Compiler TemplateParameter
474 }
475
476 /*    // Module inherits off the Instance class (_vTbl, _class, _refCount)
477 public class Module
478 {
479    class_no_expansion
480
481    Application app;
482
483    // So we can clean them up
484    OldList classes;
485    OldList defines;
486    OldList functions;
487    OldList modules;
488
489    Module prev, next;
490    const char * name;
491    void * library;
492    void (stdcall * Unload)(Module module);
493    ImportType importType;
494    // Added to solve stdcall issues with the bootstrap on Windows for Unload
495    ImportType origImportType;
496
497    NameSpace privateNameSpace;
498    NameSpace publicNameSpace;
499 };
500
501 public class Application : Module
502 {
503    int argc;
504    const char ** argv;
505    int exitCode;
506    bool isGUIApp;
507    OldList allModules;
508    const char * parsedCommand;
509    NameSpace systemNameSpace;
510 };
511 */
512 public enum MethodType { normalMethod, virtualMethod };
513
514 public class Method : struct
515 {
516 public:
517    class_fixed
518    const char * name;
519    Method parent, left, right;
520    int depth;
521    int (*function)();
522    int vid;              // For METHOD_VIRTUAL:  Index into the class virtual table
523    MethodType type;
524    Class _class;
525    void * symbol;
526    const char * dataTypeString;
527    Type dataType;
528    AccessMode memberAccess;
529 };
530
531 public enum ImportType
532 {
533    normalImport,
534    staticImport,
535    remoteImport,
536
537 // For internal usage in the compiler:
538    preDeclImport,
539    comCheckImport
540 };
541
542 public struct NameSpace
543 {
544    const char * name;
545    NameSpace * btParent, * left, * right;
546    int depth;
547
548    NameSpace * parent;
549    BinaryTree nameSpaces;
550    BinaryTree classes;
551    BinaryTree defines;
552    BinaryTree functions;
553 };
554
555 public union DataValue
556 {
557    char c;
558    unsigned char uc;
559    short s;
560    unsigned short us;
561    int i;
562    unsigned int ui;
563    void * p;
564    float f;
565    double d;
566    int64 i64;
567    uint64 ui64;
568 };
569
570 public class DataMember : struct
571 {
572 public:
573    class_fixed
574    DataMember prev, next;
575    const char * name;
576    bool isProperty;
577    AccessMode memberAccess;
578    int id;
579    Class _class;
580    const char * dataTypeString;
581    Class dataTypeClass;
582    Type dataType;
583
584    DataMemberType type;
585    int offset;
586    int memberID;
587    OldList members;
588    BinaryTree membersAlpha;
589    int memberOffset;
590    short structAlignment; short pointerAlignment;
591 };
592
593 public class BitMember : struct
594 {
595 public:
596    class_fixed
597    BitMember prev, next;
598    const char * name;
599    bool isProperty;
600    AccessMode memberAccess;
601    int id;
602    Class _class;
603    const char * dataTypeString;
604    Class dataTypeClass;
605    Type dataType;
606
607    DataMemberType type;
608    int size;
609    int pos;
610    uint64 mask;
611 };
612
613 public class ClassProperty : struct
614 {
615 public:
616    class_fixed
617    const char * name;
618    ClassProperty parent, left, right;
619    int depth;
620    void (*Set)(Class, int64);
621    int64 (*Get)(Class);
622    const char * dataTypeString;
623    Type dataType;
624    bool constant;
625 };
626
627 public class DefinedExpression : struct
628 {
629 public:
630    class_fixed
631    DefinedExpression prev, next;
632    const char * name;
633    const char * value;
634    NameSpace * nameSpace;
635 };
636
637 public class GlobalFunction : struct
638 {
639 public:
640    class_fixed
641    GlobalFunction prev, next;
642    const char * name;
643    int (*function)();
644    Module module;
645    NameSpace * nameSpace;
646    const char * dataTypeString;
647    Type dataType;
648    void * symbol;
649 };
650
651 public class EnumClassData : struct
652 {
653 public:
654    class_fixed
655    OldList values;
656    int64 largest;
657 };
658
659 class Watcher : struct
660 {
661    class_fixed
662    Watcher prev, next;
663    void (*callback)(void *, void *);
664    Instance object;
665 };
666
667 #ifdef MEMINFO
668 static class MemInfo : BTNode //struct
669 {
670    class_fixed
671
672    /*
673    byte * key;
674    MemInfo parent, left, right;
675    int depth;
676    */
677
678    byte * oldmem;
679    uint size;
680    bool freed;
681    const char * _class;
682    uint id;
683    char * allocLoc[MAX_MEMORY_LOC];
684    char * freeLoc[MAX_MEMORY_LOC];
685    bool internal;
686
687    void OutputStacks(bool showFree)
688    {
689       int c;
690
691       if(_class)
692          printf("Object of class %s\n", _class);
693       printf("   Allocation Stack:\n");
694       for(c = 0; c<MAX_MEMORY_LOC; c++)
695 #if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__)
696          if(allocLoc[c] && allocLoc[c] != (void *)0xabababababababab)
697 #else
698          if(allocLoc[c] && allocLoc[c] != (void *)0xabababab)
699 #endif
700             printf("      %s\n", allocLoc[c]);
701
702       if(showFree)
703       {
704          printf("   Free Location Stack:\n");
705          for(c = 0; c<MAX_MEMORY_LOC; c++)
706             if(freeLoc[c])
707                printf("      %s\n", freeLoc[c]);
708       }
709       //getch();
710    }
711 };
712
713 static BinaryTree memBlocks;
714
715 bool recurse = false;
716 static int blockID;
717 //Class allocateClass;
718 char * allocateClass;
719 bool allocateInternal;
720
721 #endif
722
723 static uint TOTAL_MEM = 0;
724 #if !defined(MEMINFO) && !defined(DISABLE_MEMMGR)
725 static uint OUTSIDE_MEM = 0;
726 #endif
727
728 #if !defined(__EMSCRIPTEN__)
729 #if !defined(ECERE_BOOTSTRAP)
730 static Mutex memMutex { };
731 #endif
732 #endif
733
734 private class MemBlock : struct
735 {
736    MemBlock prev, next;
737    MemPart part;
738    uint size;
739 #if defined(_DEBUG) && !defined(MEMINFO) && defined(MEMTRACKING)
740    Class _class;
741 #endif
742 };
743
744 private class MemPart : struct
745 {
746    void * memory;
747    int blocksUsed;
748    int size;
749    BlockPool * pool;
750 };
751 /*
752 #define NUM_POOLS          29
753 #define NEXT_SIZE(s)       NextFibonacci(s)
754 #define SIZE_POSITION(s)   PosFibonacci(s)
755 #define NTH_SIZE(p)        NthFibonacci(p)
756
757 static uint initNumBlocks[NUM_POOLS] =
758 {
759    1024, // 1
760    1024, // 2
761    1024, // 3
762    1024, // 5
763    1024, // 8
764    1024, // 13
765    1024, // 21
766    1024, // 34
767    1024, // 55
768    1024, // 89
769    1024, // 144
770    512,  // 233
771    512,  // 377
772    256,  // 610
773    128,  // 987
774    128,  // 1597
775    64,   // 2584
776    32,   // 4181
777    32,   // 6765
778    16,   // 10946
779    16,   // 17711
780    8,    // 28657
781    4,    // 46368
782    2,    // 75025
783    1,    // 121393
784    1,    // 196418
785    1,    // 317811
786    1,    // 514229
787    1,    // 832040
788 };
789
790 */
791 /*
792 #define NUM_POOLS 20
793 #define NEXT_SIZE(s)       pow2i(s)
794 #define SIZE_POSITION(s)   log2i(s)
795 #define NTH_SIZE(p)        (1<<p)
796
797    1024,  // 1 byte
798    4000,  // 1024,    // 2 bytes
799    2500,  // 1024,    // 4 bytes
800    18000, //1024,    // 8 bytes
801    20000, //1024,    // 16 bytes
802    29000, //1024,    // 32 bytes
803    46000, //1024,    // 64 bytes
804    20000, //1024,    // 128 bytes
805    26000, //512,     // 256 bytes
806    1400,  //256,     // 512 bytes
807    160,   //128,     // 1 K
808    500,  //64,      // 2 K
809
810 static uint initNumBlocks[NUM_POOLS] =
811 {
812    1024,  // 1 byte
813    1024,    // 2 bytes
814    1024,    // 4 bytes
815    1024,    // 8 bytes
816    1024,    // 16 bytes
817    1024,    // 32 bytes
818    1024,    // 64 bytes
819    1024,    // 128 bytes
820    512,     // 256 bytes
821    256,     // 512 bytes
822    128,     // 1 K
823    64,      // 2 K
824    32,      // 4 K
825    16,      // 8 K
826    8,       // 16 K
827    4,       // 32 K
828    2,       // 64 K
829    1,       // 128 K
830    1,       // 256 K
831    1        // 512 K
832 };
833 */
834
835 #define NUM_POOLS 31
836 #define NEXT_SIZE(s)       pow1_5i(s)
837 #define SIZE_POSITION(s)   log1_5i(s)
838 #define NTH_SIZE(p)        pow1_5(p)
839
840 #if 0
841 static int power15[] =
842 {
843 /*
844 1
845 2
846 3
847 */
848 /*
849 4     // 4
850 6     // 8
851 9     // 12
852 13    // 16
853 19    // 24
854 28    // 32
855 42    // 48
856 63    // 64
857 94    // 96
858 141   // 144
859 211   // 224
860 316   // 320
861 474   // 480
862 711   // 720
863 1066  // 1072
864 1599  // 1600
865 2398  // 2400
866 3597  // 6900
867 5395  // 5408
868 8092  // 8096
869 12138 // 12144
870 18207 // 18208
871 27310 // 27312
872 40965 // 40976
873 61447 // 61456
874 92170 // 92176
875 138255   // 138256
876 207382   // 207392
877 311073   // 311088
878 466609   // 466624
879 699913   // 699920
880 */
881 4,
882 8,
883 12,
884 16,
885 24,
886 32,
887 48,
888 64,
889 96,
890 144,
891 224,
892 320,
893 480,
894 720,
895 1072,
896 1600,
897 2400,
898 6900,
899 5408,
900 8096,
901 12144,
902 18208,
903 27312,
904 40976,
905 61456,
906 92176,
907 138256,
908 207392,
909 311088,
910 466624,
911 699920
912 };
913 #endif
914
915 private struct BlockPool
916 {
917    MemBlock first, last;
918    MemBlock free;
919    uint blockSize;
920    uint blockSpace;
921    //MemPart * parts;
922    int numParts;
923    int numBlocks;
924    uint totalSize;
925    uint usedSpace;
926
927    bool Expand(uint numBlocks)
928    {
929       byte * memory = malloc(numBlocks * blockSpace);
930       // byte * memory = calloc(1, numBlocks * blockSpace);
931       TOTAL_MEM += numBlocks * blockSpace;
932 #ifdef _DEBUG
933       /*if(blockSize == 28)
934          printf("Expanding pool %x (%d)\n", this, blockSize);*/
935 #endif
936       if(memory)
937       {
938          int c;
939 #ifdef _DEBUG
940          /*uint totalAvailable = 0, totalAllocated = 0, totalBlocks = 0, totalUsed = 0;
941          uint totalParts = 0;*/
942 #endif
943          MemBlock block = (MemBlock)memory;
944          MemPart part = calloc(1, sizeof(class MemPart));
945          TOTAL_MEM += sizeof(class MemPart);
946          free = block;
947          for(c = 0; c<numBlocks - 1; c++)
948          {
949             // block.pool = this;
950             block.part = part;
951             /*if(part.size < 0)
952                printf("WARNING! part.size < 0\n");*/
953             block.prev = null;
954             block.next = (MemBlock)((byte *)block + blockSpace);
955             block = block.next;
956          }
957          part.blocksUsed = 0;
958          part.pool = this;
959          part.memory = memory;
960          part.size = numBlocks;
961
962          // block.pool = this;
963          block.part = part;
964          /*if(part.size < 0)
965             printf("/! part.size < 0\n");
966          if(part.pool == (void*) -1)
967             printf("WARNING! pool is -1\n");*/
968          block.prev = null;
969          block.next = null;
970
971          /*if(free && free.part && (free.part.size < 0 || free.part.pool == (void *)-1))
972             printf("WARNING! Bad next free block!\n");*/
973
974          //parts = realloc(parts, sizeof(MemPart) * (numParts + 1));
975
976          totalSize += numBlocks;
977
978 #ifdef _DEBUG
979          /*
980          {
981             for(c = 0; c<NUM_POOLS; c++)
982             {
983                BlockPool * pool = &pools[c];
984                printf("[%d %s (%d)]: available: %d, allocated: %d, free: %d, used: %d k, wasted: %d k, free: %d k\n", c, (&pools[c] == this) ? "*" : " ",
985                   pools[c].blockSize, pools[c].totalSize, pools[c].numBlocks,
986                   pools[c].totalSize - pools[c].numBlocks, pools[c].usedSpace / 1024, ((pools[c].numBlocks * pools[c].blockSize) - pools[c].usedSpace) / 1024,
987                   (pools[c].totalSize - pools[c].numBlocks) * pools[c].blockSize / 1024);
988                totalAvailable += pools[c].totalSize * pools[c].blockSize;
989                totalAllocated += pools[c].numBlocks * pools[c].blockSize;
990                totalUsed += pools[c].usedSpace;
991                totalBlocks += pools[c].totalSize;
992                totalParts += pools[c].numParts;
993             }
994             printf("Total Available %d k, Total Allocated: %d k, Total Free: %d k\n", totalAvailable / 1024, totalAllocated / 1024, (totalAvailable - totalAllocated) / 1024);
995             printf("Total Number of Blocks %d, overhead of %d k\n", totalBlocks, totalBlocks * sizeof(class MemBlock) / 1024);
996             printf("Total Used Space %d k, wasted from roundup: %d k\n", totalUsed / 1024, (totalAllocated - totalUsed) / 1024);
997             printf("Total Memory Parts: %d\n", totalParts);
998             printf("TOTAL_MEM: %d k, OUTSIDE_MEM: %d k, BLOCKS: %d k\n", TOTAL_MEM / 1024, OUTSIDE_MEM / 1024, (totalAvailable + totalBlocks * sizeof(class MemBlock)) / 1024);
999             printf("\n");
1000          }
1001          */
1002 #endif
1003          //parts[] = part;
1004          numParts++;
1005          return true;
1006       }
1007       return false;
1008    }
1009
1010    MemBlock Add()
1011    {
1012       MemBlock block = null;
1013       /*if(blockSize == 28)
1014          printf("BlockPool::Add (%d)\n", blockSize);*/
1015       if(!free)
1016          Expand(Max(1, numBlocks / 2));
1017       if(free)
1018       {
1019          block = free;
1020          block.prev = last;
1021          if(block.prev)
1022             block.prev.next = block;
1023          if(!first)
1024             first = block;
1025          last = block;
1026          free = block.next;
1027          /*if(blockSize == 28)
1028             printf("Free: %x, free.part: %x, free.part.size: %d, free.part.pool: %x (this = %x), next = %x (part = %x)\n", free, free ? free.part : null,
1029                (free && free.part) ? free.part.size : 0, (free && free.part) ? free.part.pool : 0, this,
1030                (free ? free.next : 0), (free && free.next) ? free.next.part : 0);
1031          if(free && free.part && (free.part.size < 0 || free.part.pool == (void *)-1))
1032             printf("WARNING! Bad next free block!\n");*/
1033
1034          block.next = null;
1035          //if(block.part)
1036             block.part.blocksUsed++;
1037          /*else
1038          {
1039             printf("");
1040          }*/
1041          numBlocks++;
1042       }
1043       return block;
1044    }
1045
1046    void Remove(MemBlock block)
1047    {
1048       /*if(blockSize == 28)
1049          printf("BlockPool::Remove (%d)\n", blockSize);*/
1050       if(block.prev)
1051          block.prev.next = block.next;
1052       if(block.next)
1053          block.next.prev = block.prev;
1054
1055       if(first == block)
1056          first = block.next;
1057       if(last == block)
1058          last = block.prev;
1059
1060       // block.prev = null;
1061       block.next = free;
1062       free = block;
1063
1064       /*if(blockSize == 28)
1065       {
1066          printf("Setting new free block: part = %x\n", block.part);
1067       }*/
1068
1069       block.part.blocksUsed--;
1070       numBlocks--;
1071       block.part.pool->usedSpace -= block.size;
1072
1073       if(!block.part.blocksUsed && numBlocks && totalSize > numBlocks + numBlocks / 2)
1074       {
1075          MemBlock next = free, prev = null;
1076          MemPart part = block.part;
1077          free = null;
1078          totalSize -= part.size;
1079          /*if(blockSize == 28)
1080             printf("Freeing a part\n");*/
1081          while(next)
1082          {
1083             if(next.part != part)
1084             {
1085                if(prev)
1086                   prev.next = next;
1087                else
1088                   free = next;
1089                prev = next;
1090             }
1091             next = next.next;
1092          };
1093          if(prev)
1094             prev.next = null;
1095
1096          TOTAL_MEM -= part.size * blockSpace;
1097          TOTAL_MEM -= sizeof(class MemPart);
1098          numParts--;
1099
1100          ::free(part.memory);
1101          ::free(part);
1102       }
1103       /*if(free && free.part && (free.part.size < 0 || free.part.pool == (void *)-1))
1104          printf("WARNING! Bad next free block!\n");*/
1105    }
1106 };
1107
1108 #if !defined(MEMINFO) && !defined(DISABLE_MEMMGR)
1109 static BlockPool * pools; //[NUM_POOLS];
1110
1111 /*static uint PosFibonacci(uint number)
1112 {
1113    uint pos;
1114    uint last = 1, prev = 0;
1115    uint current = 1;
1116
1117    for(pos=0; ; pos++)
1118    {
1119       current += prev;
1120       prev = last;
1121       last = current;
1122       if(current >= number)
1123          break;
1124    }
1125    return pos;
1126 }
1127
1128 static uint NthFibonacci(uint number)
1129 {
1130    uint pos;
1131    uint last = 1, prev = 0;
1132    uint current = 1;
1133
1134    for(pos=0; pos <= number; pos++)
1135    {
1136       current += prev;
1137       prev = last;
1138       last = current;
1139    }
1140    return current;
1141 }
1142
1143 static uint NextFibonacci(uint number)
1144 {
1145    uint pos;
1146    uint last = 1, prev = 0;
1147    uint current = 1;
1148
1149    for(pos=0; ; pos++)
1150    {
1151       current += prev;
1152       prev = last;
1153       last = current;
1154       if(current >= number)
1155          return current;
1156    }
1157 }
1158 */
1159
1160 static uint log1_5i(uint number)
1161 {
1162    uint pos;
1163    uint64 current = sizeof(void *);
1164
1165    for(pos=0; pos < NUM_POOLS; pos++)
1166    {
1167       if(current >= number)
1168          break;
1169       current = current * 3 / 2;
1170       if(current == 1) current = 2;
1171       if(current & 7) current += 8 - (current & 7);
1172    }
1173    return pos;
1174 }
1175
1176 static uint pow1_5(uint number)
1177 {
1178    uint pos;
1179    uint64 current = sizeof(void *);
1180    for(pos=0; pos < number; pos++)
1181    {
1182       current = current * 3 / 2;
1183       if(current == 1) current = 2;
1184       if(current & 7) current += 8 - (current & 7);
1185    }
1186    return (uint)current;
1187 }
1188
1189 static uint pow1_5i(uint number)
1190 {
1191    uint pos;
1192    uint64 current = sizeof(void *);
1193
1194    for(pos=0; pos < NUM_POOLS; pos++)
1195    {
1196       if(current >= number)
1197          return (uint)current;
1198       current = current * 3 / 2;
1199       if(current == 1) current = 2;
1200       if(current & 7) current += 8 - (current & 7);
1201    }
1202    return (uint)current;
1203 }
1204 #endif
1205
1206 // -- Math Helpers ---
1207 public uint log2i(uint number)
1208 {
1209    uint power;
1210
1211    for(power=0; power<32; power++)
1212       if((1L<<power) >= number)
1213          break;
1214    return power;
1215 }
1216
1217 public uint pow2i(uint number)
1218 {
1219    return 1<<log2i(number);
1220 }
1221
1222 #if !defined(MEMINFO) && !defined(DISABLE_MEMMGR)
1223 static bool memoryInitialized = false;
1224 static void InitMemory()
1225 {
1226    int c;
1227    memoryInitialized = true;
1228    pools = calloc(1, sizeof(BlockPool) * NUM_POOLS);
1229    for(c = 0; c<NUM_POOLS; c++)
1230    {
1231       int expansion;
1232
1233       pools[c].blockSize = NTH_SIZE(c);
1234       if(pools[c].blockSize % sizeof(void *))
1235          pools[c].blockSize += sizeof(void *) - (pools[c].blockSize % sizeof(void *));
1236       pools[c].blockSpace = pools[c].blockSize;
1237       pools[c].blockSpace += sizeof(class MemBlock);
1238       // pools[c].Expand(initNumBlocks[c]);
1239
1240       expansion = (pools[c].blockSize < 128) ? 1024 : (131072 / pools[c].blockSize);
1241
1242       if(c < 12)
1243          pools[c].Expand(Max(1, expansion));
1244    }
1245 }
1246 #endif
1247
1248 #if !defined(MEMINFO) && !defined(DISABLE_MEMMGR)
1249 static void * _mymalloc(unsigned int size)
1250 {
1251    MemBlock block = null;
1252    if(size)
1253    {
1254       unsigned int p = SIZE_POSITION(size);
1255       if(!memoryInitialized) InitMemory();
1256       if(!poolingDisabled && p < NUM_POOLS)
1257       {
1258          block = pools[p].Add();
1259          if(block)
1260          {
1261 #if defined(_DEBUG) && defined(MEMTRACKING)
1262             block._class = null;
1263 #endif
1264             block.size = size;
1265             pools[p].usedSpace += size;
1266          }
1267       }
1268       else
1269       {
1270          block = malloc(sizeof(class MemBlock) + size);
1271          if(block)
1272          {
1273             TOTAL_MEM += sizeof(class MemBlock) + size;
1274             OUTSIDE_MEM += sizeof(class MemBlock) + size;
1275             block.part = null;
1276 #if defined(_DEBUG) && defined(MEMTRACKING)
1277             block._class = null;
1278 #endif
1279             block.size = size;
1280          }
1281       }
1282    }
1283    return block ? ((struct MemBlock *)block + 1) : null;
1284 }
1285
1286 static void * _mycalloc(int n, unsigned int size)
1287 {
1288    void * pointer = _mymalloc(n*size);
1289    if(pointer)
1290       memset(pointer, 0, n*size);
1291    return pointer;
1292 }
1293
1294
1295 static void _myfree(void * pointer)
1296 {
1297    if(pointer)
1298    {
1299       MemBlock block = (MemBlock)((byte *)pointer - sizeof(class MemBlock));
1300       MemPart part = block.part;
1301       BlockPool * pool = part ? part.pool : null; //block.pool;
1302       /*if(pool == (void*) -1)
1303          printf("WARNING! pool is -1\n");
1304       else   */
1305       if(pool)
1306          pool->Remove(block);
1307       else
1308       {
1309          TOTAL_MEM -= sizeof(class MemBlock) + block.size;
1310          OUTSIDE_MEM -= sizeof(class MemBlock) + block.size;
1311          free(block);
1312       }
1313    }
1314 }
1315
1316 static void * _myrealloc(void * pointer, unsigned int size)
1317 {
1318    MemBlock block = pointer ? ((MemBlock)((byte *)pointer - sizeof(class MemBlock))) : null;
1319    void * newPointer = null;
1320    MemPart part = block ? block.part : null;
1321    BlockPool * pool = part ? part.pool : null;
1322    if(block)
1323    {
1324       /*if(pool == (void*) -1)
1325          printf("WARNING! pool is -1\n");
1326       else*/
1327       if(pool)
1328       {
1329          // if((1 << pool) >= size && (pool - SIZE_POSITION(size)) <= 1)
1330          uint ns = NEXT_SIZE(size);
1331          uint mod = ns % sizeof(void *);
1332          if(mod) ns += sizeof(void *)-mod;
1333          if(ns == pool->blockSize)
1334          {
1335             newPointer = pointer;
1336             pool->usedSpace += size - block.size;
1337             block.size = size;
1338          }
1339       }
1340       else if(size)
1341       {
1342          MemBlock newBlock = realloc(block, sizeof(class MemBlock) + size);
1343          if(newBlock)
1344          {
1345             TOTAL_MEM += size - newBlock.size;
1346             OUTSIDE_MEM += size - newBlock.size;
1347             newPointer = ((struct MemBlock *)newBlock + 1);
1348             newBlock.size = size;
1349          }
1350       }
1351    }
1352    if(!newPointer)
1353    {
1354       newPointer = _mymalloc(size);
1355       if(pointer && newPointer)
1356       {
1357          memcpy(newPointer, pointer, Min(size, block.size));
1358          _myfree(pointer);
1359       }
1360    }
1361    return newPointer;
1362 }
1363
1364 static void * _mycrealloc(void * pointer, unsigned int size)
1365 {
1366    MemBlock block = pointer ? ((MemBlock)((byte *)pointer - sizeof(class MemBlock))) : null;
1367    void * newPointer = null;
1368    MemPart part = block ? block.part : null;
1369    BlockPool * pool = part ? part.pool : null;
1370    if(block)
1371    {
1372       /*if(pool == (void*) -1)
1373          printf("WARNING! pool is -1\n");
1374       else*/
1375
1376       if(pool)
1377       {
1378          // if((1 << pool) >= size && (pool - SIZE_POSITION(size)) <= 1)
1379          uint ns = NEXT_SIZE(size);
1380          uint mod = ns % sizeof(void *);
1381          if(mod) ns += sizeof(void *)-mod;
1382          if(ns == pool->blockSize)
1383          {
1384             int extra = size - block.size;
1385             newPointer = pointer;
1386             pool->usedSpace += extra;
1387             if(extra > 0)
1388                memset((byte *)pointer + block.size, 0, extra);
1389             block.size = size;
1390          }
1391       }
1392       else if(size)
1393       {
1394          MemBlock newBlock = realloc(block, sizeof(class MemBlock) + size);
1395          if(newBlock)
1396          {
1397             int extra = size - newBlock.size;
1398             TOTAL_MEM += extra;
1399             OUTSIDE_MEM += extra;
1400             newPointer = ((struct MemBlock *)newBlock + 1);
1401             if(extra > 0)
1402                memset((byte *)newPointer + newBlock.size, 0, extra);
1403             newBlock.size = size;
1404          }
1405       }
1406    }
1407    if(!newPointer)
1408    {
1409       newPointer = _mymalloc(size);
1410       if(newPointer)
1411       {
1412          if(pointer)
1413          {
1414             memcpy(newPointer, pointer, Min(size, block.size));
1415             if(size > block.size)
1416                memset((byte *)newPointer + block.size, 0, size - block.size);
1417             _myfree(pointer);
1418          }
1419          else
1420             memset((byte *)newPointer, 0, size);
1421       }
1422    }
1423    return newPointer;
1424 }
1425
1426 #undef realloc
1427 #undef crealloc
1428 #undef malloc
1429 #undef free
1430 #undef calloc
1431
1432 #define realloc _myrealloc
1433 #define crealloc _mycrealloc
1434 #define malloc _mymalloc
1435 #define free _myfree
1436 #define calloc _mycalloc
1437 #endif
1438
1439 static void * _malloc(unsigned int size)
1440 {
1441 #if defined(DISABLE_MEMMGR) && !defined(MEMINFO)
1442    return size ? malloc(size) : null;
1443 #else
1444    void * pointer;
1445
1446
1447 #if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
1448    memMutex.Wait();
1449 #endif
1450
1451    pointer = size ? malloc(size + 2 * REDZONE) : null;
1452 #ifdef MEMINFO
1453    if(pointer)
1454    {
1455       MemInfo block;
1456       MemStack stack = (MemStack)memStacks.Find(GetCurrentThreadID());
1457       if(!stack)
1458       {
1459          stack = (MemStack)calloc(1, sizeof(class MemStack));
1460          stack.key = GetCurrentThreadID();
1461          memStacks.Add(stack);
1462       }
1463
1464       if(!pointer)
1465       {
1466          int c;
1467          printf("Memory allocation of %d bytes failed\n", size);
1468          printf("Current Stack:\n");
1469          for(c = 0; c<stack.pos; c++)
1470             if(stack.frames[c])
1471                printf("      %s\n", stack.frames[c]);
1472
1473          memoryErrorsCount++;
1474 #if !defined(__EMSCRIPTEN__)
1475          memMutex.Release();
1476 #endif
1477          return null;
1478       }
1479
1480       if(!recurse && !stack.recurse)
1481       {
1482          stack.recurse = true;
1483          block = MemInfo { size = size, key = (uintptr)((byte *)pointer + REDZONE), id = blockID++ };
1484          memcpy(block.allocLoc, stack.frames + stack.pos - Min(stack.pos, MAX_MEMORY_LOC), Min(stack.pos, MAX_MEMORY_LOC) * sizeof(char *));
1485          memBlocks.Add(block);
1486          stack.recurse = false;
1487       }
1488    }
1489 #endif
1490
1491 #if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
1492    memMutex.Release();
1493 #endif
1494
1495 #if REDZONE
1496    if(pointer)
1497    {
1498       memset(pointer, 0xAB, REDZONE);
1499       memset((byte *)pointer + REDZONE + size, 0xAB, REDZONE);
1500       // ((byte *)pointer)[0] = 0x00;
1501    }
1502 #endif
1503    return pointer ? ((byte*)pointer + REDZONE) : null;
1504 #endif
1505 }
1506
1507 static void * _calloc(int n, unsigned int size)
1508 {
1509 #if defined(DISABLE_MEMMGR) && !defined(MEMINFO)
1510    return size ? calloc(n, size) : null;
1511 #else
1512    void * pointer;
1513
1514 #if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
1515    memMutex.Wait();
1516 #endif
1517
1518    pointer = (n*size) ? calloc(1, n*size + 2 * REDZONE) : null;
1519 #ifdef MEMINFO
1520    if(pointer)
1521    {
1522       MemStack stack;
1523       stack = (MemStack)memStacks.Find(GetCurrentThreadID());
1524       if(!stack)
1525       {
1526          stack = (MemStack)calloc(1, sizeof(class MemStack));
1527          stack.key = GetCurrentThreadID();
1528          memStacks.Add(stack);
1529       }
1530       if(!pointer)
1531       {
1532          int c;
1533          printf("Memory allocation of %d bytes failed\n", size);
1534          printf("Current Stack:\n");
1535          for(c = 0; c<stack.pos; c++)
1536             if(stack.frames[c])
1537                printf("      %s\n", stack.frames[c]);
1538          memoryErrorsCount++;
1539 #if !defined(__EMSCRIPTEN__)
1540          memMutex.Release();
1541 #endif
1542          return null;
1543       }
1544
1545       if(!recurse && !stack.recurse)
1546       {
1547          MemInfo block;
1548
1549          stack.recurse = true;
1550          block = MemInfo { size = (unsigned int)n*size, key = (uintptr)((byte *)pointer + REDZONE), _class = allocateClass, internal = allocateInternal, id = blockID++ };
1551          memcpy(block.allocLoc, stack.frames + stack.pos - Min(stack.pos, MAX_MEMORY_LOC), Min(stack.pos, MAX_MEMORY_LOC) * sizeof(char *));
1552          memBlocks.Add(block);
1553          stack.recurse = false;
1554       }
1555    }
1556 #endif
1557
1558 #if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
1559    memMutex.Release();
1560 #endif
1561
1562 #if REDZONE
1563    if(pointer)
1564    {
1565       memset(pointer, 0xAB, REDZONE);
1566       memset((byte *)pointer + REDZONE + (unsigned int)n*size, 0xAB, REDZONE);
1567    }
1568 #endif
1569    return pointer ? ((byte*)pointer + REDZONE) : null;
1570 #endif
1571 }
1572
1573 static void * _realloc(void * pointer, unsigned int size)
1574 {
1575 #if defined(DISABLE_MEMMGR) && !defined(MEMINFO)
1576    if(!size) { free(pointer); return null; }
1577    return realloc(pointer, size);
1578
1579 #else
1580    if(!size) { _free(pointer); return null; }
1581
1582 #if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
1583    memMutex.Wait();
1584 #endif
1585
1586 #ifdef MEMINFO
1587 {
1588    MemInfo block = null;
1589    MemStack stack;
1590    stack = (MemStack)memStacks.Find(GetCurrentThreadID());
1591    if(!stack)
1592    {
1593       stack = (MemStack)calloc(1, sizeof(class MemStack));
1594       stack.key = GetCurrentThreadID();
1595       memStacks.Add(stack);
1596    }
1597
1598    if(!recurse && !stack.recurse && pointer)
1599    {
1600       block = (MemInfo)memBlocks.Find((uintptr)pointer);
1601       if(!block)
1602       {
1603          printf("Reallocating Bad Memory\n");
1604          memoryErrorsCount++;
1605       }
1606       else if(block.freed)
1607       {
1608          printf("Reallocating Freed Memory\n");
1609          memoryErrorsCount++;
1610          block.OutputStacks(true);
1611       }
1612    }
1613
1614    pointer = malloc(size + REDZONE * 2);
1615    if(!pointer)
1616    {
1617       int c;
1618       printf("Memory allocation of %d bytes failed\n", size);
1619       printf("Current Stack:\n");
1620       for(c = 0; c<stack.pos; c++)
1621          if(stack.frames[c])
1622             printf("      %s\n", stack.frames[c]);
1623       memoryErrorsCount++;
1624 #if !defined(__EMSCRIPTEN__)
1625       memMutex.Release();
1626 #endif
1627       return null;
1628    }
1629    memset(pointer, 0xAB, REDZONE);
1630    memset((byte *)pointer + REDZONE + size, 0xAB, REDZONE);
1631
1632    if(block)
1633    {
1634       if(block.freed)
1635       {
1636          memcpy((byte *)pointer + REDZONE, block.oldmem, Min(block.size, size));
1637       }
1638       else
1639       {
1640          memcpy(block.freeLoc, stack.frames + stack.pos - Min(stack.pos, MAX_MEMORY_LOC), Min(stack.pos, MAX_MEMORY_LOC) * sizeof(char *));
1641          memcpy((byte *)pointer + REDZONE, (byte *)block.key, Min(block.size, size));
1642          block.oldmem = (byte *)malloc(block.size + REDZONE * 2);
1643          if(block.oldmem)
1644          {
1645             block.oldmem += REDZONE;
1646             memcpy(block.oldmem - REDZONE, (byte *)block.key - REDZONE, block.size + 2 * REDZONE);
1647          }
1648          memset((byte *)block.key - REDZONE, 0xEC, block.size + REDZONE * 2);
1649          block.freed = true;
1650       }
1651    }
1652
1653    if(!recurse && !stack.recurse)
1654    {
1655       MemInfo block;
1656       stack.recurse = true;
1657       block = MemInfo { size = size, key = (uintptr)((byte *)pointer + REDZONE), id = blockID++ };
1658       memcpy(block.allocLoc, stack.frames + stack.pos - Min(stack.pos, MAX_MEMORY_LOC), Min(stack.pos, MAX_MEMORY_LOC) * sizeof(char *));
1659       memBlocks.Add(block);
1660       stack.recurse = false;
1661    }
1662 }
1663 #else
1664    pointer = realloc(pointer, size);
1665 #endif
1666
1667 #if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
1668    memMutex.Release();
1669 #endif
1670    return pointer ? ((byte *)pointer + REDZONE) : null;
1671 #endif
1672 }
1673
1674 static void * _crealloc(void * pointer, unsigned int size)
1675 {
1676 #if defined(DISABLE_MEMMGR) && !defined(MEMINFO)
1677    uintsize s = pointer ? msize(pointer) : 0;
1678    void * p;
1679    if(!size) { free(pointer); return null; }
1680
1681    p = realloc(pointer, size);
1682    if(size > s)
1683       memset((byte *)p + s, 0, size - s);
1684    return p;
1685 #else
1686    if(!size) { _free(pointer); return null; }
1687
1688 #if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
1689    memMutex.Wait();
1690 #endif
1691
1692 #ifdef MEMINFO
1693 {
1694    MemInfo block = null;
1695    MemStack stack;
1696    stack = (MemStack)memStacks.Find(GetCurrentThreadID());
1697    if(!stack)
1698    {
1699       stack = (MemStack)calloc(1, sizeof(class MemStack));
1700       stack.key = GetCurrentThreadID();
1701       memStacks.Add(stack);
1702    }
1703
1704    if(!recurse && !stack.recurse && pointer)
1705    {
1706       block = (MemInfo)memBlocks.Find((uintptr)pointer);
1707       if(!block)
1708       {
1709          printf("Reallocating Bad Memory\n");
1710          memoryErrorsCount++;
1711       }
1712       else if(block.freed)
1713       {
1714          printf("Reallocating Freed Memory\n");
1715          memoryErrorsCount++;
1716          block.OutputStacks(true);
1717       }
1718    }
1719
1720    pointer = calloc(1, size + REDZONE * 2);
1721    if(!pointer)
1722    {
1723       int c;
1724       printf("Memory allocation of %d bytes failed\n", size);
1725       printf("Current Stack:\n");
1726       for(c = 0; c<stack.pos; c++)
1727          if(stack.frames[c])
1728             printf("      %s\n", stack.frames[c]);
1729       memoryErrorsCount++;
1730 #if !defined(__EMSCRIPTEN__)
1731       memMutex.Release();
1732 #endif
1733       return null;
1734    }
1735    memset(pointer, 0xAB, REDZONE);
1736    memset((byte *)pointer + REDZONE + size, 0xAB, REDZONE);
1737
1738    if(block)
1739    {
1740       if(block.freed)
1741       {
1742          memcpy((byte *)pointer + REDZONE, block.oldmem, Min(block.size, size));
1743       }
1744       else
1745       {
1746          memcpy(block.freeLoc, stack.frames + stack.pos - Min(stack.pos, MAX_MEMORY_LOC), Min(stack.pos, MAX_MEMORY_LOC) * sizeof(char *));
1747          memcpy((byte *)pointer + REDZONE, (byte *)block.key, Min(block.size, size));
1748          block.oldmem = (byte *)malloc(block.size + REDZONE * 2);
1749          if(block.oldmem)
1750          {
1751             block.oldmem += REDZONE;
1752             memcpy(block.oldmem - REDZONE, (byte *)block.key - REDZONE, block.size + 2 * REDZONE);
1753          }
1754          memset((byte *)block.key - REDZONE, 0xEC, block.size + REDZONE * 2);
1755          block.freed = true;
1756       }
1757    }
1758
1759    if(!recurse && !stack.recurse)
1760    {
1761       MemInfo block;
1762       stack.recurse = true;
1763       block = MemInfo { size = size, key = (uintptr)((byte *)pointer + REDZONE), id = blockID++ };
1764       memcpy(block.allocLoc, stack.frames + stack.pos - Min(stack.pos, MAX_MEMORY_LOC), Min(stack.pos, MAX_MEMORY_LOC) * sizeof(char *));
1765       memBlocks.Add(block);
1766       stack.recurse = false;
1767    }
1768 }
1769 #else
1770    pointer = crealloc(pointer, size);
1771 #endif
1772
1773 #if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
1774    memMutex.Release();
1775 #endif
1776    return pointer ? ((byte *)pointer + REDZONE) : null;
1777 #endif
1778 }
1779
1780 static void _free(void * pointer)
1781 {
1782    if(pointer)
1783    {
1784 #if defined(DISABLE_MEMMGR) && !defined(MEMINFO)
1785       free(pointer);
1786 #else
1787 #if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
1788       if(memMutex != pointer) memMutex.Wait();
1789 #endif
1790
1791 #ifdef MEMINFO
1792 {
1793       MemStack stack;
1794
1795       stack = (MemStack)memStacks.Find(GetCurrentThreadID());
1796       if(!stack)
1797       {
1798          stack = (MemStack)calloc(1, sizeof(class MemStack));
1799          stack.key = GetCurrentThreadID();
1800          memStacks.Add(stack);
1801       }
1802
1803       if(!recurse && !stack.recurse)
1804       {
1805          MemInfo block;
1806          stack.recurse = true;
1807          block = (MemInfo)memBlocks.Find((uintptr)pointer);
1808          if(!block)
1809          {
1810             int c;
1811             printf("Freeing Bad Memory\n");
1812             printf("Current Stack:\n");
1813             for(c = 0; c<stack.pos; c++)
1814                if(stack.frames[c])
1815                   printf("      %s\n", stack.frames[c]);
1816
1817             memoryErrorsCount++;
1818          }
1819          else if(block.freed)
1820          {
1821             int c;
1822             printf("Freeing Already Freed Memory\n");
1823             printf("Current Stack:\n");
1824             for(c = 0; c<stack.pos; c++)
1825                if(stack.frames[c])
1826                   printf("      %s\n", stack.frames[c]);
1827
1828             memoryErrorsCount++;
1829             block.OutputStacks(true);
1830          }
1831          else
1832          {
1833             /*int c;
1834             byte * address = (byte *)block.key;
1835             for(c = 0; c<REDZONE; c++)
1836             {
1837                if(address[-c-1] != 0xEC)
1838                {
1839                   printf("Buffer Underrun\n");
1840                   memoryErrorsCount++;
1841                   block.OutputStacks(block.freed);
1842                }
1843                if(address[c + block.size] != 0xEC)
1844                {
1845                   printf("Buffer Overrun\n");
1846                   memoryErrorsCount++;
1847                   block.OutputStacks(block.freed);
1848                }
1849             }*/
1850
1851             {
1852                byte * address;
1853                int c;
1854                int size = block.size;
1855                address = (byte *)block.key;
1856                for(c = 0; c<REDZONE; c++)
1857                {
1858                   if(address[-c-1] != 0xAB)
1859                   {
1860                      printf("Buffer Underrun (%d bytes before)\n", c+1);
1861                      memoryErrorsCount++;
1862                      block.OutputStacks(block.freed);
1863                   }
1864                   if(address[c + size] != 0xAB)
1865                   {
1866                      printf("Buffer Overrun (%d bytes past block)\n", c);
1867                      memoryErrorsCount++;
1868                      block.OutputStacks(block.freed);
1869                   }
1870                }
1871             }
1872
1873             block.freed = true;
1874             block.oldmem = (byte *)malloc(block.size + REDZONE * 2);
1875             if(block.oldmem)
1876             {
1877                block.oldmem += REDZONE;
1878                memcpy(block.oldmem - REDZONE, (byte *)block.key - REDZONE, block.size + REDZONE * 2);
1879             }
1880             memset((byte *)block.key - REDZONE, 0xEC, block.size + REDZONE * 2);
1881
1882             memcpy(block.freeLoc, stack.frames + stack.pos - Min(stack.pos, MAX_MEMORY_LOC), Min(stack.pos, MAX_MEMORY_LOC) * sizeof(char *));
1883          }
1884          stack.recurse = false;
1885       }
1886 }
1887 #else
1888       free(pointer);
1889 #endif
1890
1891 #if !defined(ECERE_BOOTSTRAP) && !defined(__EMSCRIPTEN__)
1892       if(memMutex != pointer) memMutex.Release();
1893 #endif
1894
1895 #endif
1896    }
1897 }
1898
1899 public void memswap(byte * a, byte * b, uint size)
1900 {
1901    uint c;
1902    byte buffer[1024];
1903    for(c = 0; c<size;)
1904    {
1905       int s = sizeof(buffer);
1906       if(c + s > size) s = size - c;
1907       memcpy(buffer, a + c, s);
1908       memcpy(a + c, b + c, s);
1909       memcpy(b + c, buffer, s);
1910       c += s;
1911    }
1912 }
1913
1914 public void CheckConsistency()
1915 {
1916 #ifdef MEMINFO
1917    if(!memBlocks.Check())
1918       printf("Memory Blocks Tree Integrity Failed\n");
1919 #endif
1920 }
1921
1922 public void CheckMemory()
1923 {
1924 #ifdef MEMINFO
1925    MemInfo block;
1926    uint leaksCount = 0;
1927    uint leakedObjects = 0;
1928    uint leaksSize = 0;
1929    recurse = true;
1930    // Verify Tree Integrity
1931    if(!memBlocks.Check())
1932    {
1933       printf("Memory Blocks Tree Integrity Failed\n");
1934       memoryErrorsCount++;
1935    }
1936    printf("Starting Memory Check\n");
1937    for(block = (MemInfo)memBlocks.first; block; block = (MemInfo)block.next)
1938    {
1939       if(!block.freed && block._class)
1940          leakedObjects++;
1941    }
1942
1943    for(block = (MemInfo)memBlocks.root; block;)
1944    {
1945       if(block.freed)
1946          memswap((byte *)block.key - REDZONE, block.oldmem - REDZONE, block.size + REDZONE * 2);
1947       else
1948       {
1949          if(block._class)
1950          {
1951             // if(!block.internal)
1952             {
1953                // printf("Object of class %s\n", block._class);
1954                block.OutputStacks(false);
1955             }
1956          }
1957          else if(!leakedObjects)
1958          {
1959             printf("Memory Leak\n");
1960             block.OutputStacks(false);
1961          }
1962
1963          leaksCount ++;
1964          leaksSize += block.size;
1965       }
1966
1967       if(block.left)
1968          block = (MemInfo)block.left;
1969       else if(block.right)
1970          block = (MemInfo)block.right;
1971       else
1972       {
1973          while(block)
1974          {
1975             MemInfo parent = (MemInfo)block.parent;
1976             if(parent && block == (MemInfo)parent.left && parent.right)
1977             {
1978                block = (MemInfo)parent.right;
1979                break;
1980             }
1981             block = parent;
1982          }
1983       }
1984    }
1985
1986    while((block = (MemInfo)memBlocks.root))
1987    {
1988       byte * address;
1989       int c;
1990       int size = block.size;
1991       if(block.freed)
1992       {
1993          address = block.oldmem;
1994          for(c = -REDZONE; c<size + REDZONE; c++)
1995             if(address[c] != 0xEC)
1996             {
1997                break;
1998             }
1999          if(c < size + REDZONE)
2000          {
2001             printf("Freed Memory Write\n");
2002             memoryErrorsCount++;
2003             block.OutputStacks(true);
2004          }
2005       }
2006
2007       address = (byte *)block.key;
2008       for(c = 0; c<REDZONE; c++)
2009       {
2010          if(address[-c-1] != 0xAB)
2011          {
2012             printf("Buffer Underrun (%d bytes before)\n", c + 1);
2013             memoryErrorsCount++;
2014             block.OutputStacks(block.freed);
2015          }
2016          if(address[c + size] != 0xAB)
2017          {
2018             printf("Buffer Overrun (%d bytes past)\n", c);
2019             memoryErrorsCount++;
2020             block.OutputStacks(block.freed);
2021          }
2022       }
2023
2024       memBlocks.Delete(block);
2025    }
2026    if(leaksCount)
2027    {
2028       printf("%d Memory Leaks Detected (%d objects, %d bytes).\n", leaksCount, leakedObjects, leaksSize);
2029       memoryErrorsCount++;
2030    }
2031    printf("Memory Check Completed.\n");
2032 #if defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
2033    if(memoryErrorsCount)
2034       system("pause");
2035 #endif
2036 #endif
2037 }
2038
2039 static void FixDerivativesBase(Class base, Class mod)
2040 {
2041    OldLink derivative;
2042
2043    ComputeClassParameters(base, strchr(base.name, '<'), null);
2044
2045    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
2046    {
2047       Class _class = derivative.data;
2048       ClassType type = _class.type;
2049       ClassType oldType = type;
2050       int size = _class.structSize - _class.offset;
2051       int oldSizeClass = _class.sizeClass;
2052       int sizeClass = _class.sizeClass - _class.offsetClass;
2053       Class enumBase = null;
2054       const char * dataTypeString = null;
2055       // NOTE: baseClass is class(class)
2056       Class baseClass;
2057       uint offsetBefore = _class.offset;
2058
2059       int offsetClass, totalSizeClass;
2060
2061       for(baseClass = base; baseClass.base; baseClass = baseClass.base);
2062
2063       if(base && !base.internalDecl && (base.type == noHeadClass || base.type == structClass || base.type == normalClass))
2064       {
2065          // Normal classes inheriting off simple classes should become no head classes
2066          if(base.type == structClass && type == normalClass)
2067             type = noHeadClass;
2068          else
2069             type = base.type;
2070       }
2071       if(base && (_class.type == normalClass || _class.type == noHeadClass || _class.type == structClass) &&
2072          (base.type == unitClass || base.type == bitClass || base.type == enumClass))
2073       {
2074          type = base.type;
2075       }
2076
2077       if(type == enumClass)
2078       {
2079          if(base.type != enumClass)
2080          {
2081             enumBase = base;
2082             base = eSystem_FindClass(_class.module, "enum");
2083          }
2084       }
2085
2086       dataTypeString = enumBase ? enumBase.dataTypeString : base.dataTypeString;
2087
2088       /////////////////////
2089
2090       offsetClass = base ? (base.templateClass ? base.templateClass.sizeClass : base.sizeClass) : (type == noHeadClass ? 0 : 0 /*sizeof(class Class)*/);
2091       totalSizeClass = offsetClass + sizeClass;
2092
2093       // TESTING WITHOUT THIS... Seems to yield better results, as it otherwise prevents ComputeClassMembers from doing its job on derived classes
2094
2095       // _class.memberID = _class.startMemberID = (base && (type == normalClass || type == noHeadClass || type == structClass)) ? base.memberID : 0;
2096
2097       if(type == normalClass || type == noHeadClass)
2098       {
2099          // Use 'memberOffset' for nohead class as the members get added without padding
2100          _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));
2101          if(_class.structAlignment && (_class.offset % _class.structAlignment))
2102             _class.offset += _class.structAlignment - _class.offset % _class.structAlignment;
2103       }
2104       else
2105          _class.offset = 0; // Force set to 0
2106
2107       if(type == structClass)
2108       {
2109          _class.memberOffset = (base && (base.templateClass ? base.templateClass.structSize : base.structSize) && base.type != systemClass) ? (base.templateClass ? base.templateClass.structSize : base.structSize) : 0;
2110          // THIS IS NEW...
2111          _class.typeSize = _class.structSize = _class.memberOffset + size;
2112       }
2113       else if(type == bitClass || type == enumClass || type == unitClass)
2114       {
2115          Class dataTypeClass = eSystem_FindClass(_class.module, dataTypeString);
2116          if(dataTypeClass)
2117             _class.typeSize = dataTypeClass.typeSize;
2118          _class.structSize = 0;
2119       }
2120       else if(type == normalClass || type == noHeadClass)
2121       {
2122          _class.structSize = _class.offset + size;
2123           _class.typeSize = sizeof(void *);
2124       }
2125
2126       /////////////////////
2127
2128       if(_class.type != systemClass)
2129          _class.type = type;
2130       delete (void *)_class.dataTypeString;
2131       _class.dataTypeString = CopyString(dataTypeString);
2132
2133       if(totalSizeClass != oldSizeClass)
2134       {
2135          _class.data = renew _class.data byte[totalSizeClass];
2136          /*
2137          memmove((byte *)_class.data + offsetClass, (byte *)_class.data + _class.offsetClass, _class.sizeClass - _class.offsetClass);
2138          if(base.type != systemClass && base.type != enumClass)
2139             memcpy((byte *)_class.data + _class.offsetClass, (byte *)base.data + _class.offsetClass, totalSizeClass - _class.sizeClass);
2140          else
2141             memset((byte *)_class.data + _class.offsetClass, 0, totalSizeClass - _class.sizeClass);
2142          */
2143          memmove((byte *)_class.data + mod.offsetClass, (byte *)_class.data, totalSizeClass - mod.sizeClass);
2144          if(base.type != systemClass && base.type != enumClass)
2145             memcpy((byte *)_class.data, (byte *)base.data, totalSizeClass - _class.sizeClass);
2146          else
2147             memset((byte *)_class.data, 0, totalSizeClass - _class.sizeClass);
2148       }
2149
2150       _class.offsetClass = offsetClass;
2151       _class.sizeClass = totalSizeClass;
2152
2153       {
2154          Method method, next;
2155          Class b;
2156          bool needUpdate = (mod != (base.templateClass ? base.templateClass : base) || _class.vTblSize != mod.vTblSize);
2157          int updateStart = -1, updateEnd = -1;
2158
2159          if(mod.base && mod.base.base && mod.base.vTblSize > baseClass.vTblSize && needUpdate)
2160          {
2161             _class.vTblSize += mod.base.vTblSize - baseClass.vTblSize;
2162             _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
2163             // memmove(_class._vTbl + mod.base.vTblSize, _class._vTbl + baseClass.vTblSize, (mod.base.vTblSize - baseClass.vTblSize) * sizeof(void *));
2164             memmove(_class._vTbl + mod.base.vTblSize, _class._vTbl + baseClass.vTblSize, (_class.vTblSize - mod.vTblSize) * sizeof(void *));
2165             memcpy(_class._vTbl + baseClass.vTblSize, mod._vTbl + baseClass.vTblSize, (mod.base.vTblSize - baseClass.vTblSize) * sizeof(void *));
2166
2167             updateStart = baseClass.vTblSize;
2168             updateEnd = updateStart + mod.base.vTblSize - baseClass.vTblSize;
2169
2170             for(method = (Method)_class.methods.first; method; method = next)
2171             {
2172                next = (Method)((BTNode)method).next;
2173                if(method.type == virtualMethod)
2174                   method.vid += mod.base.vTblSize - baseClass.vTblSize;
2175             }
2176          }
2177
2178             for(b = mod.base; b && b != null; b = b.base)
2179             {
2180                Method vMethod;
2181                for(vMethod = (Method)b.methods.first; vMethod; vMethod = (Method)((BTNode)vMethod).next)
2182                {
2183                   if(vMethod.type == virtualMethod)
2184                   {
2185                      method = (Method)_class.methods.FindString(vMethod.name);
2186                      if(method)
2187                      {
2188                         if(method.function) _class._vTbl[vMethod.vid] = method.function;
2189                         if(!method.symbol)
2190                         {
2191                            delete (void *)method.name;
2192                            delete (void *)method.dataTypeString;
2193                            _class.methods.Delete((BTNode)method);
2194                         }
2195                         else
2196                         {
2197                            delete (void *)method.dataTypeString;
2198                            method.type = vMethod.type;
2199                            method.dataTypeString = CopyString(vMethod.dataTypeString);
2200                            method._class = vMethod._class;
2201                         }
2202                      }
2203                      else if((vMethod.vid >= updateStart && vMethod.vid < updateEnd ) || _class._vTbl[vMethod.vid] == b._vTbl[vMethod.vid])
2204                         _class._vTbl[vMethod.vid] = _class.base._vTbl[vMethod.vid];
2205                   }
2206                }
2207             }
2208          //}
2209
2210          // Trying to simply move out the above block of code outside the if to handle this
2211          /*
2212          // Also doing this now, otherwise overridden methods of base classes from intermediate classes will not be set in higher level class
2213          // (e.g. OnGetString overridden in Id , Location inheriting from Id, LocationAbbreviation created later inheriting from Location would not get Id's OnGetString)
2214          for(b = mod.base; b && b != null; b = b.base)
2215          {
2216             Method vMethod;
2217             for(vMethod = (Method)b.methods.first; vMethod; vMethod = (Method)((BTNode)vMethod).next)
2218             {
2219                if(vMethod.type == virtualMethod)
2220                {
2221                   if(_class._vTbl[vMethod.vid] == b._vTbl[vMethod.vid] && _class._vTbl[vMethod.vid] != _class.base._vTbl[vMethod.vid])
2222                      _class._vTbl[vMethod.vid] = _class.base._vTbl[vMethod.vid];
2223                }
2224             }
2225          }
2226          */
2227       }
2228
2229       // _class.defaultAlignment = base ? base.defaultAlignment : 0;
2230
2231       if(type == normalClass || type == noHeadClass || type == structClass)
2232       {
2233          Property prop;
2234          DataMember member;
2235          Class c;
2236          for(c = mod.base; c; c = c.base)
2237          {
2238             Property _property;
2239             for(_property = c.membersAndProperties.first; _property; _property = _property.next)
2240             {
2241                if(_property.isProperty)
2242                {
2243                   BTNamedLink link = (BTNamedLink)_class.prop.FindString(_property.name);
2244                   if(link)
2245                   {
2246                      prop = link.data;
2247                      if(!prop.Set && !prop.Get && prop.memberAccess == baseSystemAccess)
2248                      {
2249                         SelfWatcher watcher;
2250                         for(watcher = _class.selfWatchers.first; watcher; watcher = watcher.next)
2251                         {
2252                            if(watcher._property == prop)
2253                               watcher._property = _property;
2254                         }
2255                         _property.selfWatchable = true;
2256                         _class.prop.Delete((BTNode)link);
2257                         delete (void *)prop.name;
2258                         delete (void *)prop.dataTypeString;
2259                         _class.membersAndProperties.Delete(prop);    // Remove only was done before?
2260                      }
2261                   }
2262                }
2263             }
2264          }
2265          // if(mod.base.memberID)
2266          {
2267             DataMember next;
2268             for(member = _class.membersAndProperties.first; member; member = next)
2269             {
2270                int offsetDiff = _class.offset - offsetBefore;
2271                next = member.next;
2272                if(!member.isProperty)
2273                {
2274                   if(oldType == bitClass && type != bitClass)
2275                   {
2276                      DataMember prev = member.prev;
2277                      // Correcting a bitClass to be a non-bit class (This should really never be required)
2278                      _class.membersAndProperties.Remove(member);
2279                      member = (DataMember)renew0 member byte[sizeof (class DataMember)];
2280                      _class.membersAndProperties.Insert(prev, member);
2281                   }
2282
2283                   if(offsetDiff > 0)
2284                   {
2285                      member.offset += offsetDiff;
2286                      member.memberOffset += offsetDiff;
2287                   }
2288                }
2289                member.id += mod.base.memberID;
2290             }
2291
2292             _class.memberID += mod.base.memberID;
2293             _class.startMemberID += mod.base.memberID;
2294          }
2295       }
2296       // Moved this before to ensure CPValues have their data ready
2297       FixDerivativesBase(_class, mod);
2298       {
2299          Class c;
2300          for(c = mod.base; c; c = c.base)
2301          {
2302             ClassProperty _property;
2303             for(_property = (ClassProperty)c.classProperties.first; _property; _property = (ClassProperty)((BTNode)_property).next)
2304             {
2305                SetDelayedCPValues(_class, _property);
2306             }
2307          }
2308       }
2309    }
2310
2311    {
2312       OldLink templateLink;
2313       for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
2314       {
2315          Class template = templateLink.data;
2316          //const char * templateParams = strchr(template.name, '<');
2317          template.base = base.base;
2318          template._vTbl = base._vTbl;
2319          //ComputeClassParameters(template, templateParams, null);
2320
2321          template.data = base.data;
2322          template.offset = base.offset;
2323          template.offsetClass = base.offsetClass;
2324          template.sizeClass = base.sizeClass;
2325          template.structSize = base.structSize;
2326          template.vTblSize = base.vTblSize;
2327
2328          FixDerivativesBase(template, mod);
2329       }
2330    }
2331 }
2332
2333 public dllexport Class eSystem_RegisterClass(ClassType type, const char * name, const char * baseName, int size, int sizeClass,
2334                              bool (* Constructor)(void *), void (* Destructor)(void *),
2335                              Module module, AccessMode declMode, AccessMode inheritanceAccess)
2336 {
2337    int start = 0, c;
2338    NameSpace * nameSpace = null;
2339    bool force64Bits = (module.application.isGUIApp & 2) ? true : false;
2340    bool force32Bits = (module.application.isGUIApp & 4) ? true : false;
2341    bool inCompiler = (module.application.isGUIApp & 8) ? true : false;
2342    bool crossBits = force32Bits || force64Bits;
2343    bool fixed = false;
2344    if(inCompiler && crossBits)
2345    {
2346       Class c = eSystem_FindClass(__thisModule.application, name);
2347       if(c && c.fixed)
2348          fixed = true;
2349       else if(__thisModule.name && !strcmp(__thisModule.name, "ecereCOM"))
2350          fixed = true;
2351    }
2352
2353    {
2354       nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
2355       if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
2356
2357       // if(declMode != staticAccess)
2358       {
2359          for(c = 0; name[c]; c++)
2360          {
2361             if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
2362             {
2363                NameSpace * newSpace;
2364
2365                char * spaceName = _malloc(c - start + 1);
2366                strncpy(spaceName, name + start, c - start);
2367                spaceName[c-start] = '\0';
2368
2369                newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
2370                if(!newSpace)
2371                {
2372                   newSpace = new0 NameSpace[1];
2373                   newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
2374                   newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
2375                   newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
2376                   newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
2377                   newSpace->name = spaceName;
2378                   newSpace->parent = nameSpace;
2379                   nameSpace->nameSpaces.Add((BTNode)newSpace);
2380                }
2381                else
2382                   delete spaceName;
2383                nameSpace = newSpace;
2384                if(name[c] == ':') c++;
2385                start = c+1;
2386             }
2387          }
2388       }
2389       /*else
2390          c = strlen(name);*/
2391    }
2392
2393    if(c - start)
2394    {
2395       int offsetClass;
2396       int totalSizeClass;
2397       BTNamedLink classLink = null;
2398       Class _class = null;
2399       const char * dataTypeString = null;
2400       Class enumBase = null;
2401       Class base = (baseName && baseName[0]) ? eSystem_FindClass(module, baseName) : null;
2402       Class prevBase = null;
2403
2404       if(base && !base.internalDecl && (base.type == noHeadClass || base.type == structClass || base.type == normalClass))
2405       {
2406          // Normal classes inheriting off simple classes should become no head classes
2407          if(base.type == structClass && type == normalClass)
2408             type = noHeadClass;
2409          else
2410             type = base.type;
2411       }
2412       if(base && (type == normalClass || type == noHeadClass || type == structClass) &&
2413          (base.type == unitClass || base.type == bitClass || base.type == enumClass))
2414       {
2415          type = base.type;
2416       }
2417       if(!base || base.type == systemClass || base.isInstanceClass)
2418       {
2419          if(type == enumClass)
2420          {
2421             // TO IMPROVE:
2422             if(base || !baseName || !baseName[0] ||
2423                !strcmp(baseName, "unsigned int") ||
2424                !strcmp(baseName, "uint") ||
2425                !strcmp(baseName, "unsigned int64") ||
2426                !strcmp(baseName, "uint64") ||
2427                !strcmp(baseName, "int64") ||
2428                !strcmp(baseName, "unsigned short") ||
2429                !strcmp(baseName, "short") ||
2430                !strcmp(baseName, "unsigned char") ||
2431                !strcmp(baseName, "byte") ||
2432                !strcmp(baseName, "char") ||
2433                !strcmp(baseName, "uint32") ||
2434                !strcmp(baseName, "uint16"))
2435             {
2436                base = eSystem_FindClass(module, "enum");
2437                dataTypeString = (baseName && baseName[0]) ? baseName : "int"; //"unsigned int";
2438             }
2439             else
2440             {
2441                // Undefined base
2442                base = eSystem_RegisterClass(0, baseName, null, 0,0, null, null, module, declMode, publicAccess);
2443                base.internalDecl = true;
2444
2445                enumBase = base;
2446                base = eSystem_FindClass(module, "enum");
2447                //dataTypeString = (baseName && baseName[0]) ? baseName : "unsigned int";
2448             }
2449          }
2450          else if(type == structClass && (!baseName || !baseName[0]))
2451          {
2452             base = eSystem_FindClass(module, "struct");
2453             dataTypeString = name + start;
2454          }
2455          else
2456          {
2457             if(type == normalClass)
2458                // dataTypeString = "struct Instance";
2459                dataTypeString = "struct __ecereNameSpace__ecere__com__Instance";
2460             else if(type == noHeadClass)
2461                dataTypeString = "void *";
2462             else if(type == bitClass)
2463                dataTypeString = (baseName && baseName[0]) ? baseName : "unsigned int";
2464             else if(type == unitClass)
2465                dataTypeString = (baseName && baseName[0]) ? baseName : "int";
2466             else if(type == structClass)
2467                dataTypeString = name + start;
2468
2469             // TODO: base bit, unit or enum classes not defined yet
2470             if(base || (!baseName || !baseName[0]) || type == bitClass || type == unitClass)
2471             {
2472                // DANGEROUSLY TESTING THIS... PUT IT BACK
2473                //if(!base)
2474                if(base || !baseName || !baseName[0] ||
2475                   !strcmp(baseName, "unsigned int") ||
2476                   !strcmp(baseName, "uint") ||
2477                   !strcmp(baseName, "unsigned int64") ||
2478                   !strcmp(baseName, "uint64") ||
2479                   !strcmp(baseName, "int64") ||
2480                   !strcmp(baseName, "unsigned short") ||
2481                   !strcmp(baseName, "short") ||
2482                   !strcmp(baseName, "unsigned char") ||
2483                   !strcmp(baseName, "byte") ||
2484                   !strcmp(baseName, "char") ||
2485                   !strcmp(baseName, "uint32") ||
2486                   !strcmp(baseName, "uint16"))
2487                {
2488                   if(type == normalClass && strcmp(name, "ecere::com::Instance") && strcmp(name, "enum") && strcmp(name, "struct"))
2489                      base = eSystem_FindClass(module, "ecere::com::Instance");
2490                   else
2491                      base = eSystem_FindClass(module, "class");
2492                }
2493             }
2494             else
2495             {
2496                // Base class has not been defined yet!
2497             }
2498          }
2499       }
2500       else
2501       {
2502          if(type == enumClass)
2503          {
2504             if(base.type != enumClass)
2505             {
2506                enumBase = base;
2507                base = eSystem_FindClass(module, "enum");
2508             }
2509          }
2510          dataTypeString = enumBase ? enumBase.dataTypeString : base.dataTypeString;
2511       }
2512
2513       offsetClass = base ? base.sizeClass : (type == noHeadClass ? 0 : 0 /*sizeof(class Class)*/);
2514       totalSizeClass = offsetClass + sizeClass;
2515
2516       _class = eSystem_FindClass(module, name);
2517       if(!_class)
2518       {
2519          const char * colons = RSearchString(name, "::", strlen(name), true, false);
2520          if(colons && colons)
2521          {
2522             _class = eSystem_FindClass(module, colons + 2);
2523             if(_class)
2524             {
2525                if(_class.internalDecl)
2526                {
2527                   delete (void *)_class.fullName;
2528                   _class.fullName = CopyString(name);
2529                }
2530                else
2531                   _class = null;
2532             }
2533          }
2534       }
2535       if(_class)
2536       {
2537          if(!_class.internalDecl)
2538          {
2539             if(declMode != baseSystemAccess)
2540                // i18n in instance.ec is more trouble than it's worth.
2541                printf("error: Redefinition of class %s\n", name);
2542             else
2543             {
2544                _class.comRedefinition = true;
2545                return _class;
2546             }
2547             return null;
2548          }
2549
2550          FreeTemplatesDerivatives(_class);
2551
2552          classLink = (BTNamedLink)_class.nameSpace->classes.FindString(name + start);
2553          _class.nameSpace->classes.Delete((BTNode)classLink);
2554          {
2555             OldLink t;
2556             for(t = _class.templatized.first; t; t = t.next)
2557             {
2558                Class template = t.data;
2559                classLink = (BTNamedLink)_class.nameSpace->classes.FindString(template.name);
2560
2561                _class.nameSpace->classes.Delete((BTNode)classLink);
2562             }
2563          }
2564          {
2565             NameSpace * ns = _class.nameSpace;
2566             while(ns->parent &&
2567                !ns->classes.first &&
2568                !ns->functions.first &&
2569                !ns->defines.first &&
2570                !ns->nameSpaces.first)
2571             {
2572                NameSpace * parent = ns->parent;
2573                NameSpace_Free(ns);
2574                parent->nameSpaces.Delete((BTNode)ns);
2575                ns = parent;
2576             }
2577          }
2578       }
2579       else
2580       {
2581          classLink = SearchNameSpace(module.application.privateNameSpace, name, &((NameSpace *)0)->classes);
2582          if(!classLink)
2583             classLink = SearchNameSpace(module.application.publicNameSpace, name, &((NameSpace *)0)->classes);
2584
2585          if(!classLink)
2586             classLink = SearchNameSpace(module.application.privateNameSpace, name + start, &((NameSpace *)0)->classes);
2587          if(!classLink)
2588             classLink = SearchNameSpace(module.application.publicNameSpace, name + start, &((NameSpace *)0)->classes);
2589
2590          if(classLink)
2591             _class = classLink.data;
2592          if(_class && _class.internalDecl)
2593          {
2594             FreeTemplatesDerivatives(_class);
2595
2596             _class.nameSpace->classes.Delete((BTNode)classLink);
2597             {
2598                OldLink t;
2599                for(t = _class.templatized.first; t; t = t.next)
2600                {
2601                   Class template = t.data;
2602                   classLink = (BTNamedLink)_class.nameSpace->classes.FindString(template.name);
2603                   _class.nameSpace->classes.Delete((BTNode)classLink);
2604
2605                }
2606             }
2607
2608             delete (void *)_class.fullName;
2609             _class.fullName = CopyString(name);
2610          }
2611          else
2612          {
2613             _class = _calloc(1, sizeof(class Class));
2614             _class.methods.CompareKey = (void *)BinaryTree::CompareString;
2615             _class.members.CompareKey = (void *)BinaryTree::CompareString;
2616             _class.prop.CompareKey = (void *)BinaryTree::CompareString;
2617             _class.classProperties.CompareKey = (void *)BinaryTree::CompareString;
2618
2619             _class.name = CopyString(name + start);
2620             _class.fullName = CopyString(name);
2621          }
2622       }
2623       if(nameSpace)
2624       {
2625          nameSpace->classes.Add((BTNode)BTNamedLink { name = (char *)_class.name, data = _class });
2626          {
2627             OldLink t;
2628             for(t = _class.templatized.first; t; t = t.next)
2629             {
2630                Class template = t.data;
2631                nameSpace->classes.Add((BTNode)BTNamedLink { name = (char *)template.name, data = template });
2632             }
2633          }
2634
2635       }
2636
2637       if(_class)
2638       {
2639          if(!base && baseName && strcmp(baseName, name))
2640          {
2641             // Undefined base
2642             if(strchr(baseName, '<'))
2643             {
2644                char templateClassName[1024];
2645                Class templateBase;
2646                strcpy(templateClassName, baseName);
2647                *strchr(templateClassName, '<') = '\0';
2648                templateBase = eSystem_FindClass(module, templateClassName);
2649                if(!templateBase)
2650                {
2651                   templateBase = eSystem_RegisterClass(0, templateClassName, null, 0,0, null, null, module, declMode, publicAccess);
2652                   templateBase.internalDecl = true;
2653                }
2654                base = eSystem_FindClass(module, baseName);
2655             }
2656             else
2657             {
2658                base = eSystem_RegisterClass(0, baseName, null, 0,0, null, null, module, declMode, publicAccess);
2659                base.internalDecl = true;
2660             }
2661             /*
2662             base.size = 0;
2663             base.offset = 0;
2664             base.memberOffset = 0;
2665             */
2666          }
2667          else
2668             _class.internalDecl = false;
2669
2670          if(totalSizeClass)
2671          {
2672             _class.data = renew _class.data byte[totalSizeClass];
2673             // Class Data is often not inherited... e.g. Window::pureVtbl problem
2674             // memset(_class.data, 0, totalSizeClass);
2675             if(base && base.type != systemClass && base.type != enumClass)
2676                memcpy(_class.data, base.data, offsetClass);
2677             else
2678                memset(_class.data, 0, offsetClass);
2679             memset((byte *)_class.data + offsetClass, 0, sizeClass);
2680          }
2681
2682          delete (void *)_class.dataTypeString;
2683          _class.dataTypeString = CopyString(dataTypeString);
2684          _class.defaultAlignment = base ? base.defaultAlignment : 0;
2685
2686          // Dereference the class in previous module the classed belonged to
2687          if(_class.module)
2688          {
2689             _class.module.classes.Remove(_class);
2690          }
2691
2692          if(_class.base)
2693          {
2694             //Class base = _class.base.templateClass ? _class.base.templateClass : _class.base;
2695             Class base = _class.base;
2696             OldLink deriv = base.derivatives.FindLink(_class);
2697             base.derivatives.Delete(deriv);
2698          }
2699
2700          // Reference the class in the module
2701          if(module)
2702          {
2703             module.classes.Add(_class);
2704          }
2705
2706          _class.nameSpace = nameSpace;
2707          {
2708             OldLink t;
2709             for(t = _class.templatized.first; t; t = t.next)
2710             {
2711                Class template = t.data;
2712                template.nameSpace = nameSpace;
2713             }
2714          }
2715
2716          _class.module = module;
2717          prevBase = _class.base;
2718          _class.base = base;
2719          if(base)
2720          {
2721             int numParams = 0;
2722             Class sClass;
2723             for(sClass = base; sClass; sClass = sClass.base)
2724             {
2725                if(sClass.templateClass) sClass = sClass.templateClass;
2726                numParams += sClass.templateParams.count;
2727             }
2728             if(numParams)
2729             {
2730                if(_class.templateArgs)
2731                {
2732                   FreeTemplateArgs(_class);
2733                }
2734                delete _class.templateArgs;
2735                _class.templateArgs = new0 ClassTemplateArgument[numParams];
2736                _class.numParams = numParams;
2737
2738                for(sClass = _class; sClass; sClass = sClass.base)
2739                {
2740                   Class prevClass;
2741                   ClassTemplateParameter param;
2742                   int id = 0;
2743                   if(sClass.templateClass) sClass = sClass.templateClass;
2744                   for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
2745                   {
2746                      if(prevClass.templateClass) prevClass = prevClass.templateClass;
2747                      id += prevClass.templateParams.count;
2748                   }
2749
2750                   if(base.templateArgs)   // Add numParams test here?
2751                   {
2752                      for(param = sClass.templateParams.first; param; param = param.next)
2753                      {
2754                         _class.templateArgs[id] = base.templateArgs[id];
2755                         CopyTemplateArg(param, _class.templateArgs[id]);
2756                         id++;
2757                      }
2758                   }
2759                }
2760             }
2761          }
2762          _class.memberID = _class.startMemberID = (base && (type == normalClass || type == noHeadClass || type == structClass)) ? base.memberID : 0;
2763          if(type == normalClass || type == noHeadClass)
2764             _class.offset = (base && base.structSize && base.type != systemClass) ?
2765                // Use 'memberOffset' for nohead class as the members get added without padding
2766                (base.type == normalClass ? base.structSize : base.memberOffset) : ((type == noHeadClass) ? 0 : ((force64Bits && inCompiler && fixed) ? 24 : (force32Bits && inCompiler && fixed) ? 12 : sizeof(class Instance)));
2767          else
2768             _class.offset = 0;   // Force set to 0 for redefinitions
2769
2770          // For cross-bitness-compiling
2771          if(crossBits)
2772          {
2773             // The GNOSIS runtime will use 'offset' to point to the object during compile executation
2774             // Need to rethink through our cross-bitness compiling to have a distinct 'offset' (e.g. runtimeOffset)
2775             // used by the runtime library vs. 'offset' used by the compiler to hardcode compilation results (or avoid those altogether)
2776             if(!strcmp(name, "GNOSISSystem") ||
2777                !strcmp(name, "LineStyle") ||
2778                !strcmp(name, "FillStyle") ||
2779                !strcmp(name, "FontObject") ||
2780                !strcmp(name, "SymbolStyle"))
2781             {
2782                _class.offset = force32Bits ? 24 : 12;
2783             }
2784             // Ideally, the running library should be aware of the struct size of both 32 and 64 bit, since the compiler has no knowledge whatsoever of private members
2785             else if(strstr(name, "ecere::sys::EARHeader") ||
2786                strstr(name, "AnchorValue") ||
2787                !strcmp(name, "ecere::com::CustomAVLTree") ||
2788                !strcmp(name, "ecere::com::Array") ||
2789                !strcmp(name, "ecere::gui::Window") ||
2790                !strcmp(name, "ecere::sys::Mutex"));   // Never recompute these, they're always problematic (errors, crashes)
2791             else
2792             {
2793                if(!strcmp(name, "ecere::sys::FileListing"))
2794                {
2795                   size = 3*(force32Bits ? 4 : 8);
2796                   _class.structAlignment = force32Bits ? 4 : 8;   // FileListing is problematic because it is a struct with private data that the user allocates
2797                   _class.pointerAlignment = 1;
2798                }
2799                // These we want to recompute inside the IDE to help the debugger
2800                else if(!strcmp(name, "ecere::com::Class"))           size = 0; // 616
2801                else if(!strcmp(name, "ecere::com::ClassProperty"))   size = 0; // 80
2802                else if(!strcmp(name, "ecere::com::NameSpace"))       size = 0; // 176
2803                else if(!strcmp(name, "ecere::sys::BufferedFile"))    size = 0;
2804                else if(!strcmp(name, "ecere::sys::BTNode"))          size = 0;
2805                else if(!strcmp(name, "ecere::sys::StringBTNode"))    size = 0;
2806                else if(!strcmp(name, "ecere::sys::OldList"))         size = 0; // 32
2807                else if(!strcmp(name, "ecere::sys::Item"))            size = 0;
2808                else if(!strcmp(name, "ecere::sys::NamedLink"))       size = 0;
2809                else if(!strcmp(name, "ecere::sys::NamedLink64"))     size = 0;
2810                else if(!strcmp(name, "ecere::sys::OldLink"))         size = 0;
2811                else if(!strcmp(name, "ecere::sys::NamedItem"))       size = 0;
2812                else if(!strcmp(name, "ecere::sys::NamedItem64"))     size = 0;
2813                else if(!strcmp(name, "ecere::sys::BinaryTree"))      size = 0;
2814                else if(module != module.application && inCompiler)
2815                {
2816                   // These we only want to recompute inside the compiler
2817                   if(fixed || type == structClass)
2818                      size = 0;
2819                }
2820             }
2821          }
2822          if(type == structClass)
2823          {
2824             _class.memberOffset = (base && base.structSize && base.type != systemClass) ? base.structSize : 0;
2825             // THIS IS NEW...
2826             _class.typeSize = _class.structSize = _class.memberOffset + size;
2827          }
2828          else if(type == bitClass || type == enumClass || type == unitClass)
2829          {
2830             Class dataTypeClass = eSystem_FindClass(_class.module, dataTypeString);
2831             if(dataTypeClass)
2832                _class.typeSize = dataTypeClass.typeSize;
2833             _class.structSize = 0;
2834          }
2835          else if(type == normalClass || type == noHeadClass)
2836          {
2837             _class.structSize = _class.offset + size;
2838             _class.typeSize = sizeof(void *);
2839          }
2840          _class.offsetClass = offsetClass;
2841          _class.sizeClass = totalSizeClass;
2842          _class.Constructor = Constructor;
2843          _class.Destructor = Destructor;
2844          if(_class.type != systemClass)
2845             _class.type = type;
2846          if(!size)
2847             _class.computeSize = true;
2848          else
2849             _class.computeSize = false;
2850          _class.inheritanceAccess = inheritanceAccess;
2851
2852          /*if(type == bitClass)
2853             _class.size = 0;*/
2854          if(type == enumClass)
2855          {
2856             if(enumBase)
2857                _class.base = base = enumBase;
2858             //else
2859             {
2860                EnumClassData data = (EnumClassData)_class.data;
2861                // TOCHECK: Trying this (if specifiers specified, no class found...)
2862                // What about bit classes, unit classes...
2863                if(base && base.type != enumClass)
2864                   data.largest = -1;//_class.base = null;
2865                else
2866                   data.largest = ((EnumClassData)(base.data)).largest;
2867             }
2868          }
2869          if(base)
2870          {
2871             int i;
2872             uint oldSize = _class.vTblSize;
2873             if(base.vTblSize && _class.vTblSize < base.vTblSize)
2874             {
2875                _class.vTblSize = base.vTblSize;
2876                // OK to scrap existing virtual table?
2877                //delete _class._vTbl;
2878                //_class._vTbl = _malloc(sizeof(int(*)()) * _class.vTblSize);
2879                // memcpy(_class._vTbl, base._vTbl, sizeof(int(*)()) * _class.vTblSize);
2880                _class._vTbl = _realloc(_class._vTbl, sizeof(int(*)()) * _class.vTblSize);
2881             }
2882             if(!prevBase)
2883             {
2884                if(_class.type == normalClass && strcmp(_class.name, "ecere::com::Instance") && strcmp(_class.name, "enum") && strcmp(_class.name, "struct"))
2885                   prevBase = eSystem_FindClass(module, "ecere::com::Instance");
2886                else
2887                   prevBase = eSystem_FindClass(module, "class");
2888             }
2889             for(i = 0; i < base.vTblSize; i++)
2890             {
2891                if(i >= oldSize || _class._vTbl[i] == prevBase._vTbl[i])
2892                   _class._vTbl[i] = base._vTbl[i];
2893             }
2894          }
2895
2896          if(_class.base)
2897          {
2898             OldLink link { data = _class };
2899             /*(_class.base.templateClass ? _class.base.templateClass : _class.base)*/_class.base.derivatives.Add(link);
2900          }
2901
2902          FixDerivativesBase(_class, _class);
2903
2904          return _class;
2905       }
2906    }
2907    return null;
2908 }
2909
2910 static void DataMember_Free(DataMember parentMember)
2911 {
2912    DataMember member;
2913    BTNamedLink namedLink;
2914    delete (void *)parentMember.name;
2915    delete (void *)parentMember.dataTypeString;
2916
2917    while((member = parentMember.members.first))
2918    {
2919       DataMember_Free(member);
2920       parentMember.members.Delete(member);
2921    }
2922
2923    while((namedLink = (BTNamedLink)parentMember.membersAlpha.first))
2924    {
2925       parentMember.membersAlpha.Delete((BTNode)namedLink);
2926    }
2927 }
2928
2929 static void FreeEnumValue(NamedLink64 value)
2930 {
2931    delete value.name;
2932 }
2933
2934 static void FreeTemplateArg(Class template, ClassTemplateParameter param, int id)
2935 {
2936    switch(param.type)
2937    {
2938       case type:
2939          delete (void *)template.templateArgs[id].dataTypeString;
2940          break;
2941       case identifier:
2942          delete (void *)template.templateArgs[id].memberString;
2943          break;
2944       case expression:
2945
2946          break;
2947    }
2948 }
2949
2950 static void FreeTemplateArgs(Class template)
2951 {
2952    if(template.templateArgs)
2953    {
2954       Class _class;
2955       for(_class = template; _class; _class = _class.base)
2956       {
2957          Class prevClass;
2958          ClassTemplateParameter param;
2959          int id = 0;
2960          if(_class.templateClass) _class = _class.templateClass;
2961          for(prevClass = _class.base; prevClass; prevClass = prevClass.base)
2962          {
2963             if(prevClass.templateClass) prevClass = prevClass.templateClass;
2964             id += prevClass.templateParams.count;
2965          }
2966          if(id < template.numParams)
2967          {
2968             for(param = _class.templateParams.first; param; param = param.next)
2969             {
2970                switch(param.type)
2971                {
2972                   case type:
2973                      delete (void *)template.templateArgs[id].dataTypeString;
2974                      break;
2975                   case identifier:
2976                      delete (void *)template.templateArgs[id].memberString;
2977                      break;
2978                   case expression:
2979                      // delete template.templateArgs[id].dataTypeString;
2980                      break;
2981                }
2982                id++;
2983             }
2984          }
2985       }
2986    }
2987 }
2988
2989 static void FreeTemplate(Class template)
2990 {
2991    OldLink deriv;
2992
2993    if(template.nameSpace)
2994    {
2995       BTNamedLink link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
2996       if(link)
2997          template.nameSpace->classes.Delete((BTNode)link);
2998    }
2999    FreeTemplateArgs(template);
3000
3001    delete (void *)template.fullName;
3002    delete (void *)template.name;
3003    delete (void *)template.templateArgs;
3004    delete (void *)template.dataTypeString;
3005
3006    while((deriv = template.derivatives.first))
3007    {
3008       ((Class)deriv.data).base = null;
3009       template.derivatives.Delete(deriv);
3010    }
3011
3012    if(template.module)
3013       template.module.classes.Delete(template);
3014    else
3015       _free(template);
3016 }
3017
3018 static void FreeTemplates(Class _class)
3019 {
3020    OldLink deriv, template;
3021
3022    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
3023    {
3024       FreeTemplates(deriv.data);
3025    }
3026
3027    FreeTemplateArgs(_class);
3028    //if(_class.templateArgs)
3029       //printf("Deleting  Template args for %s\n", _class.name);
3030    delete _class.templateArgs;
3031    delete (void *)_class.dataTypeString;
3032
3033    while((template = _class.templatized.first))
3034    {
3035       FreeTemplates(template.data);
3036       FreeTemplate(template.data);
3037       _class.templatized.Delete(template);
3038    }
3039 }
3040
3041 public dllexport void eClass_Unregister(Class _class)
3042 {
3043    BTNamedLink namedLink;
3044    DataMember member;
3045    Method method;
3046    OldLink deriv, template;
3047    ClassProperty classProp;
3048    ClassTemplateParameter param;
3049
3050    if(_class.templateClass)
3051    {
3052       // Unregistering templates... Used in IDE to address crash on Ecere classes templatized with imported modules
3053       OldLink templateLink;
3054       for(templateLink = _class.templateClass.templatized.first; templateLink; templateLink = templateLink.next)
3055       {
3056          if(templateLink.data == _class)
3057          {
3058             _class.templateClass.templatized.Delete(templateLink);
3059             break;
3060          }
3061       }
3062       FreeTemplate(_class);
3063       return;
3064    }
3065
3066    delete _class._vTbl;
3067
3068    FreeTemplates(_class);
3069
3070    FreeTemplateArgs(_class);
3071    delete _class.templateArgs;
3072
3073    while((template = _class.templatized.first))
3074    {
3075       FreeTemplate(template.data);
3076       _class.templatized.Delete(template);
3077    }
3078
3079    while((member = _class.membersAndProperties.first))
3080    {
3081       if(!member.isProperty && (member.type == unionMember || member.type == structMember))
3082          DataMember_Free(member);
3083       delete (void *)member.name;
3084       delete (void *)member.dataTypeString;
3085       _class.membersAndProperties.Delete(member);
3086    }
3087
3088    while((member = _class.conversions.first))
3089    {
3090       delete (void *)member.name;
3091       delete (void *)member.dataTypeString;
3092       _class.conversions.Delete(member);
3093    }
3094
3095    while((namedLink = (BTNamedLink)_class.prop.first))
3096    {
3097       _class.prop.Delete((BTNode)namedLink);
3098    }
3099
3100    while((namedLink = (BTNamedLink)_class.members.first))
3101    {
3102       _class.members.Delete((BTNode)namedLink);
3103    }
3104
3105    while((classProp = (ClassProperty)_class.classProperties.first))
3106    {
3107       delete (void *)classProp.name;
3108       delete (void *)classProp.dataTypeString;
3109       _class.classProperties.Delete((BTNode)classProp);
3110    }
3111
3112    while((method = (Method)_class.methods.first))
3113    {
3114       delete (void *)method.name;
3115       delete (void *)method.dataTypeString;
3116       _class.methods.Delete((BTNode)method);
3117    }
3118
3119    if(_class.type == enumClass)
3120    {
3121       EnumClassData data = (EnumClassData)_class.data;
3122
3123       data.values.Free((void *)FreeEnumValue);
3124    }
3125    _class.delayedCPValues.Free(null);
3126
3127    _class.selfWatchers.Free(null);
3128
3129    if(_class.base)
3130    {
3131       // Class base = _class.base.templateClass ? _class.base.templateClass : _class.base;
3132       Class base = _class.base;
3133       for(deriv = base.derivatives.first; deriv; deriv = deriv.next)
3134       {
3135          if(deriv.data == _class)
3136             break;
3137       }
3138       if(deriv)
3139          base.derivatives.Delete(deriv);
3140    }
3141    while((deriv = _class.derivatives.first))
3142    {
3143       ((Class)deriv.data).base = null;
3144       _class.derivatives.Delete(deriv);
3145    }
3146
3147    if(_class.nameSpace)
3148    {
3149       BTNamedLink link = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
3150       _class.nameSpace->classes.Delete((BTNode)link);
3151    }
3152
3153    delete (void *)_class.name;
3154    delete (void *)_class.fullName;
3155
3156    delete (void *)_class.dataTypeString;
3157
3158    delete _class.data;
3159
3160    while((param = _class.templateParams.first))
3161    {
3162       switch(param.type)
3163       {
3164          case type:
3165             delete (void *)param.defaultArg.dataTypeString;
3166             break;
3167          case identifier:
3168             delete (void *)param.defaultArg.memberString;
3169             break;
3170          case expression:
3171
3172             break;
3173       }
3174       if(param.type != identifier) delete (void *)param.dataTypeString;
3175       delete (void *)param.name;
3176
3177       _class.templateParams.Delete(param);
3178    }
3179
3180    //_class.nameSpace->classes.Delete(_class);
3181    _free(_class);
3182 }
3183
3184 static BTNamedLink ScanNameSpace(NameSpace nameSpace, const char * name, void * listOffset)
3185 {
3186    BinaryTree * tree = (BinaryTree *)((byte *)nameSpace + (uintptr)listOffset);
3187    BTNamedLink link = (BTNamedLink)tree->Find((uintptr)name);
3188    NameSpace * child;
3189    if(!link)
3190    {
3191       for(child = (NameSpace *)nameSpace.nameSpaces.first; child; child = (NameSpace *)((BTNode)child).next)
3192       {
3193          link = ScanNameSpace(child, name, listOffset);
3194          if(link)
3195             break;
3196       }
3197    }
3198    return link;
3199 }
3200
3201 static BTNamedLink SearchNameSpace(NameSpace nameSpace, const char * name, void * listOffset)
3202 {
3203    int start = 0, c;
3204    char ch;
3205    int level = 0;
3206    for(c = 0; (ch = name[c]); c++)
3207    {
3208       if(ch == '<') level++;
3209       if(ch == '>') level--;
3210       if(level == 0 && (ch == '.' || (ch == ':' && name[c+1] == ':')))
3211       {
3212          NameSpace * newSpace;
3213          char * spaceName = _malloc(c - start + 1);
3214          memcpy(spaceName, name + start, c - start);
3215          spaceName[c-start] = '\0';
3216          newSpace = (NameSpace *)nameSpace.nameSpaces.FindString(spaceName);
3217          _free(spaceName);
3218          if(!newSpace)
3219             return null;
3220          nameSpace = newSpace;
3221          if(level == 0 && ch == ':') c++;
3222          start = c+1;
3223       }
3224    }
3225    if(c - start)
3226    {
3227       return ScanNameSpace(nameSpace, name + start, listOffset);
3228    }
3229    return null;
3230 }
3231
3232 static BTNamedLink SearchModule(Module module, const char * name, void * listOffset, bool searchPrivate)
3233 {
3234    SubModule subModule;
3235    BTNamedLink link;
3236
3237    if(searchPrivate)
3238    {
3239       link = SearchNameSpace(&module.privateNameSpace, name, listOffset);
3240       if(link) return link;
3241    }
3242    link = SearchNameSpace(&module.publicNameSpace, name, listOffset);
3243    if(link) return link;
3244
3245    for(subModule = module.modules.first; subModule; subModule = subModule.next)
3246    {
3247       if(searchPrivate || subModule.importMode == publicAccess)
3248       {
3249          // TOCHECK: Reverting to false to test what we were trying to fix by passing searchPrivate
3250          // Passing searchPrivate finds ALL classes private or not and thus classes clash
3251          // SearchModule here is called mainly from eSystem_FindClass, and also for Functions and Defines
3252
3253          link = SearchModule(subModule.module, name, listOffset, false);
3254          //link = SearchModule(subModule.module, name, listOffset, searchPrivate /*false*/);
3255          if(link) return link;
3256       }
3257    }
3258    return null;
3259 }
3260
3261 public int64 _strtoi64(const char * string, const char ** endString, int base)
3262 {
3263    int64 value = 0;
3264    int sign = 1;
3265    int c;
3266    char ch;
3267    for(c = 0; (ch = string[c]) && isspace(ch); c++);
3268    if(ch =='+') c++;
3269    else if(ch == '-') { sign = -1; c++; };
3270    if(!base)
3271    {
3272       if(ch == '0' && string[c+1] == 'x')
3273       {
3274          base = 16;
3275          c+=2;
3276       }
3277       else if(ch == '0')
3278       {
3279          base = 8;
3280          c++;
3281       }
3282       else
3283          base = 10;
3284    }
3285    for( ;(ch = string[c]); c++)
3286    {
3287       if(ch >= '0' && ch <= '9')
3288          ch -= '0';
3289       else if(ch >= 'a' && ch <= 'z')
3290          ch -= ('a' - 10);
3291       else if(ch >= 'A' && ch <= 'Z')
3292          ch -= ('A'- 10);
3293       else
3294       {
3295          if(endString)
3296             *endString = string + c;
3297          // Invalid character
3298          break;
3299       }
3300       if(ch < base)
3301       {
3302          value *= base;
3303          value += ch;
3304       }
3305       else
3306       {
3307          if(endString)
3308             *endString = string + c;
3309          // Invalid character
3310          break;
3311       }
3312    }
3313    return sign*value;
3314 }
3315
3316 public uint64 _strtoui64(const char * string, const char ** endString, int base)
3317 {
3318    uint64 value = 0;
3319    int sign = 1;
3320    int c;
3321    char ch;
3322    for(c = 0; (ch = string[c]) && isspace(ch); c++);
3323    if(ch =='+') c++;
3324    else if(ch == '-') { sign = -1; c++; };
3325    if(!base)
3326    {
3327       if(ch == '0' && string[c+1] == 'x')
3328       {
3329          base = 16;
3330          c+=2;
3331       }
3332       else if(ch == '0')
3333       {
3334          base = 8;
3335          c++;
3336       }
3337       else
3338          base = 10;
3339    }
3340    for( ;(ch = string[c]); c++)
3341    {
3342       if(ch >= '0' && ch <= '9')
3343          ch -= '0';
3344       else if(ch >= 'a' && ch <= 'z')
3345          ch -= ('a' - 10);
3346       else if(ch >= 'A' && ch <= 'Z')
3347          ch -= ('A' - 10);
3348       else
3349       {
3350          if(endString)
3351             *endString = string + c;
3352          // Invalid character
3353          break;
3354       }
3355       if(ch < base)
3356       {
3357          value *= base;
3358          value += ch;
3359       }
3360       else
3361       {
3362          if(endString)
3363             *endString = string + c;
3364          // Invalid character
3365          break;
3366       }
3367    }
3368    return sign*value;
3369 }
3370
3371 public dllexport Class eSystem_FindClass(Module module, const char * name)
3372 {
3373    if(name && module)
3374    {
3375       BTNamedLink link;
3376       if(!strncmp(name, "const ", 6)) name += 6;
3377       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->classes);
3378       if(link) return link.data;
3379
3380       link = SearchModule(module, name, &((NameSpace *)0)->classes, true);
3381       if(link) return link.data;
3382
3383       {
3384          char noTemplateName[1024];
3385          char * templateParams = strchr(name, '<');
3386
3387          if(templateParams)
3388          {
3389             strncpy(noTemplateName, name, templateParams - name);
3390             noTemplateName[templateParams - name] = '\0';
3391          }
3392          else
3393             strcpy(noTemplateName, name);
3394
3395          link = SearchNameSpace(&module.application.systemNameSpace, noTemplateName, &((NameSpace *)0)->classes);
3396          if(!link)
3397             link = SearchModule(module, noTemplateName, &((NameSpace *)0)->classes, true);
3398          if(link)
3399          {
3400             Class _class = link.data;
3401             Class templatedClass = null;
3402             char className[1024];
3403             strcpy(className, _class.fullName);
3404             strcat(className, templateParams);
3405
3406             link = SearchNameSpace(&module.application.systemNameSpace, className, &((NameSpace *)0)->classes);
3407             if(link)
3408                return link.data;
3409
3410             link = SearchModule(module, className, &((NameSpace *)0)->classes, true);
3411             if(link)
3412                return link.data;
3413
3414             if(_class && templateParams)
3415             {
3416                // if(!numParams) return null;
3417
3418                templatedClass = Class { };
3419                *templatedClass = *_class;
3420                templatedClass.templateClass = _class;
3421                //templatedClass.fullName = CopyString(name);
3422                templatedClass.fullName = CopyString(className);
3423                templatedClass.dataTypeString = CopyString(_class.dataTypeString);
3424                templatedClass.name = CopyString(templatedClass.fullName + strlen(_class.fullName) - strlen(_class.name));
3425                templatedClass.nameSpace->classes.Add((BTNode)BTNamedLink { name = (char *)templatedClass.name, data = templatedClass });
3426                templatedClass.templateArgs = null;
3427                templatedClass.numParams = 0;
3428                templatedClass.derivatives = { };
3429                templatedClass.templatized = { };
3430                templatedClass.module = module;
3431                templatedClass.count = 0; // TOCHECK: Keeping track of individual templatized classes?
3432                templatedClass.prev = null;
3433                templatedClass.next = null;
3434
3435                module.classes.Add(templatedClass);
3436
3437                ComputeClassParameters(templatedClass, templateParams, module);
3438
3439                _class.templatized.Add(OldLink { data = templatedClass });
3440             }
3441             return templatedClass;
3442          }
3443       }
3444    }
3445    return null;
3446 }
3447
3448 static void CopyTemplateArg(ClassTemplateParameter param, ClassTemplateArgument arg)
3449 {
3450    switch(param.type)
3451    {
3452       case type:
3453          // TOFIX: Memory leak here on e.g. registering 'ecere::com::AVLNode<AT>' from ComputeClassParameters(
3454          /*
3455          if(arg.dataTypeString && !strcmp(arg.dataTypeString, "ecere::com::AVLNode<AT>"))
3456             ;
3457          else*/
3458             arg.dataTypeString = CopyString(arg.dataTypeString);
3459          break;
3460       case expression:
3461
3462          break;
3463       case identifier:
3464          arg.memberString = CopyString(arg.memberString);
3465          break;
3466    }
3467 }
3468
3469 static void ComputeClassParameters(Class templatedClass, const char * templateParams, Module findModule)
3470 {
3471    char ch;
3472    const char * nextParamStart = templateParams ? (templateParams + 1) : null;
3473    ClassTemplateParameter curParam = null;
3474    Class lastClass = null, sClass;
3475    int curParamID = 0;
3476    int numParams = 0;
3477    Class _class = templatedClass.templateClass ? templatedClass.templateClass : templatedClass;
3478
3479    for(sClass = _class; sClass; sClass = sClass.base)
3480    {
3481       if(sClass.templateClass) sClass = sClass.templateClass;
3482       numParams += sClass.templateParams.count;
3483    }
3484
3485    if(templatedClass.templateArgs)
3486       FreeTemplateArgs(templatedClass);
3487    delete templatedClass.templateArgs;
3488    templatedClass.templateArgs = new0 ClassTemplateArgument[numParams];
3489    templatedClass.numParams = numParams;
3490
3491    if(_class != templatedClass)
3492    {
3493       /*int c;
3494       Class sClass;
3495       memcpy(templatedClass.templateArgs, _class.templateArgs, numParams * sizeof(ClassTemplateArgument));
3496       for(sClass = _class; sClass; sClass = sClass.base)
3497       {
3498          ClassTemplateParameter param;
3499          Class prevClass;
3500          int id = 0;
3501          if(sClass.templateClass) sClass = sClass.templateClass;
3502          for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
3503          {
3504             if(prevClass.templateClass) prevClass = prevClass.templateClass;
3505             id += prevClass.templateParams.count;
3506          }
3507          for(param = sClass.templateParams.first; param; param = param.next)
3508            CopyTemplateArg(param, templatedClass.templateArgs[id++]);
3509       }*/
3510    }
3511
3512    if(templatedClass.base && templatedClass.base.templateArgs && _class == templatedClass)
3513    {
3514       Class sClass;
3515       memcpy(templatedClass.templateArgs, templatedClass.base.templateArgs,
3516          sizeof(ClassTemplateArgument) * (numParams - templatedClass.templateParams.count));
3517       for(sClass = templatedClass.base; sClass; sClass = sClass.base)
3518       {
3519          ClassTemplateParameter param;
3520          Class prevClass;
3521          int id = 0;
3522          for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
3523          {
3524             if(prevClass.templateClass) prevClass = prevClass.templateClass;
3525             id += prevClass.templateParams.count;
3526          }
3527
3528          if(sClass.templateClass) sClass = sClass.templateClass;
3529          for(param = sClass.templateParams.first; param; param = param.next)
3530             CopyTemplateArg(param, templatedClass.templateArgs[id++]);
3531       }
3532    }
3533
3534    while(nextParamStart)
3535    {
3536       const char * paramStart = nextParamStart;
3537       const char * paramEnd;
3538       int level = 0;
3539       while(*paramStart == ' ') paramStart++;
3540       paramEnd = paramStart;
3541       while((ch = *paramEnd, ch && (level > 0 || (ch != '>' && ch != ','))))
3542       {
3543          if(ch == '<') level++;
3544          if(ch == '>') level--;
3545
3546          paramEnd++;
3547       }
3548       nextParamStart = (ch == ',') ? (paramEnd + 1) : null;
3549       while(*paramEnd == ' ') paramEnd--;
3550       if(paramEnd > paramStart)
3551       {
3552          const char * ptr, * equal = null;
3553          for(ptr = paramStart; ptr <= paramEnd; ptr++)
3554          {
3555             if(*ptr == '=')
3556             {
3557                equal = ptr;
3558                break;
3559             }
3560          }
3561          if(equal)
3562          {
3563             const char * end = equal - 1;
3564             char ident[1024];
3565
3566             while(*end == ' ') end--;
3567             strncpy(ident, paramStart, end + 1 - paramStart);
3568             ident[end + 1 - paramStart] = 0;
3569
3570             for(sClass = _class; sClass; sClass = sClass.base)
3571             {
3572                if(sClass.templateClass) sClass = sClass.templateClass;
3573                for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
3574                {
3575                   if(!strcmp(curParam.name, ident))
3576                      break;
3577                }
3578                if(curParam)
3579                {
3580                   Class nextClass;
3581                   ClassTemplateParameter prevParam;
3582                   curParamID = 0;
3583                   for(prevParam = curParam.prev; prevParam; prevParam = prevParam.prev) curParamID++;
3584                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3585                   {
3586                      if(nextClass.templateClass) nextClass = nextClass.templateClass;
3587                      curParamID += nextClass.templateParams.count;
3588                   }
3589                   break;
3590                }
3591             }
3592             lastClass = sClass;
3593          }
3594          else
3595          {
3596             if(curParam)
3597             {
3598                curParam = curParam.next;
3599                curParamID++;
3600             }
3601
3602             if(!curParam)
3603             {
3604                for(sClass = lastClass ? lastClass.base : _class; sClass; sClass = sClass.base)
3605                {
3606                   ClassTemplateParameter param;
3607                   curParamID = 0;
3608                   if(sClass.templateClass) sClass = sClass.templateClass;
3609                   for(param = sClass.templateParams.first; param; param = param.next, curParamID++)
3610                   {
3611                      curParam = param;
3612                      break;
3613                   }
3614                   if(curParam)
3615                   {
3616                      Class nextClass;
3617                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3618                      {
3619                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
3620                         curParamID += nextClass.templateParams.count;
3621                      }
3622                      lastClass = sClass;
3623                      break;
3624                   }
3625                }
3626                /*
3627                for(sClass = _class; sClass; sClass = sClass.base)
3628                {
3629                   if(sClass.templateParams.first)
3630                   {
3631                      Class nextClass;
3632                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3633                         if(nextClass.templateParams.first)
3634                            break;
3635                      if(nextClass != lastClass) continue;
3636
3637                      curParam = sClass.templateParams.first;
3638                      lastClass = sClass;
3639
3640                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3641                         if(nextClass.templateParams.first)
3642                         {
3643                            curParamID += nextClass.templateParams.count;
3644                            break;
3645                         }
3646                      break;
3647                   }
3648                }
3649                */
3650             }
3651          }
3652
3653          if(curParam)
3654          {
3655             ClassTemplateArgument argument { };
3656             char value[1024];
3657             if(equal)
3658             {
3659                equal++;
3660                while(*equal == ' ') equal++;
3661                memcpy(value, equal, paramEnd - equal);
3662                value[paramEnd - equal] = 0;
3663             }
3664             else
3665             {
3666                memcpy(value, paramStart, paramEnd - paramStart);
3667                value[paramEnd - paramStart] = 0;
3668             }
3669             TrimRSpaces(value, value);
3670
3671             switch(curParam.type)
3672             {
3673                case type:
3674                   argument.dataTypeString = CopyString(value);
3675                   argument.dataTypeClass = eSystem_FindClass(findModule, value);
3676                   if(!argument.dataTypeClass)
3677                      argument.dataTypeClass = eSystem_FindClass(_class.module, value);
3678                   if(!argument.dataTypeClass)
3679                      argument.dataTypeClass = eSystem_FindClass(_class.module.application, value);
3680                   break;
3681                case expression:
3682                {
3683                   Class expClass = eSystem_FindClass(_class.module, curParam.dataTypeString);
3684                   if(!expClass) expClass = eSystem_FindClass(_class.module.application, curParam.dataTypeString);
3685                   if(expClass)
3686                   {
3687                      //if(expClass.type ==
3688                      ((bool (*)(void *, void *, const char *))(void *)expClass._vTbl[__ecereVMethodID_class_OnGetDataFromString])(expClass, &argument.expression, value);
3689                   }
3690                   // Expression should be pre simplified here
3691                   else if(value[0] == '\"')
3692                   {
3693                      char * endQuote = value + strlen(value) - 1;
3694                      if(*endQuote != '\"') endQuote++;
3695                      *endQuote = '\0';
3696                      argument.expression.p = CopyString(value + 1);
3697                   }
3698                   else if(value[0] == '\'')
3699                   {
3700                      int nb;
3701                      unichar ch = UTF8GetChar(value + 1, &nb);
3702                      argument.expression.ui = ch;
3703                   }
3704                   else if(!strcmp(curParam.dataTypeString, "uint"))
3705                   {
3706                      argument.expression.ui = (uint)strtoul(value, null, 0);
3707                   }
3708                   else if(!strcmp(curParam.dataTypeString, "char"))
3709                   {
3710                      argument.expression.c = (char)strtol(value, null, 0);
3711                   }
3712                   else if(!strcmp(curParam.dataTypeString, "byte"))
3713                   {
3714                      argument.expression.uc = (unsigned char)strtoul(value, null, 0);
3715                   }
3716                   else if(!strcmp(curParam.dataTypeString, "short"))
3717                   {
3718                      argument.expression.s = (short)strtol(value, null, 0);
3719                   }
3720                   else if(!strcmp(curParam.dataTypeString, "uint16"))
3721                   {
3722                      argument.expression.us = (unsigned short)strtoul(value, null, 0);
3723                   }
3724                   else if(!strcmp(curParam.dataTypeString, "int64"))
3725                   {
3726                      argument.expression.i64 = _strtoi64(value, null, 0);
3727                   }
3728                   else if(!strcmp(curParam.dataTypeString, "uint64"))
3729                   {
3730                      argument.expression.ui64 = _strtoui64(value, null, 0);
3731                   }
3732                   else if(!strcmp(curParam.dataTypeString, "float"))
3733                   {
3734                      argument.expression.f = (float)strtod(value, null);
3735                   }
3736                   else if(!strcmp(curParam.dataTypeString, "double"))
3737                   {
3738                      argument.expression.d = strtod(value, null);
3739                   }
3740                   else // if(!strcmp(curParam.dataTypeString, "int"))
3741                   {
3742                      argument.expression.i = (int)strtol(value, null, 0);
3743                   }
3744                   break;
3745                }
3746                case identifier:
3747                   argument.memberString = CopyString(value);
3748                   break;
3749             }
3750             FreeTemplateArg(templatedClass, curParam, curParamID);
3751             templatedClass.templateArgs[curParamID] = argument;
3752          }
3753       }
3754    }
3755
3756    // TESTING THIS BEFORE...
3757    if(templatedClass == _class)
3758    {
3759       Class sClass = _class;
3760       int curParamID = 0;
3761       Class nextClass;
3762       ClassTemplateParameter param;
3763       for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3764       {
3765          if(nextClass.templateClass) nextClass = nextClass.templateClass;
3766          curParamID += nextClass.templateParams.count;
3767       }
3768
3769       for(param = sClass.templateParams.first; param; param = param.next)
3770       {
3771          if(!templatedClass.templateArgs[curParamID].dataTypeString)
3772          {
3773             templatedClass.templateArgs[curParamID] = param.defaultArg;
3774             CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3775             if(param.type == type && param.defaultArg.dataTypeString)
3776             {
3777                templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3778                if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3779                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3780                if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3781                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3782             }
3783          }
3784          curParamID++;
3785       }
3786    }
3787
3788    if(templatedClass.base && templatedClass.base.templateArgs && numParams - _class.templateParams.count)
3789    {
3790       int c = numParams - _class.templateParams.count-1;
3791
3792       for(sClass = _class.base; sClass; sClass = sClass.base)
3793       {
3794          ClassTemplateParameter param;
3795          if(sClass.templateClass) sClass = sClass.templateClass;
3796          for(param = sClass.templateParams.last; param; param = param.prev)
3797          {
3798             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3799             ClassTemplateArgument * baseArg = &templatedClass.base.templateArgs[c];
3800             if(!arg->dataTypeString)
3801             {
3802                *arg = templatedClass.base.templateArgs[c];
3803                CopyTemplateArg(param, arg);
3804                if(param.type == type)
3805                {
3806                   if(arg->dataTypeClass && strchr(arg->dataTypeString, '<') && arg->dataTypeClass.templateArgs)
3807                   {
3808                      Class expClass = arg->dataTypeClass;
3809                      Class cClass = null;
3810                      int paramCount = 0;
3811                      int lastParam = -1;
3812
3813                      char templateString[1024];
3814                      sprintf(templateString, "%s<", expClass.templateClass.fullName);
3815                      for(cClass = expClass; cClass; cClass = cClass.base)
3816                      {
3817                         int p = 0;
3818                         ClassTemplateParameter param;
3819                         for(param = cClass.templateParams.first; param; param = param.next)
3820                         {
3821                            int id = p;
3822                            Class sClass;
3823                            ClassTemplateArgument arg;
3824                            for(sClass = expClass.base; sClass; sClass = sClass.base) id += sClass.templateParams.count;
3825                            arg = expClass.templateArgs[id];
3826
3827                            {
3828                               ClassTemplateParameter cParam;
3829                               int p = numParams - _class.templateParams.count;
3830                               for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3831                               {
3832                                  if(cParam.type == type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
3833                                  {
3834                                     arg.dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3835                                     arg.dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3836                                     break;
3837                                  }
3838                               }
3839                            }
3840
3841                            {
3842                               char argument[256];
3843                               argument[0] = '\0';
3844                               switch(param.type)
3845                               {
3846                                  case expression:
3847                                  {
3848                                     // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
3849                                     /*
3850                                     char expString[1024];
3851                                     OldList * specs = MkList();
3852                                     Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
3853                                     Expression exp;
3854                                     char * string = PrintHexUInt64(arg.expression.ui64);
3855                                     exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
3856
3857                                     ProcessExpressionType(exp);
3858                                     ComputeExpression(exp);
3859                                     expString[0] = '\0';
3860                                     PrintExpression(exp, expString);
3861                                     strcat(argument, expString);
3862                                     //delete exp;
3863                                     FreeExpression(exp);
3864                                     */
3865                                     break;
3866                                  }
3867                                  case identifier:
3868                                  {
3869                                     strcat(argument, arg.member.name);
3870                                     break;
3871                                  }
3872                                  case TemplateParameterType::type:
3873                                  {
3874                                     if(arg.dataTypeString)
3875                                        strcat(argument, arg.dataTypeString);
3876                                     break;
3877                                  }
3878                               }
3879                               if(argument[0])
3880                               {
3881                                  if(paramCount) strcat(templateString, ", ");
3882                                  if(lastParam != p - 1)
3883                                  {
3884                                     strcat(templateString, param.name);
3885                                     strcat(templateString, " = ");
3886                                  }
3887                                  strcat(templateString, argument);
3888                                  paramCount++;
3889                                  lastParam = p;
3890                               }
3891                            }
3892                            p++;
3893                         }
3894                      }
3895                      {
3896                         int len = (int)strlen(templateString);
3897                         if(templateString[len-1] == '>') templateString[len++] = ' ';
3898                         templateString[len++] = '>';
3899                         templateString[len++] = '\0';
3900                      }
3901
3902                      FreeTemplateArg(templatedClass, param, c);
3903
3904                      arg->dataTypeString = CopyString(templateString);
3905                      arg->dataTypeClass = eSystem_FindClass(findModule, templateString);
3906                      if(!arg->dataTypeClass)
3907                         arg->dataTypeClass = eSystem_FindClass(templatedClass.module, templateString);
3908                      if(!arg->dataTypeClass)
3909                         arg->dataTypeClass = eSystem_FindClass(templatedClass.module.application, templateString);
3910                   }
3911                   else
3912                   {
3913                      ClassTemplateParameter cParam;
3914                      int p = numParams - _class.templateParams.count;
3915                      for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3916                      {
3917                         // if(cParam.type == type && !strcmp(cParam.name, param.name))
3918                         if(cParam.type == type && baseArg->dataTypeString && !strcmp(cParam.name, baseArg->dataTypeString))
3919                         {
3920                            FreeTemplateArg(templatedClass, param, c);
3921
3922                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3923                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3924                            CopyTemplateArg(cParam, arg);
3925                            break;
3926                         }
3927                      }
3928                   }
3929                }
3930             }
3931             c--;
3932          }
3933       }
3934    }
3935
3936    {
3937       Class sClass;
3938       for(sClass = _class; sClass; sClass = sClass.base)
3939       {
3940          int curParamID = 0;
3941          Class nextClass;
3942          ClassTemplateParameter param;
3943          if(sClass.templateClass) sClass = sClass.templateClass;
3944
3945          for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3946          {
3947             if(nextClass.templateClass) nextClass = nextClass.templateClass;
3948             curParamID += nextClass.templateParams.count;
3949          }
3950
3951          for(param = sClass.templateParams.first; param; param = param.next)
3952          {
3953             if(!templatedClass.templateArgs[curParamID].dataTypeString)
3954             {
3955                templatedClass.templateArgs[curParamID] = param.defaultArg;
3956                CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3957                if(param.type == type && param.defaultArg.dataTypeString)
3958                {
3959                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3960                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3961                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3962                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3963                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3964                }
3965             }
3966             curParamID++;
3967          }
3968       }
3969    }
3970
3971    {
3972       int c = numParams - 1;
3973       for(sClass = _class; sClass; sClass = sClass.base)
3974       {
3975          ClassTemplateParameter param;
3976          if(sClass.templateClass) sClass = sClass.templateClass;
3977          for(param = sClass.templateParams.last; param; param = param.prev)
3978          {
3979             if(param.type == type)
3980             {
3981                ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3982                ClassTemplateParameter cParam;
3983                Class dClass;
3984                int p = numParams - 1;
3985                for(dClass = _class; dClass; dClass = dClass.base)
3986                {
3987                   if(dClass.templateClass) dClass = dClass.templateClass;
3988                   for(cParam = dClass.templateParams.last; cParam; cParam = cParam.prev, p--)
3989                   {
3990                      if(cParam.type == type && arg->dataTypeString && !strcmp(cParam.name, arg->dataTypeString))
3991                      {
3992                         if(templatedClass.templateArgs[p].dataTypeString && c != p)
3993                         {
3994                            FreeTemplateArg(templatedClass, param, c);
3995
3996                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3997                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3998                            CopyTemplateArg(cParam, arg);
3999                         }
4000                      }
4001                   }
4002                }
4003             }
4004             c--;
4005          }
4006       }
4007    }
4008
4009    {
4010       Class tClass;
4011       int c = numParams - 1;
4012       for(tClass = _class; tClass; tClass = tClass.base)
4013       {
4014          ClassTemplateParameter param;
4015          if(tClass.templateClass) tClass = tClass.templateClass;
4016          for(param = tClass.templateParams.last; param; param = param.prev)
4017          {
4018             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
4019             if(param.type == identifier && arg->memberString)
4020             {
4021                Class memberClass = templatedClass;
4022                const char * memberString = arg->memberString;
4023                const char * colon = strstr(memberString, "::");
4024                const char * memberName = memberString;
4025                if(colon) memberName = colon + 2;
4026                if(!colon)
4027                {
4028                   memberString = param.defaultArg.memberString;
4029                   colon = memberString ? strstr(memberString, "::") : null;
4030                }
4031
4032                if(colon)
4033                {
4034                   char className[1024];
4035                   Class sClass;
4036
4037                   memcpy(className, memberString, colon - memberString);
4038                   className[colon - memberString] = '\0';
4039
4040                   for(sClass = _class; sClass; sClass = sClass.base)
4041                   {
4042                      ClassTemplateParameter cParam;
4043                      Class nextClass;
4044                      int id = 0;
4045
4046                      if(sClass.templateClass) sClass = sClass.templateClass;
4047                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
4048                      {
4049                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
4050                         id += nextClass.templateParams.count;
4051                      }
4052                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
4053                      {
4054                         if(cParam.type == type && !strcmp(cParam.name, className) && templatedClass.templateArgs[id].dataTypeString)
4055                         {
4056                            strcpy(className, templatedClass.templateArgs[id].dataTypeString);
4057                         }
4058                         id++;
4059                      }
4060                   }
4061                   // TESTING: Added this here...
4062                   memberClass = eSystem_FindClass(findModule, className);
4063                   if(!memberClass)
4064                      memberClass = eSystem_FindClass(templatedClass.module, className);
4065                   if(!memberClass)
4066                      memberClass = eSystem_FindClass(templatedClass.module.application, className);
4067                }
4068
4069                if(memberClass)
4070                {
4071                   switch(param.memberType)
4072                   {
4073                      case dataMember:
4074                         arg->member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
4075                         break;
4076                      case method:
4077                         arg->method = eClass_FindMethod(memberClass, memberName, memberClass.module);
4078                         break;
4079                      case prop:
4080                         arg->prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
4081                         break;
4082                   }
4083                }
4084             }
4085             c--;
4086          }
4087       }
4088    }
4089 }
4090
4091 /*static */bool DefaultFunction()
4092 {
4093    return true;
4094 }
4095
4096 public dllexport bool eClass_IsDerived(Class _class, Class from)
4097 {
4098    if(!_class && !from)
4099       return true;
4100
4101    if(_class && from && (_class.templateClass || from.templateClass))
4102    {
4103       if(eClass_IsDerived(_class.templateClass ? _class.templateClass : _class, from.templateClass ? from.templateClass : from))
4104       {
4105          if(!from.templateClass)
4106             return true;
4107          else if(!_class.templateClass && _class == from.templateClass)
4108             return false;
4109          else
4110          {
4111             Class sClass;
4112             for(sClass = from; sClass; sClass = sClass.base)
4113             {
4114                if(sClass.templateParams.first)
4115                {
4116                   ClassTemplateParameter param;
4117                   Class nextClass;
4118                   int p = 0;
4119                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) p += nextClass.templateParams.count;
4120                   for(param = sClass.templateParams.first; param; param = param.next, p++)
4121                   {
4122                      ClassTemplateArgument * arg = &_class.templateArgs[p];
4123                      ClassTemplateArgument * fArg = &from.templateArgs[p];
4124                      if(param.type == type)
4125                      {
4126                         if(arg->dataTypeString != fArg->dataTypeString && arg->dataTypeString && fArg->dataTypeString &&
4127                           strcmp(arg->dataTypeString, fArg->dataTypeString))
4128                            break;
4129                      }
4130                      else if(param.type == identifier)
4131                      {
4132                         if(arg->member != fArg->member)
4133                            break;
4134                      }
4135                      else if(param.type == expression)
4136                      {
4137                         if(arg->expression.ui64 != fArg->expression.ui64)
4138                            break;
4139                      }
4140                   }
4141                   if(param)
4142                      return false;
4143                }
4144             }
4145             return true;
4146          }
4147       }
4148    }
4149    else
4150    {
4151       for(; _class && from; _class = _class.base)
4152       {
4153          if(_class == from || _class.templateClass == from || ((_class.type == systemClass || (_class.type == normalClass && _class.isInstanceClass)) && from.name && !strcmp(_class.name, from.name)))
4154             return true;
4155       }
4156    }
4157    return false;
4158 }
4159
4160 static void FixDerivativeVirtualMethod(Class base, const char * name, int vid, void * origFunction, const char * type)
4161 {
4162    OldLink derivative;
4163    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
4164    {
4165       Class _class = derivative.data;
4166       Method method, next;
4167       void * function = origFunction;
4168
4169       _class.vTblSize++;
4170       _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
4171       memmove(_class._vTbl + vid + 1, _class._vTbl + vid, (_class.vTblSize - vid - 1) * sizeof(void *));
4172
4173       method = (Method) _class.methods.FindString(name);
4174       if(method)
4175       {
4176          if(method.function) function = method.function;
4177
4178          if(!method.symbol)
4179          {
4180             delete (void *)method.name;
4181             delete (void *)method.dataTypeString;
4182             _class.methods.Delete((BTNode)method);
4183          }
4184          else
4185          {
4186             delete (void *)method.dataTypeString;
4187             method.type = virtualMethod;
4188             method.dataTypeString = CopyString(type);
4189             method._class = base;
4190          }
4191       }
4192       for(method = (Method)_class.methods.first; method; method = next)
4193       {
4194          next = (Method)((BTNode)method).next;
4195          if(method.type == virtualMethod)
4196             method.vid++;
4197       }
4198       _class._vTbl[vid] = function;
4199
4200       {
4201          OldLink templateLink;
4202          for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4203          {
4204             Class template = templateLink.data;
4205             template._vTbl = _class._vTbl;
4206          }
4207       }
4208       if(_class.derivatives.first || _class.templatized.first)
4209          FixDerivativeVirtualMethod(_class, name, vid, function, type);
4210    }
4211    {
4212       OldLink templateLink;
4213       for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
4214       {
4215          Class template = templateLink.data;
4216          template._vTbl = base._vTbl;
4217          FixDerivativeVirtualMethod(template, name, vid, origFunction, type);
4218       }
4219    }
4220 }
4221
4222 public dllexport Method eClass_AddMethod(Class _class, const char * name, const char * type, void * function, AccessMode declMode)
4223 {
4224    if(_class && !_class.comRedefinition && name)
4225    {
4226       Class base;
4227       for(base = _class; base; base = base.base)
4228       {
4229          Method method;
4230          if(base.templateClass) base = base.templateClass;
4231          method = (Method)base.methods.FindString(name);
4232          if(method)
4233          {
4234             // If this overrides a virtual method
4235             if(method.type == virtualMethod)
4236             {
4237                OldLink deriv;
4238                void * oldFunction = _class._vTbl[method.vid];
4239                if(method.vid >= _class.vTblSize)
4240                   printf("error: virtual methods overriding failure\n");
4241                else
4242                   _class._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
4243                for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4244                {
4245                   Class derivClass = deriv.data;
4246                   if(derivClass._vTbl[method.vid] == oldFunction)
4247                      eClass_AddMethod(derivClass, name, type, function, declMode);
4248                }
4249                {
4250                   OldLink templateLink;
4251                   for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4252                   {
4253                      Class template = templateLink.data;
4254                      for(deriv = template.derivatives.first; deriv; deriv = deriv.next)
4255                      {
4256                         Class derivClass = deriv.data;
4257                         if(derivClass._vTbl[method.vid] == oldFunction)
4258                            eClass_AddMethod(derivClass, name, type, function, declMode);
4259                      }
4260                   }
4261                }
4262
4263             }
4264             else
4265             {
4266                if(base == _class)
4267                {
4268                   // printf("error: Redefinition of method %s in class %s\n", name, _class.name);
4269                   break;
4270                }
4271                base = null;
4272                break;
4273             }
4274             return method;
4275          }
4276       }
4277
4278       if(!base)
4279       {
4280          Method method
4281          {
4282             name = CopyString(name),
4283             function = function ? function : null; //DefaultFunction;
4284             _class = _class;
4285             dataTypeString = CopyString(type);
4286             memberAccess = declMode;
4287          };
4288          _class.methods.Add((BTNode)method);
4289          return method;
4290       }
4291    }
4292    return null;
4293 }
4294
4295 public dllexport Method eClass_AddVirtualMethod(Class _class, const char * name, const char * type, void * function, AccessMode declMode)
4296 {
4297    if(_class && !_class.comRedefinition && name)
4298    {
4299       Class base;
4300       for(base = _class; base; base = base.base)
4301       {
4302          Method method = (Method)base.methods.FindString(name);
4303          if(method)
4304          {
4305             // If this overides a virtual method
4306             if(method.type == virtualMethod)
4307             {
4308                if(method.vid >= _class.vTblSize)
4309                   printf("error: virtual methods overriding failure\n");
4310                else
4311                   _class._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
4312             }
4313             else
4314                base = null;
4315             return method;
4316          }
4317       }
4318
4319       if(!base)
4320       {
4321          Method method
4322          {
4323             name = CopyString(name);
4324             function = function ? function : null; //DefaultFunction;
4325             type = virtualMethod;
4326             _class = _class;
4327             vid = _class.vTblSize++;
4328             dataTypeString = CopyString(type);
4329             memberAccess = declMode;
4330          };
4331          _class.methods.Add((BTNode)method);
4332          _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
4333          _class._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
4334
4335          // TODO: Fix derived classes
4336          if(_class.derivatives.first || _class.templatized.first)
4337             FixDerivativeVirtualMethod(_class, name, method.vid, function ? function : null /*(void *)DefaultFunction*/, type);
4338          return method;
4339       }
4340    }
4341    return null;
4342 }
4343
4344 static void FixDerivativeProperty(Class base, Property _property)
4345 {
4346    OldLink derivative;
4347    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
4348    {
4349       Class _class = derivative.data;
4350       Property prop;
4351       BTNamedLink link = (BTNamedLink)_class.prop.FindString(_property.name);
4352       if(link)
4353       {
4354          prop = link.data;
4355          if(!prop.Set && !prop.Get && prop.memberAccess == baseSystemAccess)
4356          {
4357             SelfWatcher watcher;
4358             for(watcher = _class.selfWatchers.first; watcher; watcher = watcher.next)
4359             {
4360                if(watcher._property == prop)
4361                   watcher._property = _property;
4362             }
4363             _property.selfWatchable = true;
4364
4365             delete (void *)prop.name;
4366             delete (void *)prop.dataTypeString;
4367             _class.membersAndProperties.Delete(prop);
4368             _class.prop.Delete((BTNode)link);
4369          }
4370       }
4371
4372       for(prop = _class.membersAndProperties.first; prop; prop = prop.next)
4373          prop.id++;
4374       _class.memberID++;
4375       _class.startMemberID++;
4376
4377       FixDerivativeProperty(_class, _property);
4378    }
4379 }
4380
4381 public dllexport Property eClass_AddProperty(Class _class, const char * name, const char * dataType, void * setStmt, void * getStmt, AccessMode declMode)
4382 {
4383    Property _property = null;
4384    if(_class)
4385    {
4386       BTNamedLink link = (BTNamedLink)_class.prop.FindString(name ? name : dataType);
4387       bool isConversion = name ? false : true;
4388       if(!name && dataType && !strncmp(dataType, "const ", 6))
4389       {
4390          name = dataType + 6;
4391          isConversion = true;
4392       }
4393       if(link)
4394          _property = link.data;
4395       if(!_property)
4396       {
4397          _property =
4398          {
4399             isProperty = true;
4400             name = CopyString(name ? name : dataType);
4401             id = (name && (setStmt || getStmt || dataType)) ? _class.memberID++ : 0;
4402             Set = setStmt;
4403             Get = getStmt;
4404             dataTypeString = CopyString(dataType);
4405             _class = _class;
4406             compiled = true;
4407             conversion = isConversion;
4408             memberAccess = declMode;
4409          };
4410          if(!isConversion)
4411             _class.membersAndProperties.Add(_property);
4412          else
4413             _class.conversions.Add(_property);
4414          _class.prop.Add((BTNode)BTNamedLink { name = _property.name, data = _property });
4415
4416          if(!_property.conversion)
4417          {
4418             FixDerivativeProperty(_class, _property);
4419          }
4420       }
4421    }
4422    return _property;
4423 }
4424
4425 static void SetDelayedCPValues(Class _class, ClassProperty _property)
4426 {
4427    OldLink deriv;
4428    NamedLink64 value, next;
4429
4430    for(value = _class.delayedCPValues.first; value; value = next)
4431    {
4432       next = value.next;
4433       if(!strcmp(value.name, _property.name))
4434       {
4435          // eClass_SetProperty(_class, _property.name, value.data);
4436          _property.Set(_class, value.data);
4437          _class.delayedCPValues.Delete(value);
4438       }
4439    }
4440
4441    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4442    {
4443       SetDelayedCPValues(deriv.data, _property);
4444    }
4445 }
4446
4447 public dllexport ClassProperty eClass_AddClassProperty(Class _class, const char * name, const char * dataType, void * setStmt, void * getStmt)
4448 {
4449    if(name && !_class.classProperties.FindString(name))
4450    {
4451       ClassProperty _property
4452       {
4453          name = CopyString(name);
4454          Set = setStmt;
4455          Get = getStmt;
4456          dataTypeString = CopyString(dataType);
4457       };
4458       _class.classProperties.Add((BTNode)_property);
4459       SetDelayedCPValues(_class, _property);
4460       return _property;
4461    }
4462    return null;
4463 }
4464
4465 /*import "Time"
4466
4467 Time classFindTotalTime;
4468
4469 public dllexport void ResetClassFindTime()
4470 {
4471    classFindTotalTime = 0;
4472 }
4473
4474 public dllexport Time GetClassFindTime()
4475 {
4476    return classFindTotalTime;
4477 }
4478 */
4479 public dllexport ClassProperty eClass_FindClassProperty(Class _class, const char * name)
4480 {
4481    //Time startTime = GetTime();
4482    ClassProperty _property = null;
4483    if(name && _class)
4484    {
4485       Class origClass = _class;
4486       for(; _class; _class = _class.base)
4487       {
4488          _property = (ClassProperty)_class.classProperties.FindString(name);
4489          if(_property)
4490             break;
4491       }
4492       // For enum class deriving off something else than enum to find enumSize...
4493       if(!_property && origClass.type == enumClass)
4494       {
4495          Class enumClass = eSystem_FindClass(origClass.module, "enum");
4496          _property = eClass_FindClassProperty(enumClass, name);
4497       }
4498    }
4499    /*if(!_property)
4500       eSystem_Logf("No such property (%s) for class %s\n", name, _class.name);*/
4501    //classFindTotalTime += GetTime() - startTime;
4502    return _property;
4503 }
4504
4505 public dllexport int64 eClass_GetProperty(Class _class, const char * name)
4506 {
4507    ClassProperty _property = eClass_FindClassProperty(_class, name);
4508    if(_property && _property.Get && _property.Get != (void *)1)
4509    {
4510       int64 result = _property.Get(_class);
4511       return result;
4512    }
4513    return 0;
4514 }
4515
4516 public dllexport void eClass_SetProperty(Class _class, const char * name, int64 value)
4517 {
4518    ClassProperty _property = eClass_FindClassProperty(_class, name);
4519    if(_property)
4520    {
4521       if(_property.Set)
4522          ((void(*)(void *, int64))_property.Set)(_class, value);
4523    }
4524    else
4525    {
4526       _class.delayedCPValues.Add(NamedLink64 { name = (char *)name, value });
4527    }
4528 }
4529
4530 public dllexport Method eClass_FindMethod(Class _class, const char * name, Module module)
4531 {
4532    //Time startTime = GetTime();
4533    if(_class && name)
4534    {
4535       for(; _class; _class = _class.base)
4536       {
4537          Method method;
4538          if(_class.templateClass) _class = _class.templateClass;
4539          method = (Method)_class.methods.FindString(name);
4540          if(method && (method.memberAccess == publicAccess || _class.module == module || !method.dataTypeString))
4541          {
4542             if(!method.dataTypeString)
4543             {
4544                if(_class.module != module)
4545                {
4546                   if(method.memberAccess == publicAccess)
4547                      module = _class.module;
4548                   else
4549                   {
4550                      //classFindTotalTime += GetTime() - startTime;
4551                      return null;
4552                   }
4553                }
4554             }
4555             else
4556             {
4557                //classFindTotalTime += GetTime() - startTime;
4558                return method;
4559             }
4560          }
4561          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4562       }
4563    }
4564    //classFindTotalTime += GetTime() - startTime;
4565    return null;
4566 }
4567
4568 // Construct an instance
4569 static bool ConstructInstance(void * instance, Class _class, Class from)
4570 {
4571    if(_class.templateClass) _class = _class.templateClass;
4572    if(_class.base && from != _class.base)
4573    {
4574       if(!ConstructInstance(instance, _class.base, from))
4575          return false;
4576    }
4577    if(_class.Initialize)
4578    {
4579       void (* Initialize)(Module module) = (void *)_class.Initialize;
4580       _class.Initialize = null;
4581       Initialize(_class.module);
4582    }
4583    if(_class.Constructor)
4584    {
4585       if(!_class.Constructor(instance))
4586       {
4587          for(; _class; _class = _class.base)
4588          {
4589             if(_class.templateClass) _class = _class.templateClass;
4590             if(_class.Destructor)
4591                _class.Destructor(instance);
4592          }
4593          return false;
4594       }
4595    }
4596    (_class.templateClass ? _class.templateClass : _class).count++;
4597    return true;
4598 }
4599
4600 public dllexport void * eInstance_New(Class _class)
4601 {
4602    Instance instance = null;
4603    if(_class)
4604    {
4605       // instance = _malloc(_class.size);
4606 #ifdef MEMINFO
4607
4608 #undef malloc
4609 #if !defined(__EMSCRIPTEN__)
4610    memMutex.Wait();
4611 #endif
4612       //allocateClass = _class;
4613       allocateClass = malloc(strlen(_class.name)+1);
4614       allocateInternal = _class.module == __thisModule;
4615       strcpy(allocateClass, _class.name);
4616 #ifndef MEMINFO
4617 #define malloc _mymalloc
4618 #endif
4619
4620 #endif
4621       {
4622          int size = _class.structSize;
4623          int flags = _class.module.application.isGUIApp;
4624          bool inCompiler = (flags & 8) ? true : false;
4625          bool force32Bits = (flags & 4) ? true : false;
4626          if(force32Bits && inCompiler)
4627          {
4628             // Allocate 64 bit sizes for these when cross-compiling for 32 bit to allow loaded libraries to work properly
4629             if(!strcmp(_class.name, "Module"))
4630                size = 560;
4631             else if(_class.templateClass && !strcmp(_class.templateClass.name, "Map"))
4632                size = 40;
4633             else
4634                size *= 3;
4635          }
4636          instance = _calloc(1, size);
4637       }
4638 #ifdef MEMINFO
4639       allocateClass = null;
4640 #if !defined(__EMSCRIPTEN__)
4641    memMutex.Release();
4642 #endif
4643 #endif
4644
4645 #if defined(_DEBUG) && !defined(MEMINFO) && defined(MEMTRACKING)
4646       {
4647          MemBlock block = (MemBlock)((byte *)instance - sizeof(class MemBlock));
4648          block._class = _class;
4649       }
4650 #endif
4651
4652       if(_class.type == normalClass)
4653       {
4654          instance._class = _class;
4655          // Copy the virtual table initially
4656          instance._vTbl = _class._vTbl;
4657       }
4658       if(!ConstructInstance(instance, _class, null))
4659       {
4660          _free(instance);
4661          instance = null;
4662       }
4663       /*if(_class.type == normalClass && _class.count > 1000)
4664          printf("%s: %d instances\n", _class.name, _class.count);*/
4665    }
4666    return instance;
4667 }
4668
4669 public dllexport void eInstance_Evolve(Instance * instancePtr, Class _class)
4670 {
4671    if(_class && instancePtr && *instancePtr)
4672    {
4673       bool wasApp = false, wasGuiApp = false;
4674       Instance oldInstance = *instancePtr;
4675       Instance instance = (Instance)renew *instancePtr byte[_class.structSize];
4676       Class fromClass = instance._class;
4677       *instancePtr = instance;
4678       memset(((byte *)instance) + instance._class.structSize, 0, _class.structSize - instance._class.structSize);
4679       // Fix pointers to application
4680       if((wasApp = !strcmp(instance._class.name, "Application")) ||
4681          (wasGuiApp = !strcmp(instance._class.name, "GuiApplication")))
4682       {
4683          Module module;
4684          Application app = (Application) instance;
4685          BTNamedLink link;
4686          Class _class;
4687          NameSpace * nameSpace;
4688          for(module = app.allModules.first; module; module = module.next)
4689             module.application = app;
4690
4691          for(link = (BTNamedLink)app.privateNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4692          {
4693             OldLink t;
4694             ((Class)link.data).nameSpace = &app.privateNameSpace;
4695             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4696          }
4697          for(link = (BTNamedLink)app.publicNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4698          {
4699             OldLink t;
4700             ((Class)link.data).nameSpace = &app.publicNameSpace;
4701             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4702          }
4703
4704          for(link = (BTNamedLink)app.privateNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4705             ((DefinedExpression)link.data).nameSpace = &app.privateNameSpace;
4706          for(link = (BTNamedLink)app.publicNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4707             ((DefinedExpression)link.data).nameSpace = &app.publicNameSpace;
4708
4709          for(link = (BTNamedLink)app.privateNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4710             ((GlobalFunction)link.data).nameSpace = &app.privateNameSpace;
4711          for(link = (BTNamedLink)app.publicNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4712             ((GlobalFunction)link.data).nameSpace = &app.publicNameSpace;
4713
4714          for(nameSpace = (NameSpace *)app.privateNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4715             nameSpace->parent = &app.privateNameSpace;
4716          for(nameSpace = (NameSpace *)app.publicNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4717             nameSpace->parent = &app.publicNameSpace;
4718
4719          // --------------------------------------------------
4720          for(link = (BTNamedLink)app.systemNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4721          {
4722             OldLink t;
4723             ((Class)link.data).nameSpace = &app.systemNameSpace;
4724             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4725          }
4726          for(link = (BTNamedLink)app.systemNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4727             ((DefinedExpression)link.data).nameSpace = &app.systemNameSpace;
4728          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4729             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4730          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4731             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4732          for(nameSpace = (NameSpace *)app.systemNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4733             nameSpace->parent = &app.systemNameSpace;
4734          // --------------------------------------------------
4735
4736          for(_class = app.classes.first; _class; _class = _class.next)
4737          {
4738             OldLink templateLink;
4739             _class.module = (Module) app;
4740             for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4741             {
4742                Class template = templateLink.data;
4743                if(template.module == oldInstance)
4744                   template.module = _class.module;
4745             }
4746          }
4747
4748          for(module = app.allModules.first; module; module = module.next)
4749          {
4750             for(_class = module.classes.first; _class; _class = _class.next)
4751             {
4752                OldLink templateLink;
4753                Module oldModule = _class.module;
4754                _class.module = module;
4755                for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4756                {
4757                   Class template = templateLink.data;
4758                   if(template.module == oldModule)
4759                      template.module = _class.module;
4760                }
4761             }
4762          }
4763
4764          app.application = app;
4765       }
4766
4767       {
4768          Class base;
4769          for(base = instance._class; base && base.type == normalClass && base.count; base = base.base)
4770             (base.templateClass ? base.templateClass : base).count--;
4771       }
4772
4773       instance._class = _class;
4774       // Copy the virtual table initially
4775       instance._vTbl = _class._vTbl;
4776
4777       // We don't want to reconstruct the portion already constructed...
4778       if(!ConstructInstance(instance, _class, fromClass))
4779       {
4780          _free(instance);
4781          *instancePtr = null;
4782       }
4783    }
4784 }
4785
4786 public dllexport void eInstance_Delete(Instance instance)
4787 {
4788 #ifdef MEMINFO
4789    bool checkMemory = false;
4790 #endif
4791    if(instance)
4792    {
4793       Class _class, base;
4794       bool ownVtbl;
4795
4796 #ifdef MEMINFO
4797 #if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__)
4798       if(instance._class == (void *)0xecececececececec)
4799 #else
4800       if(instance._class == (void *)0xecececec)
4801 #endif
4802          _free(instance);
4803 #endif
4804
4805       ownVtbl = instance._vTbl != instance._class._vTbl;
4806
4807       for(_class = instance._class; _class; _class = base)
4808       {
4809          if(_class.templateClass) _class = _class.templateClass;
4810          if(_class.destructionWatchOffset)
4811          {
4812             OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
4813             Watcher watcher, next;
4814
4815             for(watcher = watchers->first; watcher; watcher = next)
4816             {
4817                next = watcher.next;
4818                watchers->Remove(watcher);
4819                watcher.callback(watcher.object, instance);
4820                watchers->Delete(watcher);
4821             }
4822          }
4823
4824          /*// Loop through properties to delete all watchers? Might slow down destruction...
4825          {
4826             Property _property;
4827             for(_property = _class.membersAndProperties.first; _property; _property = _property.next)
4828             {
4829                if(_property.isProperty && _property.isWatchable)
4830                {
4831                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
4832                   Watcher watcher, next;
4833                   for(watcher = watchers->first; watcher; watcher = next)
4834                   {
4835                      next = watcher.next;
4836                      watchers->Delete(watcher);
4837                   }
4838                }
4839             }
4840          }*/
4841
4842
4843          base = _class.base;
4844          if(base && (base.type == systemClass || base.isInstanceClass)) base = null;
4845          if(_class.Destructor)
4846             _class.Destructor(instance);
4847 #ifdef MEMINFO
4848          if(_class == class(Application))
4849             checkMemory = true;
4850 #endif
4851       }
4852
4853       for(_class = instance._class; _class; _class = base)
4854       {
4855          if(_class.templateClass) _class = _class.templateClass;
4856
4857          base = _class.base;
4858          (_class.templateClass ? _class.templateClass : _class).count--;
4859          if(_class.type == normalClass && !_class.count && !_class.module)
4860          {
4861 #ifdef MEMINFO
4862             // printf("Now Destructing class %s\n", _class.name);
4863 #endif
4864             eClass_Unregister(_class);
4865          }
4866       }
4867
4868       if(ownVtbl)
4869       {
4870          delete instance._vTbl;
4871       }
4872       //instance.prop.Free(null);
4873       _free(instance);
4874 #ifdef MEMINFO
4875       if(checkMemory) CheckMemory();
4876 #endif
4877    }
4878 }
4879
4880 public dllexport Property eClass_FindProperty(Class _class, const char * name, Module module)
4881 {
4882    //Time startTime = GetTime();
4883    if(_class && name)
4884    {
4885       if(!strncmp(name, "const ", 6))
4886          name += 6;
4887
4888       for(; _class; _class = _class.base)
4889       {
4890          BTNamedLink link;
4891          if(_class.templateClass) _class = _class.templateClass;
4892          link = (BTNamedLink)_class.prop.FindString(name);
4893          if(link)
4894          {
4895             Property _property = (Property)link.data;
4896             if(_property.memberAccess == publicAccess || _class.module == module || !_property.dataTypeString)
4897             {
4898                if(!_property.dataTypeString)
4899                {
4900                   if(_class.module != module)
4901                   {
4902                      if(_property.memberAccess == publicAccess)
4903                         module = _class.module;
4904                      else
4905                      {
4906                         //classFindTotalTime += GetTime() - startTime;
4907                         return null;
4908                      }
4909                   }
4910                }
4911                else
4912                {
4913                   //classFindTotalTime += GetTime() - startTime;
4914                   return _property;
4915                }
4916             }
4917          }
4918          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4919       }
4920    }
4921    //classFindTotalTime += GetTime() - startTime;
4922    return null;
4923 }
4924
4925 static DataMember FindDataMember(OldList list, BinaryTree alist, const char * name, uint * offset, int * id, bool searchPrivate, DataMember * subMemberStack, int * subMemberStackPos)
4926 {
4927    BTNamedLink link;
4928    DataMember dataMember;
4929
4930    link = (BTNamedLink)alist.FindString(name);
4931    if(link)
4932    {
4933       dataMember = link.data;
4934       if(dataMember.type == normalMember && (dataMember.memberAccess == publicAccess || searchPrivate || !dataMember.dataTypeString))
4935       {
4936          if(offset)
4937             *offset += dataMember.offset;
4938          if(id) *id = dataMember.id;
4939          return dataMember;
4940       }
4941       return null;
4942    }
4943    for(dataMember = list.first; dataMember; dataMember = dataMember.next)
4944    {
4945       if(!dataMember.isProperty && (dataMember.memberAccess == publicAccess || searchPrivate) && !dataMember.name && (dataMember.type == unionMember || dataMember.type == structMember))
4946       {
4947          DataMember childMember;
4948          if(subMemberStackPos) subMemberStack[(*subMemberStackPos)++] = dataMember;
4949          childMember = FindDataMember(dataMember.members, dataMember.membersAlpha, name, offset, id, searchPrivate, subMemberStack, subMemberStackPos);
4950          if(childMember)
4951          {
4952             if(offset)
4953                *offset += dataMember.offset;
4954             if(id) *id += dataMember.id;
4955             return childMember;
4956          }
4957          if(subMemberStackPos) (*subMemberStackPos)--;
4958       }
4959    }
4960    return null;
4961 }
4962
4963 public dllexport DataMember eClass_FindDataMember(Class _class, const char * name, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4964 {
4965    //Time startTime = GetTime();
4966    DataMember dataMember = null;
4967    if(subMemberStackPos) *subMemberStackPos = 0;
4968    if(_class && name)
4969    {
4970       for(; _class; _class = _class.base)
4971       {
4972          if(_class.templateClass) _class = _class.templateClass;
4973          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, null, _class.module == module, subMemberStack, subMemberStackPos);
4974          if(dataMember)
4975          {
4976             if(!dataMember.dataTypeString)
4977             {
4978                if(_class.module != module)
4979                {
4980                   if(dataMember.memberAccess == publicAccess)
4981                      module = _class.module;
4982                   else
4983                   {
4984                      //classFindTotalTime += GetTime() - startTime;
4985                      return null;
4986                   }
4987                }
4988                dataMember = null;
4989             }
4990             else
4991             {
4992                // HACK: Is this good enough? avoiding setting it when adding...
4993                dataMember._class = _class.templateClass ? _class.templateClass : _class;
4994                //classFindTotalTime += GetTime() - startTime;
4995                return dataMember;
4996             }
4997          }
4998          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4999       }
5000    }
5001    //classFindTotalTime += GetTime() - startTime;
5002    return dataMember;
5003 }
5004
5005 public dllexport DataMember eClass_FindDataMemberAndOffset(Class _class, const char * name, uint * offset, Module module, DataMember * subMemberStack, int * subMemberStackPos)
5006 {
5007    //Time startTime = GetTime();
5008    DataMember dataMember = null;
5009    if(subMemberStackPos) *subMemberStackPos = 0;
5010    if(offset) *offset = 0;
5011    if(_class)
5012    {
5013       for(; _class; _class = _class.base)
5014       {
5015          if(_class.templateClass) _class = _class.templateClass;
5016          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, offset, null, _class.module == module, subMemberStack, subMemberStackPos);
5017          if(dataMember)
5018          {
5019             if(!dataMember.dataTypeString)
5020             {
5021                if(_class.module != module)
5022                {
5023                   if(dataMember.memberAccess == publicAccess)
5024                      module = _class.module;
5025                   else
5026                   {
5027                      //classFindTotalTime += GetTime() - startTime;
5028                      return null;
5029                   }
5030                }
5031                dataMember = null;
5032             }
5033             else
5034             {
5035                // HACK: Is this good enouh? avoiding setting it when adding...
5036                dataMember._class = _class;
5037                //classFindTotalTime += GetTime() - startTime;
5038                return dataMember;
5039             }
5040          }
5041          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
5042       }
5043    }
5044    //classFindTotalTime += GetTime() - startTime;
5045    return dataMember;
5046 }
5047
5048 public dllexport DataMember eClass_FindDataMemberAndId(Class _class, const char * name, int * id, Module module, DataMember * subMemberStack, int * subMemberStackPos)
5049 {
5050    //Time startTime = GetTime();
5051    DataMember dataMember = null;
5052    if(subMemberStackPos) *subMemberStackPos = 0;
5053    if(_class)
5054    {
5055       for(; _class; _class = _class.base)
5056       {
5057          if(_class.templateClass) _class = _class.templateClass;
5058          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, id, _class.module == module, subMemberStack, subMemberStackPos);  // TOCHECK: Why was this null? null, null);
5059          if(dataMember)
5060          {
5061             if(!dataMember.dataTypeString)
5062             {
5063                if(_class.module != module)
5064                {
5065                   if(dataMember.memberAccess == publicAccess)
5066                      module = _class.module;
5067                   else
5068                   {
5069                      //classFindTotalTime += GetTime() - startTime;
5070                      return null;
5071                   }
5072                }
5073                dataMember = null;
5074             }
5075             else
5076             {
5077                // HACK: Is this good enouh? avoiding setting it when adding...
5078                dataMember._class = _class;
5079                //classFindTotalTime += GetTime() - startTime;
5080                return dataMember;
5081             }
5082          }
5083          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
5084       }
5085    }
5086    //classFindTotalTime += GetTime() - startTime;
5087    return dataMember;
5088 }
5089
5090 public dllexport void eClass_FindNextMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
5091 {
5092    // THIS CODE WILL FIND NEXT MEMBER... (PUBLIC MEMBERS ONLY)
5093    if(*curMember)
5094    {
5095       *curMember = (*curMember).next;
5096
5097       if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
5098       {
5099          *curMember = subMemberStack[--(*subMemberStackPos)];
5100          *curMember = (*curMember).next;
5101       }
5102
5103       if(subMemberStackPos && *subMemberStackPos > 0)
5104       {
5105          while(*curMember && ((*curMember).memberAccess == privateAccess))
5106             *curMember = (*curMember).next;
5107       }
5108       else
5109          while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
5110          {
5111             DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
5112             if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
5113             if(dataMember && dataMember.memberAccess != privateAccess)
5114             {
5115                *curMember = dataMember;
5116                break;
5117             }
5118             else
5119                *curMember = (*curMember).next;
5120          }
5121
5122       if(subMemberStackPos)
5123       {
5124          while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
5125          {
5126             subMemberStack[(*subMemberStackPos)++] = *curMember;
5127
5128             *curMember = (*curMember).members.first;
5129             while(*curMember && ((*curMember).memberAccess == privateAccess))
5130                *curMember = (*curMember).next;
5131          }
5132       }
5133    }
5134    while(!*curMember)
5135    {
5136       if(!*curMember)
5137       {
5138          if(subMemberStackPos && *subMemberStackPos)
5139          {
5140             *curMember = subMemberStack[--(*subMemberStackPos)];
5141             *curMember = (*curMember).next;
5142          }
5143          else
5144          {
5145             Class lastCurClass = *curClass;
5146
5147             if(*curClass == _class) break;     // REACHED THE END
5148
5149             for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass && (*curClass).inheritanceAccess != privateAccess; *curClass = (*curClass).base);
5150             *curMember = (*curClass).membersAndProperties.first;
5151          }
5152
5153          if(subMemberStackPos && *subMemberStackPos > 0)
5154          {
5155             while(*curMember && ((*curMember).memberAccess == privateAccess))
5156                *curMember = (*curMember).next;
5157          }
5158          else
5159             while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
5160             {
5161                DataMember dataMember = null;
5162                if(((*curMember).memberAccess != privateAccess))
5163                {
5164                   dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
5165                   if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
5166                }
5167                if(dataMember && dataMember.memberAccess != privateAccess && dataMember.id >= 0) // Skip _vTbl, _refCount and _class in Instance
5168                {
5169                   *curMember = dataMember;
5170                   break;
5171                }
5172                else
5173                   *curMember = (*curMember).next;
5174             }
5175
5176          if(subMemberStackPos)
5177          {
5178             while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
5179             {
5180                subMemberStack[(*subMemberStackPos)++] = *curMember;
5181
5182                *curMember = (*curMember).members.first;
5183                while(*curMember && (*curMember).memberAccess == privateAccess)
5184                   *curMember = (*curMember).next;
5185             }
5186          }
5187       }
5188    }
5189 }
5190
5191 public dllexport void eInstance_SetMethod(Instance instance, const char * name, void * function)     // YET TO BE DECIDED:   , Module module)
5192 {
5193    if(instance && name)
5194    {
5195       Class _class;
5196       for(_class = instance._class; _class; _class = _class.base)
5197       {
5198          Method method = (Method)_class.methods.FindString(name);
5199          if(method && method.type == virtualMethod)
5200          {
5201             if(instance._vTbl == instance._class._vTbl)
5202             {
5203                instance._vTbl = _malloc(sizeof(void *) * instance._class.vTblSize);
5204                memcpy(instance._vTbl, instance._class._vTbl,
5205                   sizeof(int(*)()) * instance._class.vTblSize);
5206             }
5207             instance._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
5208          }
5209       }
5210    }
5211 }
5212
5213 public dllexport bool eInstance_IsDerived(Instance instance, Class from)
5214 {
5215    if(instance)
5216    {
5217       Class _class = instance._class;
5218       for(; _class; _class = _class.base)
5219       {
5220          if(_class == from)
5221             return true;
5222       }
5223    }
5224    return false;
5225 }
5226
5227 public dllexport void eInstance_IncRef(Instance instance)
5228 {
5229    if(instance)
5230       instance._refCount++;
5231 }
5232
5233 public dllexport void eInstance_DecRef(Instance instance)
5234 {
5235    if(instance)
5236    {
5237       instance._refCount--;
5238       //if(!instance._refCount)
5239       if(instance._refCount <= 0)
5240       {
5241          eInstance_Delete(instance);
5242       }
5243    }
5244 }
5245
5246 static void FixOffsets(Class _class)
5247 {
5248    OldLink deriv;
5249    _class.structSize += _class.base.structSize - _class.offset;
5250
5251    _class.offset = _class.base.structSize;
5252
5253    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
5254       FixOffsets(deriv.data);
5255 }
5256
5257 public dllexport void eClass_Resize(Class _class, int newSize)
5258 {
5259    OldLink deriv;
5260    _class.structSize = newSize;
5261    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
5262       FixOffsets(deriv.data);
5263 }
5264                                                                                                                         // F000F000 will mean a pointer size alignment
5265 public dllexport DataMember eClass_AddDataMember(Class _class, const char * name, const char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
5266 {
5267    if(_class && name)
5268    {
5269       if(!_class.members.FindString(name))
5270       {
5271          DataMember dataMember;
5272
5273          if(alignment)
5274          {
5275             bool pointerAlignment = alignment == 0xF000F000;
5276             bool force64Bits = (_class.module.application.isGUIApp & 2) ? true : false;
5277             bool force32Bits = (_class.module.application.isGUIApp & 4) ? true : false;
5278             if((force32Bits || force64Bits) && !strcmp(_class.name, "AVLNode") && !strcmp(name, "__ecerePrivateData0"))
5279             {
5280                if(force64Bits)
5281                {
5282                   type = "byte[32]";
5283                   size = 32;
5284                }
5285                if(force32Bits)
5286                {
5287                   type = "byte[16]";
5288                   size = 16;
5289                }
5290             }
5291
5292             if(pointerAlignment) alignment = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
5293
5294             if(pointerAlignment && _class.structAlignment <= 4)
5295                _class.pointerAlignment = 1;
5296             else if(!pointerAlignment && alignment >= 8)
5297                _class.pointerAlignment = 0;
5298
5299             _class.structAlignment = Max(_class.structAlignment, alignment);
5300
5301             if(_class.offset % alignment)
5302                _class.offset += alignment - (_class.offset % alignment);
5303             if(_class.memberOffset % alignment)
5304                _class.memberOffset += alignment - (_class.memberOffset % alignment);
5305          }
5306
5307          dataMember = DataMember {
5308             name = CopyString(name);
5309             dataTypeString = CopyString(type);
5310             id = _class.memberID++;
5311             _class = _class;
5312             offset = _class.memberOffset;
5313             memberOffset = size;
5314             memberAccess = declMode;
5315             membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5316          };
5317          _class.membersAndProperties.Add(dataMember);
5318          _class.memberOffset += size;
5319
5320          _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5321          return dataMember;
5322       }
5323    }
5324    return null;
5325 }
5326                                                                                                                               // F000F000 will mean a pointer size alignment
5327 public dllexport DataMember eMember_AddDataMember(DataMember member, const char * name, const char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
5328 {
5329    if(name && !member.membersAlpha.FindString(name))
5330    {
5331       DataMember dataMember;
5332
5333       if(alignment)
5334       {
5335          bool pointerAlignment = alignment == 0xF000F000;
5336          bool force64Bits = false; //(member._class.module.application.isGUIApp & 2) ? true : false;
5337          bool force32Bits = false; //(member._class.module.application.isGUIApp & 4) ? true : false;
5338          if(pointerAlignment) alignment = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
5339
5340          if(pointerAlignment && member.structAlignment <= 4)
5341             member.pointerAlignment = 1;
5342          else if(!pointerAlignment && alignment >= 8)
5343             member.pointerAlignment = 0;
5344
5345          member.structAlignment = Max(member.structAlignment, alignment);
5346
5347          if(member.memberOffset % alignment)
5348             member.memberOffset += alignment - (member.memberOffset % alignment);
5349       }
5350       dataMember = DataMember {
5351          name = CopyString(name);
5352          _class = member._class;
5353          dataTypeString = CopyString(type);
5354          id = member.memberID++;
5355          offset = (member.type == unionMember) ? 0 : member.memberOffset;
5356          memberAccess = declMode;
5357          membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5358       };
5359       member.members.Add(dataMember);
5360       if(member.type == unionMember)
5361       {
5362          if(size > member.memberOffset)
5363             member.memberOffset = size;
5364       }
5365       else
5366          member.memberOffset += size;
5367       member.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5368       return dataMember;
5369    }
5370    return null;
5371 }
5372
5373 public dllexport DataMember eMember_New(DataMemberType type, AccessMode declMode)
5374 {
5375    return DataMember { type = type, memberAccess = declMode, membersAlpha.CompareKey = (void *)BinaryTree::CompareString };
5376 }
5377
5378 static void SetMemberClass(DataMember member, Class _class)
5379 {
5380    DataMember dataMember;
5381    member._class = _class;
5382    for(dataMember = member.members.first; dataMember; dataMember = dataMember.next)
5383       SetMemberClass(dataMember, _class);
5384 }
5385
5386 public dllexport bool eMember_AddMember(DataMember addTo, DataMember dataMember)
5387 {
5388    if(dataMember.name && addTo.membersAlpha.FindString(dataMember.name))
5389    {
5390       DataMember_Free(dataMember);
5391       delete dataMember;
5392       return false;
5393    }
5394    addTo.members.Add(dataMember);
5395
5396    if(dataMember.name)
5397       addTo.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5398
5399    dataMember._class = addTo._class;
5400    // ? SetMemberClass(dataMember, addTo._class);
5401
5402    //dataMember.id = addTo.memberID++;
5403    dataMember.id = addTo.memberID;
5404    if(dataMember.type == unionMember)
5405       addTo.memberID += 1;
5406    else
5407       addTo.memberID += dataMember.memberID;
5408
5409    if(dataMember.pointerAlignment && dataMember.structAlignment <= 4)
5410       addTo.pointerAlignment = 1;
5411    else if(!dataMember.pointerAlignment && dataMember.structAlignment >= 8)
5412       addTo.pointerAlignment = 0;
5413
5414    addTo.structAlignment = Max(addTo.structAlignment, dataMember.structAlignment);
5415
5416    dataMember.offset = (addTo.type == unionMember) ? 0 : addTo.memberOffset;
5417
5418    if(dataMember.structAlignment)
5419    {
5420       if(addTo.memberOffset % dataMember.structAlignment)
5421          addTo.memberOffset += dataMember.structAlignment - (addTo.memberOffset % dataMember.structAlignment);
5422    }
5423
5424    if(addTo.type == unionMember)
5425    {
5426       if(dataMember.memberOffset > addTo.memberOffset)
5427          addTo.memberOffset = dataMember.memberOffset;
5428    }
5429    else
5430       addTo.memberOffset += dataMember.memberOffset;
5431    return true;
5432 }
5433
5434 public dllexport bool eClass_AddMember(Class _class, DataMember dataMember)
5435 {
5436    if(!_class || _class.comRedefinition || (dataMember.name && _class.members.FindString(dataMember.name)))
5437    {
5438       DataMember_Free(dataMember);
5439       delete dataMember;
5440       return false;
5441    }
5442    _class.membersAndProperties.Add(dataMember);
5443
5444    if(dataMember.name)
5445       _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5446
5447    //dataMember._class = _class;
5448    SetMemberClass(dataMember, _class);
5449
5450    //dataMember.id = _class.memberID++;
5451    dataMember.id = _class.memberID;
5452
5453    if(dataMember.pointerAlignment && dataMember.structAlignment <= 4)
5454       _class.pointerAlignment = 1;
5455    else if(!dataMember.pointerAlignment && dataMember.structAlignment >= 8)
5456       _class.pointerAlignment = 0;
5457
5458    _class.structAlignment = Max(_class.structAlignment, dataMember.structAlignment);
5459    if(dataMember.type == unionMember)
5460       _class.memberID += 1;
5461    else
5462       _class.memberID += dataMember.memberID;
5463
5464    if(dataMember.structAlignment)
5465    {
5466       if(_class.memberOffset % dataMember.structAlignment)
5467          _class.memberOffset += dataMember.structAlignment - (_class.memberOffset % dataMember.structAlignment);
5468    }
5469
5470    dataMember.offset = _class.memberOffset;
5471    _class.memberOffset += dataMember.memberOffset;
5472    return true;
5473 }
5474
5475 public dllexport BitMember eClass_AddBitMember(Class _class, const char * name, const char * type, int bitSize, int bitPos, AccessMode declMode)
5476 {
5477    if(_class && name && !_class.members.FindString(name))
5478    {
5479       uint64 mask = 0;
5480       int c;
5481       BitMember bitMember
5482       {
5483          name = CopyString(name);
5484          _class = _class;
5485          dataTypeString = CopyString(type);
5486          id = _class.memberID++;
5487          memberAccess = declMode;
5488       };
5489       _class.membersAndProperties.Add(bitMember);
5490       if(bitSize)
5491       {
5492          bitMember.pos = (bitPos == -1) ? _class.memberOffset : bitPos;
5493          bitMember.size = bitSize;
5494          _class.memberOffset = bitMember.pos + bitMember.size;
5495          for(c = 0; c<bitSize; c++)
5496          {
5497             if(c)
5498                mask <<= 1;
5499             mask |= 1;
5500          }
5501          bitMember.mask = mask << bitMember.pos;
5502       }
5503
5504      _class.members.Add((BTNode)BTNamedLink { name = bitMember.name, data = bitMember });
5505       return bitMember;
5506    }
5507    return null;
5508 }
5509
5510 static Module Module_Load(Module fromModule, const char * name, AccessMode importAccess, bool ensureCOM)
5511 {
5512    bool (stdcall * Load)(Module module) = null;
5513    bool (stdcall * Unload)(Module module) = null;
5514    Module module;
5515
5516    for(module = fromModule.application.allModules.first; module; module = module.next)
5517    {
5518       if(!strcmp(module.name, name))
5519          break;
5520    }
5521    if(ensureCOM && (!strcmp(name, "ecereCOM") || !strcmp(name, "ecere")))
5522    {
5523       for(module = fromModule.application.allModules.first; module; module = module.next)
5524       {
5525          if(!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM"))
5526             break;
5527       }
5528    }
5529    if(!module)
5530    {
5531       void * library = null;
5532
5533       if(ensureCOM && !strcmp(name, "ecereCOM"))
5534       {
5535          Load = COM_LOAD_FUNCTION;
5536          Unload = COM_UNLOAD_FUNCTION;
5537       }
5538       else
5539       {
5540          const char * libLocation = null;
5541 #if defined(__ANDROID__)
5542          libLocation = AndroidInterface_GetLibLocation(fromModule.application);
5543 #endif
5544          library = Instance_Module_Load(libLocation, name, &Load, &Unload);
5545       }
5546       if(Load)
5547       {
5548          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5549          module.application = fromModule.application;
5550          module.library = library;
5551          {
5552             char moduleName[MAX_FILENAME];
5553             char ext[MAX_EXTENSION];
5554             GetLastDirectory(name, moduleName);
5555             GetExtension(moduleName, ext);
5556             StripExtension(moduleName);
5557             if((!strcmpi(ext, "dylib") || !strcmpi(ext, "so")) && strstr(moduleName, "lib") == moduleName)
5558             {
5559                int len = (int)strlen(moduleName) - 3;
5560                memmove(moduleName, moduleName + 3, len);
5561                moduleName[len] = 0;
5562             }
5563             module.name = CopyString(moduleName);
5564          }
5565          module.Unload = Unload;
5566          module.origImportType = normalImport;
5567
5568          if(!Load(module))
5569          {
5570             eInstance_Delete((Instance)module);
5571             module = null;
5572          }
5573       }
5574       fromModule.application.allModules.Add(module);
5575    }
5576    if(ensureCOM && !strcmp(name, "ecere") && module)
5577    {
5578       name = !strcmp(module.name, "ecereCOM") ? "ecere" : "ecereCOM";
5579       if((!Load && !strcmp(module.name, "ecereCOM")) ||
5580          (Load && (!__thisModule || !__thisModule.name || !strcmp(__thisModule.name, "ecereCOM")) && Load != (void *)COM_LOAD_FUNCTION))
5581       {
5582          Module module;
5583          for(module = fromModule.application.allModules.first; module; module = module.next)
5584          {
5585             if(!strcmp(module.name, name))
5586                break;
5587          }
5588          if(!module)
5589          {
5590             Load = COM_LOAD_FUNCTION;
5591             Unload = COM_UNLOAD_FUNCTION;
5592
5593             module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5594             module.application = fromModule.application;
5595             module.library = null;
5596             module.name = CopyString(name);
5597             module.Unload = Unload;
5598
5599             if(!Load(module))
5600             {
5601                eInstance_Delete((Instance)module);
5602                module = null;
5603             }
5604
5605             fromModule.application.allModules.Add(module);
5606          }
5607          if(module)
5608          {
5609             if(fromModule)
5610             {
5611                fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5612             }
5613             incref module;
5614          }
5615       }
5616    }
5617    if(module)
5618    {
5619       if(fromModule)
5620       {
5621          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5622       }
5623       incref module;
5624    }
5625 #if defined(_DEBUG)
5626    InternalModuleLoadBreakpoint();
5627 #endif
5628    return module;
5629 }
5630
5631 public dllexport Module eModule_Load(Module fromModule, const char * name, AccessMode importAccess)
5632 {
5633    return Module_Load(fromModule, name, importAccess, true);
5634 }
5635
5636 public dllexport Module eModule_LoadStrict(Module fromModule, const char * name, AccessMode importAccess)
5637 {
5638    return Module_Load(fromModule, name, importAccess, false);
5639 }
5640
5641 public dllexport Module eModule_LoadStatic(Module fromModule, const char * name, AccessMode importAccess, bool (* Load)(Module module), bool (* Unload)(Module module))
5642 {
5643    Module module;
5644    for(module = fromModule.application.allModules.first; module; module = module.next)
5645    {
5646       if(!strcmp(module.name, name))
5647          break;
5648    }
5649    if(!module)
5650    {
5651       if(Load)
5652       {
5653          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5654          module.application = fromModule.application;
5655          module.name = CopyString(name);
5656          module.origImportType = staticImport;
5657          module.Unload = (void *)Unload;
5658          if(!Load(module))
5659          {
5660             eInstance_Delete((Instance)module);
5661             module = null;
5662          }
5663       }
5664       fromModule.application.allModules.Add(module);
5665    }
5666    if(module)
5667    {
5668       if(fromModule)
5669       {
5670          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5671       }
5672       incref module;
5673    }
5674    return module;
5675 }
5676
5677 public dllexport void eModule_Unload(Module fromModule, Module module)
5678 {
5679    OldLink m;
5680    for(m = fromModule.modules.first; m; m = m.next)
5681    {
5682       if(m.data == module)
5683          break;
5684    }
5685    if(m)
5686    {
5687       fromModule.modules.Delete(m);
5688       delete module;
5689    }
5690 }
5691
5692 public dllexport void eEnum_AddFixedValue(Class _class, const char * string, int64 value)
5693 {
5694    if(_class && _class.type == enumClass)
5695    {
5696       EnumClassData data = (EnumClassData)_class.data;
5697       NamedLink64 item;
5698
5699       for(item = data.values.first; item; item = item.next)
5700          if(!strcmp(item.name, string))
5701             break;
5702       if(!item)
5703       {
5704          data.values.Add(NamedLink64 { data = value, name = CopyString(string) });
5705          if(value > data.largest)
5706             data.largest = value;
5707       }
5708    }
5709 }
5710
5711 public dllexport int64 eEnum_AddValue(Class _class, const char * string)
5712 {
5713    if(_class && _class.type == enumClass)
5714    {
5715       EnumClassData data = (EnumClassData)_class.data;
5716       int64 value = data.largest + 1;
5717       NamedLink64 item;
5718       for(item = data.values.first; item; item = item.next)
5719          if(!strcmp(item.name, string))
5720             break;
5721       if(!item)
5722       {
5723          data.values.Add(NamedLink64 { data = value, name = CopyString(string) });
5724          if(value > data.largest)
5725             data.largest = value;
5726          return value;
5727       }
5728    }
5729    return -1;
5730 }
5731
5732 static void NameSpace_Free(NameSpace parentNameSpace)
5733 {
5734    NameSpace * nameSpace;
5735    delete (void *)parentNameSpace.name;
5736
5737          /*   {
5738       BTNamedLink n, next;
5739       for(n = (BTNamedLink)parentNameSpace.classes.first; n; n = next)
5740       {
5741          Class c = n.data;
5742
5743          next = (BTNamedLink)((BTNode)n).next;
5744
5745          if(c.templateClass)
5746             eClass_Unregister(c);
5747       }
5748    }         */
5749
5750    while((nameSpace = (NameSpace *)parentNameSpace.nameSpaces.first))
5751    {
5752       NameSpace_Free(nameSpace);
5753       parentNameSpace.nameSpaces.Delete((BTNode)nameSpace);
5754    }
5755 }
5756
5757 static void Application_Destructor(Application app)
5758 {
5759    if(app.parsedCommand)
5760    {
5761       delete (void *)app.argv;
5762       delete app.parsedCommand;
5763    }
5764 }
5765
5766 static bool Module_Constructor(Module module)
5767 {
5768    module.privateNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5769    module.privateNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5770    module.privateNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5771    module.privateNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5772
5773    module.publicNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5774    module.publicNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5775    module.publicNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5776    module.publicNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5777    return true;
5778 }
5779
5780 static void Module_Destructor(Module module)
5781 {
5782    Class _class;
5783    DefinedExpression def;
5784    GlobalFunction function;
5785    Module m;
5786    SubModule handle;
5787
5788    // printf("Destructing module %s\n", module.name);
5789
5790    // Take out references from all modules
5791    for(m = module.application.allModules.first; m; m = m.next)
5792    {
5793       SubModule next;
5794       for(handle = m.modules.first; handle; handle = next)
5795       {
5796          next = handle.next;
5797          if(handle.module == module)
5798             m.modules.Delete(handle);
5799       }
5800    }
5801
5802    if(module.Unload)
5803    {
5804       if(module.origImportType == staticImport)
5805       {
5806          bool (* Unload)(Module module) = (void *)module.Unload;
5807          Unload(module);
5808       }
5809       else
5810       {
5811          bool (stdcall * Unload)(Module module) = (void *)module.Unload;
5812          Unload(module);
5813       }
5814    }
5815
5816    // Unload dependencies
5817    {
5818       Module ourWorld = class(Class).module;
5819       void * ourHandle = null;
5820       while((handle = module.modules.last))  // STARTING WITH LAST SO THAT ecereCOM IS UNLOADED LAST...
5821       {
5822          Module depModule = handle.module;
5823          if(depModule == ourWorld)
5824          {
5825             module.modules.Remove(handle);
5826             ourHandle = handle;
5827          }
5828          else
5829          {
5830             module.modules.Delete(handle);
5831             delete depModule;
5832          }
5833       }
5834       if(ourHandle)
5835       {
5836          delete ourHandle;
5837          delete ourWorld;
5838       }
5839    }
5840
5841    // Unload classes
5842    for(;(_class = module.classes.first);)
5843    {
5844       if(_class.nameSpace)
5845       {
5846          BTNamedLink classLink = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
5847          if(classLink)
5848          {
5849             OldLink t;
5850             for(t = _class.templatized.first; t; t = t.next)
5851             {
5852                Class template = t.data;
5853                BTNamedLink link;
5854                link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
5855
5856                template.nameSpace->classes.Delete((BTNode)link);
5857                template.nameSpace = null;
5858             }
5859             _class.nameSpace->classes.Delete((BTNode)classLink);
5860          }
5861 #ifdef _DEBUG
5862          else
5863          {
5864             printf("Warning: Could not find %s in namespace classes while destructing module %s\n", _class.name, module.name);
5865          }
5866 #endif
5867          _class.nameSpace = null;
5868       }
5869       _class.module = null;
5870       module.classes.Remove(_class);
5871       if(_class.count <= 0 || _class.type != normalClass || _class.isInstanceClass)
5872          eClass_Unregister(_class);
5873       else
5874       {
5875 #ifdef MEMINFO
5876          // printf("Delayed destruction of class %s\n", _class.name);
5877 #endif
5878       }
5879    }
5880
5881    // Unload defines
5882    for(;(def = module.defines.first);)
5883    {
5884       if(def.nameSpace)
5885       {
5886          BTNamedLink defLink;
5887          for(defLink = (BTNamedLink)def.nameSpace->defines.first; defLink; defLink = (BTNamedLink)((BTNode)defLink).next)
5888             if(defLink.data == def)
5889             {
5890                def.nameSpace->defines.Delete((BTNode)defLink);
5891                break;
5892             }
5893       }
5894       delete (void *)def.name;
5895       delete (void *)def.value;
5896       module.defines.Delete(def);
5897    }
5898
5899    // Unload functions
5900    for(;(function = module.functions.first);)
5901    {
5902       if(function.nameSpace)
5903       {
5904          BTNamedLink functionLink;
5905          for(functionLink = (BTNamedLink)function.nameSpace->functions.first; functionLink; functionLink = (BTNamedLink)((BTNode)functionLink).next)
5906             if(functionLink.data == function)
5907             {
5908                function.nameSpace->functions.Delete((BTNode)functionLink);
5909                break;
5910             }
5911       }
5912       delete (void *)function.name;
5913       delete (void *)function.dataTypeString;
5914       module.functions.Delete(function);
5915    }
5916
5917    delete (void *)module.name;
5918
5919    NameSpace_Free(module.privateNameSpace);
5920    NameSpace_Free(module.publicNameSpace);
5921
5922    if(module != module.application)
5923       module.application.allModules.Remove(module);
5924    else
5925       NameSpace_Free(module.application.systemNameSpace);
5926
5927 #ifndef MEMINFO
5928    Instance_Module_Free(module.library);
5929 #endif
5930 }
5931
5932 static int64 GetEnumSize(Class _class)
5933 {
5934    EnumClassData data = (EnumClassData)_class.data;
5935    return data.largest+1;
5936 }
5937
5938 #if defined(__GNUC__)
5939 #define strcmpi strcasecmp
5940 #define strnicmp strncasecmp
5941 #endif
5942
5943 #if defined(ECERE_BOOTSTRAP) || (defined(__GNUC__) && !defined(__DJGPP__) && !defined(__WIN32__) && !defined(__EMSCRIPTEN__))
5944 #undef strlwr
5945 #undef strupr
5946 default dllexport char * strlwr(char *string)
5947 {
5948    int c;
5949    for(c=0; string[c]; c++)
5950       if(string[c]>='A' && string[c]<='Z')
5951          string[c]+='a'-'A';
5952    return string;
5953 }
5954 default dllexport char * strupr(char *string)
5955 {
5956    int c;
5957    for(c=0; string[c]; c++)
5958       if(string[c]>='a' && string[c]<='z')
5959          string[c]-='a'-'A';
5960    return string;
5961 }
5962 #endif
5963
5964 public dllexport DefinedExpression eSystem_RegisterDefine(const char * name, const char * value, Module module, AccessMode declMode)
5965 {
5966    NameSpace * nameSpace = null;
5967
5968    int start = 0, c;
5969
5970    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5971    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5972
5973    if(declMode != staticAccess)
5974    {
5975       for(c = 0; name[c]; c++)
5976       {
5977          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5978          {
5979             NameSpace * newSpace;
5980
5981             char * spaceName = _malloc(c - start + 1);
5982             strncpy(spaceName, name + start, c - start);
5983             spaceName[c-start] = '\0';
5984
5985             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5986             if(!newSpace)
5987             {
5988                newSpace = new0 NameSpace[1];
5989                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5990                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5991                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5992                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5993                newSpace->name = spaceName;
5994                newSpace->parent = nameSpace;
5995                nameSpace->nameSpaces.Add((BTNode)newSpace);
5996             }
5997             else
5998                delete spaceName;
5999             nameSpace = newSpace;
6000             if(name[c] == ':') c++;
6001             start = c+1;
6002          }
6003       }
6004    }
6005    else
6006       c = (int)strlen(name);
6007
6008    if(c - start && !nameSpace->defines.FindString(name + start))
6009    {
6010       DefinedExpression def
6011       {
6012          name = CopyString(name);
6013          nameSpace = nameSpace;
6014          value = CopyString(value);
6015       };
6016       nameSpace->defines.Add((BTNode)BTNamedLink { name = def.name + start, data = def });
6017       // Reference the definition in the module
6018       module.defines.Add(def);
6019       return def;
6020    }
6021    return null;
6022 }
6023
6024 public dllexport GlobalFunction eSystem_RegisterFunction(const char * name, const char * type, void * func, Module module, AccessMode declMode)
6025 {
6026    NameSpace * nameSpace = null;
6027    int start = 0, c;
6028
6029    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
6030    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
6031
6032    if(declMode != staticAccess)
6033    {
6034       for(c = 0; name[c]; c++)
6035       {
6036          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
6037          {
6038             NameSpace * newSpace;
6039
6040             char * spaceName = _malloc(c - start + 1);
6041             strncpy(spaceName, name + start, c - start);
6042             spaceName[c-start] = '\0';
6043
6044             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
6045             if(!newSpace)
6046             {
6047                newSpace = new0 NameSpace[1];
6048                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
6049                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
6050                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
6051                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
6052                newSpace->name = spaceName;
6053                newSpace->parent = nameSpace;
6054                nameSpace->nameSpaces.Add((BTNode)newSpace);
6055             }
6056             else
6057                delete spaceName;
6058             nameSpace = newSpace;
6059             if(name[c] == ':') c++;
6060             start = c+1;
6061          }
6062       }
6063    }
6064    else
6065       c = (int)strlen(name);
6066
6067    if(c - start && !nameSpace->functions.FindString(name + start))
6068    {
6069       GlobalFunction function
6070       {
6071          name = CopyString(name);
6072          nameSpace = nameSpace;
6073          dataTypeString = CopyString(type);
6074          function = func;
6075          module = module;
6076       };
6077       nameSpace->functions.Add((BTNode)BTNamedLink { name = function.name + start, data = function });
6078       // Reference the definition in the module
6079       module.functions.Add(function);
6080       return function;
6081    }
6082    return null;
6083 }
6084
6085 public dllexport DefinedExpression eSystem_FindDefine(Module module, const char * name)
6086 {
6087    if(name && module)
6088    {
6089       BTNamedLink link;
6090       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->defines);
6091       if(link) return link.data;
6092
6093       link = SearchModule(module, name, &((NameSpace *)0)->defines, true);
6094       if(link) return link.data;
6095    }
6096    return null;
6097 }
6098
6099 public dllexport GlobalFunction eSystem_FindFunction(Module module, const char * name)
6100 {
6101    if(name && module)
6102    {
6103       BTNamedLink link;
6104       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->functions);
6105       if(link) return link.data;
6106
6107       link = SearchModule(module, name, &((NameSpace *)0)->functions, true);
6108       if(link) return link.data;
6109    }
6110    return null;
6111 }
6112
6113 public dllexport void * eSystem_Renew(void * memory, unsigned int size)
6114 {
6115    return _realloc(memory, size);
6116 }
6117
6118 public dllexport void * eSystem_Renew0(void * memory, unsigned int size)
6119 {
6120    return _crealloc(memory, size);
6121 }
6122
6123 public dllexport void * eSystem_New(unsigned int size)
6124 {
6125 /*#ifdef _DEBUG
6126    void * pointer = _malloc(size);
6127    memset(pointer, 0xec, size);
6128    return pointer;
6129 #else*/
6130    return _malloc(size);
6131 //#endif
6132 }
6133
6134 public dllexport void * eSystem_New0(unsigned int size)
6135 {
6136    return _calloc(1,size);
6137 }
6138
6139 public dllexport void eSystem_Delete(void * memory)
6140 {
6141    if(memory)
6142       _free(memory);
6143 }
6144
6145 // Properties
6146 public dllexport void eInstance_FireSelfWatchers(Instance instance, Property _property)
6147 {
6148    if(instance && _property && _property.selfWatchable)
6149    {
6150       Class _class;
6151       for(_class = instance._class; _class; _class = _class.base)
6152       {
6153          SelfWatcher selfWatcher, next;
6154          for(selfWatcher = _class.selfWatchers.first; selfWatcher; selfWatcher = next)
6155          {
6156             next = selfWatcher.next;
6157             if(selfWatcher._property == _property)
6158                selfWatcher.callback(instance);
6159          }
6160       }
6161    }
6162 }
6163
6164 public dllexport void eInstance_FireWatchers(Instance instance, Property _property)
6165 {
6166    if(instance && _property && _property.isWatchable)
6167    {
6168       Module module = instance._class ? instance._class.module : null;
6169       Application application = module ? module.application : null;
6170       int flags = application ? application.isGUIApp : 0;
6171       bool inCompiler = (flags & 8) ? true : false;
6172       bool force32Bits = (flags & 4) ? true : false;
6173       if(!force32Bits || !inCompiler)
6174       {
6175          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6176          Watcher watcher, next;
6177
6178          for(watcher = watchers->first; watcher; watcher = next)
6179          {
6180             next = watcher.next;
6181             watcher.callback(watcher.object, instance);
6182          }
6183       }
6184    }
6185 }
6186
6187 public dllexport void eProperty_Watchable(Property _property)
6188 {
6189    if(!_property.isWatchable)
6190    {
6191       Class _class = _property._class;
6192       if(!_class.computeSize)
6193       {
6194          _property.watcherOffset = _class.structSize;
6195          _class.structSize += sizeof(OldList);
6196
6197          // highly inefficient
6198          FixDerivativesBase(_class, _class);
6199       }
6200       _property.isWatchable = true;
6201    }
6202 }
6203
6204 public dllexport void eClass_DestructionWatchable(Class _class)
6205 {
6206    if(!_class.destructionWatchOffset)
6207    {
6208       _class.destructionWatchOffset = _class.structSize;
6209       _class.structSize += sizeof(OldList);
6210       // highly inefficient
6211       FixDerivativesBase(_class, _class);
6212    }
6213 }
6214
6215 public dllexport void eProperty_SelfWatch(Class _class, const char * name, void (*callback)(void *))
6216 {
6217    if(_class)
6218    {
6219       Property _property = eClass_FindProperty(_class, name, _class.module);
6220
6221       if(!_property)
6222          _property = eClass_AddProperty(_class, name, null, null, null, baseSystemAccess /*privateAccess*/);
6223       _class.selfWatchers.Add(SelfWatcher { _property = _property, callback = callback });
6224       _property.selfWatchable = true;
6225    }
6226 }
6227
6228 public dllexport void eInstance_Watch(void * instance, Property _property, void * object, void (*callback)(void *, void *))
6229 {
6230    if(_property.isWatchable)
6231    {
6232       OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6233       watchers->Add(Watcher { callback = callback, object = object });
6234    }
6235 }
6236
6237 public dllexport void eInstance_WatchDestruction(Instance instance, Instance object, void (*callback)(void *, void *))
6238 {
6239    OldList * watchers = (OldList *)((byte *)instance + instance._class.destructionWatchOffset);
6240    watchers->Add(Watcher { callback = callback, object = object });
6241 }
6242
6243 public dllexport void eInstance_StopWatching(Instance instance, Property _property, Instance object)
6244 {
6245    if(instance && (!_property || _property.isWatchable))
6246    {
6247       if(_property)
6248       {
6249          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6250          Watcher watcher;
6251          for(watcher = watchers->first; watcher; watcher = watcher.next)
6252             if(watcher.object == object)
6253             {
6254                watchers->Delete(watcher);
6255                break;
6256             }
6257       }
6258       else
6259       {
6260          // Stop watching all properties as well as destruction
6261          Class _class, base;
6262          for(_class = instance._class; _class; _class = base)
6263          {
6264             if(_class.destructionWatchOffset)
6265             {
6266                OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
6267                Watcher watcher;
6268
6269                for(watcher = watchers->first; watcher; watcher = watcher.next)
6270                {
6271                   watchers->Delete(watcher);
6272                   break;
6273                }
6274             }
6275             for(_property = (Property)_class.membersAndProperties.first; _property; _property = _property.next)
6276             {
6277                if(_property.isProperty && _property.isWatchable)
6278                {
6279                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6280                   Watcher watcher;
6281                   for(watcher = watchers->first; watcher; watcher = watcher.next)
6282                      if(watcher.object == object)
6283                      {
6284                         watchers->Delete(watcher);
6285                         break;
6286                      }
6287                }
6288             }
6289             base = _class.base;
6290             if(base && (base.type == systemClass || base.isInstanceClass)) base = null;
6291          }
6292       }
6293    }
6294 }
6295
6296 public dllexport subclass(ClassDesignerBase) eClass_GetDesigner(Class _class)
6297 {
6298    for(;_class;_class = _class.base)
6299    {
6300       if(_class.designerClass)
6301          return (subclass(ClassDesignerBase))eSystem_FindClass(_class.module, _class.designerClass);
6302    }
6303    return null;
6304 }
6305
6306
6307 public dllexport subclass(ClassDesignerBase) eInstance_GetDesigner(Instance instance)
6308 {
6309    if(instance)
6310       return eClass_GetDesigner(instance._class);
6311    return null;
6312 }
6313
6314 public bool LocateModule(const char * name, const char * fileName)
6315 {
6316    return Instance_LocateModule(name, fileName);
6317 }
6318
6319 /*
6320 #if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__)
6321 #define _64BIT 1
6322 #else
6323 #define _64BIT 0
6324 #endif
6325
6326 #define arch_PointerSize                  sizeof(void *)
6327 #define structSize_Instance               (_64BIT ? 24 : 12)
6328 #define structSize_Module                 (_64BIT ? 560 : 300)
6329 #define structSize_BinaryTree             (_64BIT ? 32 : 16)
6330 #define structSize_OldList                (_64BIT ? 32 : 20)
6331 #define structSize_NamedLink64            (_64BIT ? 32 : 24)
6332 #define structSize_ClassTemplateArgument  (_64BIT ? 16 : 8)
6333 #define structSize_ClassTemplateParameter (_64BIT ? 64 : 40)
6334 #define structSize_OldLink                (_64BIT ? 24 : 12)
6335 #define structSize_BTNamedLink            (_64BIT ? 48 : 24)
6336 #define structSize_Application            (_64BIT ? 800 : 428)
6337 #define structSize_Watcher                (_64BIT ? 32 : 16)
6338 #define structSize_SelfWatcher            (_64BIT ? 32 : 16)
6339 #define structSize_GlobalFunction         (_64BIT ? 72 : 36)
6340 #define structSize_DefinedExpression      (_64BIT ? 40 : 20)
6341 #define structSize_BitMember              (_64BIT ? 96 : 64)
6342 #define structSize_DataMember             (_64BIT ? 160 : 96)
6343 #define structSize_ClassProperty          (_64BIT ? 80 : 40)
6344 #define structSize_Method                 (_64BIT ? 96 : 52)
6345 #define structSize_Property               (_64BIT ? 152 : 88)
6346 #define structSize_Class                  (_64BIT ? 624 : 376)
6347 */
6348
6349 static void LoadCOM(Module module)
6350 {
6351    bool force64Bits = (module.application.isGUIApp & 2) ? true : false;
6352    bool force32Bits = (module.application.isGUIApp & 4) ? true : false;
6353    bool inCompiler = (module.application.isGUIApp & 8) ? true : false;
6354    int pointerSize = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
6355    Class applicationClass;
6356    Class enumClass, structClass, boolClass;
6357    Class moduleClass;
6358
6359    // Create Base Class
6360    Class baseClass = eSystem_RegisterClass(normalClass, "class", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6361    baseClass.type = systemClass;
6362    baseClass.memberOffset = 0;
6363    baseClass.offset = 0;
6364    baseClass.structSize = 0;
6365    baseClass.typeSize = 0;
6366
6367    {
6368       Class instanceClass = eSystem_RegisterClass(normalClass, "ecere::com::Instance", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6369       instanceClass.type = normalClass;
6370       instanceClass.isInstanceClass = true;
6371       instanceClass.fixed = true;
6372       instanceClass.memberOffset = 0;
6373       instanceClass.offset = 0;
6374
6375       instanceClass.memberID = -3;
6376       instanceClass.startMemberID = -3;
6377
6378       eClass_AddDataMember(instanceClass, "_vTbl", "void **", pointerSize, pointerSize, publicAccess);
6379       eClass_AddDataMember(instanceClass, "_class", "ecere::com::Class", pointerSize, pointerSize, publicAccess);
6380       eClass_AddDataMember(instanceClass, "_refCount", "int", sizeof(int), sizeof(int), publicAccess);
6381    }
6382
6383    InitializeDataTypes1(module);
6384
6385    // Create Enum class
6386    enumClass = eSystem_RegisterClass(normalClass, "enum", null, 0, force64Bits ? 40 : sizeof(class EnumClassData), null, null, module, baseSystemAccess, publicAccess);
6387    eClass_AddClassProperty(enumClass, "enumSize", "int", null, GetEnumSize).constant = true;
6388    enumClass.type = systemClass;
6389
6390    delete (void *)enumClass.dataTypeString;
6391    enumClass.dataTypeString = CopyString(/*"unsigned int"*/"int");
6392
6393    // Create Struct (simple) class
6394    //structClass = eSystem_RegisterClass(structClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6395    structClass = eSystem_RegisterClass(normalClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6396    structClass.type = systemClass;
6397    structClass.memberOffset = 0;
6398    structClass.offset = 0;
6399    structClass.structSize = 0;
6400    structClass.typeSize = 0;
6401
6402    //eClass_AddMethod(enumClass, "AddValue", "int()", eEnum_AddValue);
6403    //eClass_AddMethod(enumClass, "AddFixedValue", "void()", eEnum_AddFixedValue);
6404
6405    InitializeDataTypes(module);
6406
6407    // Create bool class
6408    boolClass = eSystem_RegisterClass(ClassType::enumClass, "bool", "uint", 0, 0, null, null, module, baseSystemAccess, publicAccess);
6409    eEnum_AddFixedValue(boolClass, "true",  bool::true);
6410    eEnum_AddFixedValue(boolClass, "false", bool::false);
6411
6412    // Create Module class
6413    moduleClass = eSystem_RegisterClass(normalClass, "ecere::com::Module", null, force64Bits ? 8 + 32 + 32 + 32 + 32 + 8 + 8 + 8 + 8 + 8 + 4 + 4 + (32 + 8 + 8 + 4*32) + (32 + 8 + 8 + 4*32) :
6414                                                                                 sizeof(struct Module), 0, (void *)Module_Constructor, (void *)Module_Destructor, module, baseSystemAccess, publicAccess);
6415    eClass_AddVirtualMethod(moduleClass, "OnLoad", "bool()", null, publicAccess);
6416    eClass_AddVirtualMethod(moduleClass, "OnUnload", "void()", null, publicAccess);
6417    eClass_AddMethod(moduleClass, "Load", "Module(const char * name, AccessMode importAccess)", eModule_Load, publicAccess);
6418    eClass_AddMethod(moduleClass, "Unload", "void(Module module)", eModule_Unload, publicAccess);
6419    eClass_AddDataMember(moduleClass, "application", "Application", pointerSize, pointerSize, publicAccess);
6420    eClass_AddDataMember(moduleClass, "classes", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6421    eClass_AddDataMember(moduleClass, "defines", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6422    eClass_AddDataMember(moduleClass, "functions", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6423    eClass_AddDataMember(moduleClass, "modules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6424    eClass_AddDataMember(moduleClass, "prev", "Module", pointerSize, pointerSize, publicAccess);
6425    eClass_AddDataMember(moduleClass, "next", "Module", pointerSize, pointerSize, publicAccess);
6426    eClass_AddDataMember(moduleClass, "name", "const char *", pointerSize, pointerSize, publicAccess);
6427    eClass_AddDataMember(moduleClass, "library", "void *", pointerSize, pointerSize, publicAccess);
6428    eClass_AddDataMember(moduleClass, "Unload", "void *", pointerSize, pointerSize, publicAccess);
6429    eClass_AddDataMember(moduleClass, "importType", "ImportType", sizeof(ImportType), 4, publicAccess);
6430    eClass_AddDataMember(moduleClass, "origImportType", "ImportType", sizeof(ImportType), 4, publicAccess);
6431    eClass_AddDataMember(moduleClass, "privateNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6432    eClass_AddDataMember(moduleClass, "publicNameSpace", "NameSpace",  force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6433    moduleClass.fixed = true;
6434    moduleClass.count++;
6435    if(inCompiler && force32Bits)
6436       moduleClass.structSize = 12 + 4 + 20 + 20 + 20 + 20 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + (16 + 4 + 4 + 4*16) + (16 + 4 + 4 + 4*16);
6437
6438    // Create Application class
6439    applicationClass = eSystem_RegisterClass(normalClass, "ecere::com::Application", "Module", force64Bits ? (8+8+4+4 + 32 + 8 + 176) : sizeof(struct Application), 0, null, (void *)Application_Destructor, module, baseSystemAccess, publicAccess);
6440    if(inCompiler && force32Bits)
6441    {
6442       applicationClass.offset = 12 + 4 + 20 + 20 + 20 + 20 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + (16 + 4 + 4 + 4*16) + (16 + 4 + 4 + 4*16);
6443       applicationClass.structSize = applicationClass.offset + (4+4+4+4 + 20 + 4 + 88);
6444    }
6445    eClass_AddVirtualMethod(applicationClass, "Main", "void()", null, publicAccess);
6446    eClass_AddDataMember(applicationClass, "argc", "int", sizeof(int), 4, publicAccess);
6447    eClass_AddDataMember(applicationClass, "argv", "const char **", pointerSize, pointerSize, publicAccess);
6448    eClass_AddDataMember(applicationClass, "exitCode", "int", sizeof(int), 4, publicAccess);
6449    eClass_AddDataMember(applicationClass, "isGUIApp", "bool", sizeof(bool), 4, publicAccess);
6450    eClass_AddDataMember(applicationClass, "allModules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6451    eClass_AddDataMember(applicationClass, "parsedCommand", "char *", pointerSize, pointerSize, publicAccess);
6452    eClass_AddDataMember(applicationClass, "systemNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6453    applicationClass.fixed = true;
6454    applicationClass.count++;
6455
6456    //AttachConsole(-1);
6457    //AllocConsole();
6458
6459    // --- Math ---
6460    eSystem_RegisterFunction("sin", "double sin(Angle number)", sin, module, baseSystemAccess);
6461    eSystem_RegisterFunction("sinh", "double sinh(Angle number)", sinh, module, baseSystemAccess);
6462    eSystem_RegisterFunction("cosh", "double cosh(Angle number)", cosh, module, baseSystemAccess);
6463    eSystem_RegisterFunction("tanh", "double tanh(Angle number)", tanh, module, baseSystemAccess);
6464    eSystem_RegisterFunction("sqrt", "double sqrt(double number)", sqrt, module, baseSystemAccess);
6465    eSystem_RegisterFunction("cos", "double cos(Angle number)", cos, module, baseSystemAccess);
6466    eSystem_RegisterFunction("tan", "double tan(Angle number)", tan, module, baseSystemAccess);
6467    eSystem_RegisterFunction("atan2", "Angle atan2(double y, double x)", atan2, module, baseSystemAccess);
6468    eSystem_RegisterFunction("asin", "Angle asin(double number)", asin, module, baseSystemAccess);
6469    eSystem_RegisterFunction("acos", "Angle acos(double number)", acos, module, baseSystemAccess);
6470    eSystem_RegisterFunction("atan", "Angle atan(double number)", atan, module, baseSystemAccess);
6471    eSystem_RegisterFunction("asinh", "Angle asinh(double number)", asinh, module, baseSystemAccess);
6472    eSystem_RegisterFunction("acosh", "Angle acosh(double number)", acosh, module, baseSystemAccess);
6473    eSystem_RegisterFunction("atanh", "Angle atanh(double number)", atanh, module, baseSystemAccess);
6474    eSystem_RegisterFunction("pow", "double pow(double number, double number2)", pow, module, baseSystemAccess);
6475    eSystem_RegisterFunction("fmod", "double fmod(double x, double y)", fmod, module, baseSystemAccess);
6476    eSystem_RegisterFunction("fabs", "double fabs(double number)", fabs, module, baseSystemAccess);
6477    eSystem_RegisterFunction("log", "double log(double number)", log, module, baseSystemAccess);
6478    eSystem_RegisterFunction("log10", "double log10(double number)", log10, module, baseSystemAccess);
6479    eSystem_RegisterFunction("ceil", "double ceil(double number)", ceil, module, baseSystemAccess);
6480    eSystem_RegisterFunction("floor", "double floor(double number)", floor, module, baseSystemAccess);
6481    eSystem_RegisterFunction("exp", "double exp(double number)", exp, module, baseSystemAccess);
6482
6483    // --- Stdlib ---
6484    eSystem_RegisterFunction("qsort", "void qsort(void *, uintsize, uintsize, int (*)(void *, void *))", qsort, module, baseSystemAccess);
6485    eSystem_RegisterFunction("strtod", "double strtod(const char*, char**)", strtod, module, baseSystemAccess);
6486    eSystem_RegisterFunction("strtol", "int strtol(const char*, char**, int base)", strtol, module, baseSystemAccess);
6487    eSystem_RegisterFunction("strtoul", "unsigned long strtoul(const char * nptr, char ** endptr, int base)", strtoul, module, baseSystemAccess);
6488    eSystem_RegisterFunction("strtoll", "int64 strtoll(const char * nptr, char ** endptr, int base)", strtoll, module, baseSystemAccess);
6489    eSystem_RegisterFunction("strtoull", "uint64 strtoull(const char * nptr, char ** endptr, int base)", strtoull, module, baseSystemAccess);
6490    eSystem_RegisterFunction("system", "int system(const char*)", system, module, baseSystemAccess);
6491    eSystem_RegisterFunction("atoi", "int atoi(const char*)", atoi, module, baseSystemAccess);
6492    eSystem_RegisterFunction("atof", "double atof(const char*)", atof, module, baseSystemAccess);
6493    eSystem_RegisterFunction("memset", "void * memset(void * area, int value, uintsize count)", memset, module, baseSystemAccess);
6494    eSystem_RegisterFunction("getenv", "char * getenv(const char * name)", getenv, module, baseSystemAccess);
6495    eSystem_RegisterFunction("rename", "int rename(const char *oldpath, const char *newpath)", rename, module, baseSystemAccess);
6496
6497    // --- String --- (These might move to the string class)
6498    eSystem_RegisterFunction("strlen", "uintsize strlen(const char *)", strlen, module, baseSystemAccess);
6499    eSystem_RegisterFunction("strcat", "char * strcat(char *, const char *)", strcat, module, baseSystemAccess);
6500    eSystem_RegisterFunction("strncat", "char * strncat(char *, const char *, uintsize n)", strncat, module, baseSystemAccess);
6501    eSystem_RegisterFunction("strchr", "char * strchr(const char *, int)", strchr, module, baseSystemAccess);
6502    eSystem_RegisterFunction("strstr", "char * strstr(const char *, const char *)", strstr, module, baseSystemAccess);
6503    eSystem_RegisterFunction("strspn", "uintsize strspn(const char *, const char *)", strspn, module, baseSystemAccess);
6504    eSystem_RegisterFunction("strcspn", "uintsize strcspn(const char *, const char *)", strcspn, module, baseSystemAccess);
6505    eSystem_RegisterFunction("strpbrk", "char * strpbrk(const char *, const char *)", strpbrk, module, baseSystemAccess);
6506
6507    eSystem_RegisterDefine("fstrcmp", "(__runtimePlatform == win32) ? strcmpi : strcmp", module, baseSystemAccess);
6508
6509 //#if defined(__GNUC__)
6510    eSystem_RegisterDefine("strcmpi", "strcasecmp", module, baseSystemAccess);
6511    eSystem_RegisterDefine("strnicmp", "strncasecmp", module, baseSystemAccess);
6512    eSystem_RegisterFunction("strcasecmp", "int strcasecmp(const char *, const char *)", strcmpi, module, baseSystemAccess);
6513    eSystem_RegisterFunction("strncasecmp", "int strncasecmp(const char *, const char *, uintsize n)", strnicmp, module, baseSystemAccess);
6514 /*
6515 #else
6516    eSystem_RegisterDefine("strcasecmp", "strcmpi", module, baseSystemAccess);
6517    eSystem_RegisterDefine("strncasecmp", "strnicmp", module, baseSystemAccess);
6518    eSystem_RegisterFunction("strcmpi", "int strcmpi(const char *, const char *)", strcmpi, module, baseSystemAccess);
6519    eSystem_RegisterFunction("strnicmp", "int strnicmp(const char *, const char *, int n)", strnicmp, module, baseSystemAccess);
6520 #endif
6521 */
6522
6523    eSystem_RegisterFunction("strcmp", "int strcmp(const char *, const char *)", strcmp, module, baseSystemAccess);
6524    eSystem_RegisterFunction("strncmp", "int strncmp(const char *, const char *, uintsize n)", strncmp, module, baseSystemAccess);
6525    eSystem_RegisterFunction("strlwr", "char * strlwr(char *)", strlwr, module, baseSystemAccess);
6526    eSystem_RegisterFunction("strupr", "char * strupr(char *)", strupr, module, baseSystemAccess);
6527    eSystem_RegisterFunction("strcpy", "char * strcpy(char *, const char *)", strcpy, module, baseSystemAccess);
6528    eSystem_RegisterFunction("strncpy", "char * strncpy(char *, const char *, uintsize n)", strncpy, module, baseSystemAccess);
6529    eSystem_RegisterFunction("memcpy", "void * memcpy(void *, const void *, uintsize size)", memcpy, module, baseSystemAccess);
6530    eSystem_RegisterFunction("memmove", "void * memmove(void *, const void *, uintsize size)", memmove, module, baseSystemAccess);
6531    eSystem_RegisterFunction("memcmp", "int memcmp(const void *, const void *, uintsize size)", memcmp, module, baseSystemAccess);
6532
6533    // --- Stdio ---
6534    eSystem_RegisterFunction("sprintf", "int sprintf(char *, const char *, ...)", sprintf, module, baseSystemAccess);
6535    eSystem_RegisterFunction("snprintf", "int sprintf(char *, uintsize, const char *, ...)", snprintf, module, baseSystemAccess);
6536    eSystem_RegisterFunction("printf", "int printf(const char *, ...)", printf, module, baseSystemAccess);
6537    eSystem_RegisterFunction("vsprintf", "int vsprintf(char*, const char*, __builtin_va_list)", vsprintf, module, baseSystemAccess);
6538    eSystem_RegisterFunction("vsnprintf", "int vsnprintf(char*, uintsize, const char*, __builtin_va_list)", vsnprintf, module, baseSystemAccess);
6539    eSystem_RegisterFunction("puts", "int puts(const char *)", puts, module, baseSystemAccess);
6540    eSystem_RegisterFunction("fputs", "int fputs(const char *, void * stream)", fputs, module, baseSystemAccess);
6541
6542    // --- Ctype ---
6543    eSystem_RegisterFunction("tolower", "int tolower(int)", tolower, module, baseSystemAccess);
6544    eSystem_RegisterFunction("toupper", "int toupper(int)", toupper, module, baseSystemAccess);
6545    eSystem_RegisterFunction("isdigit", "bool isdigit(int)", isdigit, module, baseSystemAccess);
6546    eSystem_RegisterFunction("isxdigit","bool isxdigit(int)", isxdigit, module, baseSystemAccess);
6547    eSystem_RegisterFunction("isalnum", "int isalnum(int c)", isalnum, module, baseSystemAccess);
6548    eSystem_RegisterFunction("isspace", "int isspace(int c)", isspace, module, baseSystemAccess);
6549    eSystem_RegisterFunction("isalpha", "int isalpha(int c)", isalpha, module, baseSystemAccess);
6550    eSystem_RegisterFunction("islower", "int islower(int c)", islower, module, baseSystemAccess);
6551    eSystem_RegisterFunction("isupper", "int isupper(int c)", isupper, module, baseSystemAccess);
6552    eSystem_RegisterFunction("isprint", "int isprint(int c)", isprint, module, baseSystemAccess);
6553    eSystem_RegisterFunction("isblank", "int isblank(int c)", isblank, module, baseSystemAccess);
6554
6555 }
6556
6557 public dllexport Application __ecere_COM_Initialize(bool guiApp, int argc, char * argv[])
6558 {
6559    Application app;
6560
6561 #ifdef __ANDROID__
6562    // Clean up global variables
6563    memoryInitialized = false;
6564    pools = null;
6565 #ifdef MEMINFO
6566    memset(&memStacks, 0, sizeof(BinaryTree));
6567    memoryErrorsCount = 0;
6568    memset(&memBlocks, 0, sizeof(BinaryTree));
6569    recurse = false;
6570    blockID = 0;
6571    allocateClass = null;
6572    allocateInternal = false;
6573    TOTAL_MEM = 0;
6574    OUTSIDE_MEM = 0;
6575 #endif
6576 #endif
6577
6578 #ifdef _DEBUG
6579    // printf("Using debug ecere runtime library\n");
6580 #endif
6581    app = _calloc(1, sizeof(class Application));
6582
6583    Module_Constructor(app);
6584    app.systemNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
6585    app.systemNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
6586    app.systemNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
6587    app.systemNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
6588
6589    Instance_COM_Initialize(argc, argv, &app.parsedCommand, &app.argc, &app.argv);
6590
6591    app.application = app;
6592    app.allModules.offset = sizeof(class Instance) + (uint)(uintptr)&((struct Module *)0)->prev;
6593    app.isGUIApp = guiApp;
6594
6595    LoadCOM(app);
6596
6597    app._class = eSystem_FindClass(app, "Application");
6598
6599    return app;
6600 }
6601
6602 public dllexport ClassTemplateParameter eClass_AddTemplateParameter(Class _class, const char * name, TemplateParameterType type, const void * info, ClassTemplateArgument defaultArg)
6603 {
6604    if(_class && name)
6605    {
6606       ClassTemplateParameter param;
6607
6608       for(param = _class.templateParams.first; param; param = param.next)
6609       {
6610          if(!strcmp(param.name, name))
6611             return param;
6612       }
6613       param =
6614       {
6615          name = CopyString(name);
6616          type = type;
6617          (type == identifier) ? info : CopyString(info);
6618       };
6619       if(defaultArg != null)
6620       {
6621          param.defaultArg = defaultArg;
6622          CopyTemplateArg(param, param.defaultArg);
6623       }
6624       _class.templateParams.Add(param);
6625       return param;
6626    }
6627    return null;
6628 }
6629
6630 public dllexport void eClass_DoneAddingTemplateParameters(Class base)
6631 {
6632    if(base)
6633    {
6634       ClassTemplateParameter param;
6635       {
6636          void * first = base.templateParams.first;
6637          int count = base.templateParams.count;
6638
6639          FreeTemplateArgs(base);
6640          delete base.templateArgs;
6641
6642          base.templateParams.first = null;
6643          base.templateParams.count = 0;
6644
6645          FreeTemplatesDerivatives(base);
6646
6647          base.templateParams.first = first;
6648          base.templateParams.count = count;
6649       }
6650
6651       for(param = base.templateParams.first; param; param = param.next)
6652       {
6653          if(param.type == identifier && param.defaultArg.memberString)
6654          {
6655             Class memberClass = base;
6656             const char * colon = strstr(param.defaultArg.memberString, "::");
6657             const char * memberName;
6658             if(colon)
6659             {
6660                char className[1024];
6661                Class sClass;
6662
6663                memcpy(className, param.defaultArg.memberString, colon - param.defaultArg.memberString);
6664                className[colon - param.defaultArg.memberString] = '\0';
6665                memberName = colon + 2;
6666
6667                for(sClass = base; sClass; sClass = sClass.base)
6668                {
6669                   ClassTemplateParameter cParam;
6670                   Class nextClass;
6671                   int id = 0;
6672                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) id += nextClass.templateParams.count;
6673                   // Safety! What could cause base.templateArgs to be null?
6674                   if(sClass == base || base.templateArgs)
6675                   {
6676                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
6677                      {
6678                         if(cParam.type == type && !strcmp(cParam.name, className))
6679                            strcpy(className, (sClass == base) ? cParam.defaultArg.dataTypeString : base.templateArgs[id].dataTypeString);
6680                         id++;
6681                      }
6682                   }
6683                }
6684                memberClass = eSystem_FindClass(base.module, className);
6685                if(!memberClass)
6686                   memberClass = eSystem_FindClass(base.module.application, className);
6687             }
6688             else
6689                memberName = param.defaultArg.memberString;
6690
6691             if(memberClass)
6692             {
6693                switch(param.memberType)
6694                {
6695                   case dataMember:
6696                      param.defaultArg.member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
6697                      break;
6698                   case method:
6699                      param.defaultArg.method = eClass_FindMethod(memberClass, memberName, memberClass.module);
6700                      break;
6701                   case prop:
6702                      param.defaultArg.prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
6703                      break;
6704                }
6705             }
6706          }
6707       }
6708
6709       //ComputeClassParameters(base, null, null);
6710
6711       FixDerivativesBase(base, base);
6712    }
6713 }
6714
6715 static void FreeTemplatesDerivatives(Class base)
6716 {
6717    OldLink derivative, templateLink;
6718    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
6719    {
6720       Class _class = derivative.data;
6721       if(_class.templateArgs)
6722       {
6723          FreeTemplateArgs(_class);
6724          delete _class.templateArgs;
6725       }
6726       FreeTemplatesDerivatives(_class);
6727    }
6728
6729    for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
6730    {
6731       Class _class = templateLink.data;
6732       if(_class.templateArgs)
6733       {
6734          FreeTemplateArgs(_class);
6735          delete _class.templateArgs;
6736       }
6737       FreeTemplatesDerivatives(_class);
6738    }
6739 }
6740
6741 static const char * platformNames[Platform] = { "", "win32", "linux", "apple" }; // how to have this be accessible outside of dll/lib
6742 static const Platform firstPlatform = win32;
6743 static const Platform lastPlatform = apple;
6744
6745 public enum Platform
6746 {
6747    unknown, win32, tux, apple;
6748
6749    property const char *
6750    {
6751       get { return OnGetString(null, null, null); }
6752       set
6753       {
6754          if(value)
6755          {
6756             Platform c;
6757             for(c = firstPlatform; c <= lastPlatform; c++)
6758                if(!strcmpi(value, platformNames[c]))
6759                   return c;
6760          }
6761          return unknown;
6762       }
6763    };
6764
6765    const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
6766    {
6767       if(this >= firstPlatform && this <= lastPlatform)
6768       {
6769          if(tempString)
6770             strcpy(tempString, platformNames[this]);
6771          return platformNames[this];
6772       }
6773       if(tempString && tempString[0])
6774          tempString[0] = '\0';
6775       return null;
6776    }
6777
6778    bool OnGetDataFromString(const char * string)
6779    {
6780       this = string;
6781       return this != unknown;
6782    }
6783 };
6784
6785 default extern Platform runtimePlatform;
6786
6787 public Platform GetRuntimePlatform()
6788 {
6789    return runtimePlatform;
6790 }
6791
6792 namespace gui;
6793
6794 class Window;
6795
6796 namespace com;
6797 // CLASS DESIGNER SUPPORT
6798
6799 public class ObjectInfo : struct
6800 {
6801 public:
6802    ObjectInfo prev, next;
6803    Instance instance;
6804    char * name;
6805    Instantiation instCode;
6806    bool deleted;
6807    ObjectInfo oClass;
6808    OldList instances;
6809    ClassDefinition classDefinition;
6810    bool modified;
6811    void * i18nStrings;
6812 };
6813
6814 public class DesignerBase : Window
6815 {
6816 public:
6817    virtual bool FindObject(Instance * instance, const char * string);
6818    virtual void RenameObject(ObjectInfo object, const char * name);
6819    virtual void SelectObjectFromDesigner(ObjectInfo object);
6820    virtual void CodeAddObject(Instance instance, ObjectInfo * object);
6821    virtual void SheetAddObject(ObjectInfo object);
6822    virtual void AddToolBoxClass(Class _class);
6823    virtual void AddDefaultMethod(Instance instance, Instance classInstance);
6824    virtual void DeleteObject(ObjectInfo object);
6825    virtual bool ObjectContainsCode(ObjectInfo object);
6826    virtual void ModifyCode(void);
6827    virtual void UpdateProperties(void);
6828
6829    ClassDesignerBase classDesigner;
6830    const char * objectClass;
6831    bool isDragging;
6832
6833    // FIX THIS WITH PUBLIC:
6834    property ClassDesignerBase classDesigner
6835    {
6836       get { return classDesigner; }
6837       set { classDesigner = value; }
6838    };
6839    property const char * objectClass
6840    {
6841       get { return objectClass; }
6842       set { objectClass = value; }
6843    };
6844    property bool isDragging
6845    {
6846       get { return isDragging; }
6847       set { isDragging = value; }
6848    };
6849 }
6850
6851 public class ClassDesignerBase : Window
6852 {
6853 public:
6854    virtual void Reset(void);
6855    virtual void AddObject(void);
6856    virtual void SelectObject(ObjectInfo object, Instance control);
6857
6858    virtual void ListToolBoxClasses(DesignerBase designer);
6859
6860    virtual void ::PrepareTestObject(DesignerBase designer, Instance test);
6861    virtual void ::CreateObject(DesignerBase designer, Instance instance, ObjectInfo object, bool isClass, Instance _class);
6862    virtual void ::PostCreateObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6863    virtual void ::DroppedObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6864    virtual void ::DestroyObject(Instance object);
6865    virtual void ::FixProperty(Property prop, Instance object);
6866    virtual void ::CreateNew(EditBox editBox, Size clientSize, const char * name, const char * inherit);
6867 }
6868
6869 DesignerBase activeDesigner;
6870
6871 public void SetActiveDesigner(DesignerBase designer)
6872 {
6873    activeDesigner = designer;
6874 }
6875
6876 public DesignerBase GetActiveDesigner()
6877 {
6878    return activeDesigner;
6879 }
6880
6881
6882 bool poolingDisabled;
6883
6884 public dllexport void eSystem_SetPoolingDisabled(bool disabled)
6885 {
6886    poolingDisabled = disabled;
6887 }
6888
6889 namespace sys;
6890
6891 // constants
6892 define LEAD_OFFSET      = 0xD800 - (0x10000 >> 10);
6893 define SURROGATE_OFFSET = 0x10000 - (0xD800 << 10) - 0xDC00;
6894
6895 public bool UTF8Validate(const char * source)
6896 {
6897    if(source)
6898    {
6899       int c;
6900       for(c = 0; source[c];)
6901       {
6902          byte ch = source[c];
6903          unichar codePoint = 0;
6904          int numBytes = 1;
6905          int i;
6906          byte mask = 0x7F;
6907          if(ch & 0x80)
6908          {
6909             if(ch & 0x40)
6910             {
6911                mask >>= 2;
6912                numBytes++;
6913                if(ch & 0x20)
6914                {
6915                   numBytes++;
6916                   mask >>= 1;
6917                   if(ch & 0x10)
6918                   {
6919                      if(ch & 0x08)
6920                         return false;
6921                      numBytes++;
6922                      mask >>= 1;
6923                   }
6924                }
6925             }
6926             else
6927                return false;
6928          }
6929          for(i = 0; i<numBytes && (ch = source[c]); i++, c++)
6930          {
6931             codePoint <<= 6;
6932             codePoint |= ch & mask;
6933             mask = 0x3F;
6934             if(i > 1)
6935             {
6936                if(!(ch & 0x80) || (ch & 0x40))
6937                   return false;
6938             }
6939          }
6940          if(i < numBytes) return false;
6941
6942          if(codePoint > 0x10FFFF || (codePoint >= 0xD800 && codePoint <= 0xDFFF) ||
6943            (codePoint < 0x80 && numBytes > 1) ||
6944            (codePoint < 0x800 && numBytes > 2) ||
6945            (codePoint < 0x10000 && numBytes > 3))
6946             return false;
6947       }
6948    }
6949    return true;
6950 }
6951
6952 public int ISO8859_1toUTF8(const char * source, char * dest, int max)
6953 {
6954    int c;
6955    int d = 0;
6956    byte * byteDest = (byte *)dest;
6957    for(c = 0; source[c]; c++)
6958    {
6959       unichar ch = ((byte *)source)[c];
6960       switch(ch)
6961       {
6962          case 150: ch = (unichar)0x2012; break;
6963       }
6964       if(ch < 0x80)
6965       {
6966          if(d + 1 >= max) break;
6967          byteDest[d++] = (char)ch;
6968       }
6969       else if(ch < 0x800)
6970       {
6971          if(d + 2 >= max) break;
6972          byteDest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6973          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
6974       }
6975       else if(ch < 0x10000)
6976       {
6977          if(d + 3 >= max) break;
6978          byteDest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6979          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6980          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
6981       }
6982       else
6983       {
6984          if(d + 4 >= max) break;
6985          byteDest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6986          byteDest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6987          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6988          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
6989       }
6990    }
6991    dest[d] = 0;
6992    return d;
6993 }
6994
6995 public char * UTF16toUTF8(const uint16 * source)
6996 {
6997    int c;
6998    int d = 0;
6999    int len;
7000    byte * dest;
7001    uint16 u16;
7002    bool invert = false;
7003
7004    for(len = 0; source[len]; len++);
7005    dest = new byte[len * 3 + 1];
7006    for(c = 0; (u16 = source[c]); c++)
7007    {
7008       unichar ch;
7009       if(!c && (u16 == 0xFFFE || u16 == 0xFEFF))
7010       {
7011          if(u16 == 0xFFFE) invert = true;
7012          continue;
7013       }
7014       if(invert) { u16 = ((u16 & 0xFF00) >> 8) | ((u16 & 0x00FF) << 8); }
7015
7016       if(u16 < 0xD800 || u16 > 0xDBFF)
7017          ch = (unichar)u16;
7018       else
7019          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
7020
7021       if(ch < 0x80)
7022       {
7023          dest[d++] = (char)ch;
7024       }
7025       else if(ch < 0x800)
7026       {
7027          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
7028          dest[d++] = 0x80 | (byte)(ch & 0x03F);
7029       }
7030       else if(ch < 0x10000)
7031       {
7032          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
7033          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7034          dest[d++] = 0x80 | (byte)(ch & 0x03F);
7035       }
7036       else
7037       {
7038          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
7039          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
7040          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7041          dest[d++] = 0x80 | (byte)(ch & 0x03F);
7042       }
7043    }
7044    dest[d] = 0;
7045    dest = renew dest byte[d+1];
7046    return (char *)dest;
7047 }
7048
7049 public int UTF16toUTF8Buffer(const uint16 * source, char * dest, int max)
7050 {
7051    int c;
7052    int d = 0;
7053    uint16 u16;
7054    byte * byteDest = (byte *)dest;
7055    for(c = 0; (u16 = source[c]); c++)
7056    {
7057       unichar ch;
7058       if(u16 < 0xD800 || u16 > 0xDBFF)
7059          ch = (unichar)u16;
7060       else
7061          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
7062
7063       if(ch < 0x80)
7064       {
7065          if(d + 1 >= max) break;
7066          byteDest[d++] = (char)ch;
7067       }
7068       else if(ch < 0x800)
7069       {
7070          if(d + 2 >= max) break;
7071          byteDest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
7072          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7073       }
7074       else if(ch < 0x10000)
7075       {
7076          if(d + 3 >= max) break;
7077          byteDest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
7078          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7079          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7080       }
7081       else
7082       {
7083          if(d + 4 >= max) break;
7084          byteDest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
7085          byteDest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
7086          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7087          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7088       }
7089    }
7090    byteDest[d] = 0;
7091    return d;
7092 }
7093
7094 // NOTE: UTF8GetChar now returns 0 into numBytes for the null-terminating character ('\0')
7095 public unichar UTF8GetChar(const char * string, int * numBytes)
7096 {
7097    unichar ch;
7098    byte b = ((byte *)string)[0];
7099    int i;
7100    byte mask = 0x7F;
7101    int nb = b ? 1 : 0;
7102    ch = 0;
7103    if(b & 0x80)
7104    {
7105       if(b & 0x40)
7106       {
7107          mask >>= 2;
7108          nb++;
7109          if(b & 0x20)
7110          {
7111             nb++;
7112             mask >>= 1;
7113             if(b & 0x10)
7114             {
7115                if(b & 0x08) { nb = 0; }
7116                nb++;
7117                mask >>= 1;
7118             }
7119          }
7120       }
7121       else
7122          nb = 0;
7123    }
7124    for(i = 0; i<nb; i++)
7125    {
7126       ch <<= 6;
7127       ch |= (b = ((byte *)string)[i]) & mask;
7128       mask = 0x3F;
7129       if(i > 1 && (!(b & 0x80) || (b & 0x40)))
7130       {
7131          nb = 0;
7132          ch = 0;
7133       }
7134    }
7135
7136    if(i < nb ||
7137       ch > 0x10FFFF || (ch >= 0xD800 && ch <= 0xDFFF) ||
7138      (ch < 0x80 && nb > 1) ||
7139      (ch < 0x800 && nb > 2) ||
7140      (ch < 0x10000 && nb > 3))
7141    {
7142       ch = 0;
7143       nb = 0;
7144    }
7145    if(numBytes) *numBytes = nb;
7146    return ch;
7147 }
7148
7149 public int UTF8toUTF16Buffer(const char * source, uint16 * dest, int max)
7150 {
7151    if(source)
7152    {
7153       int c;
7154       int d = 0;
7155       for(c = 0; source[c];)
7156       {
7157          byte ch = source[c];
7158          unichar codePoint = 0;
7159          int numBytes = 1;
7160          int i;
7161          byte mask = 0x7F;
7162          if(ch & 0x80 && ch & 0x40)
7163          {
7164             mask >>= 2;
7165             numBytes++;
7166             if(ch & 0x20)
7167             {
7168                numBytes++;
7169                mask >>= 1;
7170                if(ch & 0x10)
7171                {
7172                   numBytes++;
7173                   mask >>= 1;
7174                }
7175             }
7176          }
7177          for(i = 0; i<numBytes; i++)
7178          {
7179             codePoint <<= 6;
7180             codePoint |= source[c++] & mask;
7181             mask = 0x3F;
7182          }
7183
7184          if(codePoint > 0xFFFF)
7185          {
7186             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
7187             uint16 trail = (uint16)(0xDC00 | (codePoint & 0x3FF));
7188             if(d >= max - 1) break;
7189             dest[d++] = lead;
7190             dest[d++] = trail;
7191          }
7192          else
7193          {
7194             if(d >= max) break;
7195             dest[d++] = (uint16)codePoint;
7196          }
7197       }
7198       dest[d] = 0;
7199       return d;
7200    }
7201    return 0;
7202 }
7203
7204 public int UTF32toUTF8Len(const unichar * source, int count, char * dest, int max)
7205 {
7206    int c;
7207    int d = 0;
7208    uint32 ch;
7209    byte * byteDest = (byte *)dest;
7210    for(c = 0; c<count && (ch = source[c]); c++)
7211    {
7212       if(ch < 0x80)
7213       {
7214          if(d + 1 >= max) break;
7215          byteDest[d++] = (char)ch;
7216       }
7217       else if(ch < 0x800)
7218       {
7219          if(d + 2 >= max) break;
7220          byteDest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
7221          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7222       }
7223       else if(ch < 0x10000)
7224       {
7225          if(d + 3 >= max) break;
7226          byteDest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
7227          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7228          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7229       }
7230       else
7231       {
7232          if(d + 4 >= max) break;
7233          byteDest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
7234          byteDest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
7235          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7236          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7237       }
7238    }
7239    byteDest[d] = 0;
7240    return d;
7241 }
7242
7243 public uint16 * UTF8toUTF16(const char * source, int * wordCount)
7244 {
7245    if(source)
7246    {
7247       int len = (int)strlen(source);
7248       uint16 * dest = new uint16[len + 1];
7249       int c;
7250       int d = 0;
7251       for(c = 0; source[c];)
7252       {
7253          byte ch = source[c];
7254          unichar codePoint = 0;
7255          int numBytes = 1;
7256          int i;
7257          byte mask = 0x7F;
7258          if(ch & 0x80 && ch & 0x40)
7259          {
7260             mask >>= 2;
7261             numBytes++;
7262             if(ch & 0x20)
7263             {
7264                numBytes++;
7265                mask >>= 1;
7266                if(ch & 0x10)
7267                {
7268                   numBytes++;
7269                   mask >>= 1;
7270                }
7271             }
7272          }
7273          for(i = 0; i<numBytes; i++)
7274          {
7275             codePoint <<= 6;
7276             codePoint |= source[c++] & mask;
7277             mask = 0x3F;
7278          }
7279
7280          if(codePoint > 0xFFFF)
7281          {
7282             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
7283             uint16 trail = (uint16)(0xDC00 | (codePoint & 0x3FF));
7284             dest[d++] = lead;
7285             dest[d++] = trail;
7286          }
7287          else
7288          {
7289             dest[d++] = (uint16)codePoint;
7290          }
7291       }
7292       dest[d] = 0;
7293       if(wordCount) *wordCount = d;
7294       return dest;
7295    }
7296    return null;
7297 }
7298
7299 namespace com;
7300
7301 #if defined(_DEBUG) && !defined(MEMINFO) && defined(MEMTRACKING)
7302 import "Map"
7303
7304 Map<Class, int> blocksByClass { };
7305 Map<Class, uintsize> sizeByClass { };
7306 #endif
7307
7308 public void queryMemInfo(char * string)
7309 {
7310 #if defined(_DEBUG) && !defined(MEMINFO) && defined(MEMTRACKING)
7311    char s[1024];
7312    int p;
7313    uint numBlocks = 0;
7314    uintsize totalMemUsed = 0;
7315    sprintf(s, "Total System Memory Usage: %.02f\n", TOTAL_MEM / 1048576.0f);
7316    strcat(string, s);
7317
7318    for(p = 0; pools && p < NUM_POOLS; p++)
7319    {
7320       BlockPool * pool = &pools[p];
7321       if(pool->totalSize)
7322       {
7323          numBlocks += pool->totalSize;
7324          sprintf(s, "%8d bytes: %d blocks in %d parts (%.02f mb used; taking up %.02f mb space)\n",
7325             pool->blockSize, pool->numBlocks, pool->numParts, pool->usedSpace / 1048576.0f, pool->totalSize * pool->blockSpace / 1048576.0f);
7326          totalMemUsed += pool->usedSpace;
7327          strcat(string, s);
7328       }
7329    }
7330
7331
7332    blocksByClass.Free();
7333    sizeByClass.Free();
7334 #if !defined(__EMSCRIPTEN__)
7335    memMutex.Wait();
7336 #endif
7337    for(p = 0; pools && p < NUM_POOLS; p++)
7338    {
7339       BlockPool * pool = &pools[p];
7340       MemBlock block;
7341       for(block = pool->first; block; block = block.next)
7342       {
7343          Class c = block._class;
7344          blocksByClass[c]++;
7345          sizeByClass[c] += block.size;
7346       }
7347    }
7348 #if !defined(__EMSCRIPTEN__)
7349    memMutex.Release();
7350 #endif
7351
7352    //for(c : blocksByClass)
7353    {
7354       MapIterator<Class, int> it { map = blocksByClass };
7355       while(it.Next())
7356       {
7357          int c = it.data;
7358          Class _class = it.key; //&c;
7359          uintsize size = sizeByClass[_class];
7360          float totalSize = (float) size / 1048576.0f;
7361          if(totalSize > 1)
7362          {
7363             sprintf(s, "%s (%d bytes): %d instances (%.02f mb used)\n", _class ? _class.name : "(none)", (int)size, c, totalSize);
7364             strcat(string, s);
7365          }
7366       }
7367    }
7368
7369    sprintf(s, "Non-pooled memory: %.02f\n", OUTSIDE_MEM / 1048576.0f);
7370    strcat(string, s);
7371    sprintf(s, "Total Memory in use: %.02f\n", (float)(totalMemUsed + OUTSIDE_MEM) / 1048576.0f);
7372    strcat(string, s);
7373
7374    sprintf(s, "Total Blocks Count: %d (%.02f mb overhead)\n", numBlocks, (float)sizeof(struct MemBlock) * numBlocks / 1048576.0f);
7375    strcat(string, s);
7376 #ifdef MEMORYGUARD
7377    sprintf(s, "MemoryGuard: %d blocks (%.02f mb RedZone, %.02f mb MemInfo)\n", memBlocks.count,
7378       numBlocks * 2 * REDZONE / 1048576.0f, sizeof(struct MemInfo) * memBlocks.count / 1048576.0f);
7379    strcat(string, s);
7380 #endif
7381 #endif
7382 }