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