ecere/drivers/Android: Tweaks to run with latest Android SDK/NDK on Nexus 9
[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    _free(template);
2995 }
2996
2997 static void FreeTemplates(Class _class)
2998 {
2999    OldLink deriv, template;
3000
3001    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
3002    {
3003       FreeTemplates(deriv.data);
3004    }
3005
3006    FreeTemplateArgs(_class);
3007    //if(_class.templateArgs)
3008       //printf("Deleting  Template args for %s\n", _class.name);
3009    delete _class.templateArgs;
3010    delete (void *)_class.dataTypeString;
3011
3012    while((template = _class.templatized.first))
3013    {
3014       FreeTemplates(template.data);
3015       FreeTemplate(template.data);
3016       _class.templatized.Delete(template);
3017    }
3018 }
3019
3020 public dllexport void eClass_Unregister(Class _class)
3021 {
3022    BTNamedLink namedLink;
3023    DataMember member;
3024    Method method;
3025    OldLink deriv, template;
3026    ClassProperty classProp;
3027    ClassTemplateParameter param;
3028
3029    if(_class.templateClass)
3030    {
3031       // Unregistering templates... Used in IDE to address crash on Ecere classes templatized with imported modules
3032       OldLink templateLink;
3033       for(templateLink = _class.templateClass.templatized.first; templateLink; templateLink = templateLink.next)
3034       {
3035          if(templateLink.data == _class)
3036          {
3037             _class.templateClass.templatized.Delete(templateLink);
3038             break;
3039          }
3040       }
3041       FreeTemplate(_class);
3042       return;
3043    }
3044
3045    delete _class._vTbl;
3046
3047    FreeTemplates(_class);
3048
3049    FreeTemplateArgs(_class);
3050    delete _class.templateArgs;
3051
3052    while((template = _class.templatized.first))
3053    {
3054       FreeTemplate(template.data);
3055       _class.templatized.Delete(template);
3056    }
3057
3058    while((member = _class.membersAndProperties.first))
3059    {
3060       if(!member.isProperty && (member.type == unionMember || member.type == structMember))
3061          DataMember_Free(member);
3062       delete (void *)member.name;
3063       delete (void *)member.dataTypeString;
3064       _class.membersAndProperties.Delete(member);
3065    }
3066
3067    while((member = _class.conversions.first))
3068    {
3069       delete (void *)member.name;
3070       delete (void *)member.dataTypeString;
3071       _class.conversions.Delete(member);
3072    }
3073
3074    while((namedLink = (BTNamedLink)_class.prop.first))
3075    {
3076       _class.prop.Delete((BTNode)namedLink);
3077    }
3078
3079    while((namedLink = (BTNamedLink)_class.members.first))
3080    {
3081       _class.members.Delete((BTNode)namedLink);
3082    }
3083
3084    while((classProp = (ClassProperty)_class.classProperties.first))
3085    {
3086       delete (void *)classProp.name;
3087       delete (void *)classProp.dataTypeString;
3088       _class.classProperties.Delete((BTNode)classProp);
3089    }
3090
3091    while((method = (Method)_class.methods.first))
3092    {
3093       delete (void *)method.name;
3094       delete (void *)method.dataTypeString;
3095       _class.methods.Delete((BTNode)method);
3096    }
3097
3098    if(_class.type == enumClass)
3099    {
3100       EnumClassData data = (EnumClassData)_class.data;
3101
3102       data.values.Free((void *)FreeEnumValue);
3103    }
3104    _class.delayedCPValues.Free(null);
3105
3106    _class.selfWatchers.Free(null);
3107
3108    if(_class.base)
3109    {
3110       // Class base = _class.base.templateClass ? _class.base.templateClass : _class.base;
3111       Class base = _class.base;
3112       for(deriv = base.derivatives.first; deriv; deriv = deriv.next)
3113       {
3114          if(deriv.data == _class)
3115             break;
3116       }
3117       if(deriv)
3118          base.derivatives.Delete(deriv);
3119    }
3120    while((deriv = _class.derivatives.first))
3121    {
3122       ((Class)deriv.data).base = null;
3123       _class.derivatives.Delete(deriv);
3124    }
3125
3126    if(_class.nameSpace)
3127    {
3128       BTNamedLink link = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
3129       _class.nameSpace->classes.Delete((BTNode)link);
3130    }
3131
3132    delete (void *)_class.name;
3133    delete (void *)_class.fullName;
3134
3135    delete (void *)_class.dataTypeString;
3136
3137    delete _class.data;
3138
3139    while((param = _class.templateParams.first))
3140    {
3141       switch(param.type)
3142       {
3143          case type:
3144             delete (void *)param.defaultArg.dataTypeString;
3145             break;
3146          case identifier:
3147             delete (void *)param.defaultArg.memberString;
3148             break;
3149          case expression:
3150
3151             break;
3152       }
3153       if(param.type != identifier) delete (void *)param.dataTypeString;
3154       delete (void *)param.name;
3155
3156       _class.templateParams.Delete(param);
3157    }
3158
3159    //_class.nameSpace->classes.Delete(_class);
3160    _free(_class);
3161 }
3162
3163 static BTNamedLink ScanNameSpace(NameSpace nameSpace, const char * name, void * listOffset)
3164 {
3165    BinaryTree * tree = (BinaryTree *)((byte *)nameSpace + (uintptr)listOffset);
3166    BTNamedLink link = (BTNamedLink)tree->Find((uintptr)name);
3167    NameSpace * child;
3168    if(!link)
3169    {
3170       for(child = (NameSpace *)nameSpace.nameSpaces.first; child; child = (NameSpace *)((BTNode)child).next)
3171       {
3172          link = ScanNameSpace(child, name, listOffset);
3173          if(link)
3174             break;
3175       }
3176    }
3177    return link;
3178 }
3179
3180 static BTNamedLink SearchNameSpace(NameSpace nameSpace, const char * name, void * listOffset)
3181 {
3182    int start = 0, c;
3183    char ch;
3184    int level = 0;
3185    for(c = 0; (ch = name[c]); c++)
3186    {
3187       if(ch == '<') level++;
3188       if(ch == '>') level--;
3189       if(level == 0 && (ch == '.' || (ch == ':' && name[c+1] == ':')))
3190       {
3191          NameSpace * newSpace;
3192          char * spaceName = _malloc(c - start + 1);
3193          memcpy(spaceName, name + start, c - start);
3194          spaceName[c-start] = '\0';
3195          newSpace = (NameSpace *)nameSpace.nameSpaces.FindString(spaceName);
3196          _free(spaceName);
3197          if(!newSpace)
3198             return null;
3199          nameSpace = newSpace;
3200          if(level == 0 && ch == ':') c++;
3201          start = c+1;
3202       }
3203    }
3204    if(c - start)
3205    {
3206       return ScanNameSpace(nameSpace, name + start, listOffset);
3207    }
3208    return null;
3209 }
3210
3211 static BTNamedLink SearchModule(Module module, const char * name, void * listOffset, bool searchPrivate)
3212 {
3213    SubModule subModule;
3214    BTNamedLink link;
3215
3216    if(searchPrivate)
3217    {
3218       link = SearchNameSpace(&module.privateNameSpace, name, listOffset);
3219       if(link) return link;
3220    }
3221    link = SearchNameSpace(&module.publicNameSpace, name, listOffset);
3222    if(link) return link;
3223
3224    for(subModule = module.modules.first; subModule; subModule = subModule.next)
3225    {
3226       if(searchPrivate || subModule.importMode == publicAccess)
3227       {
3228          // TOCHECK: Reverting to false to test what we were trying to fix by passing searchPrivate
3229          // Passing searchPrivate finds ALL classes private or not and thus classes clash
3230          // SearchModule here is called mainly from eSystem_FindClass, and also for Functions and Defines
3231
3232          link = SearchModule(subModule.module, name, listOffset, false);
3233          //link = SearchModule(subModule.module, name, listOffset, searchPrivate /*false*/);
3234          if(link) return link;
3235       }
3236    }
3237    return null;
3238 }
3239
3240 public int64 _strtoi64(const char * string, const char ** endString, int base)
3241 {
3242    int64 value = 0;
3243    int sign = 1;
3244    int c;
3245    char ch;
3246    for(c = 0; (ch = string[c]) && isspace(ch); c++);
3247    if(ch =='+') c++;
3248    else if(ch == '-') { sign = -1; c++; };
3249    if(!base)
3250    {
3251       if(ch == '0' && string[c+1] == 'x')
3252       {
3253          base = 16;
3254          c+=2;
3255       }
3256       else if(ch == '0')
3257       {
3258          base = 8;
3259          c++;
3260       }
3261       else
3262          base = 10;
3263    }
3264    for( ;(ch = string[c]); c++)
3265    {
3266       if(ch >= '0' && ch <= '9')
3267          ch -= '0';
3268       else if(ch >= 'a' && ch <= 'z')
3269          ch -= ('a' - 10);
3270       else if(ch >= 'A' && ch <= 'Z')
3271          ch -= ('A'- 10);
3272       else
3273       {
3274          if(endString)
3275             *endString = string + c;
3276          // Invalid character
3277          break;
3278       }
3279       if(ch < base)
3280       {
3281          value *= base;
3282          value += ch;
3283       }
3284       else
3285       {
3286          if(endString)
3287             *endString = string + c;
3288          // Invalid character
3289          break;
3290       }
3291    }
3292    return sign*value;
3293 }
3294
3295 public uint64 _strtoui64(const char * string, const char ** endString, int base)
3296 {
3297    uint64 value = 0;
3298    int sign = 1;
3299    int c;
3300    char ch;
3301    for(c = 0; (ch = string[c]) && isspace(ch); c++);
3302    if(ch =='+') c++;
3303    else if(ch == '-') { sign = -1; c++; };
3304    if(!base)
3305    {
3306       if(ch == '0' && string[c+1] == 'x')
3307       {
3308          base = 16;
3309          c+=2;
3310       }
3311       else if(ch == '0')
3312       {
3313          base = 8;
3314          c++;
3315       }
3316       else
3317          base = 10;
3318    }
3319    for( ;(ch = string[c]); c++)
3320    {
3321       if(ch >= '0' && ch <= '9')
3322          ch -= '0';
3323       else if(ch >= 'a' && ch <= 'z')
3324          ch -= ('a' - 10);
3325       else if(ch >= 'A' && ch <= 'Z')
3326          ch -= ('A' - 10);
3327       else
3328       {
3329          if(endString)
3330             *endString = string + c;
3331          // Invalid character
3332          break;
3333       }
3334       if(ch < base)
3335       {
3336          value *= base;
3337          value += ch;
3338       }
3339       else
3340       {
3341          if(endString)
3342             *endString = string + c;
3343          // Invalid character
3344          break;
3345       }
3346    }
3347    return sign*value;
3348 }
3349
3350 public dllexport Class eSystem_FindClass(Module module, const char * name)
3351 {
3352    if(name && module)
3353    {
3354       BTNamedLink link;
3355       if(!strncmp(name, "const ", 6)) name += 6;
3356       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->classes);
3357       if(link) return link.data;
3358
3359       link = SearchModule(module, name, &((NameSpace *)0)->classes, true);
3360       if(link) return link.data;
3361
3362       {
3363          char noTemplateName[1024];
3364          char * templateParams = strchr(name, '<');
3365
3366          if(templateParams)
3367          {
3368             strncpy(noTemplateName, name, templateParams - name);
3369             noTemplateName[templateParams - name] = '\0';
3370          }
3371          else
3372             strcpy(noTemplateName, name);
3373
3374          link = SearchNameSpace(&module.application.systemNameSpace, noTemplateName, &((NameSpace *)0)->classes);
3375          if(!link)
3376             link = SearchModule(module, noTemplateName, &((NameSpace *)0)->classes, true);
3377          if(link)
3378          {
3379             Class _class = link.data;
3380             Class templatedClass = null;
3381             char className[1024];
3382             strcpy(className, _class.fullName);
3383             strcat(className, templateParams);
3384
3385             link = SearchNameSpace(&module.application.systemNameSpace, className, &((NameSpace *)0)->classes);
3386             if(link)
3387                return link.data;
3388
3389             link = SearchModule(module, className, &((NameSpace *)0)->classes, true);
3390             if(link)
3391                return link.data;
3392
3393             if(_class && templateParams)
3394             {
3395                // if(!numParams) return null;
3396
3397                templatedClass = Class { };
3398                *templatedClass = *_class;
3399                templatedClass.templateClass = _class;
3400                //templatedClass.fullName = CopyString(name);
3401                templatedClass.fullName = CopyString(className);
3402                templatedClass.dataTypeString = CopyString(_class.dataTypeString);
3403                templatedClass.name = CopyString(templatedClass.fullName + strlen(_class.fullName) - strlen(_class.name));
3404                templatedClass.nameSpace->classes.Add((BTNode)BTNamedLink { name = (char *)templatedClass.name, data = templatedClass });
3405                templatedClass.templateArgs = null;
3406                templatedClass.numParams = 0;
3407                templatedClass.derivatives = { };
3408                templatedClass.templatized = { };
3409
3410                ComputeClassParameters(templatedClass, templateParams, module);
3411
3412                _class.templatized.Add(OldLink { data = templatedClass });
3413             }
3414             return templatedClass;
3415          }
3416       }
3417    }
3418    return null;
3419 }
3420
3421 static void CopyTemplateArg(ClassTemplateParameter param, ClassTemplateArgument arg)
3422 {
3423    switch(param.type)
3424    {
3425       case type:
3426          arg.dataTypeString = CopyString(arg.dataTypeString);
3427          break;
3428       case expression:
3429
3430          break;
3431       case identifier:
3432          arg.memberString = CopyString(arg.memberString);
3433          break;
3434    }
3435 }
3436
3437 static void ComputeClassParameters(Class templatedClass, const char * templateParams, Module findModule)
3438 {
3439    char ch;
3440    const char * nextParamStart = templateParams ? (templateParams + 1) : null;
3441    ClassTemplateParameter curParam = null;
3442    Class lastClass = null, sClass;
3443    int curParamID = 0;
3444    int numParams = 0;
3445    Class _class = templatedClass.templateClass ? templatedClass.templateClass : templatedClass;
3446
3447    for(sClass = _class; sClass; sClass = sClass.base)
3448    {
3449       if(sClass.templateClass) sClass = sClass.templateClass;
3450       numParams += sClass.templateParams.count;
3451    }
3452
3453    if(templatedClass.templateArgs)
3454       FreeTemplateArgs(templatedClass);
3455    delete templatedClass.templateArgs;
3456    templatedClass.templateArgs = new0 ClassTemplateArgument[numParams];
3457    templatedClass.numParams = numParams;
3458
3459    if(_class != templatedClass)
3460    {
3461       /*int c;
3462       Class sClass;
3463       memcpy(templatedClass.templateArgs, _class.templateArgs, numParams * sizeof(ClassTemplateArgument));
3464       for(sClass = _class; sClass; sClass = sClass.base)
3465       {
3466          ClassTemplateParameter param;
3467          Class prevClass;
3468          int id = 0;
3469          if(sClass.templateClass) sClass = sClass.templateClass;
3470          for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
3471          {
3472             if(prevClass.templateClass) prevClass = prevClass.templateClass;
3473             id += prevClass.templateParams.count;
3474          }
3475          for(param = sClass.templateParams.first; param; param = param.next)
3476            CopyTemplateArg(param, templatedClass.templateArgs[id++]);
3477       }*/
3478    }
3479
3480    if(templatedClass.base && templatedClass.base.templateArgs && _class == templatedClass)
3481    {
3482       Class sClass;
3483       memcpy(templatedClass.templateArgs, templatedClass.base.templateArgs,
3484          sizeof(ClassTemplateArgument) * (numParams - templatedClass.templateParams.count));
3485       for(sClass = templatedClass.base; sClass; sClass = sClass.base)
3486       {
3487          ClassTemplateParameter param;
3488          Class prevClass;
3489          int id = 0;
3490          for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
3491          {
3492             if(prevClass.templateClass) prevClass = prevClass.templateClass;
3493             id += prevClass.templateParams.count;
3494          }
3495
3496          if(sClass.templateClass) sClass = sClass.templateClass;
3497          for(param = sClass.templateParams.first; param; param = param.next)
3498             CopyTemplateArg(param, templatedClass.templateArgs[id++]);
3499       }
3500    }
3501
3502    while(nextParamStart)
3503    {
3504       const char * paramStart = nextParamStart;
3505       const char * paramEnd;
3506       int level = 0;
3507       while(*paramStart == ' ') paramStart++;
3508       paramEnd = paramStart;
3509       while((ch = *paramEnd, ch && (level > 0 || (ch != '>' && ch != ','))))
3510       {
3511          if(ch == '<') level++;
3512          if(ch == '>') level--;
3513
3514          paramEnd++;
3515       }
3516       nextParamStart = (ch == ',') ? (paramEnd + 1) : null;
3517       while(*paramEnd == ' ') paramEnd--;
3518       if(paramEnd > paramStart)
3519       {
3520          const char * ptr, * equal = null;
3521          for(ptr = paramStart; ptr <= paramEnd; ptr++)
3522          {
3523             if(*ptr == '=')
3524             {
3525                equal = ptr;
3526                break;
3527             }
3528          }
3529          if(equal)
3530          {
3531             const char * end = equal - 1;
3532             char ident[1024];
3533
3534             while(*end == ' ') end--;
3535             strncpy(ident, paramStart, end + 1 - paramStart);
3536             ident[end + 1 - paramStart] = 0;
3537
3538             for(sClass = _class; sClass; sClass = sClass.base)
3539             {
3540                if(sClass.templateClass) sClass = sClass.templateClass;
3541                for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
3542                {
3543                   if(!strcmp(curParam.name, ident))
3544                      break;
3545                }
3546                if(curParam)
3547                {
3548                   Class nextClass;
3549                   ClassTemplateParameter prevParam;
3550                   curParamID = 0;
3551                   for(prevParam = curParam.prev; prevParam; prevParam = prevParam.prev) curParamID++;
3552                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3553                   {
3554                      if(nextClass.templateClass) nextClass = nextClass.templateClass;
3555                      curParamID += nextClass.templateParams.count;
3556                   }
3557                   break;
3558                }
3559             }
3560             lastClass = sClass;
3561          }
3562          else
3563          {
3564             if(curParam)
3565             {
3566                curParam = curParam.next;
3567                curParamID++;
3568             }
3569
3570             if(!curParam)
3571             {
3572                for(sClass = lastClass ? lastClass.base : _class; sClass; sClass = sClass.base)
3573                {
3574                   ClassTemplateParameter param;
3575                   curParamID = 0;
3576                   if(sClass.templateClass) sClass = sClass.templateClass;
3577                   for(param = sClass.templateParams.first; param; param = param.next, curParamID++)
3578                   {
3579                      curParam = param;
3580                      break;
3581                   }
3582                   if(curParam)
3583                   {
3584                      Class nextClass;
3585                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3586                      {
3587                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
3588                         curParamID += nextClass.templateParams.count;
3589                      }
3590                      lastClass = sClass;
3591                      break;
3592                   }
3593                }
3594                /*
3595                for(sClass = _class; sClass; sClass = sClass.base)
3596                {
3597                   if(sClass.templateParams.first)
3598                   {
3599                      Class nextClass;
3600                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3601                         if(nextClass.templateParams.first)
3602                            break;
3603                      if(nextClass != lastClass) continue;
3604
3605                      curParam = sClass.templateParams.first;
3606                      lastClass = sClass;
3607
3608                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3609                         if(nextClass.templateParams.first)
3610                         {
3611                            curParamID += nextClass.templateParams.count;
3612                            break;
3613                         }
3614                      break;
3615                   }
3616                }
3617                */
3618             }
3619          }
3620
3621          if(curParam)
3622          {
3623             ClassTemplateArgument argument { };
3624             char value[1024];
3625             if(equal)
3626             {
3627                equal++;
3628                while(*equal == ' ') equal++;
3629                memcpy(value, equal, paramEnd - equal);
3630                value[paramEnd - equal] = 0;
3631             }
3632             else
3633             {
3634                memcpy(value, paramStart, paramEnd - paramStart);
3635                value[paramEnd - paramStart] = 0;
3636             }
3637             TrimRSpaces(value, value);
3638
3639             switch(curParam.type)
3640             {
3641                case type:
3642                   argument.dataTypeString = CopyString(value);
3643                   argument.dataTypeClass = eSystem_FindClass(findModule, value);
3644                   if(!argument.dataTypeClass)
3645                      argument.dataTypeClass = eSystem_FindClass(_class.module, value);
3646                   if(!argument.dataTypeClass)
3647                      argument.dataTypeClass = eSystem_FindClass(_class.module.application, value);
3648                   break;
3649                case expression:
3650                {
3651                   Class expClass = eSystem_FindClass(_class.module, curParam.dataTypeString);
3652                   if(!expClass) expClass = eSystem_FindClass(_class.module.application, curParam.dataTypeString);
3653                   if(expClass)
3654                   {
3655                      //if(expClass.type ==
3656                      ((bool (*)(void *, void *, const char *))(void *)expClass._vTbl[__ecereVMethodID_class_OnGetDataFromString])(expClass, &argument.expression, value);
3657                   }
3658                   // Expression should be pre simplified here
3659                   else if(value[0] == '\"')
3660                   {
3661                      char * endQuote = value + strlen(value) - 1;
3662                      if(*endQuote != '\"') endQuote++;
3663                      *endQuote = '\0';
3664                      argument.expression.p = CopyString(value + 1);
3665                   }
3666                   else if(value[0] == '\'')
3667                   {
3668                      int nb;
3669                      unichar ch = UTF8GetChar(value + 1, &nb);
3670                      argument.expression.ui = ch;
3671                   }
3672                   else if(!strcmp(curParam.dataTypeString, "uint"))
3673                   {
3674                      argument.expression.ui = (uint)strtoul(value, null, 0);
3675                   }
3676                   else if(!strcmp(curParam.dataTypeString, "char"))
3677                   {
3678                      argument.expression.c = (char)strtol(value, null, 0);
3679                   }
3680                   else if(!strcmp(curParam.dataTypeString, "byte"))
3681                   {
3682                      argument.expression.uc = (unsigned char)strtoul(value, null, 0);
3683                   }
3684                   else if(!strcmp(curParam.dataTypeString, "short"))
3685                   {
3686                      argument.expression.s = (short)strtol(value, null, 0);
3687                   }
3688                   else if(!strcmp(curParam.dataTypeString, "uint16"))
3689                   {
3690                      argument.expression.us = (unsigned short)strtoul(value, null, 0);
3691                   }
3692                   else if(!strcmp(curParam.dataTypeString, "int64"))
3693                   {
3694                      argument.expression.i64 = _strtoi64(value, null, 0);
3695                   }
3696                   else if(!strcmp(curParam.dataTypeString, "uint64"))
3697                   {
3698                      argument.expression.ui64 = _strtoui64(value, null, 0);
3699                   }
3700                   else if(!strcmp(curParam.dataTypeString, "float"))
3701                   {
3702                      argument.expression.f = (float)strtod(value, null);
3703                   }
3704                   else if(!strcmp(curParam.dataTypeString, "double"))
3705                   {
3706                      argument.expression.d = strtod(value, null);
3707                   }
3708                   else // if(!strcmp(curParam.dataTypeString, "int"))
3709                   {
3710                      argument.expression.i = (int)strtol(value, null, 0);
3711                   }
3712                   break;
3713                }
3714                case identifier:
3715                   argument.memberString = CopyString(value);
3716                   break;
3717             }
3718             FreeTemplateArg(templatedClass, curParam, curParamID);
3719             templatedClass.templateArgs[curParamID] = argument;
3720          }
3721       }
3722    }
3723
3724    // TESTING THIS BEFORE...
3725    if(templatedClass == _class)
3726    {
3727       Class sClass = _class;
3728       int curParamID = 0;
3729       Class nextClass;
3730       ClassTemplateParameter param;
3731       for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3732       {
3733          if(nextClass.templateClass) nextClass = nextClass.templateClass;
3734          curParamID += nextClass.templateParams.count;
3735       }
3736
3737       for(param = sClass.templateParams.first; param; param = param.next)
3738       {
3739          if(!templatedClass.templateArgs[curParamID].dataTypeString)
3740          {
3741             templatedClass.templateArgs[curParamID] = param.defaultArg;
3742             CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3743             if(param.type == type && param.defaultArg.dataTypeString)
3744             {
3745                templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3746                if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3747                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3748                if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3749                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3750             }
3751          }
3752          curParamID++;
3753       }
3754    }
3755
3756    if(templatedClass.base && templatedClass.base.templateArgs && numParams - _class.templateParams.count)
3757    {
3758       int c = numParams - _class.templateParams.count-1;
3759
3760       for(sClass = _class.base; sClass; sClass = sClass.base)
3761       {
3762          ClassTemplateParameter param;
3763          if(sClass.templateClass) sClass = sClass.templateClass;
3764          for(param = sClass.templateParams.last; param; param = param.prev)
3765          {
3766             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3767             ClassTemplateArgument * baseArg = &templatedClass.base.templateArgs[c];
3768             if(!arg->dataTypeString)
3769             {
3770                *arg = templatedClass.base.templateArgs[c];
3771                CopyTemplateArg(param, arg);
3772                if(param.type == type)
3773                {
3774                   if(arg->dataTypeClass && strchr(arg->dataTypeString, '<') && arg->dataTypeClass.templateArgs)
3775                   {
3776                      Class expClass = arg->dataTypeClass;
3777                      Class cClass = null;
3778                      int paramCount = 0;
3779                      int lastParam = -1;
3780
3781                      char templateString[1024];
3782                      sprintf(templateString, "%s<", expClass.templateClass.fullName);
3783                      for(cClass = expClass; cClass; cClass = cClass.base)
3784                      {
3785                         int p = 0;
3786                         ClassTemplateParameter param;
3787                         for(param = cClass.templateParams.first; param; param = param.next)
3788                         {
3789                            int id = p;
3790                            Class sClass;
3791                            ClassTemplateArgument arg;
3792                            for(sClass = expClass.base; sClass; sClass = sClass.base) id += sClass.templateParams.count;
3793                            arg = expClass.templateArgs[id];
3794
3795                            {
3796                               ClassTemplateParameter cParam;
3797                               int p = numParams - _class.templateParams.count;
3798                               for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3799                               {
3800                                  if(cParam.type == type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
3801                                  {
3802                                     arg.dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3803                                     arg.dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3804                                     break;
3805                                  }
3806                               }
3807                            }
3808
3809                            {
3810                               char argument[256];
3811                               argument[0] = '\0';
3812                               switch(param.type)
3813                               {
3814                                  case expression:
3815                                  {
3816                                     // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
3817                                     /*
3818                                     char expString[1024];
3819                                     OldList * specs = MkList();
3820                                     Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
3821                                     Expression exp;
3822                                     char * string = PrintHexUInt64(arg.expression.ui64);
3823                                     exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
3824
3825                                     ProcessExpressionType(exp);
3826                                     ComputeExpression(exp);
3827                                     expString[0] = '\0';
3828                                     PrintExpression(exp, expString);
3829                                     strcat(argument, expString);
3830                                     //delete exp;
3831                                     FreeExpression(exp);
3832                                     */
3833                                     break;
3834                                  }
3835                                  case identifier:
3836                                  {
3837                                     strcat(argument, arg.member.name);
3838                                     break;
3839                                  }
3840                                  case TemplateParameterType::type:
3841                                  {
3842                                     if(arg.dataTypeString)
3843                                        strcat(argument, arg.dataTypeString);
3844                                     break;
3845                                  }
3846                               }
3847                               if(argument[0])
3848                               {
3849                                  if(paramCount) strcat(templateString, ", ");
3850                                  if(lastParam != p - 1)
3851                                  {
3852                                     strcat(templateString, param.name);
3853                                     strcat(templateString, " = ");
3854                                  }
3855                                  strcat(templateString, argument);
3856                                  paramCount++;
3857                                  lastParam = p;
3858                               }
3859                            }
3860                            p++;
3861                         }
3862                      }
3863                      {
3864                         int len = (int)strlen(templateString);
3865                         if(templateString[len-1] == '>') templateString[len++] = ' ';
3866                         templateString[len++] = '>';
3867                         templateString[len++] = '\0';
3868                      }
3869
3870                      FreeTemplateArg(templatedClass, param, c);
3871
3872                      arg->dataTypeString = CopyString(templateString);
3873                      arg->dataTypeClass = eSystem_FindClass(findModule, templateString);
3874                      if(!arg->dataTypeClass)
3875                         arg->dataTypeClass = eSystem_FindClass(templatedClass.module, templateString);
3876                      if(!arg->dataTypeClass)
3877                         arg->dataTypeClass = eSystem_FindClass(templatedClass.module.application, templateString);
3878                   }
3879                   else
3880                   {
3881                      ClassTemplateParameter cParam;
3882                      int p = numParams - _class.templateParams.count;
3883                      for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3884                      {
3885                         // if(cParam.type == type && !strcmp(cParam.name, param.name))
3886                         if(cParam.type == type && baseArg->dataTypeString && !strcmp(cParam.name, baseArg->dataTypeString))
3887                         {
3888                            FreeTemplateArg(templatedClass, param, c);
3889
3890                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3891                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3892                            CopyTemplateArg(cParam, arg);
3893                            break;
3894                         }
3895                      }
3896                   }
3897                }
3898             }
3899             c--;
3900          }
3901       }
3902    }
3903
3904    {
3905       Class sClass;
3906       for(sClass = _class; sClass; sClass = sClass.base)
3907       {
3908          int curParamID = 0;
3909          Class nextClass;
3910          ClassTemplateParameter param;
3911          if(sClass.templateClass) sClass = sClass.templateClass;
3912
3913          for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3914          {
3915             if(nextClass.templateClass) nextClass = nextClass.templateClass;
3916             curParamID += nextClass.templateParams.count;
3917          }
3918
3919          for(param = sClass.templateParams.first; param; param = param.next)
3920          {
3921             if(!templatedClass.templateArgs[curParamID].dataTypeString)
3922             {
3923                templatedClass.templateArgs[curParamID] = param.defaultArg;
3924                CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3925                if(param.type == type && param.defaultArg.dataTypeString)
3926                {
3927                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3928                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3929                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3930                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3931                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3932                }
3933             }
3934             curParamID++;
3935          }
3936       }
3937    }
3938
3939    {
3940       int c = numParams - 1;
3941       for(sClass = _class; sClass; sClass = sClass.base)
3942       {
3943          ClassTemplateParameter param;
3944          if(sClass.templateClass) sClass = sClass.templateClass;
3945          for(param = sClass.templateParams.last; param; param = param.prev)
3946          {
3947             if(param.type == type)
3948             {
3949                ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3950                ClassTemplateParameter cParam;
3951                Class dClass;
3952                int p = numParams - 1;
3953                for(dClass = _class; dClass; dClass = dClass.base)
3954                {
3955                   if(dClass.templateClass) dClass = dClass.templateClass;
3956                   for(cParam = dClass.templateParams.last; cParam; cParam = cParam.prev, p--)
3957                   {
3958                      if(cParam.type == type && arg->dataTypeString && !strcmp(cParam.name, arg->dataTypeString))
3959                      {
3960                         if(templatedClass.templateArgs[p].dataTypeString && c != p)
3961                         {
3962                            FreeTemplateArg(templatedClass, param, c);
3963
3964                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3965                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3966                            CopyTemplateArg(cParam, arg);
3967                         }
3968                      }
3969                   }
3970                }
3971             }
3972             c--;
3973          }
3974       }
3975    }
3976
3977    {
3978       Class tClass;
3979       int c = numParams - 1;
3980       for(tClass = _class; tClass; tClass = tClass.base)
3981       {
3982          ClassTemplateParameter param;
3983          if(tClass.templateClass) tClass = tClass.templateClass;
3984          for(param = tClass.templateParams.last; param; param = param.prev)
3985          {
3986             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3987             if(param.type == identifier && arg->memberString)
3988             {
3989                Class memberClass = templatedClass;
3990                const char * memberString = arg->memberString;
3991                const char * colon = strstr(memberString, "::");
3992                const char * memberName = memberString;
3993                if(colon) memberName = colon + 2;
3994                if(!colon)
3995                {
3996                   memberString = param.defaultArg.memberString;
3997                   colon = memberString ? strstr(memberString, "::") : null;
3998                }
3999
4000                if(colon)
4001                {
4002                   char className[1024];
4003                   Class sClass;
4004
4005                   memcpy(className, memberString, colon - memberString);
4006                   className[colon - memberString] = '\0';
4007
4008                   for(sClass = _class; sClass; sClass = sClass.base)
4009                   {
4010                      ClassTemplateParameter cParam;
4011                      Class nextClass;
4012                      int id = 0;
4013
4014                      if(sClass.templateClass) sClass = sClass.templateClass;
4015                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
4016                      {
4017                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
4018                         id += nextClass.templateParams.count;
4019                      }
4020                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
4021                      {
4022                         if(cParam.type == type && !strcmp(cParam.name, className) && templatedClass.templateArgs[id].dataTypeString)
4023                         {
4024                            strcpy(className, templatedClass.templateArgs[id].dataTypeString);
4025                         }
4026                         id++;
4027                      }
4028                   }
4029                   // TESTING: Added this here...
4030                   memberClass = eSystem_FindClass(findModule, className);
4031                   if(!memberClass)
4032                      memberClass = eSystem_FindClass(templatedClass.module, className);
4033                   if(!memberClass)
4034                      memberClass = eSystem_FindClass(templatedClass.module.application, className);
4035                }
4036
4037                if(memberClass)
4038                {
4039                   switch(param.memberType)
4040                   {
4041                      case dataMember:
4042                         arg->member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
4043                         break;
4044                      case method:
4045                         arg->method = eClass_FindMethod(memberClass, memberName, memberClass.module);
4046                         break;
4047                      case prop:
4048                         arg->prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
4049                         break;
4050                   }
4051                }
4052             }
4053             c--;
4054          }
4055       }
4056    }
4057 }
4058
4059 /*static */bool DefaultFunction()
4060 {
4061    return true;
4062 }
4063
4064 public dllexport bool eClass_IsDerived(Class _class, Class from)
4065 {
4066    if(!_class && !from)
4067       return true;
4068
4069    if(_class && from && (_class.templateClass || from.templateClass))
4070    {
4071       if(eClass_IsDerived(_class.templateClass ? _class.templateClass : _class, from.templateClass ? from.templateClass : from))
4072       {
4073          if(!from.templateClass)
4074             return true;
4075          else if(!_class.templateClass && _class == from.templateClass)
4076             return false;
4077          else
4078          {
4079             Class sClass;
4080             for(sClass = from; sClass; sClass = sClass.base)
4081             {
4082                if(sClass.templateParams.first)
4083                {
4084                   ClassTemplateParameter param;
4085                   Class nextClass;
4086                   int p = 0;
4087                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) p += nextClass.templateParams.count;
4088                   for(param = sClass.templateParams.first; param; param = param.next, p++)
4089                   {
4090                      ClassTemplateArgument * arg = &_class.templateArgs[p];
4091                      ClassTemplateArgument * fArg = &from.templateArgs[p];
4092                      if(param.type == type)
4093                      {
4094                         if(arg->dataTypeString != fArg->dataTypeString && arg->dataTypeString && fArg->dataTypeString &&
4095                           strcmp(arg->dataTypeString, fArg->dataTypeString))
4096                            break;
4097                      }
4098                      else if(param.type == identifier)
4099                      {
4100                         if(arg->member != fArg->member)
4101                            break;
4102                      }
4103                      else if(param.type == expression)
4104                      {
4105                         if(arg->expression.ui64 != fArg->expression.ui64)
4106                            break;
4107                      }
4108                   }
4109                   if(param)
4110                      return false;
4111                }
4112             }
4113             return true;
4114          }
4115       }
4116    }
4117    else
4118    {
4119       for(; _class && from; _class = _class.base)
4120       {
4121          if(_class == from || _class.templateClass == from || ((_class.type == systemClass || (_class.type == normalClass && _class.isInstanceClass)) && from.name && !strcmp(_class.name, from.name)))
4122             return true;
4123       }
4124    }
4125    return false;
4126 }
4127
4128 static void FixDerivativeVirtualMethod(Class base, const char * name, int vid, void * origFunction, const char * type)
4129 {
4130    OldLink derivative;
4131    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
4132    {
4133       Class _class = derivative.data;
4134       Method method, next;
4135       void * function = origFunction;
4136
4137       _class.vTblSize++;
4138       _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
4139       memmove(_class._vTbl + vid + 1, _class._vTbl + vid, (_class.vTblSize - vid - 1) * sizeof(void *));
4140
4141       method = (Method) _class.methods.FindString(name);
4142       if(method)
4143       {
4144          if(method.function) function = method.function;
4145
4146          if(!method.symbol)
4147          {
4148             delete (void *)method.name;
4149             delete (void *)method.dataTypeString;
4150             _class.methods.Delete((BTNode)method);
4151          }
4152          else
4153          {
4154             delete (void *)method.dataTypeString;
4155             method.type = virtualMethod;
4156             method.dataTypeString = CopyString(type);
4157             method._class = base;
4158          }
4159       }
4160       for(method = (Method)_class.methods.first; method; method = next)
4161       {
4162          next = (Method)((BTNode)method).next;
4163          if(method.type == virtualMethod)
4164             method.vid++;
4165       }
4166       _class._vTbl[vid] = function;
4167
4168       {
4169          OldLink templateLink;
4170          for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4171          {
4172             Class template = templateLink.data;
4173             template._vTbl = _class._vTbl;
4174          }
4175       }
4176       if(_class.derivatives.first || _class.templatized.first)
4177          FixDerivativeVirtualMethod(_class, name, vid, function, type);
4178    }
4179    {
4180       OldLink templateLink;
4181       for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
4182       {
4183          Class template = templateLink.data;
4184          template._vTbl = base._vTbl;
4185          FixDerivativeVirtualMethod(template, name, vid, origFunction, type);
4186       }
4187    }
4188 }
4189
4190 public dllexport Method eClass_AddMethod(Class _class, const char * name, const char * type, void * function, AccessMode declMode)
4191 {
4192    if(_class && !_class.comRedefinition && name)
4193    {
4194       Class base;
4195       for(base = _class; base; base = base.base)
4196       {
4197          Method method;
4198          if(base.templateClass) base = base.templateClass;
4199          method = (Method)base.methods.FindString(name);
4200          if(method)
4201          {
4202             // If this overrides a virtual method
4203             if(method.type == virtualMethod)
4204             {
4205                OldLink deriv;
4206                void * oldFunction = _class._vTbl[method.vid];
4207                if(method.vid >= _class.vTblSize)
4208                   printf("error: virtual methods overriding failure\n");
4209                else
4210                   _class._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
4211                for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4212                {
4213                   Class derivClass = deriv.data;
4214                   if(derivClass._vTbl[method.vid] == oldFunction)
4215                      eClass_AddMethod(derivClass, name, type, function, declMode);
4216                }
4217                {
4218                   OldLink templateLink;
4219                   for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4220                   {
4221                      Class template = templateLink.data;
4222                      for(deriv = template.derivatives.first; deriv; deriv = deriv.next)
4223                      {
4224                         Class derivClass = deriv.data;
4225                         if(derivClass._vTbl[method.vid] == oldFunction)
4226                            eClass_AddMethod(derivClass, name, type, function, declMode);
4227                      }
4228                   }
4229                }
4230
4231             }
4232             else
4233             {
4234                if(base == _class)
4235                {
4236                   // printf("error: Redefinition of method %s in class %s\n", name, _class.name);
4237                   break;
4238                }
4239                base = null;
4240                break;
4241             }
4242             return method;
4243          }
4244       }
4245
4246       if(!base)
4247       {
4248          Method method
4249          {
4250             name = CopyString(name),
4251             function = function ? function : null; //DefaultFunction;
4252             _class = _class;
4253             dataTypeString = CopyString(type);
4254             memberAccess = declMode;
4255          };
4256          _class.methods.Add((BTNode)method);
4257          return method;
4258       }
4259    }
4260    return null;
4261 }
4262
4263 public dllexport Method eClass_AddVirtualMethod(Class _class, const char * name, const char * type, void * function, AccessMode declMode)
4264 {
4265    if(_class && !_class.comRedefinition && name)
4266    {
4267       Class base;
4268       for(base = _class; base; base = base.base)
4269       {
4270          Method method = (Method)base.methods.FindString(name);
4271          if(method)
4272          {
4273             // If this overides a virtual method
4274             if(method.type == virtualMethod)
4275             {
4276                if(method.vid >= _class.vTblSize)
4277                   printf("error: virtual methods overriding failure\n");
4278                else
4279                   _class._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
4280             }
4281             else
4282                base = null;
4283             return method;
4284          }
4285       }
4286
4287       if(!base)
4288       {
4289          Method method
4290          {
4291             name = CopyString(name);
4292             function = function ? function : null; //DefaultFunction;
4293             type = virtualMethod;
4294             _class = _class;
4295             vid = _class.vTblSize++;
4296             dataTypeString = CopyString(type);
4297             memberAccess = declMode;
4298          };
4299          _class.methods.Add((BTNode)method);
4300          _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
4301          _class._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
4302
4303          // TODO: Fix derived classes
4304          if(_class.derivatives.first || _class.templatized.first)
4305             FixDerivativeVirtualMethod(_class, name, method.vid, function ? function : null /*(void *)DefaultFunction*/, type);
4306          return method;
4307       }
4308    }
4309    return null;
4310 }
4311
4312 static void FixDerivativeProperty(Class base, Property _property)
4313 {
4314    OldLink derivative;
4315    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
4316    {
4317       Class _class = derivative.data;
4318       Property prop;
4319       BTNamedLink link = (BTNamedLink)_class.prop.FindString(_property.name);
4320       if(link)
4321       {
4322          prop = link.data;
4323          if(!prop.Set && !prop.Get && prop.memberAccess == baseSystemAccess)
4324          {
4325             SelfWatcher watcher;
4326             for(watcher = _class.selfWatchers.first; watcher; watcher = watcher.next)
4327             {
4328                if(watcher._property == prop)
4329                   watcher._property = _property;
4330             }
4331             _property.selfWatchable = true;
4332
4333             delete (void *)prop.name;
4334             delete (void *)prop.dataTypeString;
4335             _class.membersAndProperties.Delete(prop);
4336             _class.prop.Delete((BTNode)link);
4337          }
4338       }
4339
4340       for(prop = _class.membersAndProperties.first; prop; prop = prop.next)
4341          prop.id++;
4342       _class.memberID++;
4343       _class.startMemberID++;
4344
4345       FixDerivativeProperty(_class, _property);
4346    }
4347 }
4348
4349 public dllexport Property eClass_AddProperty(Class _class, const char * name, const char * dataType, void * setStmt, void * getStmt, AccessMode declMode)
4350 {
4351    Property _property = null;
4352    if(_class)
4353    {
4354       BTNamedLink link = (BTNamedLink)_class.prop.FindString(name ? name : dataType);
4355       bool isConversion = name ? false : true;
4356       if(!name && dataType && !strncmp(dataType, "const ", 6))
4357       {
4358          name = dataType + 6;
4359          isConversion = true;
4360       }
4361       if(link)
4362          _property = link.data;
4363       if(!_property)
4364       {
4365          _property =
4366          {
4367             isProperty = true;
4368             name = CopyString(name ? name : dataType);
4369             id = (name && (setStmt || getStmt || dataType)) ? _class.memberID++ : 0;
4370             Set = setStmt;
4371             Get = getStmt;
4372             dataTypeString = CopyString(dataType);
4373             _class = _class;
4374             compiled = true;
4375             conversion = isConversion;
4376             memberAccess = declMode;
4377          };
4378          if(!isConversion)
4379             _class.membersAndProperties.Add(_property);
4380          else
4381             _class.conversions.Add(_property);
4382          _class.prop.Add((BTNode)BTNamedLink { name = _property.name, data = _property });
4383
4384          if(!_property.conversion)
4385          {
4386             FixDerivativeProperty(_class, _property);
4387          }
4388       }
4389    }
4390    return _property;
4391 }
4392
4393 static void SetDelayedCPValues(Class _class, ClassProperty _property)
4394 {
4395    OldLink deriv;
4396    NamedLink64 value, next;
4397
4398    for(value = _class.delayedCPValues.first; value; value = next)
4399    {
4400       next = value.next;
4401       if(!strcmp(value.name, _property.name))
4402       {
4403          // eClass_SetProperty(_class, _property.name, value.data);
4404          _property.Set(_class, value.data);
4405          _class.delayedCPValues.Delete(value);
4406       }
4407    }
4408
4409    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4410    {
4411       SetDelayedCPValues(deriv.data, _property);
4412    }
4413 }
4414
4415 public dllexport ClassProperty eClass_AddClassProperty(Class _class, const char * name, const char * dataType, void * setStmt, void * getStmt)
4416 {
4417    if(name && !_class.classProperties.FindString(name))
4418    {
4419       ClassProperty _property
4420       {
4421          name = CopyString(name);
4422          Set = setStmt;
4423          Get = getStmt;
4424          dataTypeString = CopyString(dataType);
4425       };
4426       _class.classProperties.Add((BTNode)_property);
4427       SetDelayedCPValues(_class, _property);
4428       return _property;
4429    }
4430    return null;
4431 }
4432
4433 /*import "Time"
4434
4435 Time classFindTotalTime;
4436
4437 public dllexport void ResetClassFindTime()
4438 {
4439    classFindTotalTime = 0;
4440 }
4441
4442 public dllexport Time GetClassFindTime()
4443 {
4444    return classFindTotalTime;
4445 }
4446 */
4447 public dllexport ClassProperty eClass_FindClassProperty(Class _class, const char * name)
4448 {
4449    //Time startTime = GetTime();
4450    ClassProperty _property = null;
4451    if(name && _class)
4452    {
4453       Class origClass = _class;
4454       for(; _class; _class = _class.base)
4455       {
4456          _property = (ClassProperty)_class.classProperties.FindString(name);
4457          if(_property)
4458             break;
4459       }
4460       // For enum class deriving off something else than enum to find enumSize...
4461       if(!_property && origClass.type == enumClass)
4462       {
4463          Class enumClass = eSystem_FindClass(origClass.module, "enum");
4464          _property = eClass_FindClassProperty(enumClass, name);
4465       }
4466    }
4467    /*if(!_property)
4468       eSystem_Logf("No such property (%s) for class %s\n", name, _class.name);*/
4469    //classFindTotalTime += GetTime() - startTime;
4470    return _property;
4471 }
4472
4473 public dllexport int64 eClass_GetProperty(Class _class, const char * name)
4474 {
4475    ClassProperty _property = eClass_FindClassProperty(_class, name);
4476    if(_property && _property.Get && _property.Get != (void *)1)
4477    {
4478       int64 result = _property.Get(_class);
4479       return result;
4480    }
4481    return 0;
4482 }
4483
4484 public dllexport void eClass_SetProperty(Class _class, const char * name, int64 value)
4485 {
4486    ClassProperty _property = eClass_FindClassProperty(_class, name);
4487    if(_property)
4488    {
4489       if(_property.Set)
4490          ((void(*)(void *, int64))_property.Set)(_class, value);
4491    }
4492    else
4493    {
4494       _class.delayedCPValues.Add(NamedLink64 { name = (char *)name, value });
4495    }
4496 }
4497
4498 public dllexport Method eClass_FindMethod(Class _class, const char * name, Module module)
4499 {
4500    //Time startTime = GetTime();
4501    if(_class && name)
4502    {
4503       for(; _class; _class = _class.base)
4504       {
4505          Method method;
4506          if(_class.templateClass) _class = _class.templateClass;
4507          method = (Method)_class.methods.FindString(name);
4508          if(method && (method.memberAccess == publicAccess || _class.module == module || !method.dataTypeString))
4509          {
4510             if(!method.dataTypeString)
4511             {
4512                if(_class.module != module)
4513                {
4514                   if(method.memberAccess == publicAccess)
4515                      module = _class.module;
4516                   else
4517                   {
4518                      //classFindTotalTime += GetTime() - startTime;
4519                      return null;
4520                   }
4521                }
4522             }
4523             else
4524             {
4525                //classFindTotalTime += GetTime() - startTime;
4526                return method;
4527             }
4528          }
4529          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4530       }
4531    }
4532    //classFindTotalTime += GetTime() - startTime;
4533    return null;
4534 }
4535
4536 // Construct an instance
4537 static bool ConstructInstance(void * instance, Class _class, Class from)
4538 {
4539    if(_class.templateClass) _class = _class.templateClass;
4540    if(_class.base && from != _class.base)
4541    {
4542       if(!ConstructInstance(instance, _class.base, from))
4543          return false;
4544    }
4545    if(_class.Initialize)
4546    {
4547       void (* Initialize)(Module module) = (void *)_class.Initialize;
4548       _class.Initialize = null;
4549       Initialize(_class.module);
4550    }
4551    if(_class.Constructor)
4552    {
4553       if(!_class.Constructor(instance))
4554       {
4555          for(; _class; _class = _class.base)
4556          {
4557             if(_class.templateClass) _class = _class.templateClass;
4558             if(_class.Destructor)
4559                _class.Destructor(instance);
4560          }
4561          return false;
4562       }
4563    }
4564    (_class.templateClass ? _class.templateClass : _class).count++;
4565    return true;
4566 }
4567
4568 public dllexport void * eInstance_New(Class _class)
4569 {
4570    Instance instance = null;
4571    if(_class)
4572    {
4573       // instance = _malloc(_class.size);
4574 #ifdef MEMINFO
4575
4576 #undef malloc
4577    memMutex.Wait();
4578       //allocateClass = _class;
4579       allocateClass = malloc(strlen(_class.name)+1);
4580       allocateInternal = _class.module == __thisModule;
4581       strcpy(allocateClass, _class.name);
4582 #ifndef MEMINFO
4583 #define malloc _mymalloc
4584 #endif
4585
4586 #endif
4587       {
4588          int size = _class.structSize;
4589          int flags = _class.module.application.isGUIApp;
4590          bool inCompiler = (flags & 8) ? true : false;
4591          bool force32Bits = (flags & 4) ? true : false;
4592          if(force32Bits && inCompiler)
4593          {
4594             // Allocate 64 bit sizes for these when cross-compiling for 32 bit to allow loaded libraries to work properly
4595             if(!strcmp(_class.name, "Module"))
4596                size = 560;
4597             else if(_class.templateClass && !strcmp(_class.templateClass.name, "Map"))
4598                size = 40;
4599             else
4600                size *= 3;
4601          }
4602          instance = _calloc(1, size);
4603       }
4604 #ifdef MEMINFO
4605       allocateClass = null;
4606    memMutex.Release();
4607 #endif
4608
4609 #if defined(_DEBUG) && !defined(MEMINFO) && defined(MEMTRACKING)
4610       {
4611          MemBlock block = (MemBlock)((byte *)instance - sizeof(class MemBlock));
4612          block._class = _class;
4613       }
4614 #endif
4615
4616       if(_class.type == normalClass)
4617       {
4618          instance._class = _class;
4619          // Copy the virtual table initially
4620          instance._vTbl = _class._vTbl;
4621       }
4622       if(!ConstructInstance(instance, _class, null))
4623       {
4624          _free(instance);
4625          instance = null;
4626       }
4627       /*if(_class.type == normalClass && _class.count > 1000)
4628          printf("%s: %d instances\n", _class.name, _class.count);*/
4629    }
4630    return instance;
4631 }
4632
4633 public dllexport void eInstance_Evolve(Instance * instancePtr, Class _class)
4634 {
4635    if(_class && instancePtr && *instancePtr)
4636    {
4637       bool wasApp = false, wasGuiApp = false;
4638       Instance instance = (Instance)renew *instancePtr byte[_class.structSize];
4639       Class fromClass = instance._class;
4640       *instancePtr = instance;
4641       memset(((byte *)instance) + instance._class.structSize, 0, _class.structSize - instance._class.structSize);
4642       // Fix pointers to application
4643       if((wasApp = !strcmp(instance._class.name, "Application")) ||
4644          (wasGuiApp = !strcmp(instance._class.name, "GuiApplication")))
4645       {
4646          Module module;
4647          Application app = (Application) instance;
4648          BTNamedLink link;
4649          Class _class;
4650          NameSpace * nameSpace;
4651          for(module = app.allModules.first; module; module = module.next)
4652             module.application = app;
4653
4654          for(link = (BTNamedLink)app.privateNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4655          {
4656             OldLink t;
4657             ((Class)link.data).nameSpace = &app.privateNameSpace;
4658             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4659          }
4660          for(link = (BTNamedLink)app.publicNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4661          {
4662             OldLink t;
4663             ((Class)link.data).nameSpace = &app.publicNameSpace;
4664             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4665          }
4666
4667          for(link = (BTNamedLink)app.privateNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4668             ((DefinedExpression)link.data).nameSpace = &app.privateNameSpace;
4669          for(link = (BTNamedLink)app.publicNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4670             ((DefinedExpression)link.data).nameSpace = &app.publicNameSpace;
4671
4672          for(link = (BTNamedLink)app.privateNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4673             ((GlobalFunction)link.data).nameSpace = &app.privateNameSpace;
4674          for(link = (BTNamedLink)app.publicNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4675             ((GlobalFunction)link.data).nameSpace = &app.publicNameSpace;
4676
4677          for(nameSpace = (NameSpace *)app.privateNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4678             nameSpace->parent = &app.privateNameSpace;
4679          for(nameSpace = (NameSpace *)app.publicNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4680             nameSpace->parent = &app.publicNameSpace;
4681
4682          // --------------------------------------------------
4683          for(link = (BTNamedLink)app.systemNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4684          {
4685             OldLink t;
4686             ((Class)link.data).nameSpace = &app.systemNameSpace;
4687             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4688          }
4689          for(link = (BTNamedLink)app.systemNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4690             ((DefinedExpression)link.data).nameSpace = &app.systemNameSpace;
4691          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4692             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4693          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4694             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4695          for(nameSpace = (NameSpace *)app.systemNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4696             nameSpace->parent = &app.systemNameSpace;
4697          // --------------------------------------------------
4698
4699          for(_class = app.classes.first; _class; _class = _class.next)
4700          {
4701             OldLink templateLink;
4702             _class.module = (Module) app;
4703             for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4704             {
4705                Class template = templateLink.data;
4706                template.module = _class.module;
4707             }
4708          }
4709
4710          for(module = app.allModules.first; module; module = module.next)
4711          {
4712             for(_class = module.classes.first; _class; _class = _class.next)
4713             {
4714                OldLink templateLink;
4715                _class.module = module;
4716                for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4717                {
4718                   Class template = templateLink.data;
4719                   template.module = _class.module;
4720                }
4721             }
4722          }
4723
4724          app.application = app;
4725       }
4726
4727       {
4728          Class base;
4729          for(base = instance._class; base && base.type == normalClass && base.count; base = base.base)
4730             (base.templateClass ? base.templateClass : base).count--;
4731       }
4732
4733       instance._class = _class;
4734       // Copy the virtual table initially
4735       instance._vTbl = _class._vTbl;
4736
4737       // We don't want to reconstruct the portion already constructed...
4738       if(!ConstructInstance(instance, _class, fromClass))
4739       {
4740          _free(instance);
4741          *instancePtr = null;
4742       }
4743    }
4744 }
4745
4746 public dllexport void eInstance_Delete(Instance instance)
4747 {
4748 #ifdef MEMINFO
4749    bool checkMemory = false;
4750 #endif
4751    if(instance)
4752    {
4753       Class _class, base;
4754       bool ownVtbl;
4755
4756 #ifdef MEMINFO
4757 #if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__)
4758       if(instance._class == (void *)0xecececececececec)
4759 #else
4760       if(instance._class == (void *)0xecececec)
4761 #endif
4762          _free(instance);
4763 #endif
4764
4765       ownVtbl = instance._vTbl != instance._class._vTbl;
4766
4767       for(_class = instance._class; _class; _class = base)
4768       {
4769          if(_class.templateClass) _class = _class.templateClass;
4770          if(_class.destructionWatchOffset)
4771          {
4772             OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
4773             Watcher watcher, next;
4774
4775             for(watcher = watchers->first; watcher; watcher = next)
4776             {
4777                next = watcher.next;
4778                watchers->Remove(watcher);
4779                watcher.callback(watcher.object, instance);
4780                watchers->Delete(watcher);
4781             }
4782          }
4783
4784          /*// Loop through properties to delete all watchers? Might slow down destruction...
4785          {
4786             Property _property;
4787             for(_property = _class.membersAndProperties.first; _property; _property = _property.next)
4788             {
4789                if(_property.isProperty && _property.isWatchable)
4790                {
4791                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
4792                   Watcher watcher, next;
4793                   for(watcher = watchers->first; watcher; watcher = next)
4794                   {
4795                      next = watcher.next;
4796                      watchers->Delete(watcher);
4797                   }
4798                }
4799             }
4800          }*/
4801
4802
4803          base = _class.base;
4804          if(base && (base.type == systemClass || base.isInstanceClass)) base = null;
4805          if(_class.Destructor)
4806             _class.Destructor(instance);
4807 #ifdef MEMINFO
4808          if(_class == class(Application))
4809             checkMemory = true;
4810 #endif
4811       }
4812
4813       for(_class = instance._class; _class; _class = base)
4814       {
4815          if(_class.templateClass) _class = _class.templateClass;
4816
4817          base = _class.base;
4818          (_class.templateClass ? _class.templateClass : _class).count--;
4819          if(_class.type == normalClass && !_class.count && !_class.module)
4820          {
4821 #ifdef MEMINFO
4822             // printf("Now Destructing class %s\n", _class.name);
4823 #endif
4824             eClass_Unregister(_class);
4825          }
4826       }
4827
4828       if(ownVtbl)
4829       {
4830          delete instance._vTbl;
4831       }
4832       //instance.prop.Free(null);
4833       _free(instance);
4834 #ifdef MEMINFO
4835       if(checkMemory) CheckMemory();
4836 #endif
4837    }
4838 }
4839
4840 public dllexport Property eClass_FindProperty(Class _class, const char * name, Module module)
4841 {
4842    //Time startTime = GetTime();
4843    if(_class && name)
4844    {
4845       if(!strncmp(name, "const ", 6))
4846          name += 6;
4847
4848       for(; _class; _class = _class.base)
4849       {
4850          BTNamedLink link;
4851          if(_class.templateClass) _class = _class.templateClass;
4852          link = (BTNamedLink)_class.prop.FindString(name);
4853          if(link)
4854          {
4855             Property _property = (Property)link.data;
4856             if(_property.memberAccess == publicAccess || _class.module == module || !_property.dataTypeString)
4857             {
4858                if(!_property.dataTypeString)
4859                {
4860                   if(_class.module != module)
4861                   {
4862                      if(_property.memberAccess == publicAccess)
4863                         module = _class.module;
4864                      else
4865                      {
4866                         //classFindTotalTime += GetTime() - startTime;
4867                         return null;
4868                      }
4869                   }
4870                }
4871                else
4872                {
4873                   //classFindTotalTime += GetTime() - startTime;
4874                   return _property;
4875                }
4876             }
4877          }
4878          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4879       }
4880    }
4881    //classFindTotalTime += GetTime() - startTime;
4882    return null;
4883 }
4884
4885 static DataMember FindDataMember(OldList list, BinaryTree alist, const char * name, uint * offset, int * id, bool searchPrivate, DataMember * subMemberStack, int * subMemberStackPos)
4886 {
4887    BTNamedLink link;
4888    DataMember dataMember;
4889
4890    link = (BTNamedLink)alist.FindString(name);
4891    if(link)
4892    {
4893       dataMember = link.data;
4894       if(dataMember.type == normalMember && (dataMember.memberAccess == publicAccess || searchPrivate || !dataMember.dataTypeString))
4895       {
4896          if(offset)
4897             *offset += dataMember.offset;
4898          if(id) *id = dataMember.id;
4899          return dataMember;
4900       }
4901       return null;
4902    }
4903    for(dataMember = list.first; dataMember; dataMember = dataMember.next)
4904    {
4905       if(!dataMember.isProperty && (dataMember.memberAccess == publicAccess || searchPrivate) && !dataMember.name && (dataMember.type == unionMember || dataMember.type == structMember))
4906       {
4907          DataMember childMember;
4908          if(subMemberStackPos) subMemberStack[(*subMemberStackPos)++] = dataMember;
4909          childMember = FindDataMember(dataMember.members, dataMember.membersAlpha, name, offset, id, searchPrivate, subMemberStack, subMemberStackPos);
4910          if(childMember)
4911          {
4912             if(offset)
4913                *offset += dataMember.offset;
4914             if(id) *id += dataMember.id;
4915             return childMember;
4916          }
4917          if(subMemberStackPos) (*subMemberStackPos)--;
4918       }
4919    }
4920    return null;
4921 }
4922
4923 public dllexport DataMember eClass_FindDataMember(Class _class, const char * name, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4924 {
4925    //Time startTime = GetTime();
4926    DataMember dataMember = null;
4927    if(subMemberStackPos) *subMemberStackPos = 0;
4928    if(_class && name)
4929    {
4930       for(; _class; _class = _class.base)
4931       {
4932          if(_class.templateClass) _class = _class.templateClass;
4933          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, null, _class.module == module, subMemberStack, subMemberStackPos);
4934          if(dataMember)
4935          {
4936             if(!dataMember.dataTypeString)
4937             {
4938                if(_class.module != module)
4939                {
4940                   if(dataMember.memberAccess == publicAccess)
4941                      module = _class.module;
4942                   else
4943                   {
4944                      //classFindTotalTime += GetTime() - startTime;
4945                      return null;
4946                   }
4947                }
4948                dataMember = null;
4949             }
4950             else
4951             {
4952                // HACK: Is this good enough? avoiding setting it when adding...
4953                dataMember._class = _class.templateClass ? _class.templateClass : _class;
4954                //classFindTotalTime += GetTime() - startTime;
4955                return dataMember;
4956             }
4957          }
4958          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4959       }
4960    }
4961    //classFindTotalTime += GetTime() - startTime;
4962    return dataMember;
4963 }
4964
4965 public dllexport DataMember eClass_FindDataMemberAndOffset(Class _class, const char * name, uint * offset, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4966 {
4967    //Time startTime = GetTime();
4968    DataMember dataMember = null;
4969    if(subMemberStackPos) *subMemberStackPos = 0;
4970    if(offset) *offset = 0;
4971    if(_class)
4972    {
4973       for(; _class; _class = _class.base)
4974       {
4975          if(_class.templateClass) _class = _class.templateClass;
4976          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, offset, null, _class.module == module, subMemberStack, subMemberStackPos);
4977          if(dataMember)
4978          {
4979             if(!dataMember.dataTypeString)
4980             {
4981                if(_class.module != module)
4982                {
4983                   if(dataMember.memberAccess == publicAccess)
4984                      module = _class.module;
4985                   else
4986                   {
4987                      //classFindTotalTime += GetTime() - startTime;
4988                      return null;
4989                   }
4990                }
4991                dataMember = null;
4992             }
4993             else
4994             {
4995                // HACK: Is this good enouh? avoiding setting it when adding...
4996                dataMember._class = _class;
4997                //classFindTotalTime += GetTime() - startTime;
4998                return dataMember;
4999             }
5000          }
5001          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
5002       }
5003    }
5004    //classFindTotalTime += GetTime() - startTime;
5005    return dataMember;
5006 }
5007
5008 public dllexport DataMember eClass_FindDataMemberAndId(Class _class, const char * name, int * id, Module module, DataMember * subMemberStack, int * subMemberStackPos)
5009 {
5010    //Time startTime = GetTime();
5011    DataMember dataMember = null;
5012    if(subMemberStackPos) *subMemberStackPos = 0;
5013    if(_class)
5014    {
5015       for(; _class; _class = _class.base)
5016       {
5017          if(_class.templateClass) _class = _class.templateClass;
5018          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, id, _class.module == module, subMemberStack, subMemberStackPos);  // TOCHECK: Why was this null? null, null);
5019          if(dataMember)
5020          {
5021             if(!dataMember.dataTypeString)
5022             {
5023                if(_class.module != module)
5024                {
5025                   if(dataMember.memberAccess == publicAccess)
5026                      module = _class.module;
5027                   else
5028                   {
5029                      //classFindTotalTime += GetTime() - startTime;
5030                      return null;
5031                   }
5032                }
5033                dataMember = null;
5034             }
5035             else
5036             {
5037                // HACK: Is this good enouh? avoiding setting it when adding...
5038                dataMember._class = _class;
5039                //classFindTotalTime += GetTime() - startTime;
5040                return dataMember;
5041             }
5042          }
5043          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
5044       }
5045    }
5046    //classFindTotalTime += GetTime() - startTime;
5047    return dataMember;
5048 }
5049
5050 public dllexport void eClass_FindNextMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
5051 {
5052    // THIS CODE WILL FIND NEXT MEMBER... (PUBLIC MEMBERS ONLY)
5053    if(*curMember)
5054    {
5055       *curMember = (*curMember).next;
5056
5057       if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
5058       {
5059          *curMember = subMemberStack[--(*subMemberStackPos)];
5060          *curMember = (*curMember).next;
5061       }
5062
5063       if(subMemberStackPos && *subMemberStackPos > 0)
5064       {
5065          while(*curMember && ((*curMember).memberAccess == privateAccess))
5066             *curMember = (*curMember).next;
5067       }
5068       else
5069          while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
5070          {
5071             DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
5072             if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
5073             if(dataMember && dataMember.memberAccess != privateAccess)
5074             {
5075                *curMember = dataMember;
5076                break;
5077             }
5078             else
5079                *curMember = (*curMember).next;
5080          }
5081
5082       if(subMemberStackPos)
5083       {
5084          while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
5085          {
5086             subMemberStack[(*subMemberStackPos)++] = *curMember;
5087
5088             *curMember = (*curMember).members.first;
5089             while(*curMember && ((*curMember).memberAccess == privateAccess))
5090                *curMember = (*curMember).next;
5091          }
5092       }
5093    }
5094    while(!*curMember)
5095    {
5096       if(!*curMember)
5097       {
5098          if(subMemberStackPos && *subMemberStackPos)
5099          {
5100             *curMember = subMemberStack[--(*subMemberStackPos)];
5101             *curMember = (*curMember).next;
5102          }
5103          else
5104          {
5105             Class lastCurClass = *curClass;
5106
5107             if(*curClass == _class) break;     // REACHED THE END
5108
5109             for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass && (*curClass).inheritanceAccess != privateAccess; *curClass = (*curClass).base);
5110             *curMember = (*curClass).membersAndProperties.first;
5111          }
5112
5113          if(subMemberStackPos && *subMemberStackPos > 0)
5114          {
5115             while(*curMember && ((*curMember).memberAccess == privateAccess))
5116                *curMember = (*curMember).next;
5117          }
5118          else
5119             while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
5120             {
5121                DataMember dataMember = null;
5122                if(((*curMember).memberAccess != privateAccess))
5123                {
5124                   dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
5125                   if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
5126                }
5127                if(dataMember && dataMember.memberAccess != privateAccess && dataMember.id >= 0) // Skip _vTbl, _refCount and _class in Instance
5128                {
5129                   *curMember = dataMember;
5130                   break;
5131                }
5132                else
5133                   *curMember = (*curMember).next;
5134             }
5135
5136          if(subMemberStackPos)
5137          {
5138             while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
5139             {
5140                subMemberStack[(*subMemberStackPos)++] = *curMember;
5141
5142                *curMember = (*curMember).members.first;
5143                while(*curMember && (*curMember).memberAccess == privateAccess)
5144                   *curMember = (*curMember).next;
5145             }
5146          }
5147       }
5148    }
5149 }
5150
5151 public dllexport void eInstance_SetMethod(Instance instance, const char * name, void * function)     // YET TO BE DECIDED:   , Module module)
5152 {
5153    if(instance && name)
5154    {
5155       Class _class;
5156       for(_class = instance._class; _class; _class = _class.base)
5157       {
5158          Method method = (Method)_class.methods.FindString(name);
5159          if(method && method.type == virtualMethod)
5160          {
5161             if(instance._vTbl == instance._class._vTbl)
5162             {
5163                instance._vTbl = _malloc(sizeof(void *) * instance._class.vTblSize);
5164                memcpy(instance._vTbl, instance._class._vTbl,
5165                   sizeof(int(*)()) * instance._class.vTblSize);
5166             }
5167             instance._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
5168          }
5169       }
5170    }
5171 }
5172
5173 public dllexport bool eInstance_IsDerived(Instance instance, Class from)
5174 {
5175    if(instance)
5176    {
5177       Class _class = instance._class;
5178       for(; _class; _class = _class.base)
5179       {
5180          if(_class == from)
5181             return true;
5182       }
5183    }
5184    return false;
5185 }
5186
5187 public dllexport void eInstance_IncRef(Instance instance)
5188 {
5189    if(instance)
5190       instance._refCount++;
5191 }
5192
5193 public dllexport void eInstance_DecRef(Instance instance)
5194 {
5195    if(instance)
5196    {
5197       instance._refCount--;
5198       //if(!instance._refCount)
5199       if(instance._refCount <= 0)
5200       {
5201          eInstance_Delete(instance);
5202       }
5203    }
5204 }
5205
5206 static void FixOffsets(Class _class)
5207 {
5208    OldLink deriv;
5209    _class.structSize += _class.base.structSize - _class.offset;
5210
5211    _class.offset = _class.base.structSize;
5212
5213    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
5214       FixOffsets(deriv.data);
5215 }
5216
5217 public dllexport void eClass_Resize(Class _class, int newSize)
5218 {
5219    OldLink deriv;
5220    _class.structSize = newSize;
5221    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
5222       FixOffsets(deriv.data);
5223 }
5224                                                                                                                         // F000F000 will mean a pointer size alignment
5225 public dllexport DataMember eClass_AddDataMember(Class _class, const char * name, const char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
5226 {
5227    if(_class && name)
5228    {
5229       if(!_class.members.FindString(name))
5230       {
5231          DataMember dataMember;
5232
5233          if(alignment)
5234          {
5235             bool pointerAlignment = alignment == 0xF000F000;
5236             bool force64Bits = (_class.module.application.isGUIApp & 2) ? true : false;
5237             bool force32Bits = (_class.module.application.isGUIApp & 4) ? true : false;
5238             if((force32Bits || force64Bits) && !strcmp(_class.name, "AVLNode") && !strcmp(name, "__ecerePrivateData0"))
5239             {
5240                if(force64Bits)
5241                {
5242                   type = "byte[32]";
5243                   size = 32;
5244                }
5245                if(force32Bits)
5246                {
5247                   type = "byte[16]";
5248                   size = 16;
5249                }
5250             }
5251
5252             if(pointerAlignment) alignment = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
5253
5254             if(pointerAlignment && _class.structAlignment <= 4)
5255                _class.pointerAlignment = 1;
5256             else if(!pointerAlignment && alignment >= 8)
5257                _class.pointerAlignment = 0;
5258
5259             _class.structAlignment = Max(_class.structAlignment, alignment);
5260
5261             if(_class.offset % alignment)
5262                _class.offset += alignment - (_class.offset % alignment);
5263             if(_class.memberOffset % alignment)
5264                _class.memberOffset += alignment - (_class.memberOffset % alignment);
5265          }
5266
5267          dataMember = DataMember {
5268             name = CopyString(name);
5269             dataTypeString = CopyString(type);
5270             id = _class.memberID++;
5271             _class = _class;
5272             offset = _class.memberOffset;
5273             memberOffset = size;
5274             memberAccess = declMode;
5275             membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5276          };
5277          _class.membersAndProperties.Add(dataMember);
5278          _class.memberOffset += size;
5279
5280          _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5281          return dataMember;
5282       }
5283    }
5284    return null;
5285 }
5286                                                                                                                               // F000F000 will mean a pointer size alignment
5287 public dllexport DataMember eMember_AddDataMember(DataMember member, const char * name, const char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
5288 {
5289    if(name && !member.membersAlpha.FindString(name))
5290    {
5291       DataMember dataMember;
5292
5293       if(alignment)
5294       {
5295          bool pointerAlignment = alignment == 0xF000F000;
5296          bool force64Bits = false; //(member._class.module.application.isGUIApp & 2) ? true : false;
5297          bool force32Bits = false; //(member._class.module.application.isGUIApp & 4) ? true : false;
5298          if(pointerAlignment) alignment = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
5299
5300          if(pointerAlignment && member.structAlignment <= 4)
5301             member.pointerAlignment = 1;
5302          else if(!pointerAlignment && alignment >= 8)
5303             member.pointerAlignment = 0;
5304
5305          member.structAlignment = Max(member.structAlignment, alignment);
5306
5307          if(member.memberOffset % alignment)
5308             member.memberOffset += alignment - (member.memberOffset % alignment);
5309       }
5310       dataMember = DataMember {
5311          name = CopyString(name);
5312          _class = member._class;
5313          dataTypeString = CopyString(type);
5314          id = member.memberID++;
5315          offset = (member.type == unionMember) ? 0 : member.memberOffset;
5316          memberAccess = declMode;
5317          membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5318       };
5319       member.members.Add(dataMember);
5320       if(member.type == unionMember)
5321       {
5322          if(size > member.memberOffset)
5323             member.memberOffset = size;
5324       }
5325       else
5326          member.memberOffset += size;
5327       member.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5328       return dataMember;
5329    }
5330    return null;
5331 }
5332
5333 public dllexport DataMember eMember_New(DataMemberType type, AccessMode declMode)
5334 {
5335    return DataMember { type = type, memberAccess = declMode, membersAlpha.CompareKey = (void *)BinaryTree::CompareString };
5336 }
5337
5338 static void SetMemberClass(DataMember member, Class _class)
5339 {
5340    DataMember dataMember;
5341    member._class = _class;
5342    for(dataMember = member.members.first; dataMember; dataMember = dataMember.next)
5343       SetMemberClass(dataMember, _class);
5344 }
5345
5346 public dllexport bool eMember_AddMember(DataMember addTo, DataMember dataMember)
5347 {
5348    if(dataMember.name && addTo.membersAlpha.FindString(dataMember.name))
5349    {
5350       DataMember_Free(dataMember);
5351       delete dataMember;
5352       return false;
5353    }
5354    addTo.members.Add(dataMember);
5355
5356    if(dataMember.name)
5357       addTo.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5358
5359    dataMember._class = addTo._class;
5360    // ? SetMemberClass(dataMember, addTo._class);
5361
5362    //dataMember.id = addTo.memberID++;
5363    dataMember.id = addTo.memberID;
5364    if(dataMember.type == unionMember)
5365       addTo.memberID += 1;
5366    else
5367       addTo.memberID += dataMember.memberID;
5368
5369    if(dataMember.pointerAlignment && dataMember.structAlignment <= 4)
5370       addTo.pointerAlignment = 1;
5371    else if(!dataMember.pointerAlignment && dataMember.structAlignment >= 8)
5372       addTo.pointerAlignment = 0;
5373
5374    addTo.structAlignment = Max(addTo.structAlignment, dataMember.structAlignment);
5375
5376    dataMember.offset = (addTo.type == unionMember) ? 0 : addTo.memberOffset;
5377
5378    if(dataMember.structAlignment)
5379    {
5380       if(addTo.memberOffset % dataMember.structAlignment)
5381          addTo.memberOffset += dataMember.structAlignment - (addTo.memberOffset % dataMember.structAlignment);
5382    }
5383
5384    if(addTo.type == unionMember)
5385    {
5386       if(dataMember.memberOffset > addTo.memberOffset)
5387          addTo.memberOffset = dataMember.memberOffset;
5388    }
5389    else
5390       addTo.memberOffset += dataMember.memberOffset;
5391    return true;
5392 }
5393
5394 public dllexport bool eClass_AddMember(Class _class, DataMember dataMember)
5395 {
5396    if(!_class || _class.comRedefinition || (dataMember.name && _class.members.FindString(dataMember.name)))
5397    {
5398       DataMember_Free(dataMember);
5399       delete dataMember;
5400       return false;
5401    }
5402    _class.membersAndProperties.Add(dataMember);
5403
5404    if(dataMember.name)
5405       _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5406
5407    //dataMember._class = _class;
5408    SetMemberClass(dataMember, _class);
5409
5410    //dataMember.id = _class.memberID++;
5411    dataMember.id = _class.memberID;
5412
5413    if(dataMember.pointerAlignment && dataMember.structAlignment <= 4)
5414       _class.pointerAlignment = 1;
5415    else if(!dataMember.pointerAlignment && dataMember.structAlignment >= 8)
5416       _class.pointerAlignment = 0;
5417
5418    _class.structAlignment = Max(_class.structAlignment, dataMember.structAlignment);
5419    if(dataMember.type == unionMember)
5420       _class.memberID += 1;
5421    else
5422       _class.memberID += dataMember.memberID;
5423
5424    if(dataMember.structAlignment)
5425    {
5426       if(_class.memberOffset % dataMember.structAlignment)
5427          _class.memberOffset += dataMember.structAlignment - (_class.memberOffset % dataMember.structAlignment);
5428    }
5429
5430    dataMember.offset = _class.memberOffset;
5431    _class.memberOffset += dataMember.memberOffset;
5432    return true;
5433 }
5434
5435 public dllexport BitMember eClass_AddBitMember(Class _class, const char * name, const char * type, int bitSize, int bitPos, AccessMode declMode)
5436 {
5437    if(_class && name && !_class.members.FindString(name))
5438    {
5439       uint64 mask = 0;
5440       int c;
5441       BitMember bitMember
5442       {
5443          name = CopyString(name);
5444          _class = _class;
5445          dataTypeString = CopyString(type);
5446          id = _class.memberID++;
5447          memberAccess = declMode;
5448       };
5449       _class.membersAndProperties.Add(bitMember);
5450       if(bitSize)
5451       {
5452          bitMember.pos = (bitPos == -1) ? _class.memberOffset : bitPos;
5453          bitMember.size = bitSize;
5454          _class.memberOffset = bitMember.pos + bitMember.size;
5455          for(c = 0; c<bitSize; c++)
5456          {
5457             if(c)
5458                mask <<= 1;
5459             mask |= 1;
5460          }
5461          bitMember.mask = mask << bitMember.pos;
5462       }
5463
5464      _class.members.Add((BTNode)BTNamedLink { name = bitMember.name, data = bitMember });
5465       return bitMember;
5466    }
5467    return null;
5468 }
5469
5470 static Module Module_Load(Module fromModule, const char * name, AccessMode importAccess, bool ensureCOM)
5471 {
5472    bool (stdcall * Load)(Module module) = null;
5473    bool (stdcall * Unload)(Module module) = null;
5474    Module module;
5475
5476    for(module = fromModule.application.allModules.first; module; module = module.next)
5477    {
5478       if(!strcmp(module.name, name))
5479          break;
5480    }
5481    if(ensureCOM && (!strcmp(name, "ecereCOM") || !strcmp(name, "ecere")))
5482    {
5483       for(module = fromModule.application.allModules.first; module; module = module.next)
5484       {
5485          if(!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM"))
5486             break;
5487       }
5488    }
5489    if(!module)
5490    {
5491       void * library = null;
5492
5493       if(ensureCOM && !strcmp(name, "ecereCOM"))
5494       {
5495          Load = COM_LOAD_FUNCTION;
5496          Unload = COM_UNLOAD_FUNCTION;
5497       }
5498       else
5499       {
5500          const char * libLocation = null;
5501 #if defined(__ANDROID__)
5502          libLocation = AndroidInterface_GetLibLocation(fromModule.application);
5503 #endif
5504          library = Instance_Module_Load(libLocation, name, &Load, &Unload);
5505       }
5506       if(Load)
5507       {
5508          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5509          module.application = fromModule.application;
5510          module.library = library;
5511          {
5512             char moduleName[MAX_FILENAME];
5513             char ext[MAX_EXTENSION];
5514             GetLastDirectory(name, moduleName);
5515             GetExtension(moduleName, ext);
5516             StripExtension(moduleName);
5517             if((!strcmpi(ext, "dylib") || !strcmpi(ext, "so")) && strstr(moduleName, "lib") == moduleName)
5518             {
5519                int len = (int)strlen(moduleName) - 3;
5520                memmove(moduleName, moduleName + 3, len);
5521                moduleName[len] = 0;
5522             }
5523             module.name = CopyString(moduleName);
5524          }
5525          module.Unload = Unload;
5526          module.origImportType = normalImport;
5527
5528          if(!Load(module))
5529          {
5530             eInstance_Delete((Instance)module);
5531             module = null;
5532          }
5533       }
5534       fromModule.application.allModules.Add(module);
5535    }
5536    if(ensureCOM && !strcmp(name, "ecere") && module)
5537    {
5538       name = !strcmp(module.name, "ecereCOM") ? "ecere" : "ecereCOM";
5539       if((!Load && !strcmp(module.name, "ecereCOM")) ||
5540          (Load && (!__thisModule || !__thisModule.name || !strcmp(__thisModule.name, "ecereCOM")) && Load != (void *)COM_LOAD_FUNCTION))
5541       {
5542          Module module;
5543          for(module = fromModule.application.allModules.first; module; module = module.next)
5544          {
5545             if(!strcmp(module.name, name))
5546                break;
5547          }
5548          if(!module)
5549          {
5550             Load = COM_LOAD_FUNCTION;
5551             Unload = COM_UNLOAD_FUNCTION;
5552
5553             module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5554             module.application = fromModule.application;
5555             module.library = null;
5556             module.name = CopyString(name);
5557             module.Unload = Unload;
5558
5559             if(!Load(module))
5560             {
5561                eInstance_Delete((Instance)module);
5562                module = null;
5563             }
5564
5565             fromModule.application.allModules.Add(module);
5566          }
5567          if(module)
5568          {
5569             if(fromModule)
5570             {
5571                fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5572             }
5573             incref module;
5574          }
5575       }
5576    }
5577    if(module)
5578    {
5579       if(fromModule)
5580       {
5581          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5582       }
5583       incref module;
5584    }
5585 #if defined(_DEBUG)
5586    InternalModuleLoadBreakpoint();
5587 #endif
5588    return module;
5589 }
5590
5591 public dllexport Module eModule_Load(Module fromModule, const char * name, AccessMode importAccess)
5592 {
5593    return Module_Load(fromModule, name, importAccess, true);
5594 }
5595
5596 public dllexport Module eModule_LoadStrict(Module fromModule, const char * name, AccessMode importAccess)
5597 {
5598    return Module_Load(fromModule, name, importAccess, false);
5599 }
5600
5601 public dllexport Module eModule_LoadStatic(Module fromModule, const char * name, AccessMode importAccess, bool (* Load)(Module module), bool (* Unload)(Module module))
5602 {
5603    Module module;
5604    for(module = fromModule.application.allModules.first; module; module = module.next)
5605    {
5606       if(!strcmp(module.name, name))
5607          break;
5608    }
5609    if(!module)
5610    {
5611       if(Load)
5612       {
5613          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5614          module.application = fromModule.application;
5615          module.name = CopyString(name);
5616          module.origImportType = staticImport;
5617          module.Unload = (void *)Unload;
5618          if(!Load(module))
5619          {
5620             eInstance_Delete((Instance)module);
5621             module = null;
5622          }
5623       }
5624       fromModule.application.allModules.Add(module);
5625    }
5626    if(module)
5627    {
5628       if(fromModule)
5629       {
5630          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5631       }
5632       incref module;
5633    }
5634    return module;
5635 }
5636
5637 public dllexport void eModule_Unload(Module fromModule, Module module)
5638 {
5639    OldLink m;
5640    for(m = fromModule.modules.first; m; m = m.next)
5641    {
5642       if(m.data == module)
5643          break;
5644    }
5645    if(m)
5646    {
5647       fromModule.modules.Delete(m);
5648       delete module;
5649    }
5650 }
5651
5652 public dllexport void eEnum_AddFixedValue(Class _class, const char * string, int64 value)
5653 {
5654    if(_class && _class.type == enumClass)
5655    {
5656       EnumClassData data = (EnumClassData)_class.data;
5657       NamedLink64 item;
5658
5659       for(item = data.values.first; item; item = item.next)
5660          if(!strcmp(item.name, string))
5661             break;
5662       if(!item)
5663       {
5664          data.values.Add(NamedLink64 { data = value, name = CopyString(string) });
5665          if(value > data.largest)
5666             data.largest = value;
5667       }
5668    }
5669 }
5670
5671 public dllexport int64 eEnum_AddValue(Class _class, const char * string)
5672 {
5673    if(_class && _class.type == enumClass)
5674    {
5675       EnumClassData data = (EnumClassData)_class.data;
5676       int64 value = data.largest + 1;
5677       NamedLink64 item;
5678       for(item = data.values.first; item; item = item.next)
5679          if(!strcmp(item.name, string))
5680             break;
5681       if(!item)
5682       {
5683          data.values.Add(NamedLink64 { data = value, name = CopyString(string) });
5684          if(value > data.largest)
5685             data.largest = value;
5686          return value;
5687       }
5688    }
5689    return -1;
5690 }
5691
5692 static void NameSpace_Free(NameSpace parentNameSpace)
5693 {
5694    NameSpace * nameSpace;
5695    delete (void *)parentNameSpace.name;
5696
5697          /*   {
5698       BTNamedLink n, next;
5699       for(n = (BTNamedLink)parentNameSpace.classes.first; n; n = next)
5700       {
5701          Class c = n.data;
5702
5703          next = (BTNamedLink)((BTNode)n).next;
5704
5705          if(c.templateClass)
5706             eClass_Unregister(c);
5707       }
5708    }         */
5709
5710    while((nameSpace = (NameSpace *)parentNameSpace.nameSpaces.first))
5711    {
5712       NameSpace_Free(nameSpace);
5713       parentNameSpace.nameSpaces.Delete((BTNode)nameSpace);
5714    }
5715 }
5716
5717 static void Application_Destructor(Application app)
5718 {
5719    if(app.parsedCommand)
5720    {
5721       delete (void *)app.argv;
5722       delete app.parsedCommand;
5723    }
5724 }
5725
5726 static bool Module_Constructor(Module module)
5727 {
5728    module.privateNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5729    module.privateNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5730    module.privateNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5731    module.privateNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5732
5733    module.publicNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5734    module.publicNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5735    module.publicNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5736    module.publicNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5737    return true;
5738 }
5739
5740 static void Module_Destructor(Module module)
5741 {
5742    Class _class;
5743    DefinedExpression def;
5744    GlobalFunction function;
5745    Module m;
5746    SubModule handle;
5747
5748    // printf("Destructing module %s\n", module.name);
5749
5750    // Take out references from all modules
5751    for(m = module.application.allModules.first; m; m = m.next)
5752    {
5753       SubModule next;
5754       for(handle = m.modules.first; handle; handle = next)
5755       {
5756          next = handle.next;
5757          if(handle.module == module)
5758             m.modules.Delete(handle);
5759       }
5760    }
5761
5762    if(module.Unload)
5763    {
5764       if(module.origImportType == staticImport)
5765       {
5766          bool (* Unload)(Module module) = (void *)module.Unload;
5767          Unload(module);
5768       }
5769       else
5770       {
5771          bool (stdcall * Unload)(Module module) = (void *)module.Unload;
5772          Unload(module);
5773       }
5774    }
5775
5776    // Unload dependencies
5777    {
5778       Module ourWorld = class(Class).module;
5779       void * ourHandle = null;
5780       while((handle = module.modules.last))  // STARTING WITH LAST SO THAT ecereCOM IS UNLOADED LAST...
5781       {
5782          Module depModule = handle.module;
5783          if(depModule == ourWorld)
5784          {
5785             module.modules.Remove(handle);
5786             ourHandle = handle;
5787          }
5788          else
5789          {
5790             module.modules.Delete(handle);
5791             delete depModule;
5792          }
5793       }
5794       if(ourHandle)
5795       {
5796          delete ourHandle;
5797          delete ourWorld;
5798       }
5799    }
5800
5801    // Unload classes
5802    for(;(_class = module.classes.first);)
5803    {
5804       if(_class.nameSpace)
5805       {
5806          BTNamedLink classLink = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
5807          if(classLink)
5808          {
5809             OldLink t;
5810             for(t = _class.templatized.first; t; t = t.next)
5811             {
5812                Class template = t.data;
5813                BTNamedLink link;
5814                link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
5815
5816                template.nameSpace->classes.Delete((BTNode)link);
5817                template.nameSpace = null;
5818             }
5819             _class.nameSpace->classes.Delete((BTNode)classLink);
5820          }
5821 #ifdef _DEBUG
5822          else
5823          {
5824             printf("Warning: Could not find %s in namespace classes while destructing module %s\n", _class.name, module.name);
5825          }
5826 #endif
5827          _class.nameSpace = null;
5828       }
5829       _class.module = null;
5830       module.classes.Remove(_class);
5831       if(_class.count <= 0 || _class.type != normalClass || _class.isInstanceClass)
5832          eClass_Unregister(_class);
5833       else
5834       {
5835 #ifdef MEMINFO
5836          // printf("Delayed destruction of class %s\n", _class.name);
5837 #endif
5838       }
5839    }
5840
5841    // Unload defines
5842    for(;(def = module.defines.first);)
5843    {
5844       if(def.nameSpace)
5845       {
5846          BTNamedLink defLink;
5847          for(defLink = (BTNamedLink)def.nameSpace->defines.first; defLink; defLink = (BTNamedLink)((BTNode)defLink).next)
5848             if(defLink.data == def)
5849             {
5850                def.nameSpace->defines.Delete((BTNode)defLink);
5851                break;
5852             }
5853       }
5854       delete (void *)def.name;
5855       delete (void *)def.value;
5856       module.defines.Delete(def);
5857    }
5858
5859    // Unload functions
5860    for(;(function = module.functions.first);)
5861    {
5862       if(function.nameSpace)
5863       {
5864          BTNamedLink functionLink;
5865          for(functionLink = (BTNamedLink)function.nameSpace->functions.first; functionLink; functionLink = (BTNamedLink)((BTNode)functionLink).next)
5866             if(functionLink.data == function)
5867             {
5868                function.nameSpace->functions.Delete((BTNode)functionLink);
5869                break;
5870             }
5871       }
5872       delete (void *)function.name;
5873       delete (void *)function.dataTypeString;
5874       module.functions.Delete(function);
5875    }
5876
5877    delete (void *)module.name;
5878
5879    NameSpace_Free(module.privateNameSpace);
5880    NameSpace_Free(module.publicNameSpace);
5881
5882    if(module != module.application)
5883       module.application.allModules.Remove(module);
5884    else
5885       NameSpace_Free(module.application.systemNameSpace);
5886
5887 #ifndef MEMINFO
5888    Instance_Module_Free(module.library);
5889 #endif
5890 }
5891
5892 static int64 GetEnumSize(Class _class)
5893 {
5894    EnumClassData data = (EnumClassData)_class.data;
5895    return data.largest+1;
5896 }
5897
5898 #if defined(__GNUC__)
5899 #define strcmpi strcasecmp
5900 #define strnicmp strncasecmp
5901 #endif
5902
5903 #if defined(ECERE_BOOTSTRAP) || (defined(__GNUC__) && !defined(__DJGPP__) && !defined(__WIN32__) && !defined(__EMSCRIPTEN__))
5904 #undef strlwr
5905 #undef strupr
5906 default dllexport char * strlwr(char *string)
5907 {
5908    int c;
5909    for(c=0; string[c]; c++)
5910       if(string[c]>='A' && string[c]<='Z')
5911          string[c]+='a'-'A';
5912    return string;
5913 }
5914 default dllexport char * strupr(char *string)
5915 {
5916    int c;
5917    for(c=0; string[c]; c++)
5918       if(string[c]>='a' && string[c]<='z')
5919          string[c]-='a'-'A';
5920    return string;
5921 }
5922 #endif
5923
5924 public dllexport DefinedExpression eSystem_RegisterDefine(const char * name, const char * value, Module module, AccessMode declMode)
5925 {
5926    NameSpace * nameSpace = null;
5927
5928    int start = 0, c;
5929
5930    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5931    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5932
5933    if(declMode != staticAccess)
5934    {
5935       for(c = 0; name[c]; c++)
5936       {
5937          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5938          {
5939             NameSpace * newSpace;
5940
5941             char * spaceName = _malloc(c - start + 1);
5942             strncpy(spaceName, name + start, c - start);
5943             spaceName[c-start] = '\0';
5944
5945             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5946             if(!newSpace)
5947             {
5948                newSpace = new0 NameSpace[1];
5949                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5950                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5951                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5952                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5953                newSpace->name = spaceName;
5954                newSpace->parent = nameSpace;
5955                nameSpace->nameSpaces.Add((BTNode)newSpace);
5956             }
5957             else
5958                delete spaceName;
5959             nameSpace = newSpace;
5960             if(name[c] == ':') c++;
5961             start = c+1;
5962          }
5963       }
5964    }
5965    else
5966       c = (int)strlen(name);
5967
5968    if(c - start && !nameSpace->defines.FindString(name + start))
5969    {
5970       DefinedExpression def
5971       {
5972          name = CopyString(name);
5973          nameSpace = nameSpace;
5974          value = CopyString(value);
5975       };
5976       nameSpace->defines.Add((BTNode)BTNamedLink { name = def.name + start, data = def });
5977       // Reference the definition in the module
5978       module.defines.Add(def);
5979       return def;
5980    }
5981    return null;
5982 }
5983
5984 public dllexport GlobalFunction eSystem_RegisterFunction(const char * name, const char * type, void * func, Module module, AccessMode declMode)
5985 {
5986    NameSpace * nameSpace = null;
5987    int start = 0, c;
5988
5989    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5990    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5991
5992    if(declMode != staticAccess)
5993    {
5994       for(c = 0; name[c]; c++)
5995       {
5996          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5997          {
5998             NameSpace * newSpace;
5999
6000             char * spaceName = _malloc(c - start + 1);
6001             strncpy(spaceName, name + start, c - start);
6002             spaceName[c-start] = '\0';
6003
6004             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
6005             if(!newSpace)
6006             {
6007                newSpace = new0 NameSpace[1];
6008                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
6009                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
6010                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
6011                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
6012                newSpace->name = spaceName;
6013                newSpace->parent = nameSpace;
6014                nameSpace->nameSpaces.Add((BTNode)newSpace);
6015             }
6016             else
6017                delete spaceName;
6018             nameSpace = newSpace;
6019             if(name[c] == ':') c++;
6020             start = c+1;
6021          }
6022       }
6023    }
6024    else
6025       c = (int)strlen(name);
6026
6027    if(c - start && !nameSpace->functions.FindString(name + start))
6028    {
6029       GlobalFunction function
6030       {
6031          name = CopyString(name);
6032          nameSpace = nameSpace;
6033          dataTypeString = CopyString(type);
6034          function = func;
6035          module = module;
6036       };
6037       nameSpace->functions.Add((BTNode)BTNamedLink { name = function.name + start, data = function });
6038       // Reference the definition in the module
6039       module.functions.Add(function);
6040       return function;
6041    }
6042    return null;
6043 }
6044
6045 public dllexport DefinedExpression eSystem_FindDefine(Module module, const char * name)
6046 {
6047    if(name && module)
6048    {
6049       BTNamedLink link;
6050       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->defines);
6051       if(link) return link.data;
6052
6053       link = SearchModule(module, name, &((NameSpace *)0)->defines, true);
6054       if(link) return link.data;
6055    }
6056    return null;
6057 }
6058
6059 public dllexport GlobalFunction eSystem_FindFunction(Module module, const char * name)
6060 {
6061    if(name && module)
6062    {
6063       BTNamedLink link;
6064       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->functions);
6065       if(link) return link.data;
6066
6067       link = SearchModule(module, name, &((NameSpace *)0)->functions, true);
6068       if(link) return link.data;
6069    }
6070    return null;
6071 }
6072
6073 public dllexport void * eSystem_Renew(void * memory, unsigned int size)
6074 {
6075    return _realloc(memory, size);
6076 }
6077
6078 public dllexport void * eSystem_Renew0(void * memory, unsigned int size)
6079 {
6080    return _crealloc(memory, size);
6081 }
6082
6083 public dllexport void * eSystem_New(unsigned int size)
6084 {
6085 /*#ifdef _DEBUG
6086    void * pointer = _malloc(size);
6087    memset(pointer, 0xec, size);
6088    return pointer;
6089 #else*/
6090    return _malloc(size);
6091 //#endif
6092 }
6093
6094 public dllexport void * eSystem_New0(unsigned int size)
6095 {
6096    return _calloc(1,size);
6097 }
6098
6099 public dllexport void eSystem_Delete(void * memory)
6100 {
6101    if(memory)
6102       _free(memory);
6103 }
6104
6105 // Properties
6106 public dllexport void eInstance_FireSelfWatchers(Instance instance, Property _property)
6107 {
6108    if(instance && _property && _property.selfWatchable)
6109    {
6110       Class _class;
6111       for(_class = instance._class; _class; _class = _class.base)
6112       {
6113          SelfWatcher selfWatcher, next;
6114          for(selfWatcher = _class.selfWatchers.first; selfWatcher; selfWatcher = next)
6115          {
6116             next = selfWatcher.next;
6117             if(selfWatcher._property == _property)
6118                selfWatcher.callback(instance);
6119          }
6120       }
6121    }
6122 }
6123
6124 public dllexport void eInstance_FireWatchers(Instance instance, Property _property)
6125 {
6126    if(instance && _property && _property.isWatchable)
6127    {
6128       Module module = instance._class ? instance._class.module : null;
6129       Application application = module ? module.application : null;
6130       int flags = application ? application.isGUIApp : 0;
6131       bool inCompiler = (flags & 8) ? true : false;
6132       bool force32Bits = (flags & 4) ? true : false;
6133       if(!force32Bits || !inCompiler)
6134       {
6135          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6136          Watcher watcher, next;
6137
6138          for(watcher = watchers->first; watcher; watcher = next)
6139          {
6140             next = watcher.next;
6141             watcher.callback(watcher.object, instance);
6142          }
6143       }
6144    }
6145 }
6146
6147 public dllexport void eProperty_Watchable(Property _property)
6148 {
6149    if(!_property.isWatchable)
6150    {
6151       Class _class = _property._class;
6152       if(!_class.computeSize)
6153       {
6154          _property.watcherOffset = _class.structSize;
6155          _class.structSize += sizeof(OldList);
6156
6157          // highly inefficient
6158          FixDerivativesBase(_class, _class);
6159       }
6160       _property.isWatchable = true;
6161    }
6162 }
6163
6164 public dllexport void eClass_DestructionWatchable(Class _class)
6165 {
6166    if(!_class.destructionWatchOffset)
6167    {
6168       _class.destructionWatchOffset = _class.structSize;
6169       _class.structSize += sizeof(OldList);
6170       // highly inefficient
6171       FixDerivativesBase(_class, _class);
6172    }
6173 }
6174
6175 public dllexport void eProperty_SelfWatch(Class _class, const char * name, void (*callback)(void *))
6176 {
6177    if(_class)
6178    {
6179       Property _property = eClass_FindProperty(_class, name, _class.module);
6180
6181       if(!_property)
6182          _property = eClass_AddProperty(_class, name, null, null, null, baseSystemAccess /*privateAccess*/);
6183       _class.selfWatchers.Add(SelfWatcher { _property = _property, callback = callback });
6184       _property.selfWatchable = true;
6185    }
6186 }
6187
6188 public dllexport void eInstance_Watch(void * instance, Property _property, void * object, void (*callback)(void *, void *))
6189 {
6190    if(_property.isWatchable)
6191    {
6192       OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6193       watchers->Add(Watcher { callback = callback, object = object });
6194    }
6195 }
6196
6197 public dllexport void eInstance_WatchDestruction(Instance instance, Instance object, void (*callback)(void *, void *))
6198 {
6199    OldList * watchers = (OldList *)((byte *)instance + instance._class.destructionWatchOffset);
6200    watchers->Add(Watcher { callback = callback, object = object });
6201 }
6202
6203 public dllexport void eInstance_StopWatching(Instance instance, Property _property, Instance object)
6204 {
6205    if(instance && (!_property || _property.isWatchable))
6206    {
6207       if(_property)
6208       {
6209          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6210          Watcher watcher;
6211          for(watcher = watchers->first; watcher; watcher = watcher.next)
6212             if(watcher.object == object)
6213             {
6214                watchers->Delete(watcher);
6215                break;
6216             }
6217       }
6218       else
6219       {
6220          // Stop watching all properties as well as destruction
6221          Class _class, base;
6222          for(_class = instance._class; _class; _class = base)
6223          {
6224             if(_class.destructionWatchOffset)
6225             {
6226                OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
6227                Watcher watcher;
6228
6229                for(watcher = watchers->first; watcher; watcher = watcher.next)
6230                {
6231                   watchers->Delete(watcher);
6232                   break;
6233                }
6234             }
6235             for(_property = (Property)_class.membersAndProperties.first; _property; _property = _property.next)
6236             {
6237                if(_property.isProperty && _property.isWatchable)
6238                {
6239                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6240                   Watcher watcher;
6241                   for(watcher = watchers->first; watcher; watcher = watcher.next)
6242                      if(watcher.object == object)
6243                      {
6244                         watchers->Delete(watcher);
6245                         break;
6246                      }
6247                }
6248             }
6249             base = _class.base;
6250             if(base && (base.type == systemClass || base.isInstanceClass)) base = null;
6251          }
6252       }
6253    }
6254 }
6255
6256 public dllexport subclass(ClassDesignerBase) eClass_GetDesigner(Class _class)
6257 {
6258    for(;_class;_class = _class.base)
6259    {
6260       if(_class.designerClass)
6261          return (subclass(ClassDesignerBase))eSystem_FindClass(_class.module, _class.designerClass);
6262    }
6263    return null;
6264 }
6265
6266
6267 public dllexport subclass(ClassDesignerBase) eInstance_GetDesigner(Instance instance)
6268 {
6269    if(instance)
6270       return eClass_GetDesigner(instance._class);
6271    return null;
6272 }
6273
6274 public bool LocateModule(const char * name, const char * fileName)
6275 {
6276    return Instance_LocateModule(name, fileName);
6277 }
6278
6279 /*
6280 #if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__)
6281 #define _64BIT 1
6282 #else
6283 #define _64BIT 0
6284 #endif
6285
6286 #define arch_PointerSize                  sizeof(void *)
6287 #define structSize_Instance               (_64BIT ? 24 : 12)
6288 #define structSize_Module                 (_64BIT ? 560 : 300)
6289 #define structSize_BinaryTree             (_64BIT ? 32 : 16)
6290 #define structSize_OldList                (_64BIT ? 32 : 20)
6291 #define structSize_NamedLink64            (_64BIT ? 32 : 24)
6292 #define structSize_ClassTemplateArgument  (_64BIT ? 16 : 8)
6293 #define structSize_ClassTemplateParameter (_64BIT ? 64 : 40)
6294 #define structSize_OldLink                (_64BIT ? 24 : 12)
6295 #define structSize_BTNamedLink            (_64BIT ? 48 : 24)
6296 #define structSize_Application            (_64BIT ? 800 : 428)
6297 #define structSize_Watcher                (_64BIT ? 32 : 16)
6298 #define structSize_SelfWatcher            (_64BIT ? 32 : 16)
6299 #define structSize_GlobalFunction         (_64BIT ? 72 : 36)
6300 #define structSize_DefinedExpression      (_64BIT ? 40 : 20)
6301 #define structSize_BitMember              (_64BIT ? 96 : 64)
6302 #define structSize_DataMember             (_64BIT ? 160 : 96)
6303 #define structSize_ClassProperty          (_64BIT ? 80 : 40)
6304 #define structSize_Method                 (_64BIT ? 96 : 52)
6305 #define structSize_Property               (_64BIT ? 152 : 88)
6306 #define structSize_Class                  (_64BIT ? 624 : 376)
6307 */
6308
6309 static void LoadCOM(Module module)
6310 {
6311    bool force64Bits = (module.application.isGUIApp & 2) ? true : false;
6312    bool force32Bits = (module.application.isGUIApp & 4) ? true : false;
6313    bool inCompiler = (module.application.isGUIApp & 8) ? true : false;
6314    int pointerSize = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
6315    Class applicationClass;
6316    Class enumClass, structClass, boolClass;
6317    Class moduleClass;
6318
6319    // Create Base Class
6320    Class baseClass = eSystem_RegisterClass(normalClass, "class", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6321    baseClass.type = systemClass;
6322    baseClass.memberOffset = 0;
6323    baseClass.offset = 0;
6324    baseClass.structSize = 0;
6325    baseClass.typeSize = 0;
6326
6327    {
6328       Class instanceClass = eSystem_RegisterClass(normalClass, "ecere::com::Instance", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6329       instanceClass.type = normalClass;
6330       instanceClass.isInstanceClass = true;
6331       instanceClass.fixed = true;
6332       instanceClass.memberOffset = 0;
6333       instanceClass.offset = 0;
6334
6335       instanceClass.memberID = -3;
6336       instanceClass.startMemberID = -3;
6337
6338       eClass_AddDataMember(instanceClass, "_vTbl", "void **", pointerSize, pointerSize, publicAccess);
6339       eClass_AddDataMember(instanceClass, "_class", "ecere::com::Class", pointerSize, pointerSize, publicAccess);
6340       eClass_AddDataMember(instanceClass, "_refCount", "int", sizeof(int), sizeof(int), publicAccess);
6341    }
6342
6343    InitializeDataTypes1(module);
6344
6345    // Create Enum class
6346    enumClass = eSystem_RegisterClass(normalClass, "enum", null, 0, force64Bits ? 40 : sizeof(class EnumClassData), null, null, module, baseSystemAccess, publicAccess);
6347    eClass_AddClassProperty(enumClass, "enumSize", "int", null, GetEnumSize).constant = true;
6348    enumClass.type = systemClass;
6349
6350    delete (void *)enumClass.dataTypeString;
6351    enumClass.dataTypeString = CopyString(/*"unsigned int"*/"int");
6352
6353    // Create Struct (simple) class
6354    //structClass = eSystem_RegisterClass(structClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6355    structClass = eSystem_RegisterClass(normalClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6356    structClass.type = systemClass;
6357    structClass.memberOffset = 0;
6358    structClass.offset = 0;
6359    structClass.structSize = 0;
6360    structClass.typeSize = 0;
6361
6362    //eClass_AddMethod(enumClass, "AddValue", "int()", eEnum_AddValue);
6363    //eClass_AddMethod(enumClass, "AddFixedValue", "void()", eEnum_AddFixedValue);
6364
6365    InitializeDataTypes(module);
6366
6367    // Create bool class
6368    boolClass = eSystem_RegisterClass(ClassType::enumClass, "bool", "uint", 0, 0, null, null, module, baseSystemAccess, publicAccess);
6369    eEnum_AddFixedValue(boolClass, "true",  bool::true);
6370    eEnum_AddFixedValue(boolClass, "false", bool::false);
6371
6372    // Create Module class
6373    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) :
6374                                                                                 sizeof(struct Module), 0, (void *)Module_Constructor, (void *)Module_Destructor, module, baseSystemAccess, publicAccess);
6375    eClass_AddVirtualMethod(moduleClass, "OnLoad", "bool()", null, publicAccess);
6376    eClass_AddVirtualMethod(moduleClass, "OnUnload", "void()", null, publicAccess);
6377    eClass_AddMethod(moduleClass, "Load", "Module(const char * name, AccessMode importAccess)", eModule_Load, publicAccess);
6378    eClass_AddMethod(moduleClass, "Unload", "void(Module module)", eModule_Unload, publicAccess);
6379    eClass_AddDataMember(moduleClass, "application", "Application", pointerSize, pointerSize, publicAccess);
6380    eClass_AddDataMember(moduleClass, "classes", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6381    eClass_AddDataMember(moduleClass, "defines", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6382    eClass_AddDataMember(moduleClass, "functions", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6383    eClass_AddDataMember(moduleClass, "modules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6384    eClass_AddDataMember(moduleClass, "prev", "Module", pointerSize, pointerSize, publicAccess);
6385    eClass_AddDataMember(moduleClass, "next", "Module", pointerSize, pointerSize, publicAccess);
6386    eClass_AddDataMember(moduleClass, "name", "const char *", pointerSize, pointerSize, publicAccess);
6387    eClass_AddDataMember(moduleClass, "library", "void *", pointerSize, pointerSize, publicAccess);
6388    eClass_AddDataMember(moduleClass, "Unload", "void *", pointerSize, pointerSize, publicAccess);
6389    eClass_AddDataMember(moduleClass, "importType", "ImportType", sizeof(ImportType), 4, publicAccess);
6390    eClass_AddDataMember(moduleClass, "origImportType", "ImportType", sizeof(ImportType), 4, publicAccess);
6391    eClass_AddDataMember(moduleClass, "privateNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6392    eClass_AddDataMember(moduleClass, "publicNameSpace", "NameSpace",  force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6393    moduleClass.fixed = true;
6394    moduleClass.count++;
6395    if(inCompiler && force32Bits)
6396       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);
6397
6398    // Create Application class
6399    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);
6400    if(inCompiler && force32Bits)
6401    {
6402       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);
6403       applicationClass.structSize = applicationClass.offset + (4+4+4+4 + 20 + 4 + 88);
6404    }
6405    eClass_AddVirtualMethod(applicationClass, "Main", "void()", null, publicAccess);
6406    eClass_AddDataMember(applicationClass, "argc", "int", sizeof(int), 4, publicAccess);
6407    eClass_AddDataMember(applicationClass, "argv", "const char **", pointerSize, pointerSize, publicAccess);
6408    eClass_AddDataMember(applicationClass, "exitCode", "int", sizeof(int), 4, publicAccess);
6409    eClass_AddDataMember(applicationClass, "isGUIApp", "bool", sizeof(bool), 4, publicAccess);
6410    eClass_AddDataMember(applicationClass, "allModules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6411    eClass_AddDataMember(applicationClass, "parsedCommand", "char *", pointerSize, pointerSize, publicAccess);
6412    eClass_AddDataMember(applicationClass, "systemNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6413    applicationClass.fixed = true;
6414    applicationClass.count++;
6415
6416    //AttachConsole(-1);
6417    //AllocConsole();
6418
6419    // --- Math ---
6420    eSystem_RegisterFunction("sin", "double sin(Angle number)", sin, module, baseSystemAccess);
6421    eSystem_RegisterFunction("sinh", "double sinh(Angle number)", sinh, module, baseSystemAccess);
6422    eSystem_RegisterFunction("cosh", "double cosh(Angle number)", cosh, module, baseSystemAccess);
6423    eSystem_RegisterFunction("tanh", "double tanh(Angle number)", tanh, module, baseSystemAccess);
6424    eSystem_RegisterFunction("sqrt", "double sqrt(double number)", sqrt, module, baseSystemAccess);
6425    eSystem_RegisterFunction("cos", "double cos(Angle number)", cos, module, baseSystemAccess);
6426    eSystem_RegisterFunction("tan", "double tan(Angle number)", tan, module, baseSystemAccess);
6427    eSystem_RegisterFunction("atan2", "Angle atan2(double y, double x)", atan2, module, baseSystemAccess);
6428    eSystem_RegisterFunction("asin", "Angle asin(double number)", asin, module, baseSystemAccess);
6429    eSystem_RegisterFunction("acos", "Angle acos(double number)", acos, module, baseSystemAccess);
6430    eSystem_RegisterFunction("atan", "Angle atan(double number)", atan, module, baseSystemAccess);
6431    eSystem_RegisterFunction("asinh", "Angle asinh(double number)", asinh, module, baseSystemAccess);
6432    eSystem_RegisterFunction("acosh", "Angle acosh(double number)", acosh, module, baseSystemAccess);
6433    eSystem_RegisterFunction("atanh", "Angle atanh(double number)", atanh, module, baseSystemAccess);
6434    eSystem_RegisterFunction("pow", "double pow(double number, double number2)", pow, module, baseSystemAccess);
6435    eSystem_RegisterFunction("fmod", "double fmod(double x, double y)", fmod, module, baseSystemAccess);
6436    eSystem_RegisterFunction("fabs", "double fabs(double number)", fabs, module, baseSystemAccess);
6437    eSystem_RegisterFunction("log", "double log(double number)", log, module, baseSystemAccess);
6438    eSystem_RegisterFunction("log10", "double log10(double number)", log10, module, baseSystemAccess);
6439    eSystem_RegisterFunction("ceil", "double ceil(double number)", ceil, module, baseSystemAccess);
6440    eSystem_RegisterFunction("floor", "double floor(double number)", floor, module, baseSystemAccess);
6441    eSystem_RegisterFunction("exp", "double exp(double number)", exp, module, baseSystemAccess);
6442
6443    // --- Stdlib ---
6444    eSystem_RegisterFunction("qsort", "void qsort(void *, uintsize, uintsize, int (*)(void *, void *))", qsort, module, baseSystemAccess);
6445    eSystem_RegisterFunction("strtod", "double strtod(const char*, char**)", strtod, module, baseSystemAccess);
6446    eSystem_RegisterFunction("strtol", "int strtol(const char*, char**, int base)", strtol, module, baseSystemAccess);
6447    eSystem_RegisterFunction("strtoul", "unsigned long strtoul(const char * nptr, char ** endptr, int base)", strtoul, module, baseSystemAccess);
6448    eSystem_RegisterFunction("strtoll", "int64 strtoll(const char * nptr, char ** endptr, int base)", strtoll, module, baseSystemAccess);
6449    eSystem_RegisterFunction("strtoull", "uint64 strtoull(const char * nptr, char ** endptr, int base)", strtoull, module, baseSystemAccess);
6450    eSystem_RegisterFunction("system", "int system(const char*)", system, module, baseSystemAccess);
6451    eSystem_RegisterFunction("atoi", "int atoi(const char*)", atoi, module, baseSystemAccess);
6452    eSystem_RegisterFunction("atof", "double atof(const char*)", atof, module, baseSystemAccess);
6453    eSystem_RegisterFunction("memset", "void * memset(void * area, int value, uintsize count)", memset, module, baseSystemAccess);
6454    eSystem_RegisterFunction("getenv", "char * getenv(const char * name)", getenv, module, baseSystemAccess);
6455    eSystem_RegisterFunction("rename", "int rename(const char *oldpath, const char *newpath)", rename, module, baseSystemAccess);
6456
6457    // --- String --- (These might move to the string class)
6458    eSystem_RegisterFunction("strlen", "uintsize strlen(const char *)", strlen, module, baseSystemAccess);
6459    eSystem_RegisterFunction("strcat", "char * strcat(char *, const char *)", strcat, module, baseSystemAccess);
6460    eSystem_RegisterFunction("strncat", "char * strncat(char *, const char *, uintsize n)", strncat, module, baseSystemAccess);
6461    eSystem_RegisterFunction("strchr", "char * strchr(const char *, int)", strchr, module, baseSystemAccess);
6462    eSystem_RegisterFunction("strstr", "char * strstr(const char *, const char *)", strstr, module, baseSystemAccess);
6463    eSystem_RegisterFunction("strspn", "uintsize strspn(const char *, const char *)", strspn, module, baseSystemAccess);
6464    eSystem_RegisterFunction("strcspn", "uintsize strcspn(const char *, const char *)", strcspn, module, baseSystemAccess);
6465    eSystem_RegisterFunction("strpbrk", "char * strpbrk(const char *, const char *)", strpbrk, module, baseSystemAccess);
6466
6467    eSystem_RegisterDefine("fstrcmp", "(__runtimePlatform == win32) ? strcmpi : strcmp", module, baseSystemAccess);
6468
6469 //#if defined(__GNUC__)
6470    eSystem_RegisterDefine("strcmpi", "strcasecmp", module, baseSystemAccess);
6471    eSystem_RegisterDefine("strnicmp", "strncasecmp", module, baseSystemAccess);
6472    eSystem_RegisterFunction("strcasecmp", "int strcasecmp(const char *, const char *)", strcmpi, module, baseSystemAccess);
6473    eSystem_RegisterFunction("strncasecmp", "int strncasecmp(const char *, const char *, uintsize n)", strnicmp, module, baseSystemAccess);
6474 /*
6475 #else
6476    eSystem_RegisterDefine("strcasecmp", "strcmpi", module, baseSystemAccess);
6477    eSystem_RegisterDefine("strncasecmp", "strnicmp", module, baseSystemAccess);
6478    eSystem_RegisterFunction("strcmpi", "int strcmpi(const char *, const char *)", strcmpi, module, baseSystemAccess);
6479    eSystem_RegisterFunction("strnicmp", "int strnicmp(const char *, const char *, int n)", strnicmp, module, baseSystemAccess);
6480 #endif
6481 */
6482
6483    eSystem_RegisterFunction("strcmp", "int strcmp(const char *, const char *)", strcmp, module, baseSystemAccess);
6484    eSystem_RegisterFunction("strncmp", "int strncmp(const char *, const char *, uintsize n)", strncmp, module, baseSystemAccess);
6485    eSystem_RegisterFunction("strlwr", "char * strlwr(char *)", strlwr, module, baseSystemAccess);
6486    eSystem_RegisterFunction("strupr", "char * strupr(char *)", strupr, module, baseSystemAccess);
6487    eSystem_RegisterFunction("strcpy", "char * strcpy(char *, const char *)", strcpy, module, baseSystemAccess);
6488    eSystem_RegisterFunction("strncpy", "char * strncpy(char *, const char *, uintsize n)", strncpy, module, baseSystemAccess);
6489    eSystem_RegisterFunction("memcpy", "void * memcpy(void *, const void *, uintsize size)", memcpy, module, baseSystemAccess);
6490    eSystem_RegisterFunction("memmove", "void * memmove(void *, const void *, uintsize size)", memmove, module, baseSystemAccess);
6491    eSystem_RegisterFunction("memcmp", "int memcmp(const void *, const void *, uintsize size)", memcmp, module, baseSystemAccess);
6492
6493    // --- Stdio ---
6494    eSystem_RegisterFunction("sprintf", "int sprintf(char *, const char *, ...)", sprintf, module, baseSystemAccess);
6495    eSystem_RegisterFunction("snprintf", "int sprintf(char *, uintsize, const char *, ...)", snprintf, module, baseSystemAccess);
6496    eSystem_RegisterFunction("printf", "int printf(const char *, ...)", printf, module, baseSystemAccess);
6497    eSystem_RegisterFunction("vsprintf", "int vsprintf(char*, const char*, __builtin_va_list)", vsprintf, module, baseSystemAccess);
6498    eSystem_RegisterFunction("vsnprintf", "int vsnprintf(char*, uintsize, const char*, __builtin_va_list)", vsnprintf, module, baseSystemAccess);
6499    eSystem_RegisterFunction("puts", "int puts(const char *)", puts, module, baseSystemAccess);
6500    eSystem_RegisterFunction("fputs", "int fputs(const char *, void * stream)", fputs, module, baseSystemAccess);
6501
6502    // --- Ctype ---
6503    eSystem_RegisterFunction("tolower", "int tolower(int)", tolower, module, baseSystemAccess);
6504    eSystem_RegisterFunction("toupper", "int toupper(int)", toupper, module, baseSystemAccess);
6505    eSystem_RegisterFunction("isdigit", "bool isdigit(int)", isdigit, module, baseSystemAccess);
6506    eSystem_RegisterFunction("isxdigit","bool isxdigit(int)", isxdigit, module, baseSystemAccess);
6507    eSystem_RegisterFunction("isalnum", "int isalnum(int c)", isalnum, module, baseSystemAccess);
6508    eSystem_RegisterFunction("isspace", "int isspace(int c)", isspace, module, baseSystemAccess);
6509    eSystem_RegisterFunction("isalpha", "int isalpha(int c)", isalpha, module, baseSystemAccess);
6510    eSystem_RegisterFunction("islower", "int islower(int c)", islower, module, baseSystemAccess);
6511    eSystem_RegisterFunction("isupper", "int isupper(int c)", isupper, module, baseSystemAccess);
6512    eSystem_RegisterFunction("isprint", "int isprint(int c)", isprint, module, baseSystemAccess);
6513    eSystem_RegisterFunction("isblank", "int isblank(int c)", isblank, module, baseSystemAccess);
6514
6515 }
6516
6517 public dllexport Application __ecere_COM_Initialize(bool guiApp, int argc, char * argv[])
6518 {
6519    Application app;
6520
6521 #ifdef __ANDROID__
6522    // Clean up global variables
6523    memoryInitialized = false;
6524    pools = null;
6525 #ifdef MEMINFO
6526    memset(&memStacks, 0, sizeof(BinaryTree));
6527    memoryErrorsCount = 0;
6528    memset(&memBlocks, 0, sizeof(BinaryTree));
6529    recurse = false;
6530    blockID = 0;
6531    allocateClass = null;
6532    allocateInternal = false;
6533    TOTAL_MEM = 0;
6534    OUTSIDE_MEM = 0;
6535 #endif
6536 #endif
6537
6538 #ifdef _DEBUG
6539    // printf("Using debug ecere runtime library\n");
6540 #endif
6541    app = _calloc(1, sizeof(class Application));
6542
6543    Module_Constructor(app);
6544    app.systemNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
6545    app.systemNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
6546    app.systemNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
6547    app.systemNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
6548
6549    Instance_COM_Initialize(argc, argv, &app.parsedCommand, &app.argc, &app.argv);
6550
6551    app.application = app;
6552    app.allModules.offset = sizeof(class Instance) + (uint)(uintptr)&((struct Module *)0)->prev;
6553    app.isGUIApp = guiApp;
6554
6555    LoadCOM(app);
6556
6557    app._class = eSystem_FindClass(app, "Application");
6558
6559    return app;
6560 }
6561
6562 public dllexport ClassTemplateParameter eClass_AddTemplateParameter(Class _class, const char * name, TemplateParameterType type, const void * info, ClassTemplateArgument defaultArg)
6563 {
6564    if(_class && name)
6565    {
6566       ClassTemplateParameter param;
6567
6568       for(param = _class.templateParams.first; param; param = param.next)
6569       {
6570          if(!strcmp(param.name, name))
6571             return param;
6572       }
6573       param =
6574       {
6575          name = CopyString(name);
6576          type = type;
6577          (type == identifier) ? info : CopyString(info);
6578       };
6579       if(defaultArg != null)
6580       {
6581          param.defaultArg = defaultArg;
6582          CopyTemplateArg(param, param.defaultArg);
6583       }
6584       _class.templateParams.Add(param);
6585       return param;
6586    }
6587    return null;
6588 }
6589
6590 public dllexport void eClass_DoneAddingTemplateParameters(Class base)
6591 {
6592    if(base)
6593    {
6594       ClassTemplateParameter param;
6595       {
6596          void * first = base.templateParams.first;
6597          int count = base.templateParams.count;
6598
6599          FreeTemplateArgs(base);
6600          delete base.templateArgs;
6601
6602          base.templateParams.first = null;
6603          base.templateParams.count = 0;
6604
6605          FreeTemplatesDerivatives(base);
6606
6607          base.templateParams.first = first;
6608          base.templateParams.count = count;
6609       }
6610
6611       for(param = base.templateParams.first; param; param = param.next)
6612       {
6613          if(param.type == identifier && param.defaultArg.memberString)
6614          {
6615             Class memberClass = base;
6616             const char * colon = strstr(param.defaultArg.memberString, "::");
6617             const char * memberName;
6618             if(colon)
6619             {
6620                char className[1024];
6621                Class sClass;
6622
6623                memcpy(className, param.defaultArg.memberString, colon - param.defaultArg.memberString);
6624                className[colon - param.defaultArg.memberString] = '\0';
6625                memberName = colon + 2;
6626
6627                for(sClass = base; sClass; sClass = sClass.base)
6628                {
6629                   ClassTemplateParameter cParam;
6630                   Class nextClass;
6631                   int id = 0;
6632                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) id += nextClass.templateParams.count;
6633                   // Safety! What could cause base.templateArgs to be null?
6634                   if(sClass == base || base.templateArgs)
6635                   {
6636                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
6637                      {
6638                         if(cParam.type == type && !strcmp(cParam.name, className))
6639                            strcpy(className, (sClass == base) ? cParam.defaultArg.dataTypeString : base.templateArgs[id].dataTypeString);
6640                         id++;
6641                      }
6642                   }
6643                }
6644                memberClass = eSystem_FindClass(base.module, className);
6645                if(!memberClass)
6646                   memberClass = eSystem_FindClass(base.module.application, className);
6647             }
6648             else
6649                memberName = param.defaultArg.memberString;
6650
6651             if(memberClass)
6652             {
6653                switch(param.memberType)
6654                {
6655                   case dataMember:
6656                      param.defaultArg.member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
6657                      break;
6658                   case method:
6659                      param.defaultArg.method = eClass_FindMethod(memberClass, memberName, memberClass.module);
6660                      break;
6661                   case prop:
6662                      param.defaultArg.prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
6663                      break;
6664                }
6665             }
6666          }
6667       }
6668
6669       //ComputeClassParameters(base, null, null);
6670
6671       FixDerivativesBase(base, base);
6672    }
6673 }
6674
6675 static void FreeTemplatesDerivatives(Class base)
6676 {
6677    OldLink derivative, templateLink;
6678    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
6679    {
6680       Class _class = derivative.data;
6681       if(_class.templateArgs)
6682       {
6683          FreeTemplateArgs(_class);
6684          delete _class.templateArgs;
6685       }
6686       FreeTemplatesDerivatives(_class);
6687    }
6688
6689    for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
6690    {
6691       Class _class = templateLink.data;
6692       if(_class.templateArgs)
6693       {
6694          FreeTemplateArgs(_class);
6695          delete _class.templateArgs;
6696       }
6697       FreeTemplatesDerivatives(_class);
6698    }
6699 }
6700
6701 static const char * platformNames[Platform] = { "", "win32", "linux", "apple" }; // how to have this be accessible outside of dll/lib
6702 static const Platform firstPlatform = win32;
6703 static const Platform lastPlatform = apple;
6704
6705 public enum Platform
6706 {
6707    unknown, win32, tux, apple;
6708
6709    property const char *
6710    {
6711       get { return OnGetString(null, null, null); }
6712       set
6713       {
6714          if(value)
6715          {
6716             Platform c;
6717             for(c = firstPlatform; c <= lastPlatform; c++)
6718                if(!strcmpi(value, platformNames[c]))
6719                   return c;
6720          }
6721          return unknown;
6722       }
6723    };
6724
6725    const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
6726    {
6727       if(this >= firstPlatform && this <= lastPlatform)
6728       {
6729          if(tempString)
6730             strcpy(tempString, platformNames[this]);
6731          return platformNames[this];
6732       }
6733       if(tempString && tempString[0])
6734          tempString[0] = '\0';
6735       return null;
6736    }
6737
6738    bool OnGetDataFromString(const char * string)
6739    {
6740       this = string;
6741       return this != unknown;
6742    }
6743 };
6744
6745 default extern Platform runtimePlatform;
6746
6747 public Platform GetRuntimePlatform()
6748 {
6749    return runtimePlatform;
6750 }
6751
6752 namespace gui;
6753
6754 class Window;
6755
6756 namespace com;
6757 // CLASS DESIGNER SUPPORT
6758
6759 public class ObjectInfo : struct
6760 {
6761 public:
6762    ObjectInfo prev, next;
6763    Instance instance;
6764    char * name;
6765    Instantiation instCode;
6766    bool deleted;
6767    ObjectInfo oClass;
6768    OldList instances;
6769    ClassDefinition classDefinition;
6770    bool modified;
6771    void * i18nStrings;
6772 };
6773
6774 public class DesignerBase : Window
6775 {
6776 public:
6777    virtual bool FindObject(Instance * instance, const char * string);
6778    virtual void RenameObject(ObjectInfo object, const char * name);
6779    virtual void SelectObjectFromDesigner(ObjectInfo object);
6780    virtual void CodeAddObject(Instance instance, ObjectInfo * object);
6781    virtual void SheetAddObject(ObjectInfo object);
6782    virtual void AddToolBoxClass(Class _class);
6783    virtual void AddDefaultMethod(Instance instance, Instance classInstance);
6784    virtual void DeleteObject(ObjectInfo object);
6785    virtual bool ObjectContainsCode(ObjectInfo object);
6786    virtual void ModifyCode(void);
6787    virtual void UpdateProperties(void);
6788
6789    ClassDesignerBase classDesigner;
6790    const char * objectClass;
6791    bool isDragging;
6792
6793    // FIX THIS WITH PUBLIC:
6794    property ClassDesignerBase classDesigner
6795    {
6796       get { return classDesigner; }
6797       set { classDesigner = value; }
6798    };
6799    property const char * objectClass
6800    {
6801       get { return objectClass; }
6802       set { objectClass = value; }
6803    };
6804    property bool isDragging
6805    {
6806       get { return isDragging; }
6807       set { isDragging = value; }
6808    };
6809 }
6810
6811 public class ClassDesignerBase : Window
6812 {
6813 public:
6814    virtual void Reset(void);
6815    virtual void AddObject(void);
6816    virtual void SelectObject(ObjectInfo object, Instance control);
6817
6818    virtual void ListToolBoxClasses(DesignerBase designer);
6819
6820    virtual void ::PrepareTestObject(DesignerBase designer, Instance test);
6821    virtual void ::CreateObject(DesignerBase designer, Instance instance, ObjectInfo object, bool isClass, Instance _class);
6822    virtual void ::PostCreateObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6823    virtual void ::DroppedObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6824    virtual void ::DestroyObject(Instance object);
6825    virtual void ::FixProperty(Property prop, Instance object);
6826    virtual void ::CreateNew(EditBox editBox, Size clientSize, const char * name, const char * inherit);
6827 }
6828
6829 DesignerBase activeDesigner;
6830
6831 public void SetActiveDesigner(DesignerBase designer)
6832 {
6833    activeDesigner = designer;
6834 }
6835
6836 public DesignerBase GetActiveDesigner()
6837 {
6838    return activeDesigner;
6839 }
6840
6841
6842 bool poolingDisabled;
6843
6844 public dllexport void eSystem_SetPoolingDisabled(bool disabled)
6845 {
6846    poolingDisabled = disabled;
6847 }
6848
6849 namespace sys;
6850
6851 // constants
6852 define LEAD_OFFSET      = 0xD800 - (0x10000 >> 10);
6853 define SURROGATE_OFFSET = 0x10000 - (0xD800 << 10) - 0xDC00;
6854
6855 public bool UTF8Validate(const char * source)
6856 {
6857    if(source)
6858    {
6859       int c;
6860       for(c = 0; source[c];)
6861       {
6862          byte ch = source[c];
6863          unichar codePoint = 0;
6864          int numBytes = 1;
6865          int i;
6866          byte mask = 0x7F;
6867          if(ch & 0x80)
6868          {
6869             if(ch & 0x40)
6870             {
6871                mask >>= 2;
6872                numBytes++;
6873                if(ch & 0x20)
6874                {
6875                   numBytes++;
6876                   mask >>= 1;
6877                   if(ch & 0x10)
6878                   {
6879                      if(ch & 0x08)
6880                         return false;
6881                      numBytes++;
6882                      mask >>= 1;
6883                   }
6884                }
6885             }
6886             else
6887                return false;
6888          }
6889          for(i = 0; i<numBytes && (ch = source[c]); i++, c++)
6890          {
6891             codePoint <<= 6;
6892             codePoint |= ch & mask;
6893             mask = 0x3F;
6894             if(i > 1)
6895             {
6896                if(!(ch & 0x80) || (ch & 0x40))
6897                   return false;
6898             }
6899          }
6900          if(i < numBytes) return false;
6901
6902          if(codePoint > 0x10FFFF || (codePoint >= 0xD800 && codePoint <= 0xDFFF) ||
6903            (codePoint < 0x80 && numBytes > 1) ||
6904            (codePoint < 0x800 && numBytes > 2) ||
6905            (codePoint < 0x10000 && numBytes > 3))
6906             return false;
6907       }
6908    }
6909    return true;
6910 }
6911
6912 public int ISO8859_1toUTF8(const char * source, char * dest, int max)
6913 {
6914    int c;
6915    int d = 0;
6916    byte * byteDest = (byte *)dest;
6917    for(c = 0; source[c]; c++)
6918    {
6919       unichar ch = ((byte *)source)[c];
6920       switch(ch)
6921       {
6922          case 150: ch = (unichar)0x2012; break;
6923       }
6924       if(ch < 0x80)
6925       {
6926          if(d + 1 >= max) break;
6927          byteDest[d++] = (char)ch;
6928       }
6929       else if(ch < 0x800)
6930       {
6931          if(d + 2 >= max) break;
6932          byteDest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6933          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
6934       }
6935       else if(ch < 0x10000)
6936       {
6937          if(d + 3 >= max) break;
6938          byteDest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6939          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6940          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
6941       }
6942       else
6943       {
6944          if(d + 4 >= max) break;
6945          byteDest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6946          byteDest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6947          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6948          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
6949       }
6950    }
6951    dest[d] = 0;
6952    return d;
6953 }
6954
6955 public char * UTF16toUTF8(const uint16 * source)
6956 {
6957    int c;
6958    int d = 0;
6959    int len;
6960    byte * dest;
6961    uint16 u16;
6962    bool invert = false;
6963
6964    for(len = 0; source[len]; len++);
6965    dest = new byte[len * 3 + 1];
6966    for(c = 0; (u16 = source[c]); c++)
6967    {
6968       unichar ch;
6969       if(!c && (u16 == 0xFFFE || u16 == 0xFEFF))
6970       {
6971          if(u16 == 0xFFFE) invert = true;
6972          continue;
6973       }
6974       if(invert) { u16 = ((u16 & 0xFF00) >> 8) | ((u16 & 0x00FF) << 8); }
6975
6976       if(u16 < 0xD800 || u16 > 0xDBFF)
6977          ch = (unichar)u16;
6978       else
6979          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
6980
6981       if(ch < 0x80)
6982       {
6983          dest[d++] = (char)ch;
6984       }
6985       else if(ch < 0x800)
6986       {
6987          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6988          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6989       }
6990       else if(ch < 0x10000)
6991       {
6992          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6993          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6994          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6995       }
6996       else
6997       {
6998          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6999          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
7000          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7001          dest[d++] = 0x80 | (byte)(ch & 0x03F);
7002       }
7003    }
7004    dest[d] = 0;
7005    dest = renew dest byte[d+1];
7006    return (char *)dest;
7007 }
7008
7009 public int UTF16toUTF8Buffer(const uint16 * source, char * dest, int max)
7010 {
7011    int c;
7012    int d = 0;
7013    uint16 u16;
7014    byte * byteDest = (byte *)dest;
7015    for(c = 0; (u16 = source[c]); c++)
7016    {
7017       unichar ch;
7018       if(u16 < 0xD800 || u16 > 0xDBFF)
7019          ch = (unichar)u16;
7020       else
7021          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
7022
7023       if(ch < 0x80)
7024       {
7025          if(d + 1 >= max) break;
7026          byteDest[d++] = (char)ch;
7027       }
7028       else if(ch < 0x800)
7029       {
7030          if(d + 2 >= max) break;
7031          byteDest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
7032          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7033       }
7034       else if(ch < 0x10000)
7035       {
7036          if(d + 3 >= max) break;
7037          byteDest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
7038          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7039          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7040       }
7041       else
7042       {
7043          if(d + 4 >= max) break;
7044          byteDest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
7045          byteDest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
7046          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7047          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7048       }
7049    }
7050    byteDest[d] = 0;
7051    return d;
7052 }
7053
7054 // NOTE: UTF8GetChar now returns 0 into numBytes for the null-terminating character ('\0')
7055 public unichar UTF8GetChar(const char * string, int * numBytes)
7056 {
7057    unichar ch;
7058    byte b = ((byte *)string)[0];
7059    int i;
7060    byte mask = 0x7F;
7061    int nb = b ? 1 : 0;
7062    ch = 0;
7063    if(b & 0x80)
7064    {
7065       if(b & 0x40)
7066       {
7067          mask >>= 2;
7068          nb++;
7069          if(b & 0x20)
7070          {
7071             nb++;
7072             mask >>= 1;
7073             if(b & 0x10)
7074             {
7075                if(b & 0x08) { nb = 0; }
7076                nb++;
7077                mask >>= 1;
7078             }
7079          }
7080       }
7081       else
7082          nb = 0;
7083    }
7084    for(i = 0; i<nb; i++)
7085    {
7086       ch <<= 6;
7087       ch |= (b = ((byte *)string)[i]) & mask;
7088       mask = 0x3F;
7089       if(i > 1 && (!(b & 0x80) || (b & 0x40)))
7090       {
7091          nb = 0;
7092          ch = 0;
7093       }
7094    }
7095
7096    if(i < nb ||
7097       ch > 0x10FFFF || (ch >= 0xD800 && ch <= 0xDFFF) ||
7098      (ch < 0x80 && nb > 1) ||
7099      (ch < 0x800 && nb > 2) ||
7100      (ch < 0x10000 && nb > 3))
7101    {
7102       ch = 0;
7103       nb = 0;
7104    }
7105    if(numBytes) *numBytes = nb;
7106    return ch;
7107 }
7108
7109 public int UTF8toUTF16Buffer(const char * source, uint16 * dest, int max)
7110 {
7111    if(source)
7112    {
7113       int c;
7114       int d = 0;
7115       for(c = 0; source[c];)
7116       {
7117          byte ch = source[c];
7118          unichar codePoint = 0;
7119          int numBytes = 1;
7120          int i;
7121          byte mask = 0x7F;
7122          if(ch & 0x80 && ch & 0x40)
7123          {
7124             mask >>= 2;
7125             numBytes++;
7126             if(ch & 0x20)
7127             {
7128                numBytes++;
7129                mask >>= 1;
7130                if(ch & 0x10)
7131                {
7132                   numBytes++;
7133                   mask >>= 1;
7134                }
7135             }
7136          }
7137          for(i = 0; i<numBytes; i++)
7138          {
7139             codePoint <<= 6;
7140             codePoint |= source[c++] & mask;
7141             mask = 0x3F;
7142          }
7143
7144          if(codePoint > 0xFFFF)
7145          {
7146             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
7147             uint16 trail = (uint16)(0xDC00 | (codePoint & 0x3FF));
7148             if(d >= max - 1) break;
7149             dest[d++] = lead;
7150             dest[d++] = trail;
7151          }
7152          else
7153          {
7154             if(d >= max) break;
7155             dest[d++] = (uint16)codePoint;
7156          }
7157       }
7158       dest[d] = 0;
7159       return d;
7160    }
7161    return 0;
7162 }
7163
7164 public int UTF32toUTF8Len(const unichar * source, int count, char * dest, int max)
7165 {
7166    int c;
7167    int d = 0;
7168    uint32 ch;
7169    byte * byteDest = (byte *)dest;
7170    for(c = 0; c<count && (ch = source[c]); c++)
7171    {
7172       if(ch < 0x80)
7173       {
7174          if(d + 1 >= max) break;
7175          byteDest[d++] = (char)ch;
7176       }
7177       else if(ch < 0x800)
7178       {
7179          if(d + 2 >= max) break;
7180          byteDest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
7181          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7182       }
7183       else if(ch < 0x10000)
7184       {
7185          if(d + 3 >= max) break;
7186          byteDest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
7187          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7188          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7189       }
7190       else
7191       {
7192          if(d + 4 >= max) break;
7193          byteDest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
7194          byteDest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
7195          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7196          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7197       }
7198    }
7199    byteDest[d] = 0;
7200    return d;
7201 }
7202
7203 public uint16 * UTF8toUTF16(const char * source, int * wordCount)
7204 {
7205    if(source)
7206    {
7207       int len = (int)strlen(source);
7208       uint16 * dest = new uint16[len + 1];
7209       int c;
7210       int d = 0;
7211       for(c = 0; source[c];)
7212       {
7213          byte ch = source[c];
7214          unichar codePoint = 0;
7215          int numBytes = 1;
7216          int i;
7217          byte mask = 0x7F;
7218          if(ch & 0x80 && ch & 0x40)
7219          {
7220             mask >>= 2;
7221             numBytes++;
7222             if(ch & 0x20)
7223             {
7224                numBytes++;
7225                mask >>= 1;
7226                if(ch & 0x10)
7227                {
7228                   numBytes++;
7229                   mask >>= 1;
7230                }
7231             }
7232          }
7233          for(i = 0; i<numBytes; i++)
7234          {
7235             codePoint <<= 6;
7236             codePoint |= source[c++] & mask;
7237             mask = 0x3F;
7238          }
7239
7240          if(codePoint > 0xFFFF)
7241          {
7242             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
7243             uint16 trail = (uint16)(0xDC00 | (codePoint & 0x3FF));
7244             dest[d++] = lead;
7245             dest[d++] = trail;
7246          }
7247          else
7248          {
7249             dest[d++] = (uint16)codePoint;
7250          }
7251       }
7252       dest[d] = 0;
7253       if(wordCount) *wordCount = d;
7254       return dest;
7255    }
7256    return null;
7257 }
7258
7259 namespace com;
7260
7261 #if defined(_DEBUG) && !defined(MEMINFO) && defined(MEMTRACKING)
7262 import "Map"
7263
7264 Map<Class, int> blocksByClass { };
7265 Map<Class, uintsize> sizeByClass { };
7266 #endif
7267
7268 public void queryMemInfo(char * string)
7269 {
7270 #if defined(_DEBUG) && !defined(MEMINFO) && defined(MEMTRACKING)
7271    char s[1024];
7272    int p;
7273    uint numBlocks = 0;
7274    uintsize totalMemUsed = 0;
7275    sprintf(s, "Total System Memory Usage: %.02f\n", TOTAL_MEM / 1048576.0f);
7276    strcat(string, s);
7277
7278    for(p = 0; pools && p < NUM_POOLS; p++)
7279    {
7280       BlockPool * pool = &pools[p];
7281       if(pool->totalSize)
7282       {
7283          numBlocks += pool->totalSize;
7284          sprintf(s, "%8d bytes: %d blocks in %d parts (%.02f mb used; taking up %.02f mb space)\n",
7285             pool->blockSize, pool->numBlocks, pool->numParts, pool->usedSpace / 1048576.0f, pool->totalSize * pool->blockSpace / 1048576.0f);
7286          totalMemUsed += pool->usedSpace;
7287          strcat(string, s);
7288       }
7289    }
7290
7291
7292    blocksByClass.Free();
7293    sizeByClass.Free();
7294    memMutex.Wait();
7295    for(p = 0; pools && p < NUM_POOLS; p++)
7296    {
7297       BlockPool * pool = &pools[p];
7298       MemBlock block;
7299       for(block = pool->first; block; block = block.next)
7300       {
7301          Class c = block._class;
7302          blocksByClass[c]++;
7303          sizeByClass[c] += block.size;
7304       }
7305    }
7306    memMutex.Release();
7307
7308    //for(c : blocksByClass)
7309    {
7310       MapIterator<Class, int> it { map = blocksByClass };
7311       while(it.Next())
7312       {
7313          int c = it.data;
7314          Class _class = it.key; //&c;
7315          uintsize size = sizeByClass[_class];
7316          float totalSize = (float) size / 1048576.0f;
7317          if(totalSize > 1)
7318          {
7319             sprintf(s, "%s (%d bytes): %d instances (%.02f mb used)\n", _class ? _class.name : "(none)", (int)size, c, totalSize);
7320             strcat(string, s);
7321          }
7322       }
7323    }
7324
7325    sprintf(s, "Non-pooled memory: %.02f\n", OUTSIDE_MEM / 1048576.0f);
7326    strcat(string, s);
7327    sprintf(s, "Total Memory in use: %.02f\n", (float)(totalMemUsed + OUTSIDE_MEM) / 1048576.0f);
7328    strcat(string, s);
7329
7330    sprintf(s, "Total Blocks Count: %d (%.02f mb overhead)\n", numBlocks, (float)sizeof(struct MemBlock) * numBlocks / 1048576.0f);
7331    strcat(string, s);
7332 #ifdef MEMORYGUARD
7333    sprintf(s, "MemoryGuard: %d blocks (%.02f mb RedZone, %.02f mb MemInfo)\n", memBlocks.count,
7334       numBlocks * 2 * REDZONE / 1048576.0f, sizeof(struct MemInfo) * memBlocks.count / 1048576.0f);
7335    strcat(string, s);
7336 #endif
7337 #endif
7338 }