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