ecere/com/instance.ec: Simpler code in BlockPool::Remove()
[sdk] / ecere / src / com / instance.ec
1 namespace com;
2
3 // #define DISABLE_MEMMGR
4
5 import "BinaryTree"
6 import "OldList"
7 import "String"
8 import "dataTypes"
9
10 //#define JUST_CHECK_LEAKS
11 //#define JUST_CHECK_BOUNDARIES
12
13
14 #if defined(ECERE_BOOTSTRAP) || defined(ECERE_STATIC)
15 #define dllexport
16 #if !defined(ECERE_BOOTSTRAP)
17 #define stdcall
18 #endif
19 #endif
20
21 #undef __BLOCKS__
22
23 #if !defined(ECERE_BOOTSTRAP)
24 import "Mutex"
25 #endif
26
27 // #define MEMINFO
28 /*
29 #ifdef MEMINFO
30  #undef REDZONE
31  #define REDZONE   256
32 #endif
33 */
34
35 #if defined(JUST_CHECK_LEAKS) || !defined(REDZONE)
36 #undef REDZONE
37 #define REDZONE 0
38 #endif
39
40
41 #ifdef _DEBUG
42 // #define MEMTRACKING
43 #endif
44
45 #ifdef MEMINFO
46 import "Thread"
47 static define MAX_MEMORY_LOC = 40;
48 static define MAX_STACK_FRAMES = 1000;
49
50 static class MemStack : BTNode
51 {
52    const char * frames[MAX_STACK_FRAMES];
53    int pos;
54    bool recurse;
55 };
56
57 static BinaryTree memStacks { };
58 static uint memoryErrorsCount = 0;
59
60 #endif
61
62 default:
63 #define property _property
64
65 #if defined(DISABLE_MEMMGR)
66
67 #ifndef ECERE_BOOTSTRAP
68 # include <malloc.h>
69 #endif
70
71 #if defined(__WIN32__)
72 #ifdef ECERE_BOOTSTRAP
73 uintsize _msize(void * p);
74 #endif
75
76 #  define msize _msize
77 #else
78 #ifdef ECERE_BOOTSTRAP
79 uintsize malloc_usable_size(void * p);
80 #endif
81
82 #  define msize malloc_usable_size
83 #endif
84
85 #endif
86
87 #include <stdlib.h>
88 #include <stdio.h>
89
90 private:
91
92 #if defined(__ANDROID__)
93
94 default const char * AndroidInterface_GetLibLocation();
95
96 #include <android/log.h>
97 #include <android/native_activity.h>
98
99 #define printf(...)  ((void)__android_log_print(ANDROID_LOG_VERBOSE, "ecere-app", __VA_ARGS__))
100 #endif
101
102 #undef property
103
104 #undef CompareString
105
106 public define null = ((void *)0);
107
108 dllexport Class eSystem_FindClass(Module module, const char * name);
109 dllexport void * eSystem_Renew(void * memory, unsigned int size);
110 dllexport void * eSystem_Renew0(void * memory, unsigned int size);
111 dllexport void * eSystem_New(unsigned int size);
112 dllexport void * eSystem_New0(unsigned int size);
113 dllexport void eSystem_Delete(void * memory);
114 dllexport void * eInstance_New(Class _class);
115
116 default:
117 extern int __ecereVMethodID_class_OnGetDataFromString;
118
119 // IMPLEMENTATION FOR THESE IN _instance.c:
120 #if defined(__MINGW32__) && !defined(_W64) && __GNUC__ < 4
121 dllexport int isblank(int c);
122 #endif
123 bool Instance_LocateModule(const char * name, const char * fileName);
124 void Instance_COM_Initialize(int argc, char ** argv, char ** parsedCommand, int * argcPtr, const char *** argvPtr);
125 void * Instance_Module_Load(const char * libLocation, const char * name, void ** Load, void ** Unload);
126 void Instance_Module_Free(void * library);
127 #if defined(_DEBUG)
128 void InternalModuleLoadBreakpoint();
129 #endif
130
131 private:
132
133 public class Angle : double;
134
135 public class ::unichar : uint32
136 {
137
138    const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
139    {
140       UTF32toUTF8Len(&this, 1, tempString, 5);
141       return tempString;
142    }
143
144    bool OnGetDataFromString(const char * string)
145    {
146       int nb;
147       this = UTF8GetChar(string, &nb);
148       return true;
149    }
150
151 };
152
153 // Forward declarations to hook on to libec:
154 class ::Type;
155 class ::Instantiation;
156 class ::ClassDefinition;
157
158 public class Property : struct
159 {
160 public:
161    class_fixed
162    class_no_expansion
163    Property prev, next;
164    const char * name;
165    bool isProperty;
166    AccessMode memberAccess;
167    int id;
168    Class _class;
169    const char * dataTypeString;
170    Class dataTypeClass;
171    Type dataType;
172
173    void (*Set)(void *, int);
174    int (*Get)(void *);
175    bool (*IsSet)(void *);
176    void * data;
177    void * symbol;
178    int vid;
179    bool conversion;
180    uint watcherOffset;
181    const char * category;
182    bool compiled;
183    bool selfWatchable, isWatchable;
184 };
185
186 dllexport void eInstance_FireWatchers(Instance instance, Property _property);
187
188 public dllexport void MemoryGuard_PushLoc(const char * loc)
189 {
190 #ifdef MEMINFO
191    MemStack stack;
192    memMutex.Wait();
193    stack = (MemStack)memStacks.Find(GetCurrentThreadID());
194    if(!stack)
195    {
196       stack = (MemStack)calloc(1, sizeof(class MemStack));
197       stack.key = GetCurrentThreadID();
198       memStacks.Add(stack);
199    }
200    if(stack.pos < MAX_STACK_FRAMES)
201       stack.frames[stack.pos++] = loc;
202    memMutex.Release();
203 #endif
204 }
205
206 public dllexport void MemoryGuard_PopLoc()
207 {
208 #ifdef MEMINFO
209    MemStack stack;
210    memMutex.Wait();
211    stack = (MemStack)memStacks.Find(GetCurrentThreadID());
212    if(stack && stack.pos > 0)
213    {
214       stack.pos--;
215    }
216    memMutex.Release();
217 #endif
218 }
219
220 #ifdef ECERE_STATIC
221
222 #ifdef ECERE_COM_ONLY
223
224 #define COM_LOAD_FUNCTION  __ecereDll_Load_ecereCOM
225 #define COM_UNLOAD_FUNCTION  __ecereDll_Unload_ecereCOM
226
227 #else
228
229 #define COM_LOAD_FUNCTION  __ecereDll_Load_ecere
230 #define COM_UNLOAD_FUNCTION  __ecereDll_Unload_ecere
231
232 #endif
233
234 #else
235
236 #define COM_LOAD_FUNCTION  __ecereDll_Load
237 #define COM_UNLOAD_FUNCTION  __ecereDll_Unload
238
239 #endif
240
241 default:
242
243 #if defined(ECERE_BOOTSTRAP)
244 extern bool COM_LOAD_FUNCTION(Module module);
245 extern bool COM_UNLOAD_FUNCTION(Module module);
246 #else
247 extern bool stdcall COM_LOAD_FUNCTION(Module module);
248 extern bool stdcall COM_UNLOAD_FUNCTION(Module module);
249 #endif
250
251 private:
252
253 public class BTNamedLink : struct
254 {
255    class_fixed
256 public:
257    const char * name;
258    BTNamedLink parent, left, right;
259    int depth;
260    void * data;
261 };
262
263 class SelfWatcher : struct
264 {
265    class_fixed
266    SelfWatcher prev, next;
267    void (*callback)(void *);
268    Property _property;
269 };
270
271 public enum AccessMode
272 {
273    defaultAccess,
274    publicAccess,
275    privateAccess,
276    staticAccess,
277    baseSystemAccess
278 };
279
280 public class SubModule : struct
281 {
282 public:
283    SubModule prev, next;
284    Module module;
285    AccessMode importMode;
286 };
287
288 public enum DataMemberType { normalMember, unionMember, structMember };
289
290 public enum ClassType
291 {
292    normalClass,
293    structClass,
294    bitClass,
295    unitClass,
296    enumClass,
297    noHeadClass,
298    unionClass, // Temporary only in firstPass
299    systemClass = 1000
300 };
301
302 public class Class : struct
303 {
304 public:
305    class_fixed
306    class_no_expansion
307    Class prev, next;
308    const char * name;
309    int offset, structSize;
310    void ** _vTbl;
311    int vTblSize;
312    bool (*Constructor)(void *);
313    void (*Destructor)(void *);
314
315    int offsetClass, sizeClass;
316    Class base;
317    BinaryTree methods;
318    BinaryTree members;
319    BinaryTree prop;
320    OldList membersAndProperties;
321    BinaryTree classProperties;
322    OldList derivatives;
323    int memberID, startMemberID;
324    ClassType type;
325    Module module;
326    NameSpace * nameSpace;
327    const char * dataTypeString;
328    Type dataType;
329    int typeSize;
330    int defaultAlignment;
331    void (*Initialize)();
332    int memberOffset;       // For structs, this includes all base classes structSize. Otherwise it restarts at for each class hierarchy level.
333    OldList selfWatchers;
334    const char * designerClass;
335    bool noExpansion;
336    const char * defaultProperty;
337    bool comRedefinition;
338
339    int count;     // DEBUGGING
340
341    int isRemote;  // TODO: Convert to an enum, can have values 0..3
342    bool internalDecl;
343    void * data;
344    bool computeSize;
345    short structAlignment; short pointerAlignment;
346    int destructionWatchOffset;
347    bool fixed;
348    OldList delayedCPValues;
349    AccessMode inheritanceAccess;
350    const char * fullName;
351    void * symbol;
352    OldList conversions;
353
354    OldList templateParams;
355    ClassTemplateArgument * templateArgs;
356    Class templateClass;
357    OldList templatized;
358    int numParams;
359    bool isInstanceClass;
360    bool byValueSystemClass;
361
362    property const char *
363    {
364       get { return name; }
365       set
366       {
367          Class theClass = eSystem_FindClass(__thisModule, value);
368          /*
369          if(!theClass)
370             theClass = eSystem_FindClass(__thisModule.application, value);
371          */
372          return theClass;
373       }
374    };
375
376    const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
377    {
378       return name;
379    }
380
381    bool OnGetDataFromString(const char * string)
382    {
383       Class theClass;
384       theClass = eSystem_FindClass(__thisModule, string);
385       if(!theClass)
386          theClass = eSystem_FindClass(__thisModule.application, string);
387       this = (void *)theClass;
388       return theClass != null;
389    }
390
391    void OnSerialize(IOChannel channel)
392    {
393       channel.Serialize(fullName);
394    }
395
396    void OnFree()
397    {
398
399    }
400
401    void OnUnserialize(IOChannel channel)
402    {
403       Class theClass;
404       String string;
405       channel.Unserialize(string);
406       theClass = eSystem_FindClass(__thisModule, string);
407       if(!theClass)
408          theClass = eSystem_FindClass(__thisModule.application, string);
409       delete string;
410       this = (void *)theClass;
411    }
412 };
413
414
415 public enum TemplateParameterType { type, identifier, expression };
416 public enum TemplateMemberType { dataMember, method, prop };
417
418 public struct ClassTemplateArgument
419 {
420 public:
421    union
422    {
423       // For type
424       struct
425       {
426          const char * dataTypeString;
427          Class dataTypeClass;
428          // Type dataType;
429       };
430       // For expression
431       DataValue expression;
432
433       // For identifier
434       struct
435       {
436          const char * memberString;
437          union
438          {
439             DataMember member;
440             Property prop;
441             Method method;
442          };
443       };
444    };
445 };
446
447 public class ClassTemplateParameter : struct
448 {
449 class_fixed
450 public:
451    ClassTemplateParameter prev, next;
452    const char * name;
453    TemplateParameterType type;
454    union
455    {
456       // Class baseClass;                 // For type
457       const char * dataTypeString;           // For expression
458       TemplateMemberType memberType;   // For identifier
459    };
460    ClassTemplateArgument defaultArg;
461    void * param;  // To attach to Compiler TemplateParameter
462 }
463
464 /*    // Module inherits off the Instance class (_vTbl, _class, _refCount)
465 public class Module
466 {
467    class_no_expansion
468
469    Application app;
470
471    // So we can clean them up
472    OldList classes;
473    OldList defines;
474    OldList functions;
475    OldList modules;
476
477    Module prev, next;
478    const char * name;
479    void * library;
480    void (stdcall * Unload)(Module module);
481    ImportType importType;
482    // Added to solve stdcall issues with the bootstrap on Windows for Unload
483    ImportType origImportType;
484
485    NameSpace privateNameSpace;
486    NameSpace publicNameSpace;
487 };
488
489 public class Application : Module
490 {
491    int argc;
492    const char ** argv;
493    int exitCode;
494    bool isGUIApp;
495    OldList allModules;
496    const char * parsedCommand;
497    NameSpace systemNameSpace;
498 };
499 */
500 public enum MethodType { normalMethod, virtualMethod };
501
502 public class Method : struct
503 {
504 public:
505    class_fixed
506    const char * name;
507    Method parent, left, right;
508    int depth;
509    int (*function)();
510    int vid;              // For METHOD_VIRTUAL:  Index into the class virtual table
511    MethodType type;
512    Class _class;
513    void * symbol;
514    const char * dataTypeString;
515    Type dataType;
516    AccessMode memberAccess;
517 };
518
519 public enum ImportType
520 {
521    normalImport,
522    staticImport,
523    remoteImport,
524
525 // For internal usage in the compiler:
526    preDeclImport,
527    comCheckImport
528 };
529
530 public struct NameSpace
531 {
532    const char * name;
533    NameSpace * btParent, * left, * right;
534    int depth;
535
536    NameSpace * parent;
537    BinaryTree nameSpaces;
538    BinaryTree classes;
539    BinaryTree defines;
540    BinaryTree functions;
541 };
542
543 public union DataValue
544 {
545    char c;
546    unsigned char uc;
547    short s;
548    unsigned short us;
549    int i;
550    unsigned int ui;
551    void * p;
552    float f;
553    double d;
554    int64 i64;
555    uint64 ui64;
556 };
557
558 public class DataMember : struct
559 {
560 public:
561    class_fixed
562    DataMember prev, next;
563    const char * name;
564    bool isProperty;
565    AccessMode memberAccess;
566    int id;
567    Class _class;
568    const char * dataTypeString;
569    Class dataTypeClass;
570    Type dataType;
571
572    DataMemberType type;
573    int offset;
574    int memberID;
575    OldList members;
576    BinaryTree membersAlpha;
577    int memberOffset;
578    short structAlignment; short pointerAlignment;
579 };
580
581 public class BitMember : struct
582 {
583 public:
584    class_fixed
585    BitMember prev, next;
586    const char * name;
587    bool isProperty;
588    AccessMode memberAccess;
589    int id;
590    Class _class;
591    const char * dataTypeString;
592    Class dataTypeClass;
593    Type dataType;
594
595    DataMemberType type;
596    int size;
597    int pos;
598    uint64 mask;
599 };
600
601 public class ClassProperty : struct
602 {
603 public:
604    class_fixed
605    const char * name;
606    ClassProperty parent, left, right;
607    int depth;
608    void (*Set)(Class, int64);
609    int64 (*Get)(Class);
610    const char * dataTypeString;
611    Type dataType;
612    bool constant;
613 };
614
615 public class DefinedExpression : struct
616 {
617 public:
618    class_fixed
619    DefinedExpression prev, next;
620    const char * name;
621    const char * value;
622    NameSpace * nameSpace;
623 };
624
625 public class GlobalFunction : struct
626 {
627 public:
628    class_fixed
629    GlobalFunction prev, next;
630    const char * name;
631    int (*function)();
632    Module module;
633    NameSpace * nameSpace;
634    const char * dataTypeString;
635    Type dataType;
636    void * symbol;
637 };
638
639 public class EnumClassData : struct
640 {
641 public:
642    class_fixed
643    OldList values;
644    int64 largest;
645 };
646
647 class Watcher : struct
648 {
649    class_fixed
650    Watcher prev, next;
651    void (*callback)(void *, void *);
652    Instance object;
653 };
654
655 #ifdef MEMINFO
656 static class MemInfo : BTNode //struct
657 {
658    class_fixed
659
660    /*
661    byte * key;
662    MemInfo parent, left, right;
663    int depth;
664    */
665
666    byte * oldmem;
667    uint size;
668    bool freed;
669    const char * _class;
670    uint id;
671    char * allocLoc[MAX_MEMORY_LOC];
672    char * freeLoc[MAX_MEMORY_LOC];
673    bool internal;
674
675    void OutputStacks(bool showFree)
676    {
677       int c;
678
679       if(_class)
680          printf("Object of class %s\n", _class);
681       printf("   Allocation Stack:\n");
682       for(c = 0; c<MAX_MEMORY_LOC; c++)
683 #if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__)
684          if(allocLoc[c] && allocLoc[c] != (void *)0xabababababababab)
685 #else
686          if(allocLoc[c] && allocLoc[c] != (void *)0xabababab)
687 #endif
688             printf("      %s\n", allocLoc[c]);
689
690       if(showFree)
691       {
692          printf("   Free Location Stack:\n");
693          for(c = 0; c<MAX_MEMORY_LOC; c++)
694             if(freeLoc[c])
695                printf("      %s\n", freeLoc[c]);
696       }
697       //getch();
698    }
699 };
700
701 static BinaryTree memBlocks;
702
703 bool recurse = false;
704 static int blockID;
705 //Class allocateClass;
706 char * allocateClass;
707 bool allocateInternal;
708
709 #endif
710
711 static uint TOTAL_MEM = 0;
712 #if !defined(MEMINFO) && !defined(DISABLE_MEMMGR)
713 static uint OUTSIDE_MEM = 0;
714 #endif
715
716 #if !defined(ECERE_BOOTSTRAP)
717 static Mutex memMutex { };
718 #endif
719
720 private class MemBlock : struct
721 {
722    MemBlock prev, next;
723    MemPart part;
724    uint size;
725 #if !defined(MEMINFO) && defined(MEMTRACKING)
726    Class _class;
727 #endif
728 };
729
730 private class MemPart : struct
731 {
732    void * memory;
733    int blocksUsed;
734    int size;
735    BlockPool * pool;
736 };
737 /*
738 #define NUM_POOLS          29
739 #define NEXT_SIZE(s)       NextFibonacci(s)
740 #define SIZE_POSITION(s)   PosFibonacci(s)
741 #define NTH_SIZE(p)        NthFibonacci(p)
742
743 static uint initNumBlocks[NUM_POOLS] =
744 {
745    1024, // 1
746    1024, // 2
747    1024, // 3
748    1024, // 5
749    1024, // 8
750    1024, // 13
751    1024, // 21
752    1024, // 34
753    1024, // 55
754    1024, // 89
755    1024, // 144
756    512,  // 233
757    512,  // 377
758    256,  // 610
759    128,  // 987
760    128,  // 1597
761    64,   // 2584
762    32,   // 4181
763    32,   // 6765
764    16,   // 10946
765    16,   // 17711
766    8,    // 28657
767    4,    // 46368
768    2,    // 75025
769    1,    // 121393
770    1,    // 196418
771    1,    // 317811
772    1,    // 514229
773    1,    // 832040
774 };
775
776 */
777 /*
778 #define NUM_POOLS 20
779 #define NEXT_SIZE(s)       pow2i(s)
780 #define SIZE_POSITION(s)   log2i(s)
781 #define NTH_SIZE(p)        (1<<p)
782
783    1024,  // 1 byte
784    4000,  // 1024,    // 2 bytes
785    2500,  // 1024,    // 4 bytes
786    18000, //1024,    // 8 bytes
787    20000, //1024,    // 16 bytes
788    29000, //1024,    // 32 bytes
789    46000, //1024,    // 64 bytes
790    20000, //1024,    // 128 bytes
791    26000, //512,     // 256 bytes
792    1400,  //256,     // 512 bytes
793    160,   //128,     // 1 K
794    500,  //64,      // 2 K
795
796 static uint initNumBlocks[NUM_POOLS] =
797 {
798    1024,  // 1 byte
799    1024,    // 2 bytes
800    1024,    // 4 bytes
801    1024,    // 8 bytes
802    1024,    // 16 bytes
803    1024,    // 32 bytes
804    1024,    // 64 bytes
805    1024,    // 128 bytes
806    512,     // 256 bytes
807    256,     // 512 bytes
808    128,     // 1 K
809    64,      // 2 K
810    32,      // 4 K
811    16,      // 8 K
812    8,       // 16 K
813    4,       // 32 K
814    2,       // 64 K
815    1,       // 128 K
816    1,       // 256 K
817    1        // 512 K
818 };
819 */
820
821 #define NUM_POOLS 31
822 #define NEXT_SIZE(s)       pow1_5i(s)
823 #define SIZE_POSITION(s)   log1_5i(s)
824 #define NTH_SIZE(p)        pow1_5(p)
825
826 #if 0
827 static int power15[] =
828 {
829 /*
830 1
831 2
832 3
833 */
834 /*
835 4     // 4
836 6     // 8
837 9     // 12
838 13    // 16
839 19    // 24
840 28    // 32
841 42    // 48
842 63    // 64
843 94    // 96
844 141   // 144
845 211   // 224
846 316   // 320
847 474   // 480
848 711   // 720
849 1066  // 1072
850 1599  // 1600
851 2398  // 2400
852 3597  // 6900
853 5395  // 5408
854 8092  // 8096
855 12138 // 12144
856 18207 // 18208
857 27310 // 27312
858 40965 // 40976
859 61447 // 61456
860 92170 // 92176
861 138255   // 138256
862 207382   // 207392
863 311073   // 311088
864 466609   // 466624
865 699913   // 699920
866 */
867 4,
868 8,
869 12,
870 16,
871 24,
872 32,
873 48,
874 64,
875 96,
876 144,
877 224,
878 320,
879 480,
880 720,
881 1072,
882 1600,
883 2400,
884 6900,
885 5408,
886 8096,
887 12144,
888 18208,
889 27312,
890 40976,
891 61456,
892 92176,
893 138256,
894 207392,
895 311088,
896 466624,
897 699920
898 };
899 #endif
900
901 private struct BlockPool
902 {
903    MemBlock first, last;
904    MemBlock free;
905    uint blockSize;
906    uint blockSpace;
907    //MemPart * parts;
908    int numParts;
909    int numBlocks;
910    uint totalSize;
911    uint usedSpace;
912
913    bool Expand(uint numBlocks)
914    {
915       byte * memory = malloc(numBlocks * blockSpace);
916       // byte * memory = calloc(1, numBlocks * blockSpace);
917       TOTAL_MEM += numBlocks * blockSpace;
918 #ifdef _DEBUG
919       /*if(blockSize == 28)
920          printf("Expanding pool %x (%d)\n", this, blockSize);*/
921 #endif
922       if(memory)
923       {
924          int c;
925 #ifdef _DEBUG
926          /*uint totalAvailable = 0, totalAllocated = 0, totalBlocks = 0, totalUsed = 0;
927          uint totalParts = 0;*/
928 #endif
929          MemBlock block = (MemBlock)memory;
930          MemPart part = calloc(1, sizeof(class MemPart));
931          TOTAL_MEM += sizeof(class MemPart);
932          free = block;
933          for(c = 0; c<numBlocks - 1; c++)
934          {
935             // block.pool = this;
936             block.part = part;
937             /*if(part.size < 0)
938                printf("WARNING! part.size < 0\n");*/
939             block.prev = null;
940             block.next = (MemBlock)((byte *)block + blockSpace);
941             block = block.next;
942          }
943          part.blocksUsed = 0;
944          part.pool = this;
945          part.memory = memory;
946          part.size = numBlocks;
947
948          // block.pool = this;
949          block.part = part;
950          /*if(part.size < 0)
951             printf("/! part.size < 0\n");
952          if(part.pool == (void*) -1)
953             printf("WARNING! pool is -1\n");*/
954          block.prev = null;
955          block.next = null;
956
957          /*if(free && free.part && (free.part.size < 0 || free.part.pool == (void *)-1))
958             printf("WARNING! Bad next free block!\n");*/
959
960          //parts = realloc(parts, sizeof(MemPart) * (numParts + 1));
961
962          totalSize += numBlocks;
963
964 #ifdef _DEBUG
965          /*
966          {
967             for(c = 0; c<NUM_POOLS; c++)
968             {
969                BlockPool * pool = &pools[c];
970                printf("[%d %s (%d)]: available: %d, allocated: %d, free: %d, used: %d k, wasted: %d k, free: %d k\n", c, (&pools[c] == this) ? "*" : " ",
971                   pools[c].blockSize, pools[c].totalSize, pools[c].numBlocks,
972                   pools[c].totalSize - pools[c].numBlocks, pools[c].usedSpace / 1024, ((pools[c].numBlocks * pools[c].blockSize) - pools[c].usedSpace) / 1024,
973                   (pools[c].totalSize - pools[c].numBlocks) * pools[c].blockSize / 1024);
974                totalAvailable += pools[c].totalSize * pools[c].blockSize;
975                totalAllocated += pools[c].numBlocks * pools[c].blockSize;
976                totalUsed += pools[c].usedSpace;
977                totalBlocks += pools[c].totalSize;
978                totalParts += pools[c].numParts;
979             }
980             printf("Total Available %d k, Total Allocated: %d k, Total Free: %d k\n", totalAvailable / 1024, totalAllocated / 1024, (totalAvailable - totalAllocated) / 1024);
981             printf("Total Number of Blocks %d, overhead of %d k\n", totalBlocks, totalBlocks * sizeof(class MemBlock) / 1024);
982             printf("Total Used Space %d k, wasted from roundup: %d k\n", totalUsed / 1024, (totalAllocated - totalUsed) / 1024);
983             printf("Total Memory Parts: %d\n", totalParts);
984             printf("TOTAL_MEM: %d k, OUTSIDE_MEM: %d k, BLOCKS: %d k\n", TOTAL_MEM / 1024, OUTSIDE_MEM / 1024, (totalAvailable + totalBlocks * sizeof(class MemBlock)) / 1024);
985             printf("\n");
986          }
987          */
988 #endif
989          //parts[] = part;
990          numParts++;
991          return true;
992       }
993       return false;
994    }
995
996    MemBlock Add()
997    {
998       MemBlock block = null;
999       /*if(blockSize == 28)
1000          printf("BlockPool::Add (%d)\n", blockSize);*/
1001       if(!free)
1002          Expand(Max(1, numBlocks / 2));
1003       if(free)
1004       {
1005          block = free;
1006          block.prev = last;
1007          if(block.prev)
1008             block.prev.next = block;
1009          if(!first)
1010             first = block;
1011          last = block;
1012          free = block.next;
1013          /*if(blockSize == 28)
1014             printf("Free: %x, free.part: %x, free.part.size: %d, free.part.pool: %x (this = %x), next = %x (part = %x)\n", free, free ? free.part : null,
1015                (free && free.part) ? free.part.size : 0, (free && free.part) ? free.part.pool : 0, this,
1016                (free ? free.next : 0), (free && free.next) ? free.next.part : 0);
1017          if(free && free.part && (free.part.size < 0 || free.part.pool == (void *)-1))
1018             printf("WARNING! Bad next free block!\n");*/
1019
1020          block.next = null;
1021          //if(block.part)
1022             block.part.blocksUsed++;
1023          /*else
1024          {
1025             printf("");
1026          }*/
1027          numBlocks++;
1028       }
1029       return block;
1030    }
1031
1032    void Remove(MemBlock block)
1033    {
1034       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->parent &&
2565                !ns->classes.first &&
2566                !ns->functions.first &&
2567                !ns->defines.first &&
2568                !ns->nameSpaces.first)
2569             {
2570                NameSpace * parent = ns->parent;
2571                NameSpace_Free(ns);
2572                parent->nameSpaces.Delete((BTNode)ns);
2573                ns = parent;
2574             }
2575          }
2576       }
2577       else
2578       {
2579          classLink = SearchNameSpace(module.application.privateNameSpace, name, &((NameSpace *)0)->classes);
2580          if(!classLink)
2581             classLink = SearchNameSpace(module.application.publicNameSpace, name, &((NameSpace *)0)->classes);
2582
2583          if(!classLink)
2584             classLink = SearchNameSpace(module.application.privateNameSpace, name + start, &((NameSpace *)0)->classes);
2585          if(!classLink)
2586             classLink = SearchNameSpace(module.application.publicNameSpace, name + start, &((NameSpace *)0)->classes);
2587
2588          if(classLink)
2589             _class = classLink.data;
2590          if(_class && _class.internalDecl)
2591          {
2592             FreeTemplatesDerivatives(_class);
2593
2594             _class.nameSpace->classes.Delete((BTNode)classLink);
2595             {
2596                OldLink t;
2597                for(t = _class.templatized.first; t; t = t.next)
2598                {
2599                   Class template = t.data;
2600                   classLink = (BTNamedLink)_class.nameSpace->classes.FindString(template.name);
2601                   _class.nameSpace->classes.Delete((BTNode)classLink);
2602
2603                }
2604             }
2605
2606             delete (void *)_class.fullName;
2607             _class.fullName = CopyString(name);
2608          }
2609          else
2610          {
2611             _class = _calloc(1, sizeof(class Class));
2612             _class.methods.CompareKey = (void *)BinaryTree::CompareString;
2613             _class.members.CompareKey = (void *)BinaryTree::CompareString;
2614             _class.prop.CompareKey = (void *)BinaryTree::CompareString;
2615             _class.classProperties.CompareKey = (void *)BinaryTree::CompareString;
2616
2617             _class.name = CopyString(name + start);
2618             _class.fullName = CopyString(name);
2619          }
2620       }
2621       if(nameSpace)
2622       {
2623          nameSpace->classes.Add((BTNode)BTNamedLink { name = (char *)_class.name, data = _class });
2624          {
2625             OldLink t;
2626             for(t = _class.templatized.first; t; t = t.next)
2627             {
2628                Class template = t.data;
2629                nameSpace->classes.Add((BTNode)BTNamedLink { name = (char *)template.name, data = template });
2630             }
2631          }
2632
2633       }
2634
2635       if(_class)
2636       {
2637          if(!base && baseName && strcmp(baseName, name))
2638          {
2639             // Undefined base
2640             if(strchr(baseName, '<'))
2641             {
2642                char templateClassName[1024];
2643                Class templateBase;
2644                strcpy(templateClassName, baseName);
2645                *strchr(templateClassName, '<') = '\0';
2646                templateBase = eSystem_FindClass(module, templateClassName);
2647                if(!templateBase)
2648                {
2649                   templateBase = eSystem_RegisterClass(0, templateClassName, null, 0,0, null, null, module, declMode, publicAccess);
2650                   templateBase.internalDecl = true;
2651                }
2652                base = eSystem_FindClass(module, baseName);
2653             }
2654             else
2655             {
2656                base = eSystem_RegisterClass(0, baseName, null, 0,0, null, null, module, declMode, publicAccess);
2657                base.internalDecl = true;
2658             }
2659             /*
2660             base.size = 0;
2661             base.offset = 0;
2662             base.memberOffset = 0;
2663             */
2664          }
2665          else
2666             _class.internalDecl = false;
2667
2668          if(totalSizeClass)
2669          {
2670             _class.data = renew _class.data byte[totalSizeClass];
2671             // Class Data is often not inherited... e.g. Window::pureVtbl problem
2672             // memset(_class.data, 0, totalSizeClass);
2673             if(base && base.type != systemClass && base.type != enumClass)
2674                memcpy(_class.data, base.data, offsetClass);
2675             else
2676                memset(_class.data, 0, offsetClass);
2677             memset((byte *)_class.data + offsetClass, 0, sizeClass);
2678          }
2679
2680          delete (void *)_class.dataTypeString;
2681          _class.dataTypeString = CopyString(dataTypeString);
2682          _class.defaultAlignment = base ? base.defaultAlignment : 0;
2683
2684          // Dereference the class in previous module the classed belonged to
2685          if(_class.module)
2686          {
2687             _class.module.classes.Remove(_class);
2688          }
2689
2690          if(_class.base)
2691          {
2692             //Class base = _class.base.templateClass ? _class.base.templateClass : _class.base;
2693             Class base = _class.base;
2694             OldLink deriv = base.derivatives.FindLink(_class);
2695             base.derivatives.Delete(deriv);
2696          }
2697
2698          // Reference the class in the module
2699          if(module)
2700          {
2701             module.classes.Add(_class);
2702          }
2703
2704          _class.nameSpace = nameSpace;
2705          {
2706             OldLink t;
2707             for(t = _class.templatized.first; t; t = t.next)
2708             {
2709                Class template = t.data;
2710                template.nameSpace = nameSpace;
2711             }
2712          }
2713
2714          _class.module = module;
2715          prevBase = _class.base;
2716          _class.base = base;
2717          if(base)
2718          {
2719             int numParams = 0;
2720             Class sClass;
2721             for(sClass = base; sClass; sClass = sClass.base)
2722             {
2723                if(sClass.templateClass) sClass = sClass.templateClass;
2724                numParams += sClass.templateParams.count;
2725             }
2726             if(numParams)
2727             {
2728                if(_class.templateArgs)
2729                {
2730                   FreeTemplateArgs(_class);
2731                }
2732                delete _class.templateArgs;
2733                _class.templateArgs = new0 ClassTemplateArgument[numParams];
2734                _class.numParams = numParams;
2735
2736                for(sClass = _class; sClass; sClass = sClass.base)
2737                {
2738                   Class prevClass;
2739                   ClassTemplateParameter param;
2740                   int id = 0;
2741                   if(sClass.templateClass) sClass = sClass.templateClass;
2742                   for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
2743                   {
2744                      if(prevClass.templateClass) prevClass = prevClass.templateClass;
2745                      id += prevClass.templateParams.count;
2746                   }
2747
2748                   if(base.templateArgs)   // Add numParams test here?
2749                   {
2750                      for(param = sClass.templateParams.first; param; param = param.next)
2751                      {
2752                         _class.templateArgs[id] = base.templateArgs[id];
2753                         CopyTemplateArg(param, _class.templateArgs[id]);
2754                         id++;
2755                      }
2756                   }
2757                }
2758             }
2759          }
2760          _class.memberID = _class.startMemberID = (base && (type == normalClass || type == noHeadClass || type == structClass)) ? base.memberID : 0;
2761          if(type == normalClass || type == noHeadClass)
2762             _class.offset = (base && base.structSize && base.type != systemClass) ?
2763                // Use 'memberOffset' for nohead class as the members get added without padding
2764                (base.type == normalClass ? base.structSize : base.memberOffset) : ((type == noHeadClass) ? 0 : ((force64Bits && inCompiler && fixed) ? 24 : (force32Bits && inCompiler && fixed) ? 12 : sizeof(class Instance)));
2765          else
2766             _class.offset = 0;   // Force set to 0 for redefinitions
2767
2768          // For cross-bitness-compiling
2769          if(crossBits)
2770          {
2771             // The GNOSIS runtime will use 'offset' to point to the object during compile executation
2772             // Need to rethink through our cross-bitness compiling to have a distinct 'offset' (e.g. runtimeOffset)
2773             // used by the runtime library vs. 'offset' used by the compiler to hardcode compilation results (or avoid those altogether)
2774             if(!strcmp(name, "GNOSISSystem") ||
2775                !strcmp(name, "LineStyle") ||
2776                !strcmp(name, "FillStyle") ||
2777                !strcmp(name, "FontObject") ||
2778                !strcmp(name, "SymbolStyle"))
2779             {
2780                _class.offset = force32Bits ? 24 : 12;
2781             }
2782             // 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
2783             else if(strstr(name, "ecere::sys::EARHeader") ||
2784                strstr(name, "AnchorValue") ||
2785                !strcmp(name, "ecere::com::CustomAVLTree") ||
2786                !strcmp(name, "ecere::com::Array") ||
2787                !strcmp(name, "ecere::gui::Window") ||
2788                !strcmp(name, "ecere::sys::Mutex"));   // Never recompute these, they're always problematic (errors, crashes)
2789             else
2790             {
2791                if(!strcmp(name, "ecere::sys::FileListing"))
2792                {
2793                   size = 3*(force32Bits ? 4 : 8);
2794                   _class.structAlignment = force32Bits ? 4 : 8;   // FileListing is problematic because it is a struct with private data that the user allocates
2795                   _class.pointerAlignment = 1;
2796                }
2797                // These we want to recompute inside the IDE to help the debugger
2798                else if(!strcmp(name, "ecere::com::Class"))           size = 0; // 616
2799                else if(!strcmp(name, "ecere::com::ClassProperty"))   size = 0; // 80
2800                else if(!strcmp(name, "ecere::com::NameSpace"))       size = 0; // 176
2801                else if(!strcmp(name, "ecere::sys::BufferedFile"))    size = 0;
2802                else if(!strcmp(name, "ecere::sys::BTNode"))          size = 0;
2803                else if(!strcmp(name, "ecere::sys::StringBTNode"))    size = 0;
2804                else if(!strcmp(name, "ecere::sys::OldList"))         size = 0; // 32
2805                else if(!strcmp(name, "ecere::sys::Item"))            size = 0;
2806                else if(!strcmp(name, "ecere::sys::NamedLink"))       size = 0;
2807                else if(!strcmp(name, "ecere::sys::NamedLink64"))     size = 0;
2808                else if(!strcmp(name, "ecere::sys::OldLink"))         size = 0;
2809                else if(!strcmp(name, "ecere::sys::NamedItem"))       size = 0;
2810                else if(!strcmp(name, "ecere::sys::NamedItem64"))     size = 0;
2811                else if(!strcmp(name, "ecere::sys::BinaryTree"))      size = 0;
2812                else if(module != module.application && inCompiler)
2813                {
2814                   // These we only want to recompute inside the compiler
2815                   if(fixed || type == structClass)
2816                      size = 0;
2817                }
2818             }
2819          }
2820          if(type == structClass)
2821          {
2822             _class.memberOffset = (base && base.structSize && base.type != systemClass) ? base.structSize : 0;
2823             // THIS IS NEW...
2824             _class.typeSize = _class.structSize = _class.memberOffset + size;
2825          }
2826          else if(type == bitClass || type == enumClass || type == unitClass)
2827          {
2828             Class dataTypeClass = eSystem_FindClass(_class.module, dataTypeString);
2829             if(dataTypeClass)
2830                _class.typeSize = dataTypeClass.typeSize;
2831             _class.structSize = 0;
2832          }
2833          else if(type == normalClass || type == noHeadClass)
2834          {
2835             _class.structSize = _class.offset + size;
2836             _class.typeSize = sizeof(void *);
2837          }
2838          _class.offsetClass = offsetClass;
2839          _class.sizeClass = totalSizeClass;
2840          _class.Constructor = Constructor;
2841          _class.Destructor = Destructor;
2842          if(_class.type != systemClass)
2843             _class.type = type;
2844          if(!size)
2845             _class.computeSize = true;
2846          else
2847             _class.computeSize = false;
2848          _class.inheritanceAccess = inheritanceAccess;
2849
2850          /*if(type == bitClass)
2851             _class.size = 0;*/
2852          if(type == enumClass)
2853          {
2854             if(enumBase)
2855                _class.base = base = enumBase;
2856             //else
2857             {
2858                EnumClassData data = (EnumClassData)_class.data;
2859                // TOCHECK: Trying this (if specifiers specified, no class found...)
2860                // What about bit classes, unit classes...
2861                if(base && base.type != enumClass)
2862                   data.largest = -1;//_class.base = null;
2863                else
2864                   data.largest = ((EnumClassData)(base.data)).largest;
2865             }
2866          }
2867          if(base)
2868          {
2869             int i;
2870             uint oldSize = _class.vTblSize;
2871             if(base.vTblSize && _class.vTblSize < base.vTblSize)
2872             {
2873                _class.vTblSize = base.vTblSize;
2874                // OK to scrap existing virtual table?
2875                //delete _class._vTbl;
2876                //_class._vTbl = _malloc(sizeof(int(*)()) * _class.vTblSize);
2877                // memcpy(_class._vTbl, base._vTbl, sizeof(int(*)()) * _class.vTblSize);
2878                _class._vTbl = _realloc(_class._vTbl, sizeof(int(*)()) * _class.vTblSize);
2879             }
2880             if(!prevBase)
2881             {
2882                if(_class.type == normalClass && strcmp(_class.name, "ecere::com::Instance") && strcmp(_class.name, "enum") && strcmp(_class.name, "struct"))
2883                   prevBase = eSystem_FindClass(module, "ecere::com::Instance");
2884                else
2885                   prevBase = eSystem_FindClass(module, "class");
2886             }
2887             for(i = 0; i < base.vTblSize; i++)
2888             {
2889                if(i >= oldSize || _class._vTbl[i] == prevBase._vTbl[i])
2890                   _class._vTbl[i] = base._vTbl[i];
2891             }
2892          }
2893
2894          if(_class.base)
2895          {
2896             OldLink link { data = _class };
2897             /*(_class.base.templateClass ? _class.base.templateClass : _class.base)*/_class.base.derivatives.Add(link);
2898          }
2899
2900          FixDerivativesBase(_class, _class);
2901
2902          return _class;
2903       }
2904    }
2905    return null;
2906 }
2907
2908 static void DataMember_Free(DataMember parentMember)
2909 {
2910    DataMember member;
2911    BTNamedLink namedLink;
2912    delete (void *)parentMember.name;
2913    delete (void *)parentMember.dataTypeString;
2914
2915    while((member = parentMember.members.first))
2916    {
2917       DataMember_Free(member);
2918       parentMember.members.Delete(member);
2919    }
2920
2921    while((namedLink = (BTNamedLink)parentMember.membersAlpha.first))
2922    {
2923       parentMember.membersAlpha.Delete((BTNode)namedLink);
2924    }
2925 }
2926
2927 static void FreeEnumValue(NamedLink64 value)
2928 {
2929    delete value.name;
2930 }
2931
2932 static void FreeTemplateArg(Class template, ClassTemplateParameter param, int id)
2933 {
2934    switch(param.type)
2935    {
2936       case type:
2937          delete (void *)template.templateArgs[id].dataTypeString;
2938          break;
2939       case identifier:
2940          delete (void *)template.templateArgs[id].memberString;
2941          break;
2942       case expression:
2943
2944          break;
2945    }
2946 }
2947
2948 static void FreeTemplateArgs(Class template)
2949 {
2950    if(template.templateArgs)
2951    {
2952       Class _class;
2953       for(_class = template; _class; _class = _class.base)
2954       {
2955          Class prevClass;
2956          ClassTemplateParameter param;
2957          int id = 0;
2958          if(_class.templateClass) _class = _class.templateClass;
2959          for(prevClass = _class.base; prevClass; prevClass = prevClass.base)
2960          {
2961             if(prevClass.templateClass) prevClass = prevClass.templateClass;
2962             id += prevClass.templateParams.count;
2963          }
2964          if(id < template.numParams)
2965          {
2966             for(param = _class.templateParams.first; param; param = param.next)
2967             {
2968                switch(param.type)
2969                {
2970                   case type:
2971                      delete (void *)template.templateArgs[id].dataTypeString;
2972                      break;
2973                   case identifier:
2974                      delete (void *)template.templateArgs[id].memberString;
2975                      break;
2976                   case expression:
2977                      // delete template.templateArgs[id].dataTypeString;
2978                      break;
2979                }
2980                id++;
2981             }
2982          }
2983       }
2984    }
2985 }
2986
2987 static void FreeTemplate(Class template)
2988 {
2989    OldLink deriv;
2990
2991    if(template.nameSpace)
2992    {
2993       BTNamedLink link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
2994       if(link)
2995          template.nameSpace->classes.Delete((BTNode)link);
2996    }
2997    FreeTemplateArgs(template);
2998
2999    delete (void *)template.fullName;
3000    delete (void *)template.name;
3001    delete (void *)template.templateArgs;
3002    delete (void *)template.dataTypeString;
3003
3004    while((deriv = template.derivatives.first))
3005    {
3006       ((Class)deriv.data).base = null;
3007       template.derivatives.Delete(deriv);
3008    }
3009
3010    if(template.module)
3011       template.module.classes.Delete(template);
3012    else
3013       _free(template);
3014 }
3015
3016 static void FreeTemplates(Class _class)
3017 {
3018    OldLink deriv, template;
3019
3020    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
3021    {
3022       FreeTemplates(deriv.data);
3023    }
3024
3025    FreeTemplateArgs(_class);
3026    //if(_class.templateArgs)
3027       //printf("Deleting  Template args for %s\n", _class.name);
3028    delete _class.templateArgs;
3029    delete (void *)_class.dataTypeString;
3030
3031    while((template = _class.templatized.first))
3032    {
3033       FreeTemplates(template.data);
3034       FreeTemplate(template.data);
3035       _class.templatized.Delete(template);
3036    }
3037 }
3038
3039 public dllexport void eClass_Unregister(Class _class)
3040 {
3041    BTNamedLink namedLink;
3042    DataMember member;
3043    Method method;
3044    OldLink deriv, template;
3045    ClassProperty classProp;
3046    ClassTemplateParameter param;
3047
3048    if(_class.templateClass)
3049    {
3050       // Unregistering templates... Used in IDE to address crash on Ecere classes templatized with imported modules
3051       OldLink templateLink;
3052       for(templateLink = _class.templateClass.templatized.first; templateLink; templateLink = templateLink.next)
3053       {
3054          if(templateLink.data == _class)
3055          {
3056             _class.templateClass.templatized.Delete(templateLink);
3057             break;
3058          }
3059       }
3060       FreeTemplate(_class);
3061       return;
3062    }
3063
3064    delete _class._vTbl;
3065
3066    FreeTemplates(_class);
3067
3068    FreeTemplateArgs(_class);
3069    delete _class.templateArgs;
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                            ClassTemplateArgument arg;
3817                            for(sClass = expClass.base; sClass; sClass = sClass.base) id += sClass.templateParams.count;
3818                            arg = expClass.templateArgs[id];
3819
3820                            {
3821                               ClassTemplateParameter cParam;
3822                               int p = numParams - _class.templateParams.count;
3823                               for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3824                               {
3825                                  if(cParam.type == type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
3826                                  {
3827                                     arg.dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3828                                     arg.dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
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                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3916                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3917                            CopyTemplateArg(cParam, arg);
3918                            break;
3919                         }
3920                      }
3921                   }
3922                }
3923             }
3924             c--;
3925          }
3926       }
3927    }
3928
3929    {
3930       Class sClass;
3931       for(sClass = _class; sClass; sClass = sClass.base)
3932       {
3933          int curParamID = 0;
3934          Class nextClass;
3935          ClassTemplateParameter param;
3936          if(sClass.templateClass) sClass = sClass.templateClass;
3937
3938          for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3939          {
3940             if(nextClass.templateClass) nextClass = nextClass.templateClass;
3941             curParamID += nextClass.templateParams.count;
3942          }
3943
3944          for(param = sClass.templateParams.first; param; param = param.next)
3945          {
3946             if(!templatedClass.templateArgs[curParamID].dataTypeString)
3947             {
3948                templatedClass.templateArgs[curParamID] = param.defaultArg;
3949                CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3950                if(param.type == type && param.defaultArg.dataTypeString)
3951                {
3952                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3953                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3954                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3955                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3956                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3957                }
3958             }
3959             curParamID++;
3960          }
3961       }
3962    }
3963
3964    {
3965       int c = numParams - 1;
3966       for(sClass = _class; sClass; sClass = sClass.base)
3967       {
3968          ClassTemplateParameter param;
3969          if(sClass.templateClass) sClass = sClass.templateClass;
3970          for(param = sClass.templateParams.last; param; param = param.prev)
3971          {
3972             if(param.type == type)
3973             {
3974                ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3975                ClassTemplateParameter cParam;
3976                Class dClass;
3977                int p = numParams - 1;
3978                for(dClass = _class; dClass; dClass = dClass.base)
3979                {
3980                   if(dClass.templateClass) dClass = dClass.templateClass;
3981                   for(cParam = dClass.templateParams.last; cParam; cParam = cParam.prev, p--)
3982                   {
3983                      if(cParam.type == type && arg->dataTypeString && !strcmp(cParam.name, arg->dataTypeString))
3984                      {
3985                         if(templatedClass.templateArgs[p].dataTypeString && c != p)
3986                         {
3987                            FreeTemplateArg(templatedClass, param, c);
3988
3989                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3990                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3991                            CopyTemplateArg(cParam, arg);
3992                         }
3993                      }
3994                   }
3995                }
3996             }
3997             c--;
3998          }
3999       }
4000    }
4001
4002    {
4003       Class tClass;
4004       int c = numParams - 1;
4005       for(tClass = _class; tClass; tClass = tClass.base)
4006       {
4007          ClassTemplateParameter param;
4008          if(tClass.templateClass) tClass = tClass.templateClass;
4009          for(param = tClass.templateParams.last; param; param = param.prev)
4010          {
4011             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
4012             if(param.type == identifier && arg->memberString)
4013             {
4014                Class memberClass = templatedClass;
4015                const char * memberString = arg->memberString;
4016                const char * colon = strstr(memberString, "::");
4017                const char * memberName = memberString;
4018                if(colon) memberName = colon + 2;
4019                if(!colon)
4020                {
4021                   memberString = param.defaultArg.memberString;
4022                   colon = memberString ? strstr(memberString, "::") : null;
4023                }
4024
4025                if(colon)
4026                {
4027                   char className[1024];
4028                   Class sClass;
4029
4030                   memcpy(className, memberString, colon - memberString);
4031                   className[colon - memberString] = '\0';
4032
4033                   for(sClass = _class; sClass; sClass = sClass.base)
4034                   {
4035                      ClassTemplateParameter cParam;
4036                      Class nextClass;
4037                      int id = 0;
4038
4039                      if(sClass.templateClass) sClass = sClass.templateClass;
4040                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
4041                      {
4042                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
4043                         id += nextClass.templateParams.count;
4044                      }
4045                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
4046                      {
4047                         if(cParam.type == type && !strcmp(cParam.name, className) && templatedClass.templateArgs[id].dataTypeString)
4048                         {
4049                            strcpy(className, templatedClass.templateArgs[id].dataTypeString);
4050                         }
4051                         id++;
4052                      }
4053                   }
4054                   // TESTING: Added this here...
4055                   memberClass = eSystem_FindClass(findModule, className);
4056                   if(!memberClass)
4057                      memberClass = eSystem_FindClass(templatedClass.module, className);
4058                   if(!memberClass)
4059                      memberClass = eSystem_FindClass(templatedClass.module.application, className);
4060                }
4061
4062                if(memberClass)
4063                {
4064                   switch(param.memberType)
4065                   {
4066                      case dataMember:
4067                         arg->member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
4068                         break;
4069                      case method:
4070                         arg->method = eClass_FindMethod(memberClass, memberName, memberClass.module);
4071                         break;
4072                      case prop:
4073                         arg->prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
4074                         break;
4075                   }
4076                }
4077             }
4078             c--;
4079          }
4080       }
4081    }
4082 }
4083
4084 /*static */bool DefaultFunction()
4085 {
4086    return true;
4087 }
4088
4089 public dllexport bool eClass_IsDerived(Class _class, Class from)
4090 {
4091    if(!_class && !from)
4092       return true;
4093
4094    if(_class && from && (_class.templateClass || from.templateClass))
4095    {
4096       if(eClass_IsDerived(_class.templateClass ? _class.templateClass : _class, from.templateClass ? from.templateClass : from))
4097       {
4098          if(!from.templateClass)
4099             return true;
4100          else if(!_class.templateClass && _class == from.templateClass)
4101             return false;
4102          else
4103          {
4104             Class sClass;
4105             for(sClass = from; sClass; sClass = sClass.base)
4106             {
4107                if(sClass.templateParams.first)
4108                {
4109                   ClassTemplateParameter param;
4110                   Class nextClass;
4111                   int p = 0;
4112                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) p += nextClass.templateParams.count;
4113                   for(param = sClass.templateParams.first; param; param = param.next, p++)
4114                   {
4115                      ClassTemplateArgument * arg = &_class.templateArgs[p];
4116                      ClassTemplateArgument * fArg = &from.templateArgs[p];
4117                      if(param.type == type)
4118                      {
4119                         if(arg->dataTypeString != fArg->dataTypeString && arg->dataTypeString && fArg->dataTypeString &&
4120                           strcmp(arg->dataTypeString, fArg->dataTypeString))
4121                            break;
4122                      }
4123                      else if(param.type == identifier)
4124                      {
4125                         if(arg->member != fArg->member)
4126                            break;
4127                      }
4128                      else if(param.type == expression)
4129                      {
4130                         if(arg->expression.ui64 != fArg->expression.ui64)
4131                            break;
4132                      }
4133                   }
4134                   if(param)
4135                      return false;
4136                }
4137             }
4138             return true;
4139          }
4140       }
4141    }
4142    else
4143    {
4144       for(; _class && from; _class = _class.base)
4145       {
4146          if(_class == from || _class.templateClass == from || ((_class.type == systemClass || (_class.type == normalClass && _class.isInstanceClass)) && from.name && !strcmp(_class.name, from.name)))
4147             return true;
4148       }
4149    }
4150    return false;
4151 }
4152
4153 static void FixDerivativeVirtualMethod(Class base, const char * name, int vid, void * origFunction, const char * type)
4154 {
4155    OldLink derivative;
4156    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
4157    {
4158       Class _class = derivative.data;
4159       Method method, next;
4160       void * function = origFunction;
4161
4162       _class.vTblSize++;
4163       _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
4164       memmove(_class._vTbl + vid + 1, _class._vTbl + vid, (_class.vTblSize - vid - 1) * sizeof(void *));
4165
4166       method = (Method) _class.methods.FindString(name);
4167       if(method)
4168       {
4169          if(method.function) function = method.function;
4170
4171          if(!method.symbol)
4172          {
4173             delete (void *)method.name;
4174             delete (void *)method.dataTypeString;
4175             _class.methods.Delete((BTNode)method);
4176          }
4177          else
4178          {
4179             delete (void *)method.dataTypeString;
4180             method.type = virtualMethod;
4181             method.dataTypeString = CopyString(type);
4182             method._class = base;
4183          }
4184       }
4185       for(method = (Method)_class.methods.first; method; method = next)
4186       {
4187          next = (Method)((BTNode)method).next;
4188          if(method.type == virtualMethod)
4189             method.vid++;
4190       }
4191       _class._vTbl[vid] = function;
4192
4193       {
4194          OldLink templateLink;
4195          for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4196          {
4197             Class template = templateLink.data;
4198             template._vTbl = _class._vTbl;
4199          }
4200       }
4201       if(_class.derivatives.first || _class.templatized.first)
4202          FixDerivativeVirtualMethod(_class, name, vid, function, type);
4203    }
4204    {
4205       OldLink templateLink;
4206       for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
4207       {
4208          Class template = templateLink.data;
4209          template._vTbl = base._vTbl;
4210          FixDerivativeVirtualMethod(template, name, vid, origFunction, type);
4211       }
4212    }
4213 }
4214
4215 public dllexport Method eClass_AddMethod(Class _class, const char * name, const char * type, void * function, AccessMode declMode)
4216 {
4217    if(_class && !_class.comRedefinition && name)
4218    {
4219       Class base;
4220       for(base = _class; base; base = base.base)
4221       {
4222          Method method;
4223          if(base.templateClass) base = base.templateClass;
4224          method = (Method)base.methods.FindString(name);
4225          if(method)
4226          {
4227             // If this overrides a virtual method
4228             if(method.type == virtualMethod)
4229             {
4230                OldLink deriv;
4231                void * oldFunction = _class._vTbl[method.vid];
4232                if(method.vid >= _class.vTblSize)
4233                   printf("error: virtual methods overriding failure\n");
4234                else
4235                   _class._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
4236                for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4237                {
4238                   Class derivClass = deriv.data;
4239                   if(derivClass._vTbl[method.vid] == oldFunction)
4240                      eClass_AddMethod(derivClass, name, type, function, declMode);
4241                }
4242                {
4243                   OldLink templateLink;
4244                   for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4245                   {
4246                      Class template = templateLink.data;
4247                      for(deriv = template.derivatives.first; deriv; deriv = deriv.next)
4248                      {
4249                         Class derivClass = deriv.data;
4250                         if(derivClass._vTbl[method.vid] == oldFunction)
4251                            eClass_AddMethod(derivClass, name, type, function, declMode);
4252                      }
4253                   }
4254                }
4255
4256             }
4257             else
4258             {
4259                if(base == _class)
4260                {
4261                   // printf("error: Redefinition of method %s in class %s\n", name, _class.name);
4262                   break;
4263                }
4264                base = null;
4265                break;
4266             }
4267             return method;
4268          }
4269       }
4270
4271       if(!base)
4272       {
4273          Method method
4274          {
4275             name = CopyString(name),
4276             function = function ? function : null; //DefaultFunction;
4277             _class = _class;
4278             dataTypeString = CopyString(type);
4279             memberAccess = declMode;
4280          };
4281          _class.methods.Add((BTNode)method);
4282          return method;
4283       }
4284    }
4285    return null;
4286 }
4287
4288 public dllexport Method eClass_AddVirtualMethod(Class _class, const char * name, const char * type, void * function, AccessMode declMode)
4289 {
4290    if(_class && !_class.comRedefinition && name)
4291    {
4292       Class base;
4293       for(base = _class; base; base = base.base)
4294       {
4295          Method method = (Method)base.methods.FindString(name);
4296          if(method)
4297          {
4298             // If this overides a virtual method
4299             if(method.type == virtualMethod)
4300             {
4301                if(method.vid >= _class.vTblSize)
4302                   printf("error: virtual methods overriding failure\n");
4303                else
4304                   _class._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
4305             }
4306             else
4307                base = null;
4308             return method;
4309          }
4310       }
4311
4312       if(!base)
4313       {
4314          Method method
4315          {
4316             name = CopyString(name);
4317             function = function ? function : null; //DefaultFunction;
4318             type = virtualMethod;
4319             _class = _class;
4320             vid = _class.vTblSize++;
4321             dataTypeString = CopyString(type);
4322             memberAccess = declMode;
4323          };
4324          _class.methods.Add((BTNode)method);
4325          _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
4326          _class._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
4327
4328          // TODO: Fix derived classes
4329          if(_class.derivatives.first || _class.templatized.first)
4330             FixDerivativeVirtualMethod(_class, name, method.vid, function ? function : null /*(void *)DefaultFunction*/, type);
4331          return method;
4332       }
4333    }
4334    return null;
4335 }
4336
4337 static void FixDerivativeProperty(Class base, Property _property)
4338 {
4339    OldLink derivative;
4340    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
4341    {
4342       Class _class = derivative.data;
4343       Property prop;
4344       BTNamedLink link = (BTNamedLink)_class.prop.FindString(_property.name);
4345       if(link)
4346       {
4347          prop = link.data;
4348          if(!prop.Set && !prop.Get && prop.memberAccess == baseSystemAccess)
4349          {
4350             SelfWatcher watcher;
4351             for(watcher = _class.selfWatchers.first; watcher; watcher = watcher.next)
4352             {
4353                if(watcher._property == prop)
4354                   watcher._property = _property;
4355             }
4356             _property.selfWatchable = true;
4357
4358             delete (void *)prop.name;
4359             delete (void *)prop.dataTypeString;
4360             _class.membersAndProperties.Delete(prop);
4361             _class.prop.Delete((BTNode)link);
4362          }
4363       }
4364
4365       for(prop = _class.membersAndProperties.first; prop; prop = prop.next)
4366          prop.id++;
4367       _class.memberID++;
4368       _class.startMemberID++;
4369
4370       FixDerivativeProperty(_class, _property);
4371    }
4372 }
4373
4374 public dllexport Property eClass_AddProperty(Class _class, const char * name, const char * dataType, void * setStmt, void * getStmt, AccessMode declMode)
4375 {
4376    Property _property = null;
4377    if(_class)
4378    {
4379       BTNamedLink link = (BTNamedLink)_class.prop.FindString(name ? name : dataType);
4380       bool isConversion = name ? false : true;
4381       if(!name && dataType && !strncmp(dataType, "const ", 6))
4382       {
4383          name = dataType + 6;
4384          isConversion = true;
4385       }
4386       if(link)
4387          _property = link.data;
4388       if(!_property)
4389       {
4390          _property =
4391          {
4392             isProperty = true;
4393             name = CopyString(name ? name : dataType);
4394             id = (name && (setStmt || getStmt || dataType)) ? _class.memberID++ : 0;
4395             Set = setStmt;
4396             Get = getStmt;
4397             dataTypeString = CopyString(dataType);
4398             _class = _class;
4399             compiled = true;
4400             conversion = isConversion;
4401             memberAccess = declMode;
4402          };
4403          if(!isConversion)
4404             _class.membersAndProperties.Add(_property);
4405          else
4406             _class.conversions.Add(_property);
4407          _class.prop.Add((BTNode)BTNamedLink { name = _property.name, data = _property });
4408
4409          if(!_property.conversion)
4410          {
4411             FixDerivativeProperty(_class, _property);
4412          }
4413       }
4414    }
4415    return _property;
4416 }
4417
4418 static void SetDelayedCPValues(Class _class, ClassProperty _property)
4419 {
4420    OldLink deriv;
4421    NamedLink64 value, next;
4422
4423    for(value = _class.delayedCPValues.first; value; value = next)
4424    {
4425       next = value.next;
4426       if(!strcmp(value.name, _property.name))
4427       {
4428          // eClass_SetProperty(_class, _property.name, value.data);
4429          _property.Set(_class, value.data);
4430          _class.delayedCPValues.Delete(value);
4431       }
4432    }
4433
4434    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4435    {
4436       SetDelayedCPValues(deriv.data, _property);
4437    }
4438 }
4439
4440 public dllexport ClassProperty eClass_AddClassProperty(Class _class, const char * name, const char * dataType, void * setStmt, void * getStmt)
4441 {
4442    if(name && !_class.classProperties.FindString(name))
4443    {
4444       ClassProperty _property
4445       {
4446          name = CopyString(name);
4447          Set = setStmt;
4448          Get = getStmt;
4449          dataTypeString = CopyString(dataType);
4450       };
4451       _class.classProperties.Add((BTNode)_property);
4452       SetDelayedCPValues(_class, _property);
4453       return _property;
4454    }
4455    return null;
4456 }
4457
4458 /*import "Time"
4459
4460 Time classFindTotalTime;
4461
4462 public dllexport void ResetClassFindTime()
4463 {
4464    classFindTotalTime = 0;
4465 }
4466
4467 public dllexport Time GetClassFindTime()
4468 {
4469    return classFindTotalTime;
4470 }
4471 */
4472 public dllexport ClassProperty eClass_FindClassProperty(Class _class, const char * name)
4473 {
4474    //Time startTime = GetTime();
4475    ClassProperty _property = null;
4476    if(name && _class)
4477    {
4478       Class origClass = _class;
4479       for(; _class; _class = _class.base)
4480       {
4481          _property = (ClassProperty)_class.classProperties.FindString(name);
4482          if(_property)
4483             break;
4484       }
4485       // For enum class deriving off something else than enum to find enumSize...
4486       if(!_property && origClass.type == enumClass)
4487       {
4488          Class enumClass = eSystem_FindClass(origClass.module, "enum");
4489          _property = eClass_FindClassProperty(enumClass, name);
4490       }
4491    }
4492    /*if(!_property)
4493       eSystem_Logf("No such property (%s) for class %s\n", name, _class.name);*/
4494    //classFindTotalTime += GetTime() - startTime;
4495    return _property;
4496 }
4497
4498 public dllexport int64 eClass_GetProperty(Class _class, const char * name)
4499 {
4500    ClassProperty _property = eClass_FindClassProperty(_class, name);
4501    if(_property && _property.Get && _property.Get != (void *)1)
4502    {
4503       int64 result = _property.Get(_class);
4504       return result;
4505    }
4506    return 0;
4507 }
4508
4509 public dllexport void eClass_SetProperty(Class _class, const char * name, int64 value)
4510 {
4511    ClassProperty _property = eClass_FindClassProperty(_class, name);
4512    if(_property)
4513    {
4514       if(_property.Set)
4515          ((void(*)(void *, int64))_property.Set)(_class, value);
4516    }
4517    else
4518    {
4519       _class.delayedCPValues.Add(NamedLink64 { name = (char *)name, value });
4520    }
4521 }
4522
4523 public dllexport Method eClass_FindMethod(Class _class, const char * name, Module module)
4524 {
4525    //Time startTime = GetTime();
4526    if(_class && name)
4527    {
4528       for(; _class; _class = _class.base)
4529       {
4530          Method method;
4531          if(_class.templateClass) _class = _class.templateClass;
4532          method = (Method)_class.methods.FindString(name);
4533          if(method && (method.memberAccess == publicAccess || _class.module == module || !method.dataTypeString))
4534          {
4535             if(!method.dataTypeString)
4536             {
4537                if(_class.module != module)
4538                {
4539                   if(method.memberAccess == publicAccess)
4540                      module = _class.module;
4541                   else
4542                   {
4543                      //classFindTotalTime += GetTime() - startTime;
4544                      return null;
4545                   }
4546                }
4547             }
4548             else
4549             {
4550                //classFindTotalTime += GetTime() - startTime;
4551                return method;
4552             }
4553          }
4554          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4555       }
4556    }
4557    //classFindTotalTime += GetTime() - startTime;
4558    return null;
4559 }
4560
4561 // Construct an instance
4562 static bool ConstructInstance(void * instance, Class _class, Class from)
4563 {
4564    if(_class.templateClass) _class = _class.templateClass;
4565    if(_class.base && from != _class.base)
4566    {
4567       if(!ConstructInstance(instance, _class.base, from))
4568          return false;
4569    }
4570    if(_class.Initialize)
4571    {
4572       void (* Initialize)(Module module) = (void *)_class.Initialize;
4573       _class.Initialize = null;
4574       Initialize(_class.module);
4575    }
4576    if(_class.Constructor)
4577    {
4578       if(!_class.Constructor(instance))
4579       {
4580          for(; _class; _class = _class.base)
4581          {
4582             if(_class.templateClass) _class = _class.templateClass;
4583             if(_class.Destructor)
4584                _class.Destructor(instance);
4585          }
4586          return false;
4587       }
4588    }
4589    (_class.templateClass ? _class.templateClass : _class).count++;
4590    return true;
4591 }
4592
4593 public dllexport void * eInstance_New(Class _class)
4594 {
4595    Instance instance = null;
4596    if(_class)
4597    {
4598       // instance = _malloc(_class.size);
4599 #ifdef MEMINFO
4600
4601 #undef malloc
4602    memMutex.Wait();
4603       //allocateClass = _class;
4604       allocateClass = malloc(strlen(_class.name)+1);
4605       allocateInternal = _class.module == __thisModule;
4606       strcpy(allocateClass, _class.name);
4607 #ifndef MEMINFO
4608 #define malloc _mymalloc
4609 #endif
4610
4611 #endif
4612       {
4613          int size = _class.structSize;
4614          int flags = _class.module.application.isGUIApp;
4615          bool inCompiler = (flags & 8) ? true : false;
4616          bool force32Bits = (flags & 4) ? true : false;
4617          if(force32Bits && inCompiler)
4618          {
4619             // Allocate 64 bit sizes for these when cross-compiling for 32 bit to allow loaded libraries to work properly
4620             if(!strcmp(_class.name, "Module"))
4621                size = 560;
4622             else if(_class.templateClass && !strcmp(_class.templateClass.name, "Map"))
4623                size = 40;
4624             else
4625                size *= 3;
4626          }
4627          instance = _calloc(1, size);
4628       }
4629 #ifdef MEMINFO
4630       allocateClass = null;
4631    memMutex.Release();
4632 #endif
4633
4634 #if !defined(MEMINFO) && defined(MEMTRACKING)
4635       {
4636          MemBlock block = (MemBlock)((byte *)instance - sizeof(class MemBlock));
4637          block._class = _class;
4638       }
4639 #endif
4640
4641       if(_class.type == normalClass)
4642       {
4643          instance._class = _class;
4644          // Copy the virtual table initially
4645          instance._vTbl = _class._vTbl;
4646       }
4647       if(!ConstructInstance(instance, _class, null))
4648       {
4649          _free(instance);
4650          instance = null;
4651       }
4652       /*if(_class.type == normalClass && _class.count > 1000)
4653          printf("%s: %d instances\n", _class.name, _class.count);*/
4654    }
4655    return instance;
4656 }
4657
4658 public dllexport void eInstance_Evolve(Instance * instancePtr, Class _class)
4659 {
4660    if(_class && instancePtr && *instancePtr)
4661    {
4662       bool wasApp = false, wasGuiApp = false;
4663       Instance oldInstance = *instancePtr;
4664       Instance instance = (Instance)renew *instancePtr byte[_class.structSize];
4665       Class fromClass = instance._class;
4666       *instancePtr = instance;
4667       memset(((byte *)instance) + instance._class.structSize, 0, _class.structSize - instance._class.structSize);
4668       // Fix pointers to application
4669       if((wasApp = !strcmp(instance._class.name, "Application")) ||
4670          (wasGuiApp = !strcmp(instance._class.name, "GuiApplication")))
4671       {
4672          Module module;
4673          Application app = (Application) instance;
4674          BTNamedLink link;
4675          Class _class;
4676          NameSpace * nameSpace;
4677          for(module = app.allModules.first; module; module = module.next)
4678             module.application = app;
4679
4680          for(link = (BTNamedLink)app.privateNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4681          {
4682             OldLink t;
4683             ((Class)link.data).nameSpace = &app.privateNameSpace;
4684             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4685          }
4686          for(link = (BTNamedLink)app.publicNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4687          {
4688             OldLink t;
4689             ((Class)link.data).nameSpace = &app.publicNameSpace;
4690             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4691          }
4692
4693          for(link = (BTNamedLink)app.privateNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4694             ((DefinedExpression)link.data).nameSpace = &app.privateNameSpace;
4695          for(link = (BTNamedLink)app.publicNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4696             ((DefinedExpression)link.data).nameSpace = &app.publicNameSpace;
4697
4698          for(link = (BTNamedLink)app.privateNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4699             ((GlobalFunction)link.data).nameSpace = &app.privateNameSpace;
4700          for(link = (BTNamedLink)app.publicNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4701             ((GlobalFunction)link.data).nameSpace = &app.publicNameSpace;
4702
4703          for(nameSpace = (NameSpace *)app.privateNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4704             nameSpace->parent = &app.privateNameSpace;
4705          for(nameSpace = (NameSpace *)app.publicNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4706             nameSpace->parent = &app.publicNameSpace;
4707
4708          // --------------------------------------------------
4709          for(link = (BTNamedLink)app.systemNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4710          {
4711             OldLink t;
4712             ((Class)link.data).nameSpace = &app.systemNameSpace;
4713             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4714          }
4715          for(link = (BTNamedLink)app.systemNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4716             ((DefinedExpression)link.data).nameSpace = &app.systemNameSpace;
4717          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4718             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4719          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4720             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4721          for(nameSpace = (NameSpace *)app.systemNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4722             nameSpace->parent = &app.systemNameSpace;
4723          // --------------------------------------------------
4724
4725          for(_class = app.classes.first; _class; _class = _class.next)
4726          {
4727             OldLink templateLink;
4728             _class.module = (Module) app;
4729             for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4730             {
4731                Class template = templateLink.data;
4732                if(template.module == oldInstance)
4733                   template.module = _class.module;
4734             }
4735          }
4736
4737          for(module = app.allModules.first; module; module = module.next)
4738          {
4739             for(_class = module.classes.first; _class; _class = _class.next)
4740             {
4741                OldLink templateLink;
4742                Module oldModule = _class.module;
4743                _class.module = module;
4744                for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4745                {
4746                   Class template = templateLink.data;
4747                   if(template.module == oldModule)
4748                      template.module = _class.module;
4749                }
4750             }
4751          }
4752
4753          app.application = app;
4754       }
4755
4756       {
4757          Class base;
4758          for(base = instance._class; base && base.type == normalClass && base.count; base = base.base)
4759             (base.templateClass ? base.templateClass : base).count--;
4760       }
4761
4762       instance._class = _class;
4763       // Copy the virtual table initially
4764       instance._vTbl = _class._vTbl;
4765
4766       // We don't want to reconstruct the portion already constructed...
4767       if(!ConstructInstance(instance, _class, fromClass))
4768       {
4769          _free(instance);
4770          *instancePtr = null;
4771       }
4772    }
4773 }
4774
4775 public dllexport void eInstance_Delete(Instance instance)
4776 {
4777 #ifdef MEMINFO
4778    bool checkMemory = false;
4779 #endif
4780    if(instance)
4781    {
4782       Class _class, base;
4783       bool ownVtbl;
4784
4785 #ifdef MEMINFO
4786 #if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__)
4787       if(instance._class == (void *)0xecececececececec)
4788 #else
4789       if(instance._class == (void *)0xecececec)
4790 #endif
4791          _free(instance);
4792 #endif
4793
4794       ownVtbl = instance._vTbl != instance._class._vTbl;
4795
4796       for(_class = instance._class; _class; _class = base)
4797       {
4798          if(_class.templateClass) _class = _class.templateClass;
4799          if(_class.destructionWatchOffset)
4800          {
4801             OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
4802             Watcher watcher, next;
4803
4804             for(watcher = watchers->first; watcher; watcher = next)
4805             {
4806                next = watcher.next;
4807                watchers->Remove(watcher);
4808                watcher.callback(watcher.object, instance);
4809                watchers->Delete(watcher);
4810             }
4811          }
4812
4813          /*// Loop through properties to delete all watchers? Might slow down destruction...
4814          {
4815             Property _property;
4816             for(_property = _class.membersAndProperties.first; _property; _property = _property.next)
4817             {
4818                if(_property.isProperty && _property.isWatchable)
4819                {
4820                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
4821                   Watcher watcher, next;
4822                   for(watcher = watchers->first; watcher; watcher = next)
4823                   {
4824                      next = watcher.next;
4825                      watchers->Delete(watcher);
4826                   }
4827                }
4828             }
4829          }*/
4830
4831
4832          base = _class.base;
4833          if(base && (base.type == systemClass || base.isInstanceClass)) base = null;
4834          if(_class.Destructor)
4835             _class.Destructor(instance);
4836 #ifdef MEMINFO
4837          if(_class == class(Application))
4838             checkMemory = true;
4839 #endif
4840       }
4841
4842       for(_class = instance._class; _class; _class = base)
4843       {
4844          if(_class.templateClass) _class = _class.templateClass;
4845
4846          base = _class.base;
4847          (_class.templateClass ? _class.templateClass : _class).count--;
4848          if(_class.type == normalClass && !_class.count && !_class.module)
4849          {
4850 #ifdef MEMINFO
4851             // printf("Now Destructing class %s\n", _class.name);
4852 #endif
4853             eClass_Unregister(_class);
4854          }
4855       }
4856
4857       if(ownVtbl)
4858       {
4859          delete instance._vTbl;
4860       }
4861       //instance.prop.Free(null);
4862       _free(instance);
4863 #ifdef MEMINFO
4864       if(checkMemory) CheckMemory();
4865 #endif
4866    }
4867 }
4868
4869 public dllexport Property eClass_FindProperty(Class _class, const char * name, Module module)
4870 {
4871    //Time startTime = GetTime();
4872    if(_class && name)
4873    {
4874       if(!strncmp(name, "const ", 6))
4875          name += 6;
4876
4877       for(; _class; _class = _class.base)
4878       {
4879          BTNamedLink link;
4880          if(_class.templateClass) _class = _class.templateClass;
4881          link = (BTNamedLink)_class.prop.FindString(name);
4882          if(link)
4883          {
4884             Property _property = (Property)link.data;
4885             if(_property.memberAccess == publicAccess || _class.module == module || !_property.dataTypeString)
4886             {
4887                if(!_property.dataTypeString)
4888                {
4889                   if(_class.module != module)
4890                   {
4891                      if(_property.memberAccess == publicAccess)
4892                         module = _class.module;
4893                      else
4894                      {
4895                         //classFindTotalTime += GetTime() - startTime;
4896                         return null;
4897                      }
4898                   }
4899                }
4900                else
4901                {
4902                   //classFindTotalTime += GetTime() - startTime;
4903                   return _property;
4904                }
4905             }
4906          }
4907          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4908       }
4909    }
4910    //classFindTotalTime += GetTime() - startTime;
4911    return null;
4912 }
4913
4914 static DataMember FindDataMember(OldList list, BinaryTree alist, const char * name, uint * offset, int * id, bool searchPrivate, DataMember * subMemberStack, int * subMemberStackPos)
4915 {
4916    BTNamedLink link;
4917    DataMember dataMember;
4918
4919    link = (BTNamedLink)alist.FindString(name);
4920    if(link)
4921    {
4922       dataMember = link.data;
4923       if(dataMember.type == normalMember && (dataMember.memberAccess == publicAccess || searchPrivate || !dataMember.dataTypeString))
4924       {
4925          if(offset)
4926             *offset += dataMember.offset;
4927          if(id) *id = dataMember.id;
4928          return dataMember;
4929       }
4930       return null;
4931    }
4932    for(dataMember = list.first; dataMember; dataMember = dataMember.next)
4933    {
4934       if(!dataMember.isProperty && (dataMember.memberAccess == publicAccess || searchPrivate) && !dataMember.name && (dataMember.type == unionMember || dataMember.type == structMember))
4935       {
4936          DataMember childMember;
4937          if(subMemberStackPos) subMemberStack[(*subMemberStackPos)++] = dataMember;
4938          childMember = FindDataMember(dataMember.members, dataMember.membersAlpha, name, offset, id, searchPrivate, subMemberStack, subMemberStackPos);
4939          if(childMember)
4940          {
4941             if(offset)
4942                *offset += dataMember.offset;
4943             if(id) *id += dataMember.id;
4944             return childMember;
4945          }
4946          if(subMemberStackPos) (*subMemberStackPos)--;
4947       }
4948    }
4949    return null;
4950 }
4951
4952 public dllexport DataMember eClass_FindDataMember(Class _class, const char * name, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4953 {
4954    //Time startTime = GetTime();
4955    DataMember dataMember = null;
4956    if(subMemberStackPos) *subMemberStackPos = 0;
4957    if(_class && name)
4958    {
4959       for(; _class; _class = _class.base)
4960       {
4961          if(_class.templateClass) _class = _class.templateClass;
4962          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, null, _class.module == module, subMemberStack, subMemberStackPos);
4963          if(dataMember)
4964          {
4965             if(!dataMember.dataTypeString)
4966             {
4967                if(_class.module != module)
4968                {
4969                   if(dataMember.memberAccess == publicAccess)
4970                      module = _class.module;
4971                   else
4972                   {
4973                      //classFindTotalTime += GetTime() - startTime;
4974                      return null;
4975                   }
4976                }
4977                dataMember = null;
4978             }
4979             else
4980             {
4981                // HACK: Is this good enough? avoiding setting it when adding...
4982                dataMember._class = _class.templateClass ? _class.templateClass : _class;
4983                //classFindTotalTime += GetTime() - startTime;
4984                return dataMember;
4985             }
4986          }
4987          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4988       }
4989    }
4990    //classFindTotalTime += GetTime() - startTime;
4991    return dataMember;
4992 }
4993
4994 public dllexport DataMember eClass_FindDataMemberAndOffset(Class _class, const char * name, uint * offset, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4995 {
4996    //Time startTime = GetTime();
4997    DataMember dataMember = null;
4998    if(subMemberStackPos) *subMemberStackPos = 0;
4999    if(offset) *offset = 0;
5000    if(_class)
5001    {
5002       for(; _class; _class = _class.base)
5003       {
5004          if(_class.templateClass) _class = _class.templateClass;
5005          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, offset, null, _class.module == module, subMemberStack, subMemberStackPos);
5006          if(dataMember)
5007          {
5008             if(!dataMember.dataTypeString)
5009             {
5010                if(_class.module != module)
5011                {
5012                   if(dataMember.memberAccess == publicAccess)
5013                      module = _class.module;
5014                   else
5015                   {
5016                      //classFindTotalTime += GetTime() - startTime;
5017                      return null;
5018                   }
5019                }
5020                dataMember = null;
5021             }
5022             else
5023             {
5024                // HACK: Is this good enouh? avoiding setting it when adding...
5025                dataMember._class = _class;
5026                //classFindTotalTime += GetTime() - startTime;
5027                return dataMember;
5028             }
5029          }
5030          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
5031       }
5032    }
5033    //classFindTotalTime += GetTime() - startTime;
5034    return dataMember;
5035 }
5036
5037 public dllexport DataMember eClass_FindDataMemberAndId(Class _class, const char * name, int * id, Module module, DataMember * subMemberStack, int * subMemberStackPos)
5038 {
5039    //Time startTime = GetTime();
5040    DataMember dataMember = null;
5041    if(subMemberStackPos) *subMemberStackPos = 0;
5042    if(_class)
5043    {
5044       for(; _class; _class = _class.base)
5045       {
5046          if(_class.templateClass) _class = _class.templateClass;
5047          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, id, _class.module == module, subMemberStack, subMemberStackPos);  // TOCHECK: Why was this null? null, null);
5048          if(dataMember)
5049          {
5050             if(!dataMember.dataTypeString)
5051             {
5052                if(_class.module != module)
5053                {
5054                   if(dataMember.memberAccess == publicAccess)
5055                      module = _class.module;
5056                   else
5057                   {
5058                      //classFindTotalTime += GetTime() - startTime;
5059                      return null;
5060                   }
5061                }
5062                dataMember = null;
5063             }
5064             else
5065             {
5066                // HACK: Is this good enouh? avoiding setting it when adding...
5067                dataMember._class = _class;
5068                //classFindTotalTime += GetTime() - startTime;
5069                return dataMember;
5070             }
5071          }
5072          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
5073       }
5074    }
5075    //classFindTotalTime += GetTime() - startTime;
5076    return dataMember;
5077 }
5078
5079 public dllexport void eClass_FindNextMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
5080 {
5081    // THIS CODE WILL FIND NEXT MEMBER... (PUBLIC MEMBERS ONLY)
5082    if(*curMember)
5083    {
5084       *curMember = (*curMember).next;
5085
5086       if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
5087       {
5088          *curMember = subMemberStack[--(*subMemberStackPos)];
5089          *curMember = (*curMember).next;
5090       }
5091
5092       if(subMemberStackPos && *subMemberStackPos > 0)
5093       {
5094          while(*curMember && ((*curMember).memberAccess == privateAccess))
5095             *curMember = (*curMember).next;
5096       }
5097       else
5098          while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
5099          {
5100             DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
5101             if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
5102             if(dataMember && dataMember.memberAccess != privateAccess)
5103             {
5104                *curMember = dataMember;
5105                break;
5106             }
5107             else
5108                *curMember = (*curMember).next;
5109          }
5110
5111       if(subMemberStackPos)
5112       {
5113          while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
5114          {
5115             subMemberStack[(*subMemberStackPos)++] = *curMember;
5116
5117             *curMember = (*curMember).members.first;
5118             while(*curMember && ((*curMember).memberAccess == privateAccess))
5119                *curMember = (*curMember).next;
5120          }
5121       }
5122    }
5123    while(!*curMember)
5124    {
5125       if(!*curMember)
5126       {
5127          if(subMemberStackPos && *subMemberStackPos)
5128          {
5129             *curMember = subMemberStack[--(*subMemberStackPos)];
5130             *curMember = (*curMember).next;
5131          }
5132          else
5133          {
5134             Class lastCurClass = *curClass;
5135
5136             if(*curClass == _class) break;     // REACHED THE END
5137
5138             for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass && (*curClass).inheritanceAccess != privateAccess; *curClass = (*curClass).base);
5139             *curMember = (*curClass).membersAndProperties.first;
5140          }
5141
5142          if(subMemberStackPos && *subMemberStackPos > 0)
5143          {
5144             while(*curMember && ((*curMember).memberAccess == privateAccess))
5145                *curMember = (*curMember).next;
5146          }
5147          else
5148             while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
5149             {
5150                DataMember dataMember = null;
5151                if(((*curMember).memberAccess != privateAccess))
5152                {
5153                   dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
5154                   if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
5155                }
5156                if(dataMember && dataMember.memberAccess != privateAccess && dataMember.id >= 0) // Skip _vTbl, _refCount and _class in Instance
5157                {
5158                   *curMember = dataMember;
5159                   break;
5160                }
5161                else
5162                   *curMember = (*curMember).next;
5163             }
5164
5165          if(subMemberStackPos)
5166          {
5167             while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
5168             {
5169                subMemberStack[(*subMemberStackPos)++] = *curMember;
5170
5171                *curMember = (*curMember).members.first;
5172                while(*curMember && (*curMember).memberAccess == privateAccess)
5173                   *curMember = (*curMember).next;
5174             }
5175          }
5176       }
5177    }
5178 }
5179
5180 public dllexport void eInstance_SetMethod(Instance instance, const char * name, void * function)     // YET TO BE DECIDED:   , Module module)
5181 {
5182    if(instance && name)
5183    {
5184       Class _class;
5185       for(_class = instance._class; _class; _class = _class.base)
5186       {
5187          Method method = (Method)_class.methods.FindString(name);
5188          if(method && method.type == virtualMethod)
5189          {
5190             if(instance._vTbl == instance._class._vTbl)
5191             {
5192                instance._vTbl = _malloc(sizeof(void *) * instance._class.vTblSize);
5193                memcpy(instance._vTbl, instance._class._vTbl,
5194                   sizeof(int(*)()) * instance._class.vTblSize);
5195             }
5196             instance._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
5197          }
5198       }
5199    }
5200 }
5201
5202 public dllexport bool eInstance_IsDerived(Instance instance, Class from)
5203 {
5204    if(instance)
5205    {
5206       Class _class = instance._class;
5207       for(; _class; _class = _class.base)
5208       {
5209          if(_class == from)
5210             return true;
5211       }
5212    }
5213    return false;
5214 }
5215
5216 public dllexport void eInstance_IncRef(Instance instance)
5217 {
5218    if(instance)
5219       instance._refCount++;
5220 }
5221
5222 public dllexport void eInstance_DecRef(Instance instance)
5223 {
5224    if(instance)
5225    {
5226       instance._refCount--;
5227       //if(!instance._refCount)
5228       if(instance._refCount <= 0)
5229       {
5230          eInstance_Delete(instance);
5231       }
5232    }
5233 }
5234
5235 static void FixOffsets(Class _class)
5236 {
5237    OldLink deriv;
5238    _class.structSize += _class.base.structSize - _class.offset;
5239
5240    _class.offset = _class.base.structSize;
5241
5242    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
5243       FixOffsets(deriv.data);
5244 }
5245
5246 public dllexport void eClass_Resize(Class _class, int newSize)
5247 {
5248    OldLink deriv;
5249    _class.structSize = newSize;
5250    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
5251       FixOffsets(deriv.data);
5252 }
5253                                                                                                                         // F000F000 will mean a pointer size alignment
5254 public dllexport DataMember eClass_AddDataMember(Class _class, const char * name, const char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
5255 {
5256    if(_class && name)
5257    {
5258       if(!_class.members.FindString(name))
5259       {
5260          DataMember dataMember;
5261
5262          if(alignment)
5263          {
5264             bool pointerAlignment = alignment == 0xF000F000;
5265             bool force64Bits = (_class.module.application.isGUIApp & 2) ? true : false;
5266             bool force32Bits = (_class.module.application.isGUIApp & 4) ? true : false;
5267             if((force32Bits || force64Bits) && !strcmp(_class.name, "AVLNode") && !strcmp(name, "__ecerePrivateData0"))
5268             {
5269                if(force64Bits)
5270                {
5271                   type = "byte[32]";
5272                   size = 32;
5273                }
5274                if(force32Bits)
5275                {
5276                   type = "byte[16]";
5277                   size = 16;
5278                }
5279             }
5280
5281             if(pointerAlignment) alignment = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
5282
5283             if(pointerAlignment && _class.structAlignment <= 4)
5284                _class.pointerAlignment = 1;
5285             else if(!pointerAlignment && alignment >= 8)
5286                _class.pointerAlignment = 0;
5287
5288             _class.structAlignment = Max(_class.structAlignment, alignment);
5289
5290             if(_class.offset % alignment)
5291             {
5292                _class.structSize += alignment - (_class.offset % alignment);
5293                _class.offset += alignment - (_class.offset % alignment);
5294             }
5295             if(_class.memberOffset % alignment)
5296                _class.memberOffset += alignment - (_class.memberOffset % alignment);
5297          }
5298
5299          dataMember = DataMember {
5300             name = CopyString(name);
5301             dataTypeString = CopyString(type);
5302             id = _class.memberID++;
5303             _class = _class;
5304             offset = _class.memberOffset;
5305             memberOffset = size;
5306             memberAccess = declMode;
5307             membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5308          };
5309          _class.membersAndProperties.Add(dataMember);
5310          _class.memberOffset += size;
5311
5312          _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5313          return dataMember;
5314       }
5315    }
5316    return null;
5317 }
5318                                                                                                                               // F000F000 will mean a pointer size alignment
5319 public dllexport DataMember eMember_AddDataMember(DataMember member, const char * name, const char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
5320 {
5321    if(name && !member.membersAlpha.FindString(name))
5322    {
5323       DataMember dataMember;
5324
5325       if(alignment)
5326       {
5327          bool pointerAlignment = alignment == 0xF000F000;
5328          bool force64Bits = false; //(member._class.module.application.isGUIApp & 2) ? true : false;
5329          bool force32Bits = false; //(member._class.module.application.isGUIApp & 4) ? true : false;
5330          if(pointerAlignment) alignment = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
5331
5332          if(pointerAlignment && member.structAlignment <= 4)
5333             member.pointerAlignment = 1;
5334          else if(!pointerAlignment && alignment >= 8)
5335             member.pointerAlignment = 0;
5336
5337          member.structAlignment = Max(member.structAlignment, alignment);
5338
5339          if(member.memberOffset % alignment)
5340             member.memberOffset += alignment - (member.memberOffset % alignment);
5341       }
5342       dataMember = DataMember {
5343          name = CopyString(name);
5344          _class = member._class;
5345          dataTypeString = CopyString(type);
5346          id = member.memberID++;
5347          offset = (member.type == unionMember) ? 0 : member.memberOffset;
5348          memberAccess = declMode;
5349          membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5350       };
5351       member.members.Add(dataMember);
5352       if(member.type == unionMember)
5353       {
5354          if(size > member.memberOffset)
5355             member.memberOffset = size;
5356       }
5357       else
5358          member.memberOffset += size;
5359       member.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5360       return dataMember;
5361    }
5362    return null;
5363 }
5364
5365 public dllexport DataMember eMember_New(DataMemberType type, AccessMode declMode)
5366 {
5367    return DataMember { type = type, memberAccess = declMode, membersAlpha.CompareKey = (void *)BinaryTree::CompareString };
5368 }
5369
5370 static void SetMemberClass(DataMember member, Class _class)
5371 {
5372    DataMember dataMember;
5373    member._class = _class;
5374    for(dataMember = member.members.first; dataMember; dataMember = dataMember.next)
5375       SetMemberClass(dataMember, _class);
5376 }
5377
5378 public dllexport bool eMember_AddMember(DataMember addTo, DataMember dataMember)
5379 {
5380    if(dataMember.name && addTo.membersAlpha.FindString(dataMember.name))
5381    {
5382       DataMember_Free(dataMember);
5383       delete dataMember;
5384       return false;
5385    }
5386    addTo.members.Add(dataMember);
5387
5388    if(dataMember.name)
5389       addTo.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5390
5391    dataMember._class = addTo._class;
5392    // ? SetMemberClass(dataMember, addTo._class);
5393
5394    //dataMember.id = addTo.memberID++;
5395    dataMember.id = addTo.memberID;
5396    if(dataMember.type == unionMember)
5397       addTo.memberID += 1;
5398    else
5399       addTo.memberID += dataMember.memberID;
5400
5401    if(dataMember.pointerAlignment && dataMember.structAlignment <= 4)
5402       addTo.pointerAlignment = 1;
5403    else if(!dataMember.pointerAlignment && dataMember.structAlignment >= 8)
5404       addTo.pointerAlignment = 0;
5405
5406    addTo.structAlignment = Max(addTo.structAlignment, dataMember.structAlignment);
5407
5408    dataMember.offset = (addTo.type == unionMember) ? 0 : addTo.memberOffset;
5409
5410    if(dataMember.structAlignment)
5411    {
5412       if(addTo.memberOffset % dataMember.structAlignment)
5413          addTo.memberOffset += dataMember.structAlignment - (addTo.memberOffset % dataMember.structAlignment);
5414    }
5415
5416    if(addTo.type == unionMember)
5417    {
5418       if(dataMember.memberOffset > addTo.memberOffset)
5419          addTo.memberOffset = dataMember.memberOffset;
5420    }
5421    else
5422       addTo.memberOffset += dataMember.memberOffset;
5423    return true;
5424 }
5425
5426 public dllexport bool eClass_AddMember(Class _class, DataMember dataMember)
5427 {
5428    if(!_class || _class.comRedefinition || (dataMember.name && _class.members.FindString(dataMember.name)))
5429    {
5430       DataMember_Free(dataMember);
5431       delete dataMember;
5432       return false;
5433    }
5434    _class.membersAndProperties.Add(dataMember);
5435
5436    if(dataMember.name)
5437       _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5438
5439    //dataMember._class = _class;
5440    SetMemberClass(dataMember, _class);
5441
5442    //dataMember.id = _class.memberID++;
5443    dataMember.id = _class.memberID;
5444
5445    if(dataMember.pointerAlignment && dataMember.structAlignment <= 4)
5446       _class.pointerAlignment = 1;
5447    else if(!dataMember.pointerAlignment && dataMember.structAlignment >= 8)
5448       _class.pointerAlignment = 0;
5449
5450    _class.structAlignment = Max(_class.structAlignment, dataMember.structAlignment);
5451    if(dataMember.type == unionMember)
5452       _class.memberID += 1;
5453    else
5454       _class.memberID += dataMember.memberID;
5455
5456    if(dataMember.structAlignment)
5457    {
5458       if(_class.memberOffset % dataMember.structAlignment)
5459          _class.memberOffset += dataMember.structAlignment - (_class.memberOffset % dataMember.structAlignment);
5460    }
5461
5462    dataMember.offset = _class.memberOffset;
5463    _class.memberOffset += dataMember.memberOffset;
5464    return true;
5465 }
5466
5467 public dllexport BitMember eClass_AddBitMember(Class _class, const char * name, const char * type, int bitSize, int bitPos, AccessMode declMode)
5468 {
5469    if(_class && name && !_class.members.FindString(name))
5470    {
5471       uint64 mask = 0;
5472       int c;
5473       BitMember bitMember
5474       {
5475          name = CopyString(name);
5476          _class = _class;
5477          dataTypeString = CopyString(type);
5478          id = _class.memberID++;
5479          memberAccess = declMode;
5480       };
5481       _class.membersAndProperties.Add(bitMember);
5482       if(bitSize)
5483       {
5484          bitMember.pos = (bitPos == -1) ? _class.memberOffset : bitPos;
5485          bitMember.size = bitSize;
5486          _class.memberOffset = bitMember.pos + bitMember.size;
5487          for(c = 0; c<bitSize; c++)
5488          {
5489             if(c)
5490                mask <<= 1;
5491             mask |= 1;
5492          }
5493          bitMember.mask = mask << bitMember.pos;
5494       }
5495
5496      _class.members.Add((BTNode)BTNamedLink { name = bitMember.name, data = bitMember });
5497       return bitMember;
5498    }
5499    return null;
5500 }
5501
5502 static Module Module_Load(Module fromModule, const char * name, AccessMode importAccess, bool ensureCOM)
5503 {
5504    bool (stdcall * Load)(Module module) = null;
5505    bool (stdcall * Unload)(Module module) = null;
5506    Module module;
5507
5508    for(module = fromModule.application.allModules.first; module; module = module.next)
5509    {
5510       if(!strcmp(module.name, name))
5511          break;
5512    }
5513    if(ensureCOM && (!strcmp(name, "ecereCOM") || !strcmp(name, "ecere")))
5514    {
5515       for(module = fromModule.application.allModules.first; module; module = module.next)
5516       {
5517          if(!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM"))
5518             break;
5519       }
5520    }
5521    if(!module)
5522    {
5523       void * library = null;
5524
5525       if(ensureCOM && !strcmp(name, "ecereCOM"))
5526       {
5527          Load = COM_LOAD_FUNCTION;
5528          Unload = COM_UNLOAD_FUNCTION;
5529       }
5530       else
5531       {
5532          const char * libLocation = null;
5533 #if defined(__ANDROID__)
5534          libLocation = AndroidInterface_GetLibLocation();
5535 #endif
5536          library = Instance_Module_Load(libLocation, name, &Load, &Unload);
5537       }
5538       if(Load)
5539       {
5540          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5541          module.application = fromModule.application;
5542          module.library = library;
5543          {
5544             char moduleName[MAX_FILENAME];
5545             char ext[MAX_EXTENSION];
5546             GetLastDirectory(name, moduleName);
5547             GetExtension(moduleName, ext);
5548             StripExtension(moduleName);
5549             if((!strcmpi(ext, "dylib") || !strcmpi(ext, "so")) && strstr(moduleName, "lib") == moduleName)
5550             {
5551                int len = (int)strlen(moduleName) - 3;
5552                memmove(moduleName, moduleName + 3, len);
5553                moduleName[len] = 0;
5554             }
5555             module.name = CopyString(moduleName);
5556          }
5557          module.Unload = Unload;
5558          module.origImportType = normalImport;
5559
5560          if(!Load(module))
5561          {
5562             eInstance_Delete((Instance)module);
5563             module = null;
5564          }
5565       }
5566       fromModule.application.allModules.Add(module);
5567    }
5568    if(ensureCOM && !strcmp(name, "ecere") && module)
5569    {
5570       name = !strcmp(module.name, "ecereCOM") ? "ecere" : "ecereCOM";
5571       if((!Load && !strcmp(module.name, "ecereCOM")) ||
5572          (Load && (!__thisModule || !__thisModule.name || !strcmp(__thisModule.name, "ecereCOM")) && Load != (void *)COM_LOAD_FUNCTION))
5573       {
5574          Module module;
5575          for(module = fromModule.application.allModules.first; module; module = module.next)
5576          {
5577             if(!strcmp(module.name, name))
5578                break;
5579          }
5580          if(!module)
5581          {
5582             Load = COM_LOAD_FUNCTION;
5583             Unload = COM_UNLOAD_FUNCTION;
5584
5585             module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5586             module.application = fromModule.application;
5587             module.library = null;
5588             module.name = CopyString(name);
5589             module.Unload = Unload;
5590
5591             if(!Load(module))
5592             {
5593                eInstance_Delete((Instance)module);
5594                module = null;
5595             }
5596
5597             fromModule.application.allModules.Add(module);
5598          }
5599          if(module)
5600          {
5601             if(fromModule)
5602             {
5603                fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5604             }
5605             incref module;
5606          }
5607       }
5608    }
5609    if(module)
5610    {
5611       if(fromModule)
5612       {
5613          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5614       }
5615       incref module;
5616    }
5617 #if defined(_DEBUG)
5618    InternalModuleLoadBreakpoint();
5619 #endif
5620    return module;
5621 }
5622
5623 public dllexport Module eModule_Load(Module fromModule, const char * name, AccessMode importAccess)
5624 {
5625    return Module_Load(fromModule, name, importAccess, true);
5626 }
5627
5628 public dllexport Module eModule_LoadStrict(Module fromModule, const char * name, AccessMode importAccess)
5629 {
5630    return Module_Load(fromModule, name, importAccess, false);
5631 }
5632
5633 public dllexport Module eModule_LoadStatic(Module fromModule, const char * name, AccessMode importAccess, bool (* Load)(Module module), bool (* Unload)(Module module))
5634 {
5635    Module module;
5636    for(module = fromModule.application.allModules.first; module; module = module.next)
5637    {
5638       if(!strcmp(module.name, name))
5639          break;
5640    }
5641    if(!module)
5642    {
5643       if(Load)
5644       {
5645          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5646          module.application = fromModule.application;
5647          module.name = CopyString(name);
5648          module.origImportType = staticImport;
5649          module.Unload = (void *)Unload;
5650          if(!Load(module))
5651          {
5652             eInstance_Delete((Instance)module);
5653             module = null;
5654          }
5655       }
5656       fromModule.application.allModules.Add(module);
5657    }
5658    if(module)
5659    {
5660       if(fromModule)
5661       {
5662          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5663       }
5664       incref module;
5665    }
5666    return module;
5667 }
5668
5669 public dllexport void eModule_Unload(Module fromModule, Module module)
5670 {
5671    OldLink m;
5672    for(m = fromModule.modules.first; m; m = m.next)
5673    {
5674       if(m.data == module)
5675          break;
5676    }
5677    if(m)
5678    {
5679       fromModule.modules.Delete(m);
5680       delete module;
5681    }
5682 }
5683
5684 public dllexport void eEnum_AddFixedValue(Class _class, const char * string, int64 value)
5685 {
5686    if(_class && _class.type == enumClass)
5687    {
5688       EnumClassData data = (EnumClassData)_class.data;
5689       NamedLink64 item;
5690
5691       for(item = data.values.first; item; item = item.next)
5692          if(!strcmp(item.name, string))
5693             break;
5694       if(!item)
5695       {
5696          data.values.Add(NamedLink64 { data = value, name = CopyString(string) });
5697          if(value > data.largest)
5698             data.largest = value;
5699       }
5700    }
5701 }
5702
5703 public dllexport int64 eEnum_AddValue(Class _class, const char * string)
5704 {
5705    if(_class && _class.type == enumClass)
5706    {
5707       EnumClassData data = (EnumClassData)_class.data;
5708       int64 value = data.largest + 1;
5709       NamedLink64 item;
5710       for(item = data.values.first; item; item = item.next)
5711          if(!strcmp(item.name, string))
5712             break;
5713       if(!item)
5714       {
5715          data.values.Add(NamedLink64 { data = value, name = CopyString(string) });
5716          if(value > data.largest)
5717             data.largest = value;
5718          return value;
5719       }
5720    }
5721    return -1;
5722 }
5723
5724 static void NameSpace_Free(NameSpace parentNameSpace)
5725 {
5726    NameSpace * nameSpace;
5727    delete (void *)parentNameSpace.name;
5728
5729          /*   {
5730       BTNamedLink n, next;
5731       for(n = (BTNamedLink)parentNameSpace.classes.first; n; n = next)
5732       {
5733          Class c = n.data;
5734
5735          next = (BTNamedLink)((BTNode)n).next;
5736
5737          if(c.templateClass)
5738             eClass_Unregister(c);
5739       }
5740    }         */
5741
5742    while((nameSpace = (NameSpace *)parentNameSpace.nameSpaces.first))
5743    {
5744       NameSpace_Free(nameSpace);
5745       parentNameSpace.nameSpaces.Delete((BTNode)nameSpace);
5746    }
5747 }
5748
5749 static void Application_Destructor(Application app)
5750 {
5751    if(app.parsedCommand)
5752    {
5753       delete (void *)app.argv;
5754       delete app.parsedCommand;
5755    }
5756 }
5757
5758 static bool Module_Constructor(Module module)
5759 {
5760    module.privateNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5761    module.privateNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5762    module.privateNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5763    module.privateNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5764
5765    module.publicNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5766    module.publicNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5767    module.publicNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5768    module.publicNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5769    return true;
5770 }
5771
5772 static void Module_Destructor(Module module)
5773 {
5774    Class _class;
5775    DefinedExpression def;
5776    GlobalFunction function;
5777    Module m;
5778    SubModule handle;
5779
5780    // printf("Destructing module %s\n", module.name);
5781
5782    // Take out references from all modules
5783    for(m = module.application.allModules.first; m; m = m.next)
5784    {
5785       SubModule next;
5786       for(handle = m.modules.first; handle; handle = next)
5787       {
5788          next = handle.next;
5789          if(handle.module == module)
5790             m.modules.Delete(handle);
5791       }
5792    }
5793
5794    if(module.Unload)
5795    {
5796       if(module.origImportType == staticImport)
5797       {
5798          bool (* Unload)(Module module) = (void *)module.Unload;
5799          Unload(module);
5800       }
5801       else
5802       {
5803          bool (stdcall * Unload)(Module module) = (void *)module.Unload;
5804          Unload(module);
5805       }
5806    }
5807
5808    // Unload dependencies
5809    {
5810       Module ourWorld = class(Class).module;
5811       void * ourHandle = null;
5812       while((handle = module.modules.last))  // STARTING WITH LAST SO THAT ecereCOM IS UNLOADED LAST...
5813       {
5814          Module depModule = handle.module;
5815          if(depModule == ourWorld)
5816          {
5817             module.modules.Remove(handle);
5818             ourHandle = handle;
5819          }
5820          else
5821          {
5822             module.modules.Delete(handle);
5823             delete depModule;
5824          }
5825       }
5826       if(ourHandle)
5827       {
5828          delete ourHandle;
5829          delete ourWorld;
5830       }
5831    }
5832
5833    // Unload classes
5834    for(;(_class = module.classes.first);)
5835    {
5836       if(_class.nameSpace)
5837       {
5838          BTNamedLink classLink = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
5839          if(classLink)
5840          {
5841             OldLink t;
5842             for(t = _class.templatized.first; t; t = t.next)
5843             {
5844                Class template = t.data;
5845                BTNamedLink link;
5846                link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
5847
5848                template.nameSpace->classes.Delete((BTNode)link);
5849                template.nameSpace = null;
5850             }
5851             _class.nameSpace->classes.Delete((BTNode)classLink);
5852          }
5853 #ifdef _DEBUG
5854          else
5855          {
5856             printf("Warning: Could not find %s in namespace classes while destructing module %s\n", _class.name, module.name);
5857          }
5858 #endif
5859          _class.nameSpace = null;
5860       }
5861       _class.module = null;
5862       module.classes.Remove(_class);
5863       if(_class.count <= 0 || _class.type != normalClass || _class.isInstanceClass)
5864          eClass_Unregister(_class);
5865       else
5866       {
5867 #ifdef MEMINFO
5868          // printf("Delayed destruction of class %s\n", _class.name);
5869 #endif
5870       }
5871    }
5872
5873    // Unload defines
5874    for(;(def = module.defines.first);)
5875    {
5876       if(def.nameSpace)
5877       {
5878          BTNamedLink defLink;
5879          for(defLink = (BTNamedLink)def.nameSpace->defines.first; defLink; defLink = (BTNamedLink)((BTNode)defLink).next)
5880             if(defLink.data == def)
5881             {
5882                def.nameSpace->defines.Delete((BTNode)defLink);
5883                break;
5884             }
5885       }
5886       delete (void *)def.name;
5887       delete (void *)def.value;
5888       module.defines.Delete(def);
5889    }
5890
5891    // Unload functions
5892    for(;(function = module.functions.first);)
5893    {
5894       if(function.nameSpace)
5895       {
5896          BTNamedLink functionLink;
5897          for(functionLink = (BTNamedLink)function.nameSpace->functions.first; functionLink; functionLink = (BTNamedLink)((BTNode)functionLink).next)
5898             if(functionLink.data == function)
5899             {
5900                function.nameSpace->functions.Delete((BTNode)functionLink);
5901                break;
5902             }
5903       }
5904       delete (void *)function.name;
5905       delete (void *)function.dataTypeString;
5906       module.functions.Delete(function);
5907    }
5908
5909    delete (void *)module.name;
5910
5911    NameSpace_Free(module.privateNameSpace);
5912    NameSpace_Free(module.publicNameSpace);
5913
5914    if(module != module.application)
5915       module.application.allModules.Remove(module);
5916    else
5917       NameSpace_Free(module.application.systemNameSpace);
5918
5919 #ifndef MEMINFO
5920    Instance_Module_Free(module.library);
5921 #endif
5922 }
5923
5924 static int64 GetEnumSize(Class _class)
5925 {
5926    EnumClassData data = (EnumClassData)_class.data;
5927    return data.largest+1;
5928 }
5929
5930 #if defined(__GNUC__)
5931 #define strcmpi strcasecmp
5932 #define strnicmp strncasecmp
5933 #endif
5934
5935 #if defined(ECERE_BOOTSTRAP) || (defined(__GNUC__) && !defined(__DJGPP__) && !defined(__WIN32__))
5936 #undef strlwr
5937 #undef strupr
5938 default dllexport char * strlwr(char *string)
5939 {
5940    int c;
5941    for(c=0; string[c]; c++)
5942       if(string[c]>='A' && string[c]<='Z')
5943          string[c]+='a'-'A';
5944    return string;
5945 }
5946 default dllexport char * strupr(char *string)
5947 {
5948    int c;
5949    for(c=0; string[c]; c++)
5950       if(string[c]>='a' && string[c]<='z')
5951          string[c]-='a'-'A';
5952    return string;
5953 }
5954 #endif
5955
5956 public dllexport DefinedExpression eSystem_RegisterDefine(const char * name, const char * value, Module module, AccessMode declMode)
5957 {
5958    NameSpace * nameSpace = null;
5959
5960    int start = 0, c;
5961
5962    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5963    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5964
5965    if(declMode != staticAccess)
5966    {
5967       for(c = 0; name[c]; c++)
5968       {
5969          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5970          {
5971             NameSpace * newSpace;
5972
5973             char * spaceName = _malloc(c - start + 1);
5974             strncpy(spaceName, name + start, c - start);
5975             spaceName[c-start] = '\0';
5976
5977             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5978             if(!newSpace)
5979             {
5980                newSpace = new0 NameSpace[1];
5981                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5982                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5983                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5984                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5985                newSpace->name = spaceName;
5986                newSpace->parent = nameSpace;
5987                nameSpace->nameSpaces.Add((BTNode)newSpace);
5988             }
5989             else
5990                delete spaceName;
5991             nameSpace = newSpace;
5992             if(name[c] == ':') c++;
5993             start = c+1;
5994          }
5995       }
5996    }
5997    else
5998       c = (int)strlen(name);
5999
6000    if(c - start && !nameSpace->defines.FindString(name + start))
6001    {
6002       DefinedExpression def
6003       {
6004          name = CopyString(name);
6005          nameSpace = nameSpace;
6006          value = CopyString(value);
6007       };
6008       nameSpace->defines.Add((BTNode)BTNamedLink { name = def.name + start, data = def });
6009       // Reference the definition in the module
6010       module.defines.Add(def);
6011       return def;
6012    }
6013    return null;
6014 }
6015
6016 public dllexport GlobalFunction eSystem_RegisterFunction(const char * name, const char * type, void * func, Module module, AccessMode declMode)
6017 {
6018    NameSpace * nameSpace = null;
6019    int start = 0, c;
6020
6021    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
6022    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
6023
6024    if(declMode != staticAccess)
6025    {
6026       for(c = 0; name[c]; c++)
6027       {
6028          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
6029          {
6030             NameSpace * newSpace;
6031
6032             char * spaceName = _malloc(c - start + 1);
6033             strncpy(spaceName, name + start, c - start);
6034             spaceName[c-start] = '\0';
6035
6036             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
6037             if(!newSpace)
6038             {
6039                newSpace = new0 NameSpace[1];
6040                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
6041                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
6042                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
6043                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
6044                newSpace->name = spaceName;
6045                newSpace->parent = nameSpace;
6046                nameSpace->nameSpaces.Add((BTNode)newSpace);
6047             }
6048             else
6049                delete spaceName;
6050             nameSpace = newSpace;
6051             if(name[c] == ':') c++;
6052             start = c+1;
6053          }
6054       }
6055    }
6056    else
6057       c = (int)strlen(name);
6058
6059    if(c - start && !nameSpace->functions.FindString(name + start))
6060    {
6061       GlobalFunction function
6062       {
6063          name = CopyString(name);
6064          nameSpace = nameSpace;
6065          dataTypeString = CopyString(type);
6066          function = func;
6067          module = module;
6068       };
6069       nameSpace->functions.Add((BTNode)BTNamedLink { name = function.name + start, data = function });
6070       // Reference the definition in the module
6071       module.functions.Add(function);
6072       return function;
6073    }
6074    return null;
6075 }
6076
6077 public dllexport DefinedExpression eSystem_FindDefine(Module module, const char * name)
6078 {
6079    if(name && module)
6080    {
6081       BTNamedLink link;
6082       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->defines);
6083       if(link) return link.data;
6084
6085       link = SearchModule(module, name, &((NameSpace *)0)->defines, true);
6086       if(link) return link.data;
6087    }
6088    return null;
6089 }
6090
6091 public dllexport GlobalFunction eSystem_FindFunction(Module module, const char * name)
6092 {
6093    if(name && module)
6094    {
6095       BTNamedLink link;
6096       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->functions);
6097       if(link) return link.data;
6098
6099       link = SearchModule(module, name, &((NameSpace *)0)->functions, true);
6100       if(link) return link.data;
6101    }
6102    return null;
6103 }
6104
6105 public dllexport void * eSystem_Renew(void * memory, unsigned int size)
6106 {
6107    return _realloc(memory, size);
6108 }
6109
6110 public dllexport void * eSystem_Renew0(void * memory, unsigned int size)
6111 {
6112    return _crealloc(memory, size);
6113 }
6114
6115 public dllexport void * eSystem_New(unsigned int size)
6116 {
6117 /*#ifdef _DEBUG
6118    void * pointer = _malloc(size);
6119    memset(pointer, 0xec, size);
6120    return pointer;
6121 #else*/
6122    return _malloc(size);
6123 //#endif
6124 }
6125
6126 public dllexport void * eSystem_New0(unsigned int size)
6127 {
6128    return _calloc(1,size);
6129 }
6130
6131 public dllexport void eSystem_Delete(void * memory)
6132 {
6133    if(memory)
6134       _free(memory);
6135 }
6136
6137 // Properties
6138 public dllexport void eInstance_FireSelfWatchers(Instance instance, Property _property)
6139 {
6140    if(instance && _property && _property.selfWatchable)
6141    {
6142       Class _class;
6143       for(_class = instance._class; _class; _class = _class.base)
6144       {
6145          SelfWatcher selfWatcher, next;
6146          for(selfWatcher = _class.selfWatchers.first; selfWatcher; selfWatcher = next)
6147          {
6148             next = selfWatcher.next;
6149             if(selfWatcher._property == _property)
6150                selfWatcher.callback(instance);
6151          }
6152       }
6153    }
6154 }
6155
6156 public dllexport void eInstance_FireWatchers(Instance instance, Property _property)
6157 {
6158    if(instance && _property && _property.isWatchable)
6159    {
6160       Module module = instance._class ? instance._class.module : null;
6161       Application application = module ? module.application : null;
6162       int flags = application ? application.isGUIApp : 0;
6163       bool inCompiler = (flags & 8) ? true : false;
6164       bool force32Bits = (flags & 4) ? true : false;
6165       if(!force32Bits || !inCompiler)
6166       {
6167          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6168          Watcher watcher, next;
6169
6170          for(watcher = watchers->first; watcher; watcher = next)
6171          {
6172             next = watcher.next;
6173             watcher.callback(watcher.object, instance);
6174          }
6175       }
6176    }
6177 }
6178
6179 public dllexport void eProperty_Watchable(Property _property)
6180 {
6181    if(!_property.isWatchable)
6182    {
6183       Class _class = _property._class;
6184       if(!_class.computeSize)
6185       {
6186          _property.watcherOffset = _class.structSize;
6187          _class.structSize += sizeof(OldList);
6188
6189          // highly inefficient
6190          FixDerivativesBase(_class, _class);
6191       }
6192       _property.isWatchable = true;
6193    }
6194 }
6195
6196 public dllexport void eClass_DestructionWatchable(Class _class)
6197 {
6198    if(!_class.destructionWatchOffset)
6199    {
6200       _class.destructionWatchOffset = _class.structSize;
6201       _class.structSize += sizeof(OldList);
6202       // highly inefficient
6203       FixDerivativesBase(_class, _class);
6204    }
6205 }
6206
6207 public dllexport void eProperty_SelfWatch(Class _class, const char * name, void (*callback)(void *))
6208 {
6209    if(_class)
6210    {
6211       Property _property = eClass_FindProperty(_class, name, _class.module);
6212
6213       if(!_property)
6214          _property = eClass_AddProperty(_class, name, null, null, null, baseSystemAccess /*privateAccess*/);
6215       _class.selfWatchers.Add(SelfWatcher { _property = _property, callback = callback });
6216       _property.selfWatchable = true;
6217    }
6218 }
6219
6220 public dllexport void eInstance_Watch(void * instance, Property _property, void * object, void (*callback)(void *, void *))
6221 {
6222    if(_property.isWatchable)
6223    {
6224       OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6225       watchers->Add(Watcher { callback = callback, object = object });
6226    }
6227 }
6228
6229 public dllexport void eInstance_WatchDestruction(Instance instance, Instance object, void (*callback)(void *, void *))
6230 {
6231    OldList * watchers = (OldList *)((byte *)instance + instance._class.destructionWatchOffset);
6232    watchers->Add(Watcher { callback = callback, object = object });
6233 }
6234
6235 public dllexport void eInstance_StopWatching(Instance instance, Property _property, Instance object)
6236 {
6237    if(instance && (!_property || _property.isWatchable))
6238    {
6239       if(_property)
6240       {
6241          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6242          Watcher watcher;
6243          for(watcher = watchers->first; watcher; watcher = watcher.next)
6244             if(watcher.object == object)
6245             {
6246                watchers->Delete(watcher);
6247                break;
6248             }
6249       }
6250       else
6251       {
6252          // Stop watching all properties as well as destruction
6253          Class _class, base;
6254          for(_class = instance._class; _class; _class = base)
6255          {
6256             if(_class.destructionWatchOffset)
6257             {
6258                OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
6259                Watcher watcher;
6260
6261                for(watcher = watchers->first; watcher; watcher = watcher.next)
6262                {
6263                   watchers->Delete(watcher);
6264                   break;
6265                }
6266             }
6267             for(_property = (Property)_class.membersAndProperties.first; _property; _property = _property.next)
6268             {
6269                if(_property.isProperty && _property.isWatchable)
6270                {
6271                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6272                   Watcher watcher;
6273                   for(watcher = watchers->first; watcher; watcher = watcher.next)
6274                      if(watcher.object == object)
6275                      {
6276                         watchers->Delete(watcher);
6277                         break;
6278                      }
6279                }
6280             }
6281             base = _class.base;
6282             if(base && (base.type == systemClass || base.isInstanceClass)) base = null;
6283          }
6284       }
6285    }
6286 }
6287
6288 public dllexport subclass(ClassDesignerBase) eClass_GetDesigner(Class _class)
6289 {
6290    for(;_class;_class = _class.base)
6291    {
6292       if(_class.designerClass)
6293          return (subclass(ClassDesignerBase))eSystem_FindClass(_class.module, _class.designerClass);
6294    }
6295    return null;
6296 }
6297
6298
6299 public dllexport subclass(ClassDesignerBase) eInstance_GetDesigner(Instance instance)
6300 {
6301    if(instance)
6302       return eClass_GetDesigner(instance._class);
6303    return null;
6304 }
6305
6306 public bool LocateModule(const char * name, const char * fileName)
6307 {
6308    return Instance_LocateModule(name, fileName);
6309 }
6310
6311 /*
6312 #if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__)
6313 #define _64BIT 1
6314 #else
6315 #define _64BIT 0
6316 #endif
6317
6318 #define arch_PointerSize                  sizeof(void *)
6319 #define structSize_Instance               (_64BIT ? 24 : 12)
6320 #define structSize_Module                 (_64BIT ? 560 : 300)
6321 #define structSize_BinaryTree             (_64BIT ? 32 : 16)
6322 #define structSize_OldList                (_64BIT ? 32 : 20)
6323 #define structSize_NamedLink64            (_64BIT ? 32 : 24)
6324 #define structSize_ClassTemplateArgument  (_64BIT ? 16 : 8)
6325 #define structSize_ClassTemplateParameter (_64BIT ? 64 : 40)
6326 #define structSize_OldLink                (_64BIT ? 24 : 12)
6327 #define structSize_BTNamedLink            (_64BIT ? 48 : 24)
6328 #define structSize_Application            (_64BIT ? 800 : 428)
6329 #define structSize_Watcher                (_64BIT ? 32 : 16)
6330 #define structSize_SelfWatcher            (_64BIT ? 32 : 16)
6331 #define structSize_GlobalFunction         (_64BIT ? 72 : 36)
6332 #define structSize_DefinedExpression      (_64BIT ? 40 : 20)
6333 #define structSize_BitMember              (_64BIT ? 96 : 64)
6334 #define structSize_DataMember             (_64BIT ? 160 : 96)
6335 #define structSize_ClassProperty          (_64BIT ? 80 : 40)
6336 #define structSize_Method                 (_64BIT ? 96 : 52)
6337 #define structSize_Property               (_64BIT ? 152 : 88)
6338 #define structSize_Class                  (_64BIT ? 624 : 376)
6339 */
6340
6341 static void LoadCOM(Module module)
6342 {
6343    bool force64Bits = (module.application.isGUIApp & 2) ? true : false;
6344    bool force32Bits = (module.application.isGUIApp & 4) ? true : false;
6345    bool inCompiler = (module.application.isGUIApp & 8) ? true : false;
6346    int pointerSize = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
6347    Class applicationClass;
6348    Class enumClass, structClass, boolClass;
6349    Class moduleClass;
6350
6351    // Create Base Class
6352    Class baseClass = eSystem_RegisterClass(normalClass, "class", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6353    baseClass.type = systemClass;
6354    baseClass.memberOffset = 0;
6355    baseClass.offset = 0;
6356    baseClass.structSize = 0;
6357    baseClass.typeSize = 0;
6358
6359    {
6360       Class instanceClass = eSystem_RegisterClass(normalClass, "ecere::com::Instance", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6361       instanceClass.type = normalClass;
6362       instanceClass.isInstanceClass = true;
6363       instanceClass.fixed = true;
6364       instanceClass.memberOffset = 0;
6365       instanceClass.offset = 0;
6366
6367       instanceClass.memberID = -3;
6368       instanceClass.startMemberID = -3;
6369
6370       eClass_AddDataMember(instanceClass, "_vTbl", "void **", pointerSize, pointerSize, publicAccess);
6371       eClass_AddDataMember(instanceClass, "_class", "ecere::com::Class", pointerSize, pointerSize, publicAccess);
6372       eClass_AddDataMember(instanceClass, "_refCount", "int", sizeof(int), sizeof(int), publicAccess);
6373    }
6374
6375    InitializeDataTypes1(module);
6376
6377    // Create Enum class
6378    enumClass = eSystem_RegisterClass(normalClass, "enum", null, 0, force64Bits ? 40 : sizeof(class EnumClassData), null, null, module, baseSystemAccess, publicAccess);
6379    eClass_AddClassProperty(enumClass, "enumSize", "int", null, GetEnumSize).constant = true;
6380    enumClass.type = systemClass;
6381
6382    delete (void *)enumClass.dataTypeString;
6383    enumClass.dataTypeString = CopyString(/*"unsigned int"*/"int");
6384
6385    // Create Struct (simple) class
6386    //structClass = eSystem_RegisterClass(structClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6387    structClass = eSystem_RegisterClass(normalClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6388    structClass.type = systemClass;
6389    structClass.memberOffset = 0;
6390    structClass.offset = 0;
6391    structClass.structSize = 0;
6392    structClass.typeSize = 0;
6393
6394    //eClass_AddMethod(enumClass, "AddValue", "int()", eEnum_AddValue);
6395    //eClass_AddMethod(enumClass, "AddFixedValue", "void()", eEnum_AddFixedValue);
6396
6397    InitializeDataTypes(module);
6398
6399    // Create bool class
6400    boolClass = eSystem_RegisterClass(ClassType::enumClass, "bool", "uint", 0, 0, null, null, module, baseSystemAccess, publicAccess);
6401    eEnum_AddFixedValue(boolClass, "true",  bool::true);
6402    eEnum_AddFixedValue(boolClass, "false", bool::false);
6403
6404    // Create Module class
6405    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) :
6406                                                                                 sizeof(struct Module), 0, (void *)Module_Constructor, (void *)Module_Destructor, module, baseSystemAccess, publicAccess);
6407    eClass_AddVirtualMethod(moduleClass, "OnLoad", "bool()", null, publicAccess);
6408    eClass_AddVirtualMethod(moduleClass, "OnUnload", "void()", null, publicAccess);
6409    eClass_AddMethod(moduleClass, "Load", "Module(const char * name, AccessMode importAccess)", eModule_Load, publicAccess);
6410    eClass_AddMethod(moduleClass, "Unload", "void(Module module)", eModule_Unload, publicAccess);
6411    eClass_AddDataMember(moduleClass, "application", "Application", pointerSize, pointerSize, publicAccess);
6412    eClass_AddDataMember(moduleClass, "classes", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6413    eClass_AddDataMember(moduleClass, "defines", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6414    eClass_AddDataMember(moduleClass, "functions", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6415    eClass_AddDataMember(moduleClass, "modules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6416    eClass_AddDataMember(moduleClass, "prev", "Module", pointerSize, pointerSize, publicAccess);
6417    eClass_AddDataMember(moduleClass, "next", "Module", pointerSize, pointerSize, publicAccess);
6418    eClass_AddDataMember(moduleClass, "name", "const char *", pointerSize, pointerSize, publicAccess);
6419    eClass_AddDataMember(moduleClass, "library", "void *", pointerSize, pointerSize, publicAccess);
6420    eClass_AddDataMember(moduleClass, "Unload", "void *", pointerSize, pointerSize, publicAccess);
6421    eClass_AddDataMember(moduleClass, "importType", "ImportType", sizeof(ImportType), 4, publicAccess);
6422    eClass_AddDataMember(moduleClass, "origImportType", "ImportType", sizeof(ImportType), 4, publicAccess);
6423    eClass_AddDataMember(moduleClass, "privateNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6424    eClass_AddDataMember(moduleClass, "publicNameSpace", "NameSpace",  force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6425    moduleClass.fixed = true;
6426    moduleClass.count++;
6427    if(inCompiler && force32Bits)
6428       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);
6429
6430    // Create Application class
6431    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);
6432    if(inCompiler && force32Bits)
6433    {
6434       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);
6435       applicationClass.structSize = applicationClass.offset + (4+4+4+4 + 20 + 4 + 88);
6436    }
6437    eClass_AddVirtualMethod(applicationClass, "Main", "void()", null, publicAccess);
6438    eClass_AddDataMember(applicationClass, "argc", "int", sizeof(int), 4, publicAccess);
6439    eClass_AddDataMember(applicationClass, "argv", "const char **", pointerSize, pointerSize, publicAccess);
6440    eClass_AddDataMember(applicationClass, "exitCode", "int", sizeof(int), 4, publicAccess);
6441    eClass_AddDataMember(applicationClass, "isGUIApp", "bool", sizeof(bool), 4, publicAccess);
6442    eClass_AddDataMember(applicationClass, "allModules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6443    eClass_AddDataMember(applicationClass, "parsedCommand", "char *", pointerSize, pointerSize, publicAccess);
6444    eClass_AddDataMember(applicationClass, "systemNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6445    applicationClass.fixed = true;
6446    applicationClass.count++;
6447
6448    //AttachConsole(-1);
6449    //AllocConsole();
6450
6451    // --- Math ---
6452    eSystem_RegisterFunction("sin", "double sin(Angle number)", sin, module, baseSystemAccess);
6453    eSystem_RegisterFunction("sinh", "double sinh(Angle number)", sinh, module, baseSystemAccess);
6454    eSystem_RegisterFunction("cosh", "double cosh(Angle number)", cosh, module, baseSystemAccess);
6455    eSystem_RegisterFunction("tanh", "double tanh(Angle number)", tanh, module, baseSystemAccess);
6456    eSystem_RegisterFunction("sqrt", "double sqrt(double number)", sqrt, module, baseSystemAccess);
6457    eSystem_RegisterFunction("cos", "double cos(Angle number)", cos, module, baseSystemAccess);
6458    eSystem_RegisterFunction("tan", "double tan(Angle number)", tan, module, baseSystemAccess);
6459    eSystem_RegisterFunction("atan2", "Angle atan2(double y, double x)", atan2, module, baseSystemAccess);
6460    eSystem_RegisterFunction("asin", "Angle asin(double number)", asin, module, baseSystemAccess);
6461    eSystem_RegisterFunction("acos", "Angle acos(double number)", acos, module, baseSystemAccess);
6462    eSystem_RegisterFunction("atan", "Angle atan(double number)", atan, module, baseSystemAccess);
6463    eSystem_RegisterFunction("asinh", "Angle asinh(double number)", asinh, module, baseSystemAccess);
6464    eSystem_RegisterFunction("acosh", "Angle acosh(double number)", acosh, module, baseSystemAccess);
6465    eSystem_RegisterFunction("atanh", "Angle atanh(double number)", atanh, module, baseSystemAccess);
6466    eSystem_RegisterFunction("pow", "double pow(double number, double number2)", pow, module, baseSystemAccess);
6467    eSystem_RegisterFunction("fmod", "double fmod(double x, double y)", fmod, module, baseSystemAccess);
6468    eSystem_RegisterFunction("fabs", "double fabs(double number)", fabs, module, baseSystemAccess);
6469    eSystem_RegisterFunction("log", "double log(double number)", log, module, baseSystemAccess);
6470    eSystem_RegisterFunction("log10", "double log10(double number)", log10, module, baseSystemAccess);
6471    eSystem_RegisterFunction("ceil", "double ceil(double number)", ceil, module, baseSystemAccess);
6472    eSystem_RegisterFunction("floor", "double floor(double number)", floor, module, baseSystemAccess);
6473    eSystem_RegisterFunction("exp", "double exp(double number)", exp, module, baseSystemAccess);
6474
6475    // --- Stdlib ---
6476    eSystem_RegisterFunction("qsort", "void qsort(void *, uintsize, uintsize, int (*)(void *, void *))", qsort, module, baseSystemAccess);
6477    eSystem_RegisterFunction("strtod", "double strtod(const char*, char**)", strtod, module, baseSystemAccess);
6478    eSystem_RegisterFunction("strtol", "int strtol(const char*, char**, int base)", strtol, module, baseSystemAccess);
6479    eSystem_RegisterFunction("strtoul", "unsigned long strtoul(const char * nptr, char ** endptr, int base)", strtoul, module, baseSystemAccess);
6480    eSystem_RegisterFunction("strtoll", "int64 strtoll(const char * nptr, char ** endptr, int base)", strtoll, module, baseSystemAccess);
6481    eSystem_RegisterFunction("strtoull", "uint64 strtoull(const char * nptr, char ** endptr, int base)", strtoull, module, baseSystemAccess);
6482    eSystem_RegisterFunction("system", "int system(const char*)", system, module, baseSystemAccess);
6483    eSystem_RegisterFunction("atoi", "int atoi(const char*)", atoi, module, baseSystemAccess);
6484    eSystem_RegisterFunction("atof", "double atof(const char*)", atof, module, baseSystemAccess);
6485    eSystem_RegisterFunction("memset", "void * memset(void * area, int value, uintsize count)", memset, module, baseSystemAccess);
6486    eSystem_RegisterFunction("getenv", "char * getenv(const char * name)", getenv, module, baseSystemAccess);
6487    eSystem_RegisterFunction("rename", "int rename(const char *oldpath, const char *newpath)", rename, module, baseSystemAccess);
6488
6489    // --- String --- (These might move to the string class)
6490    eSystem_RegisterFunction("strlen", "uintsize strlen(const char *)", strlen, module, baseSystemAccess);
6491    eSystem_RegisterFunction("strcat", "char * strcat(char *, const char *)", strcat, module, baseSystemAccess);
6492    eSystem_RegisterFunction("strncat", "char * strncat(char *, const char *, uintsize n)", strncat, module, baseSystemAccess);
6493    eSystem_RegisterFunction("strchr", "char * strchr(const char *, int)", strchr, module, baseSystemAccess);
6494    eSystem_RegisterFunction("strstr", "char * strstr(const char *, const char *)", strstr, module, baseSystemAccess);
6495    eSystem_RegisterFunction("strspn", "uintsize strspn(const char *, const char *)", strspn, module, baseSystemAccess);
6496    eSystem_RegisterFunction("strcspn", "uintsize strcspn(const char *, const char *)", strcspn, module, baseSystemAccess);
6497    eSystem_RegisterFunction("strpbrk", "char * strpbrk(const char *, const char *)", strpbrk, module, baseSystemAccess);
6498
6499    eSystem_RegisterDefine("fstrcmp", "(__runtimePlatform == win32) ? strcmpi : strcmp", module, baseSystemAccess);
6500
6501 //#if defined(__GNUC__)
6502    eSystem_RegisterDefine("strcmpi", "strcasecmp", module, baseSystemAccess);
6503    eSystem_RegisterDefine("strnicmp", "strncasecmp", module, baseSystemAccess);
6504    eSystem_RegisterFunction("strcasecmp", "int strcasecmp(const char *, const char *)", strcmpi, module, baseSystemAccess);
6505    eSystem_RegisterFunction("strncasecmp", "int strncasecmp(const char *, const char *, uintsize n)", strnicmp, module, baseSystemAccess);
6506 /*
6507 #else
6508    eSystem_RegisterDefine("strcasecmp", "strcmpi", module, baseSystemAccess);
6509    eSystem_RegisterDefine("strncasecmp", "strnicmp", module, baseSystemAccess);
6510    eSystem_RegisterFunction("strcmpi", "int strcmpi(const char *, const char *)", strcmpi, module, baseSystemAccess);
6511    eSystem_RegisterFunction("strnicmp", "int strnicmp(const char *, const char *, int n)", strnicmp, module, baseSystemAccess);
6512 #endif
6513 */
6514
6515    eSystem_RegisterFunction("strcmp", "int strcmp(const char *, const char *)", strcmp, module, baseSystemAccess);
6516    eSystem_RegisterFunction("strncmp", "int strncmp(const char *, const char *, uintsize n)", strncmp, module, baseSystemAccess);
6517    eSystem_RegisterFunction("strlwr", "char * strlwr(char *)", strlwr, module, baseSystemAccess);
6518    eSystem_RegisterFunction("strupr", "char * strupr(char *)", strupr, module, baseSystemAccess);
6519    eSystem_RegisterFunction("strcpy", "char * strcpy(char *, const char *)", strcpy, module, baseSystemAccess);
6520    eSystem_RegisterFunction("strncpy", "char * strncpy(char *, const char *, uintsize n)", strncpy, module, baseSystemAccess);
6521    eSystem_RegisterFunction("memcpy", "void * memcpy(void *, const void *, uintsize size)", memcpy, module, baseSystemAccess);
6522    eSystem_RegisterFunction("memmove", "void * memmove(void *, const void *, uintsize size)", memmove, module, baseSystemAccess);
6523    eSystem_RegisterFunction("memcmp", "int memcmp(const void *, const void *, uintsize size)", memcmp, module, baseSystemAccess);
6524
6525    // --- Stdio ---
6526    eSystem_RegisterFunction("sprintf", "int sprintf(char *, const char *, ...)", sprintf, module, baseSystemAccess);
6527    eSystem_RegisterFunction("snprintf", "int sprintf(char *, uintsize, const char *, ...)", snprintf, module, baseSystemAccess);
6528    eSystem_RegisterFunction("printf", "int printf(const char *, ...)", printf, module, baseSystemAccess);
6529    eSystem_RegisterFunction("vsprintf", "int vsprintf(char*, const char*, __builtin_va_list)", vsprintf, module, baseSystemAccess);
6530    eSystem_RegisterFunction("vsnprintf", "int vsnprintf(char*, uintsize, const char*, __builtin_va_list)", vsnprintf, module, baseSystemAccess);
6531    eSystem_RegisterFunction("puts", "int puts(const char *)", puts, module, baseSystemAccess);
6532    eSystem_RegisterFunction("fputs", "int fputs(const char *, void * stream)", fputs, module, baseSystemAccess);
6533
6534    // --- Ctype ---
6535    eSystem_RegisterFunction("tolower", "int tolower(int)", tolower, module, baseSystemAccess);
6536    eSystem_RegisterFunction("toupper", "int toupper(int)", toupper, module, baseSystemAccess);
6537    eSystem_RegisterFunction("isdigit", "bool isdigit(int)", isdigit, module, baseSystemAccess);
6538    eSystem_RegisterFunction("isxdigit","bool isxdigit(int)", isxdigit, module, baseSystemAccess);
6539    eSystem_RegisterFunction("isalnum", "int isalnum(int c)", isalnum, module, baseSystemAccess);
6540    eSystem_RegisterFunction("isspace", "int isspace(int c)", isspace, module, baseSystemAccess);
6541    eSystem_RegisterFunction("isalpha", "int isalpha(int c)", isalpha, module, baseSystemAccess);
6542    eSystem_RegisterFunction("islower", "int islower(int c)", islower, module, baseSystemAccess);
6543    eSystem_RegisterFunction("isupper", "int isupper(int c)", isupper, module, baseSystemAccess);
6544    eSystem_RegisterFunction("isprint", "int isprint(int c)", isprint, module, baseSystemAccess);
6545    eSystem_RegisterFunction("isblank", "int isblank(int c)", isblank, module, baseSystemAccess);
6546
6547 }
6548
6549 public dllexport Application __ecere_COM_Initialize(bool guiApp, int argc, char * argv[])
6550 {
6551    Application app;
6552
6553 #ifdef __ANDROID__
6554    // Clean up global variables
6555    memoryInitialized = false;
6556    pools = null;
6557 #ifdef MEMINFO
6558    memset(&memStacks, 0, sizeof(BinaryTree));
6559    memoryErrorsCount = 0;
6560    memset(&memBlocks, 0, sizeof(BinaryTree));
6561    recurse = false;
6562    blockID = 0;
6563    allocateClass = null;
6564    allocateInternal = false;
6565    TOTAL_MEM = 0;
6566    OUTSIDE_MEM = 0;
6567 #endif
6568 #endif
6569
6570 #ifdef _DEBUG
6571    // printf("Using debug ecere runtime library\n");
6572 #endif
6573    app = _calloc(1, sizeof(class Application));
6574
6575    Module_Constructor(app);
6576    app.systemNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
6577    app.systemNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
6578    app.systemNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
6579    app.systemNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
6580
6581    Instance_COM_Initialize(argc, argv, &app.parsedCommand, &app.argc, &app.argv);
6582
6583    app.application = app;
6584    app.allModules.offset = sizeof(class Instance) + (uint)(uintptr)&((struct Module *)0)->prev;
6585    app.isGUIApp = guiApp;
6586
6587    LoadCOM(app);
6588
6589    app._class = eSystem_FindClass(app, "Application");
6590
6591    return app;
6592 }
6593
6594 public dllexport ClassTemplateParameter eClass_AddTemplateParameter(Class _class, const char * name, TemplateParameterType type, const void * info, ClassTemplateArgument defaultArg)
6595 {
6596    if(_class && name)
6597    {
6598       ClassTemplateParameter param;
6599
6600       for(param = _class.templateParams.first; param; param = param.next)
6601       {
6602          if(!strcmp(param.name, name))
6603             return param;
6604       }
6605       param =
6606       {
6607          name = CopyString(name);
6608          type = type;
6609          (type == identifier) ? info : CopyString(info);
6610       };
6611       if(defaultArg != null)
6612       {
6613          param.defaultArg = defaultArg;
6614          CopyTemplateArg(param, param.defaultArg);
6615       }
6616       _class.templateParams.Add(param);
6617       return param;
6618    }
6619    return null;
6620 }
6621
6622 public dllexport void eClass_DoneAddingTemplateParameters(Class base)
6623 {
6624    if(base)
6625    {
6626       ClassTemplateParameter param;
6627       {
6628          void * first = base.templateParams.first;
6629          int count = base.templateParams.count;
6630
6631          FreeTemplateArgs(base);
6632          delete base.templateArgs;
6633
6634          base.templateParams.first = null;
6635          base.templateParams.count = 0;
6636
6637          FreeTemplatesDerivatives(base);
6638
6639          base.templateParams.first = first;
6640          base.templateParams.count = count;
6641       }
6642
6643       for(param = base.templateParams.first; param; param = param.next)
6644       {
6645          if(param.type == identifier && param.defaultArg.memberString)
6646          {
6647             Class memberClass = base;
6648             const char * colon = strstr(param.defaultArg.memberString, "::");
6649             const char * memberName;
6650             if(colon)
6651             {
6652                char className[1024];
6653                Class sClass;
6654
6655                memcpy(className, param.defaultArg.memberString, colon - param.defaultArg.memberString);
6656                className[colon - param.defaultArg.memberString] = '\0';
6657                memberName = colon + 2;
6658
6659                for(sClass = base; sClass; sClass = sClass.base)
6660                {
6661                   ClassTemplateParameter cParam;
6662                   Class nextClass;
6663                   int id = 0;
6664                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) id += nextClass.templateParams.count;
6665                   // Safety! What could cause base.templateArgs to be null?
6666                   if(sClass == base || base.templateArgs)
6667                   {
6668                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
6669                      {
6670                         if(cParam.type == type && !strcmp(cParam.name, className))
6671                            strcpy(className, (sClass == base) ? cParam.defaultArg.dataTypeString : base.templateArgs[id].dataTypeString);
6672                         id++;
6673                      }
6674                   }
6675                }
6676                memberClass = eSystem_FindClass(base.module, className);
6677                if(!memberClass)
6678                   memberClass = eSystem_FindClass(base.module.application, className);
6679             }
6680             else
6681                memberName = param.defaultArg.memberString;
6682
6683             if(memberClass)
6684             {
6685                switch(param.memberType)
6686                {
6687                   case dataMember:
6688                      param.defaultArg.member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
6689                      break;
6690                   case method:
6691                      param.defaultArg.method = eClass_FindMethod(memberClass, memberName, memberClass.module);
6692                      break;
6693                   case prop:
6694                      param.defaultArg.prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
6695                      break;
6696                }
6697             }
6698          }
6699       }
6700
6701       //ComputeClassParameters(base, null, null);
6702
6703       FixDerivativesBase(base, base);
6704    }
6705 }
6706
6707 static void FreeTemplatesDerivatives(Class base)
6708 {
6709    OldLink derivative, templateLink;
6710    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
6711    {
6712       Class _class = derivative.data;
6713       if(_class.templateArgs)
6714       {
6715          FreeTemplateArgs(_class);
6716          delete _class.templateArgs;
6717       }
6718       FreeTemplatesDerivatives(_class);
6719    }
6720
6721    for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
6722    {
6723       Class _class = templateLink.data;
6724       if(_class.templateArgs)
6725       {
6726          FreeTemplateArgs(_class);
6727          delete _class.templateArgs;
6728       }
6729       FreeTemplatesDerivatives(_class);
6730    }
6731 }
6732
6733 static const char * platformNames[Platform] = { "", "win32", "linux", "apple" }; // how to have this be accessible outside of dll/lib
6734 static const Platform firstPlatform = win32;
6735 static const Platform lastPlatform = apple;
6736
6737 public enum Platform
6738 {
6739    unknown, win32, tux, apple;
6740
6741    property const char *
6742    {
6743       get { return OnGetString(null, null, null); }
6744       set
6745       {
6746          if(value)
6747          {
6748             Platform c;
6749             for(c = firstPlatform; c <= lastPlatform; c++)
6750                if(!strcmpi(value, platformNames[c]))
6751                   return c;
6752          }
6753          return unknown;
6754       }
6755    };
6756
6757    const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
6758    {
6759       if(this >= firstPlatform && this <= lastPlatform)
6760       {
6761          if(tempString)
6762             strcpy(tempString, platformNames[this]);
6763          return platformNames[this];
6764       }
6765       if(tempString && tempString[0])
6766          tempString[0] = '\0';
6767       return null;
6768    }
6769
6770    bool OnGetDataFromString(const char * string)
6771    {
6772       this = string;
6773       return this != unknown;
6774    }
6775 };
6776
6777 default extern Platform runtimePlatform;
6778
6779 public Platform GetRuntimePlatform()
6780 {
6781    return runtimePlatform;
6782 }
6783
6784 namespace gui;
6785
6786 class Window;
6787
6788 namespace com;
6789 // CLASS DESIGNER SUPPORT
6790
6791 public class ObjectInfo : struct
6792 {
6793 public:
6794    ObjectInfo prev, next;
6795    Instance instance;
6796    char * name;
6797    Instantiation instCode;
6798    bool deleted;
6799    ObjectInfo oClass;
6800    OldList instances;
6801    ClassDefinition classDefinition;
6802    bool modified;
6803    void * i18nStrings;
6804 };
6805
6806 public class DesignerBase : Window
6807 {
6808 public:
6809    virtual bool FindObject(Instance * instance, const char * string);
6810    virtual void RenameObject(ObjectInfo object, const char * name);
6811    virtual void SelectObjectFromDesigner(ObjectInfo object);
6812    virtual void CodeAddObject(Instance instance, ObjectInfo * object);
6813    virtual void SheetAddObject(ObjectInfo object);
6814    virtual void AddToolBoxClass(Class _class);
6815    virtual void AddDefaultMethod(Instance instance, Instance classInstance);
6816    virtual void DeleteObject(ObjectInfo object);
6817    virtual bool ObjectContainsCode(ObjectInfo object);
6818    virtual void ModifyCode(void);
6819    virtual void UpdateProperties(void);
6820
6821    ClassDesignerBase classDesigner;
6822    const char * objectClass;
6823    bool isDragging;
6824
6825    // FIX THIS WITH PUBLIC:
6826    property ClassDesignerBase classDesigner
6827    {
6828       get { return classDesigner; }
6829       set { classDesigner = value; }
6830    };
6831    property const char * objectClass
6832    {
6833       get { return objectClass; }
6834       set { objectClass = value; }
6835    };
6836    property bool isDragging
6837    {
6838       get { return isDragging; }
6839       set { isDragging = value; }
6840    };
6841 }
6842
6843 public class ClassDesignerBase : Window
6844 {
6845 public:
6846    virtual void Reset(void);
6847    virtual void AddObject(void);
6848    virtual void SelectObject(ObjectInfo object, Instance control);
6849
6850    virtual void ListToolBoxClasses(DesignerBase designer);
6851
6852    virtual void ::PrepareTestObject(DesignerBase designer, Instance test);
6853    virtual void ::CreateObject(DesignerBase designer, Instance instance, ObjectInfo object, bool isClass, Instance _class);
6854    virtual void ::PostCreateObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6855    virtual void ::DroppedObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6856    virtual void ::DestroyObject(Instance object);
6857    virtual void ::FixProperty(Property prop, Instance object);
6858    virtual void ::CreateNew(EditBox editBox, Size clientSize, const char * name, const char * inherit);
6859 }
6860
6861 DesignerBase activeDesigner;
6862
6863 public void SetActiveDesigner(DesignerBase designer)
6864 {
6865    activeDesigner = designer;
6866 }
6867
6868 public DesignerBase GetActiveDesigner()
6869 {
6870    return activeDesigner;
6871 }
6872
6873
6874 bool poolingDisabled;
6875
6876 public dllexport void eSystem_SetPoolingDisabled(bool disabled)
6877 {
6878    poolingDisabled = disabled;
6879 }
6880
6881 namespace sys;
6882
6883 // constants
6884 define LEAD_OFFSET      = 0xD800 - (0x10000 >> 10);
6885 define SURROGATE_OFFSET = 0x10000 - (0xD800 << 10) - 0xDC00;
6886
6887 public bool UTF8Validate(const char * source)
6888 {
6889    if(source)
6890    {
6891       int c;
6892       for(c = 0; source[c];)
6893       {
6894          byte ch = source[c];
6895          unichar codePoint = 0;
6896          int numBytes = 1;
6897          int i;
6898          byte mask = 0x7F;
6899          if(ch & 0x80)
6900          {
6901             if(ch & 0x40)
6902             {
6903                mask >>= 2;
6904                numBytes++;
6905                if(ch & 0x20)
6906                {
6907                   numBytes++;
6908                   mask >>= 1;
6909                   if(ch & 0x10)
6910                   {
6911                      if(ch & 0x08)
6912                         return false;
6913                      numBytes++;
6914                      mask >>= 1;
6915                   }
6916                }
6917             }
6918             else
6919                return false;
6920          }
6921          for(i = 0; i<numBytes && (ch = source[c]); i++, c++)
6922          {
6923             codePoint <<= 6;
6924             codePoint |= ch & mask;
6925             mask = 0x3F;
6926             if(i > 1)
6927             {
6928                if(!(ch & 0x80) || (ch & 0x40))
6929                   return false;
6930             }
6931          }
6932          if(i < numBytes) return false;
6933
6934          if(codePoint > 0x10FFFF || (codePoint >= 0xD800 && codePoint <= 0xDFFF) ||
6935            (codePoint < 0x80 && numBytes > 1) ||
6936            (codePoint < 0x800 && numBytes > 2) ||
6937            (codePoint < 0x10000 && numBytes > 3))
6938             return false;
6939       }
6940    }
6941    return true;
6942 }
6943
6944 public int ISO8859_1toUTF8(const char * source, char * dest, int max)
6945 {
6946    int c;
6947    int d = 0;
6948    byte * byteDest = (byte *)dest;
6949    for(c = 0; source[c]; c++)
6950    {
6951       unichar ch = ((byte *)source)[c];
6952       switch(ch)
6953       {
6954          case 150: ch = (unichar)0x2012; break;
6955       }
6956       if(ch < 0x80)
6957       {
6958          if(d + 1 >= max) break;
6959          byteDest[d++] = (char)ch;
6960       }
6961       else if(ch < 0x800)
6962       {
6963          if(d + 2 >= max) break;
6964          byteDest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6965          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
6966       }
6967       else if(ch < 0x10000)
6968       {
6969          if(d + 3 >= max) break;
6970          byteDest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6971          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6972          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
6973       }
6974       else
6975       {
6976          if(d + 4 >= max) break;
6977          byteDest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6978          byteDest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6979          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6980          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
6981       }
6982    }
6983    dest[d] = 0;
6984    return d;
6985 }
6986
6987 public char * UTF16toUTF8(const uint16 * source)
6988 {
6989    int c;
6990    int d = 0;
6991    int len;
6992    byte * dest;
6993    uint16 u16;
6994    bool invert = false;
6995
6996    for(len = 0; source[len]; len++);
6997    dest = new byte[len * 3 + 1];
6998    for(c = 0; (u16 = source[c]); c++)
6999    {
7000       unichar ch;
7001       if(!c && (u16 == 0xFFFE || u16 == 0xFEFF))
7002       {
7003          if(u16 == 0xFFFE) invert = true;
7004          continue;
7005       }
7006       if(invert) { u16 = ((u16 & 0xFF00) >> 8) | ((u16 & 0x00FF) << 8); }
7007
7008       if(u16 < 0xD800 || u16 > 0xDBFF)
7009          ch = (unichar)u16;
7010       else
7011          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
7012
7013       if(ch < 0x80)
7014       {
7015          dest[d++] = (char)ch;
7016       }
7017       else if(ch < 0x800)
7018       {
7019          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
7020          dest[d++] = 0x80 | (byte)(ch & 0x03F);
7021       }
7022       else if(ch < 0x10000)
7023       {
7024          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
7025          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7026          dest[d++] = 0x80 | (byte)(ch & 0x03F);
7027       }
7028       else
7029       {
7030          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
7031          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
7032          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7033          dest[d++] = 0x80 | (byte)(ch & 0x03F);
7034       }
7035    }
7036    dest[d] = 0;
7037    dest = renew dest byte[d+1];
7038    return (char *)dest;
7039 }
7040
7041 public int UTF16toUTF8Buffer(const uint16 * source, char * dest, int max)
7042 {
7043    int c;
7044    int d = 0;
7045    uint16 u16;
7046    byte * byteDest = (byte *)dest;
7047    for(c = 0; (u16 = source[c]); c++)
7048    {
7049       unichar ch;
7050       if(u16 < 0xD800 || u16 > 0xDBFF)
7051          ch = (unichar)u16;
7052       else
7053          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
7054
7055       if(ch < 0x80)
7056       {
7057          if(d + 1 >= max) break;
7058          byteDest[d++] = (char)ch;
7059       }
7060       else if(ch < 0x800)
7061       {
7062          if(d + 2 >= max) break;
7063          byteDest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
7064          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7065       }
7066       else if(ch < 0x10000)
7067       {
7068          if(d + 3 >= max) break;
7069          byteDest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
7070          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7071          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7072       }
7073       else
7074       {
7075          if(d + 4 >= max) break;
7076          byteDest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
7077          byteDest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
7078          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7079          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7080       }
7081    }
7082    byteDest[d] = 0;
7083    return d;
7084 }
7085
7086 // NOTE: UTF8GetChar now returns 0 into numBytes for the null-terminating character ('\0')
7087 public unichar UTF8GetChar(const char * string, int * numBytes)
7088 {
7089    unichar ch;
7090    byte b = ((byte *)string)[0];
7091    int i;
7092    byte mask = 0x7F;
7093    int nb = b ? 1 : 0;
7094    ch = 0;
7095    if(b & 0x80)
7096    {
7097       if(b & 0x40)
7098       {
7099          mask >>= 2;
7100          nb++;
7101          if(b & 0x20)
7102          {
7103             nb++;
7104             mask >>= 1;
7105             if(b & 0x10)
7106             {
7107                if(b & 0x08) { nb = 0; }
7108                nb++;
7109                mask >>= 1;
7110             }
7111          }
7112       }
7113       else
7114          nb = 0;
7115    }
7116    for(i = 0; i<nb; i++)
7117    {
7118       ch <<= 6;
7119       ch |= (b = ((byte *)string)[i]) & mask;
7120       mask = 0x3F;
7121       if(i > 1 && (!(b & 0x80) || (b & 0x40)))
7122       {
7123          nb = 0;
7124          ch = 0;
7125       }
7126    }
7127
7128    if(i < nb ||
7129       ch > 0x10FFFF || (ch >= 0xD800 && ch <= 0xDFFF) ||
7130      (ch < 0x80 && nb > 1) ||
7131      (ch < 0x800 && nb > 2) ||
7132      (ch < 0x10000 && nb > 3))
7133    {
7134       ch = 0;
7135       nb = 0;
7136    }
7137    if(numBytes) *numBytes = nb;
7138    return ch;
7139 }
7140
7141 public int UTF8toUTF16Buffer(const char * source, uint16 * dest, int max)
7142 {
7143    if(source)
7144    {
7145       int c;
7146       int d = 0;
7147       for(c = 0; source[c];)
7148       {
7149          byte ch = source[c];
7150          unichar codePoint = 0;
7151          int numBytes = 1;
7152          int i;
7153          byte mask = 0x7F;
7154          if(ch & 0x80 && ch & 0x40)
7155          {
7156             mask >>= 2;
7157             numBytes++;
7158             if(ch & 0x20)
7159             {
7160                numBytes++;
7161                mask >>= 1;
7162                if(ch & 0x10)
7163                {
7164                   numBytes++;
7165                   mask >>= 1;
7166                }
7167             }
7168          }
7169          for(i = 0; i<numBytes; i++)
7170          {
7171             codePoint <<= 6;
7172             codePoint |= source[c++] & mask;
7173             mask = 0x3F;
7174          }
7175
7176          if(codePoint > 0xFFFF)
7177          {
7178             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
7179             uint16 trail = (uint16)(0xDC00 | (codePoint & 0x3FF));
7180             if(d >= max - 1) break;
7181             dest[d++] = lead;
7182             dest[d++] = trail;
7183          }
7184          else
7185          {
7186             if(d >= max) break;
7187             dest[d++] = (uint16)codePoint;
7188          }
7189       }
7190       dest[d] = 0;
7191       return d;
7192    }
7193    return 0;
7194 }
7195
7196 public int UTF32toUTF8Len(const unichar * source, int count, char * dest, int max)
7197 {
7198    int c;
7199    int d = 0;
7200    uint32 ch;
7201    byte * byteDest = (byte *)dest;
7202    for(c = 0; c<count && (ch = source[c]); c++)
7203    {
7204       if(ch < 0x80)
7205       {
7206          if(d + 1 >= max) break;
7207          byteDest[d++] = (char)ch;
7208       }
7209       else if(ch < 0x800)
7210       {
7211          if(d + 2 >= max) break;
7212          byteDest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
7213          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7214       }
7215       else if(ch < 0x10000)
7216       {
7217          if(d + 3 >= max) break;
7218          byteDest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
7219          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7220          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7221       }
7222       else
7223       {
7224          if(d + 4 >= max) break;
7225          byteDest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
7226          byteDest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
7227          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7228          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7229       }
7230    }
7231    byteDest[d] = 0;
7232    return d;
7233 }
7234
7235 public uint16 * UTF8toUTF16(const char * source, int * wordCount)
7236 {
7237    if(source)
7238    {
7239       int len = (int)strlen(source);
7240       uint16 * dest = new uint16[len + 1];
7241       int c;
7242       int d = 0;
7243       for(c = 0; source[c];)
7244       {
7245          byte ch = source[c];
7246          unichar codePoint = 0;
7247          int numBytes = 1;
7248          int i;
7249          byte mask = 0x7F;
7250          if(ch & 0x80 && ch & 0x40)
7251          {
7252             mask >>= 2;
7253             numBytes++;
7254             if(ch & 0x20)
7255             {
7256                numBytes++;
7257                mask >>= 1;
7258                if(ch & 0x10)
7259                {
7260                   numBytes++;
7261                   mask >>= 1;
7262                }
7263             }
7264          }
7265          for(i = 0; i<numBytes; i++)
7266          {
7267             codePoint <<= 6;
7268             codePoint |= source[c++] & mask;
7269             mask = 0x3F;
7270          }
7271
7272          if(codePoint > 0xFFFF)
7273          {
7274             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
7275             uint16 trail = (uint16)(0xDC00 | (codePoint & 0x3FF));
7276             dest[d++] = lead;
7277             dest[d++] = trail;
7278          }
7279          else
7280          {
7281             dest[d++] = (uint16)codePoint;
7282          }
7283       }
7284       dest[d] = 0;
7285       if(wordCount) *wordCount = d;
7286       return dest;
7287    }
7288    return null;
7289 }
7290
7291 namespace com;
7292
7293 #if !defined(MEMINFO) && defined(MEMTRACKING)
7294 import "Map"
7295
7296 Map<Class, int> blocksByClass { };
7297 Map<Class, uintsize> sizeByClass { };
7298 #endif
7299
7300 public void queryMemInfo(char * string)
7301 {
7302 #if !defined(MEMINFO) && defined(MEMTRACKING) && !defined(DISABLE_MEMMGR)
7303    char s[1024];
7304    int p;
7305    uint numBlocks = 0;
7306    uintsize totalMemUsed = 0;
7307    sprintf(s, "Total System Memory Usage: %.02f\n", TOTAL_MEM / 1048576.0f);
7308    strcat(string, s);
7309
7310    for(p = 0; pools && p < NUM_POOLS; p++)
7311    {
7312       BlockPool * pool = &pools[p];
7313       if(pool->totalSize)
7314       {
7315          numBlocks += pool->totalSize;
7316          sprintf(s, "%8d bytes: %d blocks in %d parts (%.02f mb used; taking up %.02f mb space)\n",
7317             pool->blockSize, pool->numBlocks, pool->numParts, pool->usedSpace / 1048576.0f, pool->totalSize * pool->blockSpace / 1048576.0f);
7318          totalMemUsed += pool->usedSpace;
7319          strcat(string, s);
7320       }
7321    }
7322
7323
7324    blocksByClass.Free();
7325    sizeByClass.Free();
7326    memMutex.Wait();
7327    for(p = 0; pools && p < NUM_POOLS; p++)
7328    {
7329       BlockPool * pool = &pools[p];
7330       MemBlock block;
7331       for(block = pool->first; block; block = block.next)
7332       {
7333          Class c = block._class;
7334          blocksByClass[c]++;
7335          sizeByClass[c] += block.size;
7336       }
7337    }
7338    memMutex.Release();
7339
7340    //for(c : blocksByClass)
7341    {
7342       MapIterator<Class, int> it { map = blocksByClass };
7343       while(it.Next())
7344       {
7345          int c = it.data;
7346          Class _class = it.key; //&c;
7347          uintsize size = sizeByClass[_class];
7348          float totalSize = (float) size / 1048576.0f;
7349          if(totalSize > 1)
7350          {
7351             sprintf(s, "%s (%d bytes): %d instances (%.02f mb used)\n", _class ? _class.name : "(none)", (int)size, c, totalSize);
7352             strcat(string, s);
7353          }
7354       }
7355    }
7356
7357    sprintf(s, "Non-pooled memory: %.02f\n", OUTSIDE_MEM / 1048576.0f);
7358    strcat(string, s);
7359    sprintf(s, "Total Memory in use: %.02f\n", (float)(totalMemUsed + OUTSIDE_MEM) / 1048576.0f);
7360    strcat(string, s);
7361
7362    sprintf(s, "Total Blocks Count: %d (%.02f mb overhead)\n", numBlocks, (float)sizeof(struct MemBlock) * numBlocks / 1048576.0f);
7363    strcat(string, s);
7364 #ifdef MEMORYGUARD
7365    sprintf(s, "MemoryGuard: %d blocks (%.02f mb RedZone, %.02f mb MemInfo)\n", memBlocks.count,
7366       numBlocks * 2 * REDZONE / 1048576.0f, sizeof(struct MemInfo) * memBlocks.count / 1048576.0f);
7367    strcat(string, s);
7368 #endif
7369 #endif
7370 }