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