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