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