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