628b8d348b2dffaa5ae7115084236756231e5f77
[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    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, 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(char * name, char * fileName);
85 void Instance_COM_Initialize(int argc, char ** argv, char ** parsedCommand, int * argcPtr, 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    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
100    {
101       UTF32toUTF8Len(&this, 1, tempString, 5);
102       return tempString;
103    }
104
105    bool OnGetDataFromString(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    char * name;
121    bool isProperty;
122    AccessMode memberAccess;
123    int id;
124    Class _class;
125    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    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(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    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    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    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    char * designerClass;
295    bool noExpansion;
296    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    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 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    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
337    {
338       return name;
339    }
340
341    bool OnGetDataFromString(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          char * dataTypeString;
387          Class dataTypeClass;
388          // Type dataType;
389       };
390       // For expression
391       DataValue expression;
392
393       // For identifier
394       struct
395       {
396          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    char * name;
413    TemplateParameterType type;
414    union
415    {
416       // Class baseClass;                 // For type
417       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    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    char ** argv;
453    int exitCode;
454    bool isGUIApp;
455    OldList allModules;
456    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    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    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    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    char * name;
524    bool isProperty;
525    AccessMode memberAccess;
526    int id;
527    Class _class;
528    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    char * name;
547    bool isProperty;
548    AccessMode memberAccess;
549    int id;
550    Class _class;
551    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    char * name;
566    ClassProperty parent, left, right;
567    int depth;
568    void (*Set)(Class, int64);
569    int64 (*Get)(Class);
570    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    char * name;
581    char * value;
582    NameSpace * nameSpace;
583 };
584
585 public class GlobalFunction : struct
586 {
587 public:
588    class_fixed
589    GlobalFunction prev, next;
590    char * name;
591    int (*function)();
592    Module module;
593    NameSpace * nameSpace;
594    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    int 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    char * _class;
630    uint id;
631    char * allocLoc[MAX_MEMORY_LOC];
632    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 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       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 _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 method.name;
2059                            delete method.dataTypeString;
2060                            _class.methods.Delete((BTNode)method);
2061                         }
2062                         else
2063                         {
2064                            delete 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 prop.name;
2125                         delete 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          //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, char * name, 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       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          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 _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 _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 = _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 = 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 _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::OldLink"))         size = 0;
2672                else if(!strcmp(name, "ecere::sys::NamedItem"))       size = 0;
2673                else if(!strcmp(name, "ecere::sys::NamedItem64"))     size = 0;
2674                else if(!strcmp(name, "ecere::sys::BinaryTree"))      size = 0;
2675                else if(module != module.application && inCompiler)
2676                {
2677                   // These we only want to recompute inside the compiler
2678                   if(fixed || type == structClass)
2679                      size = 0;
2680                }
2681             }
2682          }
2683          if(type == structClass)
2684          {
2685             _class.memberOffset = (base && base.structSize && base.type != systemClass) ? base.structSize : 0;
2686             // THIS IS NEW...
2687             _class.typeSize = _class.structSize = _class.memberOffset + size;
2688          }
2689          else if(type == bitClass || type == enumClass || type == unitClass)
2690          {
2691             Class dataTypeClass = eSystem_FindClass(_class.module, dataTypeString);
2692             if(dataTypeClass)
2693                _class.typeSize = dataTypeClass.typeSize;
2694             _class.structSize = 0;
2695          }
2696          else if(type == normalClass || type == noHeadClass)
2697          {
2698             _class.structSize = _class.offset + size;
2699             _class.typeSize = sizeof(void *);
2700          }
2701          _class.offsetClass = offsetClass;
2702          _class.sizeClass = totalSizeClass;
2703          _class.Constructor = (void *)Constructor;
2704          _class.Destructor = Destructor;
2705          if(_class.type != systemClass)
2706             _class.type = type;
2707          if(!size)
2708             _class.computeSize = true;
2709          else
2710             _class.computeSize = false;
2711          _class.inheritanceAccess = inheritanceAccess;
2712
2713          /*if(type == bitClass)
2714             _class.size = 0;*/
2715          if(type == enumClass)
2716          {
2717             if(enumBase)
2718                _class.base = base = enumBase;
2719             //else
2720             {
2721                EnumClassData data = (EnumClassData)_class.data;
2722                // TOCHECK: Trying this (if specifiers specified, no class found...)
2723                // What about bit classes, unit classes...
2724                if(base && base.type != enumClass)
2725                   data.largest = -1;//_class.base = null;
2726                else
2727                   data.largest = ((EnumClassData)(base.data)).largest;
2728             }
2729          }
2730          if(base)
2731          {
2732             int i;
2733             uint oldSize = _class.vTblSize;
2734             if(base.vTblSize && _class.vTblSize < base.vTblSize)
2735             {
2736                _class.vTblSize = base.vTblSize;
2737                // OK to scrap existing virtual table?
2738                //delete _class._vTbl;
2739                //_class._vTbl = _malloc(sizeof(int(*)()) * _class.vTblSize);
2740                // memcpy(_class._vTbl, base._vTbl, sizeof(int(*)()) * _class.vTblSize);
2741                _class._vTbl = _realloc(_class._vTbl, sizeof(int(*)()) * _class.vTblSize);
2742             }
2743             if(!prevBase)
2744             {
2745                if(_class.type == normalClass && strcmp(_class.name, "ecere::com::Instance") && strcmp(_class.name, "enum") && strcmp(_class.name, "struct"))
2746                   prevBase = eSystem_FindClass(module, "ecere::com::Instance");
2747                else
2748                   prevBase = eSystem_FindClass(module, "class");
2749             }
2750             for(i = 0; i < base.vTblSize; i++)
2751             {
2752                if(i >= oldSize || _class._vTbl[i] == prevBase._vTbl[i])
2753                   _class._vTbl[i] = base._vTbl[i];
2754             }
2755          }
2756
2757          if(_class.base)
2758          {
2759             OldLink link { data = _class };
2760             /*(_class.base.templateClass ? _class.base.templateClass : _class.base)*/_class.base.derivatives.Add(link);
2761          }
2762
2763          FixDerivativesBase(_class, _class);
2764
2765          return _class;
2766       }
2767    }
2768    return null;
2769 }
2770
2771 static void DataMember_Free(DataMember parentMember)
2772 {
2773    DataMember member;
2774    BTNamedLink namedLink;
2775    delete parentMember.name;
2776    delete parentMember.dataTypeString;
2777
2778    while((member = parentMember.members.first))
2779    {
2780       DataMember_Free(member);
2781       parentMember.members.Delete(member);
2782    }
2783
2784    while((namedLink = (BTNamedLink)parentMember.membersAlpha.first))
2785    {
2786       parentMember.membersAlpha.Delete((BTNode)namedLink);
2787    }
2788 }
2789
2790 static void FreeEnumValue(NamedLink value)
2791 {
2792    delete value.name;
2793 }
2794
2795 static void FreeTemplateArg(Class template, ClassTemplateParameter param, int id)
2796 {
2797    switch(param.type)
2798    {
2799       case type:
2800          delete template.templateArgs[id].dataTypeString;
2801          break;
2802       case identifier:
2803          delete template.templateArgs[id].memberString;
2804          break;
2805       case expression:
2806
2807          break;
2808    }
2809 }
2810
2811 static void FreeTemplateArgs(Class template)
2812 {
2813    if(template.templateArgs)
2814    {
2815       Class _class;
2816       for(_class = template; _class; _class = _class.base)
2817       {
2818          Class prevClass;
2819          ClassTemplateParameter param;
2820          int id = 0;
2821          if(_class.templateClass) _class = _class.templateClass;
2822          for(prevClass = _class.base; prevClass; prevClass = prevClass.base)
2823          {
2824             if(prevClass.templateClass) prevClass = prevClass.templateClass;
2825             id += prevClass.templateParams.count;
2826          }
2827          if(id < template.numParams)
2828          {
2829             for(param = _class.templateParams.first; param; param = param.next)
2830             {
2831                switch(param.type)
2832                {
2833                   case type:
2834                      delete template.templateArgs[id].dataTypeString;
2835                      break;
2836                   case identifier:
2837                      delete template.templateArgs[id].memberString;
2838                      break;
2839                   case expression:
2840                      // delete template.templateArgs[id].dataTypeString;
2841                      break;
2842                }
2843                id++;
2844             }
2845          }
2846       }
2847    }
2848 }
2849
2850 static void FreeTemplate(Class template)
2851 {
2852    OldLink deriv;
2853
2854    if(template.nameSpace)
2855    {
2856       BTNamedLink link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
2857       template.nameSpace->classes.Delete((BTNode)link);
2858    }
2859    FreeTemplateArgs(template);
2860
2861    delete template.fullName;
2862    delete template.name;
2863    delete template.templateArgs;
2864    delete template.dataTypeString;
2865
2866    while((deriv = template.derivatives.first))
2867    {
2868       ((Class)deriv.data).base = null;
2869       template.derivatives.Delete(deriv);
2870    }
2871
2872    _free(template);
2873 }
2874
2875 static void FreeTemplates(Class _class)
2876 {
2877    OldLink deriv, template;
2878
2879    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
2880    {
2881       FreeTemplates(deriv.data);
2882    }
2883
2884    FreeTemplateArgs(_class);
2885    //if(_class.templateArgs)
2886       //printf("Deleting  Template args for %s\n", _class.name);
2887    delete _class.templateArgs;
2888    delete _class.dataTypeString;
2889
2890    while((template = _class.templatized.first))
2891    {
2892       FreeTemplates(template.data);
2893       FreeTemplate(template.data);
2894       _class.templatized.Delete(template);
2895    }
2896 }
2897
2898 public dllexport void eClass_Unregister(Class _class)
2899 {
2900    BTNamedLink namedLink;
2901    DataMember member;
2902    Method method;
2903    OldLink deriv, template;
2904    ClassProperty classProp;
2905    ClassTemplateParameter param;
2906
2907    delete _class._vTbl;
2908
2909    FreeTemplates(_class);
2910
2911    FreeTemplateArgs(_class);
2912    delete _class.templateArgs;
2913
2914    while((template = _class.templatized.first))
2915    {
2916       FreeTemplate(template.data);
2917       _class.templatized.Delete(template);
2918    }
2919
2920    while((member = _class.membersAndProperties.first))
2921    {
2922       if(!member.isProperty && (member.type == unionMember || member.type == structMember))
2923          DataMember_Free(member);
2924       delete member.name;
2925       delete member.dataTypeString;
2926       _class.membersAndProperties.Delete(member);
2927    }
2928
2929    while((member = _class.conversions.first))
2930    {
2931       delete member.name;
2932       delete member.dataTypeString;
2933       _class.conversions.Delete(member);
2934    }
2935
2936    while((namedLink = (BTNamedLink)_class.prop.first))
2937    {
2938       _class.prop.Delete((BTNode)namedLink);
2939    }
2940
2941    while((namedLink = (BTNamedLink)_class.members.first))
2942    {
2943       _class.members.Delete((BTNode)namedLink);
2944    }
2945
2946    while((classProp = (ClassProperty)_class.classProperties.first))
2947    {
2948       delete classProp.name;
2949       delete classProp.dataTypeString;
2950       _class.classProperties.Delete((BTNode)classProp);
2951    }
2952
2953    while((method = (Method)_class.methods.first))
2954    {
2955       delete method.name;
2956       delete method.dataTypeString;
2957       _class.methods.Delete((BTNode)method);
2958    }
2959
2960    if(_class.type == enumClass)
2961    {
2962       EnumClassData data = (EnumClassData)_class.data;
2963
2964       data.values.Free((void *)FreeEnumValue);
2965    }
2966    _class.delayedCPValues.Free(null);
2967
2968    _class.selfWatchers.Free(null);
2969
2970    if(_class.base)
2971    {
2972       // Class base = _class.base.templateClass ? _class.base.templateClass : _class.base;
2973       Class base = _class.base;
2974       for(deriv = base.derivatives.first; deriv; deriv = deriv.next)
2975       {
2976          if(deriv.data == _class)
2977             break;
2978       }
2979       if(deriv)
2980          base.derivatives.Delete(deriv);
2981    }
2982    while((deriv = _class.derivatives.first))
2983    {
2984       ((Class)deriv.data).base = null;
2985       _class.derivatives.Delete(deriv);
2986    }
2987
2988    if(_class.nameSpace)
2989    {
2990       BTNamedLink link = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
2991       _class.nameSpace->classes.Delete((BTNode)link);
2992    }
2993
2994    delete _class.name;
2995    delete _class.fullName;
2996
2997    delete _class.dataTypeString;
2998
2999    delete _class.data;
3000
3001    while((param = _class.templateParams.first))
3002    {
3003       switch(param.type)
3004       {
3005          case type:
3006             delete param.defaultArg.dataTypeString;
3007             break;
3008          case identifier:
3009             delete param.defaultArg.memberString;
3010             break;
3011          case expression:
3012
3013             break;
3014       }
3015       if(param.type != identifier) delete param.dataTypeString;
3016       delete param.name;
3017
3018       _class.templateParams.Delete(param);
3019    }
3020
3021    //_class.nameSpace->classes.Delete(_class);
3022    _free(_class);
3023 }
3024
3025 static BTNamedLink ScanNameSpace(NameSpace nameSpace, char * name, void * listOffset)
3026 {
3027    BinaryTree * tree = (BinaryTree *)((byte *)nameSpace + (uintptr)listOffset);
3028    BTNamedLink link = (BTNamedLink)tree->Find((uintptr)name);
3029    NameSpace * child;
3030    if(!link)
3031    {
3032       for(child = (NameSpace *)nameSpace.nameSpaces.first; child; child = (NameSpace *)((BTNode)child).next)
3033       {
3034          link = ScanNameSpace(child, name, listOffset);
3035          if(link)
3036             break;
3037       }
3038    }
3039    return link;
3040 }
3041
3042 static BTNamedLink SearchNameSpace(NameSpace nameSpace, char * name, void * listOffset)
3043 {
3044    int start = 0, c;
3045    char ch;
3046    int level = 0;
3047    for(c = 0; (ch = name[c]); c++)
3048    {
3049       if(ch == '<') level++;
3050       if(ch == '>') level--;
3051       if(level == 0 && (ch == '.' || (ch == ':' && name[c+1] == ':')))
3052       {
3053          NameSpace * newSpace;
3054          char * spaceName = _malloc(c - start + 1);
3055          memcpy(spaceName, name + start, c - start);
3056          spaceName[c-start] = '\0';
3057          newSpace = (NameSpace *)nameSpace.nameSpaces.FindString(spaceName);
3058          _free(spaceName);
3059          if(!newSpace)
3060             return null;
3061          nameSpace = newSpace;
3062          if(level == 0 && ch == ':') c++;
3063          start = c+1;
3064       }
3065    }
3066    if(c - start)
3067    {
3068       return ScanNameSpace(nameSpace, name + start, listOffset);
3069    }
3070    return null;
3071 }
3072
3073 static BTNamedLink SearchModule(Module module, char * name, void * listOffset, bool searchPrivate)
3074 {
3075    SubModule subModule;
3076    BTNamedLink link;
3077
3078    if(searchPrivate)
3079    {
3080       link = SearchNameSpace(&module.privateNameSpace, name, listOffset);
3081       if(link) return link;
3082    }
3083    link = SearchNameSpace(&module.publicNameSpace, name, listOffset);
3084    if(link) return link;
3085
3086    for(subModule = module.modules.first; subModule; subModule = subModule.next)
3087    {
3088       if(searchPrivate || subModule.importMode == publicAccess)
3089       {
3090          // TOCHECK: Reverting to false to test what we were trying to fix by passing searchPrivate
3091          // Passing searchPrivate finds ALL classes private or not and thus classes clash
3092          // SearchModule here is called mainly from eSystem_FindClass, and also for Functions and Defines
3093
3094          link = SearchModule(subModule.module, name, listOffset, false);
3095          //link = SearchModule(subModule.module, name, listOffset, searchPrivate /*false*/);
3096          if(link) return link;
3097       }
3098    }
3099    return null;
3100 }
3101
3102 public int64 _strtoi64(char * string, char ** endString, int base)
3103 {
3104    int64 value = 0;
3105    int sign = 1;
3106    int c;
3107    char ch;
3108    for(c = 0; (ch = string[c]) && isspace(ch); c++);
3109    if(ch =='+') c++;
3110    else if(ch == '-') { sign = -1; c++; };
3111    if(!base)
3112    {
3113       if(ch == '0' && string[c+1] == 'x')
3114       {
3115          base = 16;
3116          c+=2;
3117       }
3118       else if(ch == '0')
3119       {
3120          base = 8;
3121          c++;
3122       }
3123       else
3124          base = 10;
3125    }
3126    for( ;(ch = string[c]); c++)
3127    {
3128       if(ch >= '0' && ch <= '9')
3129          ch -= '0';
3130       else if(ch >= 'a' && ch <= 'z')
3131          ch -= ('a' - 10);
3132       else if(ch >= 'A' && ch <= 'Z')
3133          ch -= ('A'- 10);
3134       else
3135       {
3136          if(endString)
3137             *endString = string + c;
3138          // Invalid character
3139          break;
3140       }
3141       if(ch < base)
3142       {
3143          value *= base;
3144          value += ch;
3145       }
3146       else
3147       {
3148          if(endString)
3149             *endString = string + c;
3150          // Invalid character
3151          break;
3152       }
3153    }
3154    return sign*value;
3155 }
3156
3157 public uint64 _strtoui64(char * string, char ** endString, int base)
3158 {
3159    uint64 value = 0;
3160    int sign = 1;
3161    int c;
3162    char ch;
3163    for(c = 0; (ch = string[c]) && isspace(ch); c++);
3164    if(ch =='+') c++;
3165    else if(ch == '-') { sign = -1; c++; };
3166    if(!base)
3167    {
3168       if(ch == '0' && string[c+1] == 'x')
3169       {
3170          base = 16;
3171          c+=2;
3172       }
3173       else if(ch == '0')
3174       {
3175          base = 8;
3176          c++;
3177       }
3178       else
3179          base = 10;
3180    }
3181    for( ;(ch = string[c]); c++)
3182    {
3183       if(ch >= '0' && ch <= '9')
3184          ch -= '0';
3185       else if(ch >= 'a' && ch <= 'z')
3186          ch -= ('a' - 10);
3187       else if(ch >= 'A' && ch <= 'Z')
3188          ch -= ('A' - 10);
3189       else
3190       {
3191          if(endString)
3192             *endString = string + c;
3193          // Invalid character
3194          break;
3195       }
3196       if(ch < base)
3197       {
3198          value *= base;
3199          value += ch;
3200       }
3201       else
3202       {
3203          if(endString)
3204             *endString = string + c;
3205          // Invalid character
3206          break;
3207       }
3208    }
3209    return sign*value;
3210 }
3211
3212 public dllexport Class eSystem_FindClass(Module module, char * name)
3213 {
3214    if(name && module)
3215    {
3216       BTNamedLink link;
3217       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->classes);
3218       if(link) return link.data;
3219
3220       link = SearchModule(module, name, &((NameSpace *)0)->classes, true);
3221       if(link) return link.data;
3222
3223       {
3224          char noTemplateName[1024];
3225          char * templateParams = strchr(name, '<');
3226
3227          if(templateParams)
3228          {
3229             strncpy(noTemplateName, name, templateParams - name);
3230             noTemplateName[templateParams - name] = '\0';
3231          }
3232          else
3233             strcpy(noTemplateName, name);
3234
3235          link = SearchNameSpace(&module.application.systemNameSpace, noTemplateName, &((NameSpace *)0)->classes);
3236          if(!link)
3237             link = SearchModule(module, noTemplateName, &((NameSpace *)0)->classes, true);
3238          if(link)
3239          {
3240             Class _class = link.data;
3241             Class templatedClass = null;
3242             char className[1024];
3243             strcpy(className, _class.fullName);
3244             strcat(className, templateParams);
3245
3246             link = SearchNameSpace(&module.application.systemNameSpace, className, &((NameSpace *)0)->classes);
3247             if(link)
3248                return link.data;
3249
3250             link = SearchModule(module, className, &((NameSpace *)0)->classes, true);
3251             if(link)
3252                return link.data;
3253
3254             if(_class && templateParams)
3255             {
3256                // if(!numParams) return null;
3257
3258                templatedClass = Class { };
3259                *templatedClass = *_class;
3260                templatedClass.templateClass = _class;
3261                //templatedClass.fullName = CopyString(name);
3262                templatedClass.fullName = CopyString(className);
3263                templatedClass.dataTypeString = CopyString(_class.dataTypeString);
3264                templatedClass.name = CopyString(templatedClass.fullName + strlen(_class.fullName) - strlen(_class.name));
3265                templatedClass.nameSpace->classes.Add((BTNode)BTNamedLink { name = templatedClass.name, data = templatedClass });
3266                templatedClass.templateArgs = null;
3267                templatedClass.numParams = 0;
3268                templatedClass.derivatives = { };
3269                templatedClass.templatized = { };
3270
3271                ComputeClassParameters(templatedClass, templateParams, module);
3272
3273                _class.templatized.Add(OldLink { data = templatedClass });
3274             }
3275             return templatedClass;
3276          }
3277       }
3278    }
3279    return null;
3280 }
3281
3282 static void CopyTemplateArg(ClassTemplateParameter param, ClassTemplateArgument arg)
3283 {
3284    switch(param.type)
3285    {
3286       case type:
3287          arg.dataTypeString = CopyString(arg.dataTypeString);
3288          break;
3289       case expression:
3290
3291          break;
3292       case identifier:
3293          arg.memberString = CopyString(arg.memberString);
3294          break;
3295    }
3296 }
3297
3298 static void ComputeClassParameters(Class templatedClass, char * templateParams, Module findModule)
3299 {
3300    char ch;
3301    char * nextParamStart = templateParams ? (templateParams + 1) : null;
3302    ClassTemplateParameter curParam = null;
3303    Class lastClass = null, sClass;
3304    int curParamID = 0;
3305    int numParams = 0;
3306    Class _class = templatedClass.templateClass ? templatedClass.templateClass : templatedClass;
3307
3308    for(sClass = _class; sClass; sClass = sClass.base)
3309    {
3310       if(sClass.templateClass) sClass = sClass.templateClass;
3311       numParams += sClass.templateParams.count;
3312    }
3313
3314    if(templatedClass.templateArgs)
3315       FreeTemplateArgs(templatedClass);
3316    delete templatedClass.templateArgs;
3317    templatedClass.templateArgs = new0 ClassTemplateArgument[numParams];
3318    templatedClass.numParams = numParams;
3319
3320    if(_class != templatedClass)
3321    {
3322       /*int c;
3323       Class sClass;
3324       memcpy(templatedClass.templateArgs, _class.templateArgs, numParams * sizeof(ClassTemplateArgument));
3325       for(sClass = _class; sClass; sClass = sClass.base)
3326       {
3327          ClassTemplateParameter param;
3328          Class prevClass;
3329          int id = 0;
3330          if(sClass.templateClass) sClass = sClass.templateClass;
3331          for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
3332          {
3333             if(prevClass.templateClass) prevClass = prevClass.templateClass;
3334             id += prevClass.templateParams.count;
3335          }
3336          for(param = sClass.templateParams.first; param; param = param.next)
3337            CopyTemplateArg(param, templatedClass.templateArgs[id++]);
3338       }*/
3339    }
3340
3341    if(templatedClass.base && templatedClass.base.templateArgs && _class == templatedClass)
3342    {
3343       Class sClass;
3344       memcpy(templatedClass.templateArgs, templatedClass.base.templateArgs,
3345          sizeof(ClassTemplateArgument) * (numParams - templatedClass.templateParams.count));
3346       for(sClass = templatedClass.base; sClass; sClass = sClass.base)
3347       {
3348          ClassTemplateParameter param;
3349          Class prevClass;
3350          int id = 0;
3351          for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
3352          {
3353             if(prevClass.templateClass) prevClass = prevClass.templateClass;
3354             id += prevClass.templateParams.count;
3355          }
3356
3357          if(sClass.templateClass) sClass = sClass.templateClass;
3358          for(param = sClass.templateParams.first; param; param = param.next)
3359             CopyTemplateArg(param, templatedClass.templateArgs[id++]);
3360       }
3361    }
3362
3363    while(nextParamStart)
3364    {
3365       char * paramStart = nextParamStart;
3366       char * paramEnd;
3367       int level = 0;
3368       while(*paramStart == ' ') paramStart++;
3369       paramEnd = paramStart;
3370       while((ch = *paramEnd, ch && (level > 0 || (ch != '>' && ch != ','))))
3371       {
3372          if(ch == '<') level++;
3373          if(ch == '>') level--;
3374
3375          paramEnd++;
3376       }
3377       nextParamStart = (ch == ',') ? (paramEnd + 1) : null;
3378       while(*paramEnd == ' ') paramEnd--;
3379       if(paramEnd > paramStart)
3380       {
3381          char * ptr, * equal = null;
3382          for(ptr = paramStart; ptr <= paramEnd; ptr++)
3383          {
3384             if(*ptr == '=')
3385             {
3386                equal = ptr;
3387                break;
3388             }
3389          }
3390          if(equal)
3391          {
3392             char * end = equal - 1;
3393             char ident[1024];
3394
3395             while(*end == ' ') end--;
3396             strncpy(ident, paramStart, end + 1 - paramStart);
3397             ident[end + 1 - paramStart] = 0;
3398
3399             for(sClass = _class; sClass; sClass = sClass.base)
3400             {
3401                if(sClass.templateClass) sClass = sClass.templateClass;
3402                for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
3403                {
3404                   if(!strcmp(curParam.name, ident))
3405                      break;
3406                }
3407                if(curParam)
3408                {
3409                   Class nextClass;
3410                   ClassTemplateParameter prevParam;
3411                   curParamID = 0;
3412                   for(prevParam = curParam.prev; prevParam; prevParam = prevParam.prev) curParamID++;
3413                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3414                   {
3415                      if(nextClass.templateClass) nextClass = nextClass.templateClass;
3416                      curParamID += nextClass.templateParams.count;
3417                   }
3418                   break;
3419                }
3420             }
3421             lastClass = sClass;
3422          }
3423          else
3424          {
3425             if(curParam)
3426             {
3427                curParam = curParam.next;
3428                curParamID++;
3429             }
3430
3431             if(!curParam)
3432             {
3433                for(sClass = lastClass ? lastClass.base : _class; sClass; sClass = sClass.base)
3434                {
3435                   ClassTemplateParameter param;
3436                   curParamID = 0;
3437                   if(sClass.templateClass) sClass = sClass.templateClass;
3438                   for(param = sClass.templateParams.first; param; param = param.next, curParamID++)
3439                   {
3440                      curParam = param;
3441                      break;
3442                   }
3443                   if(curParam)
3444                   {
3445                      Class nextClass;
3446                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3447                      {
3448                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
3449                         curParamID += nextClass.templateParams.count;
3450                      }
3451                      lastClass = sClass;
3452                      break;
3453                   }
3454                }
3455                /*
3456                for(sClass = _class; sClass; sClass = sClass.base)
3457                {
3458                   if(sClass.templateParams.first)
3459                   {
3460                      Class nextClass;
3461                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3462                         if(nextClass.templateParams.first)
3463                            break;
3464                      if(nextClass != lastClass) continue;
3465
3466                      curParam = sClass.templateParams.first;
3467                      lastClass = sClass;
3468
3469                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3470                         if(nextClass.templateParams.first)
3471                         {
3472                            curParamID += nextClass.templateParams.count;
3473                            break;
3474                         }
3475                      break;
3476                   }
3477                }
3478                */
3479             }
3480          }
3481
3482          if(curParam)
3483          {
3484             ClassTemplateArgument argument { };
3485             char value[1024];
3486             if(equal)
3487             {
3488                equal++;
3489                while(*equal == ' ') equal++;
3490                memcpy(value, equal, paramEnd - equal);
3491                value[paramEnd - equal] = 0;
3492             }
3493             else
3494             {
3495                memcpy(value, paramStart, paramEnd - paramStart);
3496                value[paramEnd - paramStart] = 0;
3497             }
3498             TrimRSpaces(value, value);
3499
3500             switch(curParam.type)
3501             {
3502                case type:
3503                   argument.dataTypeString = CopyString(value);
3504                   argument.dataTypeClass = eSystem_FindClass(_class.module, value);
3505                   if(!argument.dataTypeClass) argument.dataTypeClass = eSystem_FindClass(_class.module.application, value);
3506                   if(!argument.dataTypeClass) argument.dataTypeClass = eSystem_FindClass(findModule, value);
3507                   break;
3508                case expression:
3509                {
3510                   Class expClass = eSystem_FindClass(_class.module, curParam.dataTypeString);
3511                   if(!expClass) expClass = eSystem_FindClass(_class.module.application, curParam.dataTypeString);
3512                   if(expClass)
3513                   {
3514                      //if(expClass.type ==
3515                      ((bool (*)(void *, void *, const char *))(void *)expClass._vTbl[__ecereVMethodID_class_OnGetDataFromString])(expClass, &argument.expression, value);
3516                   }
3517                   // Expression should be pre simplified here
3518                   else if(value[0] == '\"')
3519                   {
3520                      char * endQuote = value + strlen(value) - 1;
3521                      if(*endQuote != '\"') endQuote++;
3522                      *endQuote = '\0';
3523                      argument.expression.p = CopyString(value + 1);
3524                   }
3525                   else if(value[0] == '\'')
3526                   {
3527                      int nb;
3528                      unichar ch = UTF8GetChar(value + 1, &nb);
3529                      argument.expression.ui = ch;
3530                   }
3531                   else if(!strcmp(curParam.dataTypeString, "uint"))
3532                   {
3533                      argument.expression.ui = (uint)strtoul(value, null, 0);
3534                   }
3535                   else if(!strcmp(curParam.dataTypeString, "char"))
3536                   {
3537                      argument.expression.c = (char)strtol(value, null, 0);
3538                   }
3539                   else if(!strcmp(curParam.dataTypeString, "byte"))
3540                   {
3541                      argument.expression.uc = (unsigned char)strtoul(value, null, 0);
3542                   }
3543                   else if(!strcmp(curParam.dataTypeString, "short"))
3544                   {
3545                      argument.expression.s = (short)strtol(value, null, 0);
3546                   }
3547                   else if(!strcmp(curParam.dataTypeString, "uint16"))
3548                   {
3549                      argument.expression.us = (unsigned short)strtoul(value, null, 0);
3550                   }
3551                   else if(!strcmp(curParam.dataTypeString, "int64"))
3552                   {
3553                      argument.expression.i64 = _strtoi64(value, null, 0);
3554                   }
3555                   else if(!strcmp(curParam.dataTypeString, "uint64"))
3556                   {
3557                      argument.expression.ui64 = _strtoui64(value, null, 0);
3558                   }
3559                   else if(!strcmp(curParam.dataTypeString, "float"))
3560                   {
3561                      argument.expression.f = (float)strtod(value, null);
3562                   }
3563                   else if(!strcmp(curParam.dataTypeString, "double"))
3564                   {
3565                      argument.expression.d = strtod(value, null);
3566                   }
3567                   else // if(!strcmp(curParam.dataTypeString, "int"))
3568                   {
3569                      argument.expression.i = (int)strtol(value, null, 0);
3570                   }
3571                   break;
3572                }
3573                case identifier:
3574                   argument.memberString = CopyString(value);
3575                   break;
3576             }
3577             FreeTemplateArg(templatedClass, curParam, curParamID);
3578             templatedClass.templateArgs[curParamID] = argument;
3579          }
3580       }
3581    }
3582
3583    // TESTING THIS BEFORE...
3584    if(templatedClass == _class)
3585    {
3586       Class sClass = _class;
3587       int curParamID = 0;
3588       Class nextClass;
3589       ClassTemplateParameter param;
3590       for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3591       {
3592          if(nextClass.templateClass) nextClass = nextClass.templateClass;
3593          curParamID += nextClass.templateParams.count;
3594       }
3595
3596       for(param = sClass.templateParams.first; param; param = param.next)
3597       {
3598          if(!templatedClass.templateArgs[curParamID].dataTypeString)
3599          {
3600             templatedClass.templateArgs[curParamID] = param.defaultArg;
3601             CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3602             if(param.type == type && param.defaultArg.dataTypeString)
3603             {
3604                templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3605                if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3606                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3607                if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3608                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3609             }
3610          }
3611          curParamID++;
3612       }
3613    }
3614
3615    if(templatedClass.base && templatedClass.base.templateArgs && numParams - _class.templateParams.count)
3616    {
3617       int c = numParams - _class.templateParams.count-1;
3618
3619       for(sClass = _class.base; sClass; sClass = sClass.base)
3620       {
3621          ClassTemplateParameter param;
3622          if(sClass.templateClass) sClass = sClass.templateClass;
3623          for(param = sClass.templateParams.last; param; param = param.prev)
3624          {
3625             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3626             ClassTemplateArgument * baseArg = &templatedClass.base.templateArgs[c];
3627             if(!arg->dataTypeString)
3628             {
3629                *arg = templatedClass.base.templateArgs[c];
3630                CopyTemplateArg(param, arg);
3631                if(param.type == type)
3632                {
3633                   if(arg->dataTypeClass && strchr(arg->dataTypeString, '<') && arg->dataTypeClass.templateArgs)
3634                   {
3635                      Class expClass = arg->dataTypeClass;
3636                      Class cClass = null;
3637                      int paramCount = 0;
3638                      int lastParam = -1;
3639
3640                      char templateString[1024];
3641                      sprintf(templateString, "%s<", expClass.templateClass.fullName);
3642                      for(cClass = expClass; cClass; cClass = cClass.base)
3643                      {
3644                         int p = 0;
3645                         ClassTemplateParameter param;
3646                         for(param = cClass.templateParams.first; param; param = param.next)
3647                         {
3648                            int id = p;
3649                            Class sClass;
3650                            ClassTemplateArgument arg;
3651                            for(sClass = expClass.base; sClass; sClass = sClass.base) id += sClass.templateParams.count;
3652                            arg = expClass.templateArgs[id];
3653
3654                            {
3655                               ClassTemplateParameter cParam;
3656                               int p = numParams - _class.templateParams.count;
3657                               for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3658                               {
3659                                  if(cParam.type == type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
3660                                  {
3661                                     arg.dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3662                                     arg.dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3663                                     break;
3664                                  }
3665                               }
3666                            }
3667
3668                            {
3669                               char argument[256];
3670                               argument[0] = '\0';
3671                               switch(param.type)
3672                               {
3673                                  case expression:
3674                                  {
3675                                     // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
3676                                     /*
3677                                     char expString[1024];
3678                                     OldList * specs = MkList();
3679                                     Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
3680                                     Expression exp;
3681                                     char * string = PrintHexUInt64(arg.expression.ui64);
3682                                     exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
3683
3684                                     ProcessExpressionType(exp);
3685                                     ComputeExpression(exp);
3686                                     expString[0] = '\0';
3687                                     PrintExpression(exp, expString);
3688                                     strcat(argument, expString);
3689                                     //delete exp;
3690                                     FreeExpression(exp);
3691                                     */
3692                                     break;
3693                                  }
3694                                  case identifier:
3695                                  {
3696                                     strcat(argument, arg.member.name);
3697                                     break;
3698                                  }
3699                                  case TemplateParameterType::type:
3700                                  {
3701                                     if(arg.dataTypeString)
3702                                        strcat(argument, arg.dataTypeString);
3703                                     break;
3704                                  }
3705                               }
3706                               if(argument[0])
3707                               {
3708                                  if(paramCount) strcat(templateString, ", ");
3709                                  if(lastParam != p - 1)
3710                                  {
3711                                     strcat(templateString, param.name);
3712                                     strcat(templateString, " = ");
3713                                  }
3714                                  strcat(templateString, argument);
3715                                  paramCount++;
3716                                  lastParam = p;
3717                               }
3718                            }
3719                            p++;
3720                         }
3721                      }
3722                      {
3723                         int len = (int)strlen(templateString);
3724                         if(templateString[len-1] == '>') templateString[len++] = ' ';
3725                         templateString[len++] = '>';
3726                         templateString[len++] = '\0';
3727                      }
3728
3729                      FreeTemplateArg(templatedClass, param, c);
3730
3731                      arg->dataTypeString = CopyString(templateString);
3732                      arg->dataTypeClass = eSystem_FindClass(templatedClass.module, templateString);
3733                      if(!arg->dataTypeClass)
3734                         arg->dataTypeClass = eSystem_FindClass(templatedClass.module.application, templateString);
3735                   }
3736                   else
3737                   {
3738                      ClassTemplateParameter cParam;
3739                      int p = numParams - _class.templateParams.count;
3740                      for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3741                      {
3742                         // if(cParam.type == type && !strcmp(cParam.name, param.name))
3743                         if(cParam.type == type && baseArg->dataTypeString && !strcmp(cParam.name, baseArg->dataTypeString))
3744                         {
3745                            FreeTemplateArg(templatedClass, param, c);
3746
3747                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3748                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3749                            CopyTemplateArg(cParam, arg);
3750                            break;
3751                         }
3752                      }
3753                   }
3754                }
3755             }
3756             c--;
3757          }
3758       }
3759    }
3760
3761    {
3762       Class sClass;
3763       for(sClass = _class; sClass; sClass = sClass.base)
3764       {
3765          int curParamID = 0;
3766          Class nextClass;
3767          ClassTemplateParameter param;
3768          if(sClass.templateClass) sClass = sClass.templateClass;
3769
3770          for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3771          {
3772             if(nextClass.templateClass) nextClass = nextClass.templateClass;
3773             curParamID += nextClass.templateParams.count;
3774          }
3775
3776          for(param = sClass.templateParams.first; param; param = param.next)
3777          {
3778             if(!templatedClass.templateArgs[curParamID].dataTypeString)
3779             {
3780                templatedClass.templateArgs[curParamID] = param.defaultArg;
3781                CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3782                if(param.type == type && param.defaultArg.dataTypeString)
3783                {
3784                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3785                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3786                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3787                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3788                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3789                }
3790             }
3791             curParamID++;
3792          }
3793       }
3794    }
3795
3796    {
3797       int c = numParams - 1;
3798       for(sClass = _class; sClass; sClass = sClass.base)
3799       {
3800          ClassTemplateParameter param;
3801          if(sClass.templateClass) sClass = sClass.templateClass;
3802          for(param = sClass.templateParams.last; param; param = param.prev)
3803          {
3804             if(param.type == type)
3805             {
3806                ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3807                ClassTemplateParameter cParam;
3808                Class dClass;
3809                int p = numParams - 1;
3810                for(dClass = _class; dClass; dClass = dClass.base)
3811                {
3812                   if(dClass.templateClass) dClass = dClass.templateClass;
3813                   for(cParam = dClass.templateParams.last; cParam; cParam = cParam.prev, p--)
3814                   {
3815                      if(cParam.type == type && arg->dataTypeString && !strcmp(cParam.name, arg->dataTypeString))
3816                      {
3817                         if(templatedClass.templateArgs[p].dataTypeString && c != p)
3818                         {
3819                            FreeTemplateArg(templatedClass, param, c);
3820
3821                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3822                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3823                            CopyTemplateArg(cParam, arg);
3824                         }
3825                      }
3826                   }
3827                }
3828             }
3829             c--;
3830          }
3831       }
3832    }
3833
3834    {
3835       Class tClass;
3836       int c = numParams - 1;
3837       for(tClass = _class; tClass; tClass = tClass.base)
3838       {
3839          ClassTemplateParameter param;
3840          if(tClass.templateClass) tClass = tClass.templateClass;
3841          for(param = tClass.templateParams.last; param; param = param.prev)
3842          {
3843             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3844             if(param.type == identifier && arg->memberString)
3845             {
3846                Class memberClass = templatedClass;
3847                char * memberString = arg->memberString;
3848                char * colon = strstr(memberString, "::");
3849                char * memberName = memberString;
3850                if(colon) memberName = colon + 2;
3851                if(!colon)
3852                {
3853                   memberString = param.defaultArg.memberString;
3854                   colon = memberString ? strstr(memberString, "::") : null;
3855                }
3856
3857                if(colon)
3858                {
3859                   char className[1024];
3860                   Class sClass;
3861
3862                   memcpy(className, memberString, colon - memberString);
3863                   className[colon - memberString] = '\0';
3864
3865                   for(sClass = _class; sClass; sClass = sClass.base)
3866                   {
3867                      ClassTemplateParameter cParam;
3868                      Class nextClass;
3869                      int id = 0;
3870
3871                      if(sClass.templateClass) sClass = sClass.templateClass;
3872                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3873                      {
3874                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
3875                         id += nextClass.templateParams.count;
3876                      }
3877                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
3878                      {
3879                         if(cParam.type == type && !strcmp(cParam.name, className) && templatedClass.templateArgs[id].dataTypeString)
3880                         {
3881                            strcpy(className, templatedClass.templateArgs[id].dataTypeString);
3882                         }
3883                         id++;
3884                      }
3885                   }
3886                   memberClass = eSystem_FindClass(templatedClass.module, className);
3887                   // TESTING: Added this here...
3888                   if(!memberClass)
3889                      memberClass = eSystem_FindClass(findModule, className);
3890                   if(!memberClass)
3891                      memberClass = eSystem_FindClass(templatedClass.module.application, className);
3892                }
3893
3894                if(memberClass)
3895                {
3896                   switch(param.memberType)
3897                   {
3898                      case dataMember:
3899                         arg->member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
3900                         break;
3901                      case method:
3902                         arg->method = eClass_FindMethod(memberClass, memberName, memberClass.module);
3903                         break;
3904                      case prop:
3905                         arg->prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
3906                         break;
3907                   }
3908                }
3909             }
3910             c--;
3911          }
3912       }
3913    }
3914 }
3915
3916 /*static */bool DefaultFunction()
3917 {
3918    return true;
3919 }
3920
3921 public dllexport bool eClass_IsDerived(Class _class, Class from)
3922 {
3923    if(!_class && !from)
3924       return true;
3925
3926    if(_class && from && (_class.templateClass || from.templateClass))
3927    {
3928       if(eClass_IsDerived(_class.templateClass ? _class.templateClass : _class, from.templateClass ? from.templateClass : from))
3929       {
3930          if(!from.templateClass)
3931             return true;
3932          else if(!_class.templateClass && _class == from.templateClass)
3933             return false;
3934          else
3935          {
3936             Class sClass;
3937             for(sClass = from; sClass; sClass = sClass.base)
3938             {
3939                if(sClass.templateParams.first)
3940                {
3941                   ClassTemplateParameter param;
3942                   Class nextClass;
3943                   int p = 0;
3944                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) p += nextClass.templateParams.count;
3945                   for(param = sClass.templateParams.first; param; param = param.next, p++)
3946                   {
3947                      ClassTemplateArgument * arg = &_class.templateArgs[p];
3948                      ClassTemplateArgument * fArg = &from.templateArgs[p];
3949                      if(param.type == type)
3950                      {
3951                         if(arg->dataTypeString != fArg->dataTypeString && arg->dataTypeString && fArg->dataTypeString &&
3952                           strcmp(arg->dataTypeString, fArg->dataTypeString))
3953                            break;
3954                      }
3955                      else if(param.type == identifier)
3956                      {
3957                         if(arg->member != fArg->member)
3958                            break;
3959                      }
3960                      else if(param.type == expression)
3961                      {
3962                         if(arg->expression.ui64 != fArg->expression.ui64)
3963                            break;
3964                      }
3965                   }
3966                   if(param)
3967                      return false;
3968                }
3969             }
3970             return true;
3971          }
3972       }
3973    }
3974    else
3975    {
3976       for(; _class && from; _class = _class.base)
3977       {
3978          if(_class == from || _class.templateClass == from || ((_class.type == systemClass || (_class.type == normalClass && _class.isInstanceClass)) && from.name && !strcmp(_class.name, from.name)))
3979             return true;
3980       }
3981    }
3982    return false;
3983 }
3984
3985 static void FixDerivativeVirtualMethod(Class base, char * name, int vid, void * origFunction, char * type)
3986 {
3987    OldLink derivative;
3988    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
3989    {
3990       Class _class = derivative.data;
3991       Method method, next;
3992       void * function = origFunction;
3993
3994       _class.vTblSize++;
3995       _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
3996       memmove(_class._vTbl + vid + 1, _class._vTbl + vid, (_class.vTblSize - vid - 1) * sizeof(void *));
3997
3998       method = (Method) _class.methods.FindString(name);
3999       if(method)
4000       {
4001          if(method.function) function = method.function;
4002
4003          if(!method.symbol)
4004          {
4005             delete method.name;
4006             delete method.dataTypeString;
4007             _class.methods.Delete((BTNode)method);
4008          }
4009          else
4010          {
4011             delete method.dataTypeString;
4012             method.type = virtualMethod;
4013             method.dataTypeString = CopyString(type);
4014             method._class = base;
4015          }
4016       }
4017       for(method = (Method)_class.methods.first; method; method = next)
4018       {
4019          next = (Method)((BTNode)method).next;
4020          if(method.type == virtualMethod)
4021             method.vid++;
4022       }
4023       _class._vTbl[vid] = function;
4024
4025       {
4026          OldLink templateLink;
4027          for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4028          {
4029             Class template = templateLink.data;
4030             template._vTbl = _class._vTbl;
4031          }
4032       }
4033       if(_class.derivatives.first || _class.templatized.first)
4034          FixDerivativeVirtualMethod(_class, name, vid, function, type);
4035    }
4036    {
4037       OldLink templateLink;
4038       for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
4039       {
4040          Class template = templateLink.data;
4041          template._vTbl = base._vTbl;
4042          FixDerivativeVirtualMethod(template, name, vid, origFunction, type);
4043       }
4044    }
4045 }
4046
4047 public dllexport Method eClass_AddMethod(Class _class, char * name, char * type, void * function, AccessMode declMode)
4048 {
4049    if(_class && !_class.comRedefinition && name)
4050    {
4051       Class base;
4052       for(base = _class; base; base = base.base)
4053       {
4054          Method method;
4055          if(base.templateClass) base = base.templateClass;
4056          method = (Method)base.methods.FindString(name);
4057          if(method)
4058          {
4059             // If this overrides a virtual method
4060             if(method.type == virtualMethod)
4061             {
4062                OldLink deriv;
4063                void * oldFunction = _class._vTbl[method.vid];
4064                if(method.vid >= _class.vTblSize)
4065                   printf("error: virtual methods overriding failure\n");
4066                else
4067                   _class._vTbl[method.vid] = function ? function : DefaultFunction;
4068                for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4069                {
4070                   Class derivClass = deriv.data;
4071                   if(derivClass._vTbl[method.vid] == oldFunction)
4072                      eClass_AddMethod(derivClass, name, type, function, declMode);
4073                }
4074                {
4075                   OldLink templateLink;
4076                   for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4077                   {
4078                      Class template = templateLink.data;
4079                      for(deriv = template.derivatives.first; deriv; deriv = deriv.next)
4080                      {
4081                         Class derivClass = deriv.data;
4082                         if(derivClass._vTbl[method.vid] == oldFunction)
4083                            eClass_AddMethod(derivClass, name, type, function, declMode);
4084                      }
4085                   }
4086                }
4087
4088             }
4089             else
4090             {
4091                if(base == _class)
4092                {
4093                   // printf("error: Redefinition of method %s in class %s\n", name, _class.name);
4094                   break;
4095                }
4096                base = null;
4097                break;
4098             }
4099             return method;
4100          }
4101       }
4102
4103       if(!base)
4104       {
4105          Method method
4106          {
4107             name = CopyString(name),
4108             function = function ? function : DefaultFunction;
4109             _class = _class;
4110             dataTypeString = CopyString(type);
4111             memberAccess = declMode;
4112          };
4113          _class.methods.Add((BTNode)method);
4114          return method;
4115       }
4116    }
4117    return null;
4118 }
4119
4120 public dllexport Method eClass_AddVirtualMethod(Class _class, char * name, char * type, void * function, AccessMode declMode)
4121 {
4122    if(_class && !_class.comRedefinition && name)
4123    {
4124       Class base;
4125       for(base = _class; base; base = base.base)
4126       {
4127          Method method = (Method)base.methods.FindString(name);
4128          if(method)
4129          {
4130             // If this overides a virtual method
4131             if(method.type == virtualMethod)
4132             {
4133                if(method.vid >= _class.vTblSize)
4134                   printf("error: virtual methods overriding failure\n");
4135                else
4136                   _class._vTbl[method.vid] = function ? function : DefaultFunction;
4137             }
4138             else
4139                base = null;
4140             return method;
4141          }
4142       }
4143
4144       if(!base)
4145       {
4146          Method method
4147          {
4148             name = CopyString(name);
4149             function = function ? function : DefaultFunction;
4150             type = virtualMethod;
4151             _class = _class;
4152             vid = _class.vTblSize++;
4153             dataTypeString = CopyString(type);
4154             memberAccess = declMode;
4155          };
4156          _class.methods.Add((BTNode)method);
4157          _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
4158          _class._vTbl[method.vid] = function ? function : DefaultFunction;
4159
4160          // TODO: Fix derived classes
4161          if(_class.derivatives.first || _class.templatized.first)
4162             FixDerivativeVirtualMethod(_class, name, method.vid, function ? function : (void *)DefaultFunction, type);
4163          return method;
4164       }
4165    }
4166    return null;
4167 }
4168
4169 static void FixDerivativeProperty(Class base, Property _property)
4170 {
4171    OldLink derivative;
4172    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
4173    {
4174       Class _class = derivative.data;
4175       Property prop;
4176       BTNamedLink link = (BTNamedLink)_class.prop.FindString(_property.name);
4177       if(link)
4178       {
4179          prop = link.data;
4180          if(!prop.Set && !prop.Get && prop.memberAccess == baseSystemAccess)
4181          {
4182             SelfWatcher watcher;
4183             for(watcher = _class.selfWatchers.first; watcher; watcher = watcher.next)
4184             {
4185                if(watcher._property == prop)
4186                   watcher._property = _property;
4187             }
4188             _property.selfWatchable = true;
4189
4190             delete prop.name;
4191             delete prop.dataTypeString;
4192             _class.membersAndProperties.Delete(prop);
4193             _class.prop.Delete((BTNode)link);
4194          }
4195       }
4196
4197       for(prop = _class.membersAndProperties.first; prop; prop = prop.next)
4198          prop.id++;
4199       _class.memberID++;
4200       _class.startMemberID++;
4201
4202       FixDerivativeProperty(_class, _property);
4203    }
4204 }
4205
4206 public dllexport Property eClass_AddProperty(Class _class, char * name, char * dataType, void * setStmt, void * getStmt, AccessMode declMode)
4207 {
4208    Property _property = null;
4209    if(_class)
4210    {
4211       BTNamedLink link = (BTNamedLink)_class.prop.FindString(name ? name : dataType);
4212       if(link)
4213          _property = link.data;
4214       if(!_property)
4215       {
4216          _property =
4217          {
4218             isProperty = true;
4219             name = CopyString(name ? name : dataType);
4220             id = (name && (setStmt || getStmt || dataType)) ? _class.memberID++ : 0;
4221             Set = setStmt;
4222             Get = getStmt;
4223             dataTypeString = CopyString(dataType);
4224             _class = _class;
4225             compiled = true;
4226             conversion = name ? false : true;
4227             memberAccess = declMode;
4228          };
4229          if(name)
4230             _class.membersAndProperties.Add(_property);
4231          else
4232             _class.conversions.Add(_property);
4233          _class.prop.Add((BTNode)BTNamedLink { name = _property.name, data = _property });
4234
4235          if(!_property.conversion)
4236          {
4237             FixDerivativeProperty(_class, _property);
4238          }
4239       }
4240    }
4241    return _property;
4242 }
4243
4244 static void SetDelayedCPValues(Class _class, ClassProperty _property)
4245 {
4246    OldLink deriv;
4247    NamedLink64 value, next;
4248
4249    for(value = _class.delayedCPValues.first; value; value = next)
4250    {
4251       next = value.next;
4252       if(!strcmp(value.name, _property.name))
4253       {
4254          // eClass_SetProperty(_class, _property.name, value.data);
4255          _property.Set(_class, value.data);
4256          _class.delayedCPValues.Delete(value);
4257       }
4258    }
4259
4260    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4261    {
4262       SetDelayedCPValues(deriv.data, _property);
4263    }
4264 }
4265
4266 public dllexport ClassProperty eClass_AddClassProperty(Class _class, char * name, char * dataType, void * setStmt, void * getStmt)
4267 {
4268    if(name && !_class.classProperties.FindString(name))
4269    {
4270       ClassProperty _property
4271       {
4272          name = CopyString(name);
4273          Set = setStmt;
4274          Get = getStmt;
4275          dataTypeString = CopyString(dataType);
4276       };
4277       _class.classProperties.Add((BTNode)_property);
4278       SetDelayedCPValues(_class, _property);
4279       return _property;
4280    }
4281    return null;
4282 }
4283
4284 /*import "Time"
4285
4286 Time classFindTotalTime;
4287
4288 public dllexport void ResetClassFindTime()
4289 {
4290    classFindTotalTime = 0;
4291 }
4292
4293 public dllexport Time GetClassFindTime()
4294 {
4295    return classFindTotalTime;
4296 }
4297 */
4298 public dllexport ClassProperty eClass_FindClassProperty(Class _class, char * name)
4299 {
4300    //Time startTime = GetTime();
4301    ClassProperty _property = null;
4302    if(name && _class)
4303    {
4304       Class origClass = _class;
4305       for(; _class; _class = _class.base)
4306       {
4307          _property = (ClassProperty)_class.classProperties.FindString(name);
4308          if(_property)
4309             break;
4310       }
4311       // For enum class deriving off something else than enum to find enumSize...
4312       if(!_property && origClass.type == enumClass)
4313       {
4314          Class enumClass = eSystem_FindClass(origClass.module, "enum");
4315          _property = eClass_FindClassProperty(enumClass, name);
4316       }
4317    }
4318    /*if(!_property)
4319       eSystem_Logf("No such property (%s) for class %s\n", name, _class.name);*/
4320    //classFindTotalTime += GetTime() - startTime;
4321    return _property;
4322 }
4323
4324 public dllexport int64 eClass_GetProperty(Class _class, char * name)
4325 {
4326    ClassProperty _property = eClass_FindClassProperty(_class, name);
4327    if(_property && _property.Get && _property.Get != (void *)1)
4328    {
4329       int64 result = _property.Get(_class);
4330       return result;
4331    }
4332    return 0;
4333 }
4334
4335 public dllexport void eClass_SetProperty(Class _class, char * name, int64 value)
4336 {
4337    ClassProperty _property = eClass_FindClassProperty(_class, name);
4338    if(_property)
4339    {
4340       if(_property.Set)
4341          ((void(*)(void *, int64))_property.Set)(_class, value);
4342    }
4343    else
4344    {
4345       _class.delayedCPValues.Add(NamedLink64 { name = name, value });
4346    }
4347 }
4348
4349 public dllexport Method eClass_FindMethod(Class _class, char * name, Module module)
4350 {
4351    //Time startTime = GetTime();
4352    if(_class && name)
4353    {
4354       for(; _class; _class = _class.base)
4355       {
4356          Method method;
4357          if(_class.templateClass) _class = _class.templateClass;
4358          method = (Method)_class.methods.FindString(name);
4359          if(method && (method.memberAccess == publicAccess || _class.module == module || !method.dataTypeString))
4360          {
4361             if(!method.dataTypeString)
4362             {
4363                if(_class.module != module)
4364                {
4365                   if(method.memberAccess == publicAccess)
4366                      module = _class.module;
4367                   else
4368                   {
4369                      //classFindTotalTime += GetTime() - startTime;
4370                      return null;
4371                   }
4372                }
4373             }
4374             else
4375             {
4376                //classFindTotalTime += GetTime() - startTime;
4377                return method;
4378             }
4379          }
4380          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4381       }
4382    }
4383    //classFindTotalTime += GetTime() - startTime;
4384    return null;
4385 }
4386
4387 // Construct an instance
4388 static bool ConstructInstance(void * instance, Class _class, Class from)
4389 {
4390    if(_class.templateClass) _class = _class.templateClass;
4391    if(_class.base && from != _class.base)
4392    {
4393       if(!ConstructInstance(instance, _class.base, from))
4394          return false;
4395    }
4396    if(_class.Initialize)
4397    {
4398       void (* Initialize)(Module module) = (void *)_class.Initialize;
4399       _class.Initialize = null;
4400       Initialize(_class.module);
4401    }
4402    if(_class.Constructor)
4403    {
4404       if(!_class.Constructor(instance))
4405       {
4406          for(; _class; _class = _class.base)
4407          {
4408             if(_class.templateClass) _class = _class.templateClass;
4409             if(_class.Destructor)
4410                _class.Destructor(instance);
4411          }
4412          return false;
4413       }
4414    }
4415    (_class.templateClass ? _class.templateClass : _class).count++;
4416    return true;
4417 }
4418
4419 public dllexport void * eInstance_New(Class _class)
4420 {
4421    Instance instance = null;
4422    if(_class)
4423    {
4424       // instance = _malloc(_class.size);
4425 #ifdef MEMINFO
4426
4427 #undef malloc
4428    memMutex.Wait();
4429       //allocateClass = _class;
4430       allocateClass = malloc(strlen(_class.name)+1);
4431       allocateInternal = _class.module == __thisModule;
4432       strcpy(allocateClass, _class.name);
4433 #ifndef MEMINFO
4434 #define malloc _mymalloc
4435 #endif
4436
4437 #endif
4438       {
4439          int size = _class.structSize;
4440          int flags = _class.module.application.isGUIApp;
4441          bool inCompiler = (flags & 8) ? true : false;
4442          bool force32Bits = (flags & 4) ? true : false;
4443          if(force32Bits && inCompiler)
4444          {
4445             // Allocate 64 bit sizes for these when cross-compiling for 32 bit to allow loaded libraries to work properly
4446             if(!strcmp(_class.name, "Module"))
4447                size = 560;
4448             else if(_class.templateClass && !strcmp(_class.templateClass.name, "Map"))
4449                size = 40;
4450             else
4451                size *= 3;
4452          }
4453          instance = _calloc(1, size);
4454       }
4455 #ifdef MEMINFO
4456       allocateClass = null;
4457    memMutex.Release();
4458 #endif
4459       if(_class.type == normalClass)
4460       {
4461          instance._class = _class;
4462          // Copy the virtual table initially
4463          instance._vTbl = _class._vTbl;
4464       }
4465       if(!ConstructInstance(instance, _class, null))
4466       {
4467          _free(instance);
4468          instance = null;
4469       }
4470       /*if(_class.type == normalClass && _class.count > 1000)
4471          printf("%s: %d instances\n", _class.name, _class.count);*/
4472    }
4473    return instance;
4474 }
4475
4476 public dllexport void eInstance_Evolve(Instance * instancePtr, Class _class)
4477 {
4478    if(_class && instancePtr && *instancePtr)
4479    {
4480       bool wasApp = false, wasGuiApp = false;
4481       Instance instance = (Instance)renew *instancePtr byte[_class.structSize];
4482       Class fromClass = instance._class;
4483       *instancePtr = instance;
4484       memset(((byte *)instance) + instance._class.structSize, 0, _class.structSize - instance._class.structSize);
4485       // Fix pointers to application
4486       if((wasApp = !strcmp(instance._class.name, "Application")) ||
4487          (wasGuiApp = !strcmp(instance._class.name, "GuiApplication")))
4488       {
4489          Module module;
4490          Application app = (Application) instance;
4491          BTNamedLink link;
4492          Class _class;
4493          NameSpace * nameSpace;
4494          for(module = app.allModules.first; module; module = module.next)
4495             module.application = app;
4496
4497          for(link = (BTNamedLink)app.privateNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4498          {
4499             OldLink t;
4500             ((Class)link.data).nameSpace = &app.privateNameSpace;
4501             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4502          }
4503          for(link = (BTNamedLink)app.publicNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4504          {
4505             OldLink t;
4506             ((Class)link.data).nameSpace = &app.publicNameSpace;
4507             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4508          }
4509
4510          for(link = (BTNamedLink)app.privateNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4511             ((DefinedExpression)link.data).nameSpace = &app.privateNameSpace;
4512          for(link = (BTNamedLink)app.publicNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4513             ((DefinedExpression)link.data).nameSpace = &app.publicNameSpace;
4514
4515          for(link = (BTNamedLink)app.privateNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4516             ((GlobalFunction)link.data).nameSpace = &app.privateNameSpace;
4517          for(link = (BTNamedLink)app.publicNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4518             ((GlobalFunction)link.data).nameSpace = &app.publicNameSpace;
4519
4520          for(nameSpace = (NameSpace *)app.privateNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4521             nameSpace->parent = &app.privateNameSpace;
4522          for(nameSpace = (NameSpace *)app.publicNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4523             nameSpace->parent = &app.publicNameSpace;
4524
4525          // --------------------------------------------------
4526          for(link = (BTNamedLink)app.systemNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4527          {
4528             OldLink t;
4529             ((Class)link.data).nameSpace = &app.systemNameSpace;
4530             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4531          }
4532          for(link = (BTNamedLink)app.systemNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4533             ((DefinedExpression)link.data).nameSpace = &app.systemNameSpace;
4534          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4535             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4536          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4537             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4538          for(nameSpace = (NameSpace *)app.systemNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4539             nameSpace->parent = &app.systemNameSpace;
4540          // --------------------------------------------------
4541
4542          for(_class = app.classes.first; _class; _class = _class.next)
4543          {
4544             OldLink templateLink;
4545             _class.module = (Module) app;
4546             for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4547             {
4548                Class template = templateLink.data;
4549                template.module = _class.module;
4550             }
4551          }
4552
4553          for(module = app.allModules.first; module; module = module.next)
4554          {
4555             for(_class = module.classes.first; _class; _class = _class.next)
4556             {
4557                OldLink templateLink;
4558                _class.module = module;
4559                for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4560                {
4561                   Class template = templateLink.data;
4562                   template.module = _class.module;
4563                }
4564             }
4565          }
4566
4567          app.application = app;
4568       }
4569
4570       {
4571          Class base;
4572          for(base = instance._class; base && base.type == normalClass && base.count; base = base.base)
4573             (base.templateClass ? base.templateClass : base).count--;
4574       }
4575
4576       instance._class = _class;
4577       // Copy the virtual table initially
4578       instance._vTbl = _class._vTbl;
4579
4580       // We don't want to reconstruct the portion already constructed...
4581       if(!ConstructInstance(instance, _class, fromClass))
4582       {
4583          _free(instance);
4584          *instancePtr = null;
4585       }
4586    }
4587 }
4588
4589 public dllexport void eInstance_Delete(Instance instance)
4590 {
4591 #ifdef MEMINFO
4592    bool checkMemory = false;
4593 #endif
4594    if(instance)
4595    {
4596       Class _class, base;
4597       bool ownVtbl;
4598
4599 #ifdef MEMINFO
4600 #if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__)
4601       if(instance._class == (void *)0xecececececececec)
4602 #else
4603       if(instance._class == (void *)0xecececec)
4604 #endif
4605          _free(instance);
4606 #endif
4607
4608       ownVtbl = instance._vTbl != instance._class._vTbl;
4609
4610       for(_class = instance._class; _class; _class = base)
4611       {
4612          if(_class.templateClass) _class = _class.templateClass;
4613          if(_class.destructionWatchOffset)
4614          {
4615             OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
4616             Watcher watcher, next;
4617
4618             for(watcher = watchers->first; watcher; watcher = next)
4619             {
4620                next = watcher.next;
4621                watchers->Remove(watcher);
4622                watcher.callback(watcher.object, instance);
4623                watchers->Delete(watcher);
4624             }
4625          }
4626
4627          /*// Loop through properties to delete all watchers? Might slow down destruction...
4628          {
4629             Property _property;
4630             for(_property = _class.membersAndProperties.first; _property; _property = _property.next)
4631             {
4632                if(_property.isProperty && _property.isWatchable)
4633                {
4634                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
4635                   Watcher watcher, next;
4636                   for(watcher = watchers->first; watcher; watcher = next)
4637                   {
4638                      next = watcher.next;
4639                      watchers->Delete(watcher);
4640                   }
4641                }
4642             }
4643          }*/
4644
4645
4646          base = _class.base;
4647          if(base && (base.type == systemClass || base.isInstanceClass)) base = null;
4648          if(_class.Destructor)
4649             _class.Destructor(instance);
4650 #ifdef MEMINFO
4651          if(_class == class(Application))
4652             checkMemory = true;
4653 #endif
4654       }
4655
4656       for(_class = instance._class; _class; _class = base)
4657       {
4658          if(_class.templateClass) _class = _class.templateClass;
4659
4660          base = _class.base;
4661          (_class.templateClass ? _class.templateClass : _class).count--;
4662          if(_class.type == normalClass && !_class.count && !_class.module)
4663          {
4664 #ifdef MEMINFO
4665             // printf("Now Destructing class %s\n", _class.name);
4666 #endif
4667             eClass_Unregister(_class);
4668          }
4669       }
4670
4671       if(ownVtbl)
4672       {
4673          delete instance._vTbl;
4674       }
4675       //instance.prop.Free(null);
4676       _free(instance);
4677 #ifdef MEMINFO
4678       if(checkMemory) CheckMemory();
4679 #endif
4680    }
4681 }
4682
4683 public dllexport Property eClass_FindProperty(Class _class, char * name, Module module)
4684 {
4685    //Time startTime = GetTime();
4686    if(_class && name)
4687    {
4688       for(; _class; _class = _class.base)
4689       {
4690          BTNamedLink link;
4691          if(_class.templateClass) _class = _class.templateClass;
4692          link = (BTNamedLink)_class.prop.FindString(name);
4693          if(link)
4694          {
4695             Property _property = (Property)link.data;
4696             if(_property.memberAccess == publicAccess || _class.module == module || !_property.dataTypeString)
4697             {
4698                if(!_property.dataTypeString)
4699                {
4700                   if(_class.module != module)
4701                   {
4702                      if(_property.memberAccess == publicAccess)
4703                         module = _class.module;
4704                      else
4705                      {
4706                         //classFindTotalTime += GetTime() - startTime;
4707                         return null;
4708                      }
4709                   }
4710                }
4711                else
4712                {
4713                   //classFindTotalTime += GetTime() - startTime;
4714                   return _property;
4715                }
4716             }
4717          }
4718          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4719       }
4720    }
4721    //classFindTotalTime += GetTime() - startTime;
4722    return null;
4723 }
4724
4725 static DataMember FindDataMember(OldList list, BinaryTree alist, char * name, uint * offset, int * id, bool searchPrivate, DataMember * subMemberStack, int * subMemberStackPos)
4726 {
4727    BTNamedLink link;
4728    DataMember dataMember;
4729
4730    link = (BTNamedLink)alist.FindString(name);
4731    if(link)
4732    {
4733       dataMember = link.data;
4734       if(dataMember.type == normalMember && (dataMember.memberAccess == publicAccess || searchPrivate || !dataMember.dataTypeString))
4735       {
4736          if(offset)
4737             *offset += dataMember.offset;
4738          if(id) *id = dataMember.id;
4739          return dataMember;
4740       }
4741       return null;
4742    }
4743    for(dataMember = list.first; dataMember; dataMember = dataMember.next)
4744    {
4745       if(!dataMember.isProperty && (dataMember.memberAccess == publicAccess || searchPrivate) && !dataMember.name && (dataMember.type == unionMember || dataMember.type == structMember))
4746       {
4747          DataMember childMember;
4748          if(subMemberStackPos) subMemberStack[(*subMemberStackPos)++] = dataMember;
4749          childMember = FindDataMember(dataMember.members, dataMember.membersAlpha, name, offset, id, searchPrivate, subMemberStack, subMemberStackPos);
4750          if(childMember)
4751          {
4752             if(offset)
4753                *offset += dataMember.offset;
4754             if(id) *id += dataMember.id;
4755             return childMember;
4756          }
4757          if(subMemberStackPos) (*subMemberStackPos)--;
4758       }
4759    }
4760    return null;
4761 }
4762
4763 public dllexport DataMember eClass_FindDataMember(Class _class, char * name, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4764 {
4765    //Time startTime = GetTime();
4766    DataMember dataMember = null;
4767    if(subMemberStackPos) *subMemberStackPos = 0;
4768    if(_class && name)
4769    {
4770       for(; _class; _class = _class.base)
4771       {
4772          if(_class.templateClass) _class = _class.templateClass;
4773          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, null, _class.module == module, subMemberStack, subMemberStackPos);
4774          if(dataMember)
4775          {
4776             if(!dataMember.dataTypeString)
4777             {
4778                if(_class.module != module)
4779                {
4780                   if(dataMember.memberAccess == publicAccess)
4781                      module = _class.module;
4782                   else
4783                   {
4784                      //classFindTotalTime += GetTime() - startTime;
4785                      return null;
4786                   }
4787                }
4788                dataMember = null;
4789             }
4790             else
4791             {
4792                // HACK: Is this good enough? avoiding setting it when adding...
4793                dataMember._class = _class.templateClass ? _class.templateClass : _class;
4794                //classFindTotalTime += GetTime() - startTime;
4795                return dataMember;
4796             }
4797          }
4798          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4799       }
4800    }
4801    //classFindTotalTime += GetTime() - startTime;
4802    return dataMember;
4803 }
4804
4805 public dllexport DataMember eClass_FindDataMemberAndOffset(Class _class, char * name, uint * offset, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4806 {
4807    //Time startTime = GetTime();
4808    DataMember dataMember = null;
4809    if(subMemberStackPos) *subMemberStackPos = 0;
4810    if(offset) *offset = 0;
4811    if(_class)
4812    {
4813       for(; _class; _class = _class.base)
4814       {
4815          if(_class.templateClass) _class = _class.templateClass;
4816          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, offset, null, _class.module == module, subMemberStack, subMemberStackPos);
4817          if(dataMember)
4818          {
4819             if(!dataMember.dataTypeString)
4820             {
4821                if(_class.module != module)
4822                {
4823                   if(dataMember.memberAccess == publicAccess)
4824                      module = _class.module;
4825                   else
4826                   {
4827                      //classFindTotalTime += GetTime() - startTime;
4828                      return null;
4829                   }
4830                }
4831                dataMember = null;
4832             }
4833             else
4834             {
4835                // HACK: Is this good enouh? avoiding setting it when adding...
4836                dataMember._class = _class;
4837                //classFindTotalTime += GetTime() - startTime;
4838                return dataMember;
4839             }
4840          }
4841          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4842       }
4843    }
4844    //classFindTotalTime += GetTime() - startTime;
4845    return dataMember;
4846 }
4847
4848 public dllexport DataMember eClass_FindDataMemberAndId(Class _class, char * name, int * id, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4849 {
4850    //Time startTime = GetTime();
4851    DataMember dataMember = null;
4852    if(subMemberStackPos) *subMemberStackPos = 0;
4853    if(_class)
4854    {
4855       for(; _class; _class = _class.base)
4856       {
4857          if(_class.templateClass) _class = _class.templateClass;
4858          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, id, _class.module == module, subMemberStack, subMemberStackPos);  // TOCHECK: Why was this null? null, null);
4859          if(dataMember)
4860          {
4861             if(!dataMember.dataTypeString)
4862             {
4863                if(_class.module != module)
4864                {
4865                   if(dataMember.memberAccess == publicAccess)
4866                      module = _class.module;
4867                   else
4868                   {
4869                      //classFindTotalTime += GetTime() - startTime;
4870                      return null;
4871                   }
4872                }
4873                dataMember = null;
4874             }
4875             else
4876             {
4877                // HACK: Is this good enouh? avoiding setting it when adding...
4878                dataMember._class = _class;
4879                //classFindTotalTime += GetTime() - startTime;
4880                return dataMember;
4881             }
4882          }
4883          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4884       }
4885    }
4886    //classFindTotalTime += GetTime() - startTime;
4887    return dataMember;
4888 }
4889
4890 public dllexport void eClass_FindNextMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
4891 {
4892    // THIS CODE WILL FIND NEXT MEMBER... (PUBLIC MEMBERS ONLY)
4893    if(*curMember)
4894    {
4895       *curMember = (*curMember).next;
4896
4897       if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
4898       {
4899          *curMember = subMemberStack[--(*subMemberStackPos)];
4900          *curMember = (*curMember).next;
4901       }
4902
4903       if(subMemberStackPos && *subMemberStackPos > 0)
4904       {
4905          while(*curMember && ((*curMember).memberAccess == privateAccess))
4906             *curMember = (*curMember).next;
4907       }
4908       else
4909          while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
4910          {
4911             DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
4912             if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
4913             if(dataMember && dataMember.memberAccess != privateAccess)
4914             {
4915                *curMember = dataMember;
4916                break;
4917             }
4918             else
4919                *curMember = (*curMember).next;
4920          }
4921
4922       if(subMemberStackPos)
4923       {
4924          while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
4925          {
4926             subMemberStack[(*subMemberStackPos)++] = *curMember;
4927
4928             *curMember = (*curMember).members.first;
4929             while(*curMember && ((*curMember).memberAccess == privateAccess))
4930                *curMember = (*curMember).next;
4931          }
4932       }
4933    }
4934    while(!*curMember)
4935    {
4936       if(!*curMember)
4937       {
4938          if(subMemberStackPos && *subMemberStackPos)
4939          {
4940             *curMember = subMemberStack[--(*subMemberStackPos)];
4941             *curMember = (*curMember).next;
4942          }
4943          else
4944          {
4945             Class lastCurClass = *curClass;
4946
4947             if(*curClass == _class) break;     // REACHED THE END
4948
4949             for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass && (*curClass).inheritanceAccess != privateAccess; *curClass = (*curClass).base);
4950             *curMember = (*curClass).membersAndProperties.first;
4951          }
4952
4953          if(subMemberStackPos && *subMemberStackPos > 0)
4954          {
4955             while(*curMember && ((*curMember).memberAccess == privateAccess))
4956                *curMember = (*curMember).next;
4957          }
4958          else
4959             while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
4960             {
4961                DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
4962                if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
4963                if(dataMember && dataMember.memberAccess != privateAccess && dataMember.id >= 0) // Skip _vTbl, _refCount and _class in Instance
4964                {
4965                   *curMember = dataMember;
4966                   break;
4967                }
4968                else
4969                   *curMember = (*curMember).next;
4970             }
4971
4972          if(subMemberStackPos)
4973          {
4974             while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
4975             {
4976                subMemberStack[(*subMemberStackPos)++] = *curMember;
4977
4978                *curMember = (*curMember).members.first;
4979                while(*curMember && (*curMember).memberAccess == privateAccess)
4980                   *curMember = (*curMember).next;
4981             }
4982          }
4983       }
4984    }
4985 }
4986
4987 public dllexport void eInstance_SetMethod(Instance instance, char * name, void * function)     // YET TO BE DECIDED:   , Module module)
4988 {
4989    if(instance && name)
4990    {
4991       Class _class;
4992       for(_class = instance._class; _class; _class = _class.base)
4993       {
4994          Method method = (Method)_class.methods.FindString(name);
4995          if(method && method.type == virtualMethod)
4996          {
4997             if(instance._vTbl == instance._class._vTbl)
4998             {
4999                instance._vTbl = _malloc(sizeof(void *) * instance._class.vTblSize);
5000                memcpy(instance._vTbl, instance._class._vTbl,
5001                   sizeof(int(*)()) * instance._class.vTblSize);
5002             }
5003             instance._vTbl[method.vid] = function ? function : DefaultFunction;
5004          }
5005       }
5006    }
5007 }
5008
5009 public dllexport bool eInstance_IsDerived(Instance instance, Class from)
5010 {
5011    if(instance)
5012    {
5013       Class _class = instance._class;
5014       for(; _class; _class = _class.base)
5015       {
5016          if(_class == from)
5017             return true;
5018       }
5019    }
5020    return false;
5021 }
5022
5023 public dllexport void eInstance_IncRef(Instance instance)
5024 {
5025    if(instance)
5026       instance._refCount++;
5027 }
5028
5029 public dllexport void eInstance_DecRef(Instance instance)
5030 {
5031    if(instance)
5032    {
5033       instance._refCount--;
5034       //if(!instance._refCount)
5035       if(instance._refCount <= 0)
5036       {
5037          eInstance_Delete(instance);
5038       }
5039    }
5040 }
5041
5042 static void FixOffsets(Class _class)
5043 {
5044    OldLink deriv;
5045    _class.structSize += _class.base.structSize - _class.offset;
5046
5047    _class.offset = _class.base.structSize;
5048
5049    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
5050       FixOffsets(deriv.data);
5051 }
5052
5053 public dllexport void eClass_Resize(Class _class, int newSize)
5054 {
5055    OldLink deriv;
5056    _class.structSize = newSize;
5057    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
5058       FixOffsets(deriv.data);
5059 }
5060
5061 public dllexport DataMember eClass_AddDataMember(Class _class, char * name, char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
5062 {
5063    if(_class && name)
5064    {
5065       if(!_class.members.FindString(name))
5066       {
5067          DataMember dataMember;
5068
5069          if(alignment)
5070          {
5071             _class.structAlignment = Max(_class.structAlignment, alignment);
5072
5073             if(_class.memberOffset % alignment)
5074                _class.memberOffset += alignment - (_class.memberOffset % alignment);
5075          }
5076
5077          dataMember = DataMember {
5078             name = CopyString(name);
5079             dataTypeString = CopyString(type);
5080             id = _class.memberID++;
5081             _class = _class;
5082             offset = _class.memberOffset;
5083             memberOffset = size;
5084             memberAccess = declMode;
5085             membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5086          };
5087          _class.membersAndProperties.Add(dataMember);
5088          _class.memberOffset += size;
5089
5090          _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5091          return dataMember;
5092       }
5093    }
5094    return null;
5095 }
5096
5097 public dllexport DataMember eMember_AddDataMember(DataMember member, char * name, char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
5098 {
5099    if(name && !member.membersAlpha.FindString(name))
5100    {
5101       DataMember dataMember;
5102
5103       if(alignment)
5104       {
5105          member.structAlignment = Max(member.structAlignment, alignment);
5106
5107          if(member.memberOffset % alignment)
5108             member.memberOffset += alignment - (member.memberOffset % alignment);
5109       }
5110       dataMember = DataMember {
5111          name = CopyString(name);
5112          _class = member._class;
5113          dataTypeString = CopyString(type);
5114          id = member.memberID++;
5115          offset = (member.type == unionMember) ? 0 : member.memberOffset;
5116          memberAccess = declMode;
5117          membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5118       };
5119       member.members.Add(dataMember);
5120       if(member.type == unionMember)
5121       {
5122          if(size > member.memberOffset)
5123             member.memberOffset = size;
5124       }
5125       else
5126          member.memberOffset += size;
5127       member.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5128       return dataMember;
5129    }
5130    return null;
5131 }
5132
5133 public dllexport DataMember eMember_New(DataMemberType type, AccessMode declMode)
5134 {
5135    return DataMember { type = type, memberAccess = declMode, membersAlpha.CompareKey = (void *)BinaryTree::CompareString };
5136 }
5137
5138 static void SetMemberClass(DataMember member, Class _class)
5139 {
5140    DataMember dataMember;
5141    member._class = _class;
5142    for(dataMember = member.members.first; dataMember; dataMember = dataMember.next)
5143       SetMemberClass(dataMember, _class);
5144 }
5145
5146 public dllexport bool eMember_AddMember(DataMember addTo, DataMember dataMember)
5147 {
5148    if(dataMember.name && addTo.membersAlpha.FindString(dataMember.name))
5149    {
5150       DataMember_Free(dataMember);
5151       delete dataMember;
5152       return false;
5153    }
5154    addTo.members.Add(dataMember);
5155
5156    if(dataMember.name)
5157       addTo.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5158
5159    dataMember._class = addTo._class;
5160    // ? SetMemberClass(dataMember, addTo._class);
5161
5162    //dataMember.id = addTo.memberID++;
5163    dataMember.id = addTo.memberID;
5164    if(dataMember.type == unionMember)
5165       addTo.memberID += 1;
5166    else
5167       addTo.memberID += dataMember.memberID;
5168
5169    addTo.structAlignment = Max(addTo.structAlignment, dataMember.structAlignment);
5170    dataMember.offset = (addTo.type == unionMember) ? 0 : addTo.memberOffset;
5171
5172    if(dataMember.structAlignment)
5173    {
5174       addTo.structAlignment = Max(addTo.structAlignment, dataMember.structAlignment);
5175
5176       if(addTo.memberOffset % dataMember.structAlignment)
5177          addTo.memberOffset += dataMember.structAlignment - (addTo.memberOffset % dataMember.structAlignment);
5178    }
5179
5180    if(addTo.type == unionMember)
5181    {
5182       if(dataMember.memberOffset > addTo.memberOffset)
5183          addTo.memberOffset = dataMember.memberOffset;
5184    }
5185    else
5186       addTo.memberOffset += dataMember.memberOffset;
5187    return true;
5188 }
5189
5190 public dllexport bool eClass_AddMember(Class _class, DataMember dataMember)
5191 {
5192    if(!_class || _class.comRedefinition || (dataMember.name && _class.members.FindString(dataMember.name)))
5193    {
5194       DataMember_Free(dataMember);
5195       delete dataMember;
5196       return false;
5197    }
5198    _class.membersAndProperties.Add(dataMember);
5199
5200    if(dataMember.name)
5201       _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5202
5203    //dataMember._class = _class;
5204    SetMemberClass(dataMember, _class);
5205
5206    //dataMember.id = _class.memberID++;
5207    dataMember.id = _class.memberID;
5208
5209    _class.structAlignment = Max(_class.structAlignment, dataMember.structAlignment);
5210    if(dataMember.type == unionMember)
5211       _class.memberID += 1;
5212    else
5213       _class.memberID += dataMember.memberID;
5214
5215    if(dataMember.structAlignment)
5216    {
5217       _class.structAlignment = Max(_class.structAlignment, dataMember.structAlignment);
5218
5219       if(_class.memberOffset % dataMember.structAlignment)
5220          _class.memberOffset += dataMember.structAlignment - (_class.memberOffset % dataMember.structAlignment);
5221    }
5222
5223    dataMember.offset = _class.memberOffset;
5224    _class.memberOffset += dataMember.memberOffset;
5225    return true;
5226 }
5227
5228 public dllexport BitMember eClass_AddBitMember(Class _class, char * name, char * type, int bitSize, int bitPos, AccessMode declMode)
5229 {
5230    if(_class && name && !_class.members.FindString(name))
5231    {
5232       uint64 mask = 0;
5233       int c;
5234       BitMember bitMember
5235       {
5236          name = CopyString(name);
5237          _class = _class;
5238          dataTypeString = CopyString(type);
5239          id = _class.memberID++;
5240          memberAccess = declMode;
5241       };
5242       _class.membersAndProperties.Add(bitMember);
5243       if(bitSize)
5244       {
5245          bitMember.pos = (bitPos == -1) ? _class.memberOffset : bitPos;
5246          bitMember.size = bitSize;
5247          _class.memberOffset = bitMember.pos + bitMember.size;
5248          for(c = 0; c<bitSize; c++)
5249          {
5250             if(c)
5251                mask <<= 1;
5252             mask |= 1;
5253          }
5254          bitMember.mask = mask << bitMember.pos;
5255       }
5256
5257      _class.members.Add((BTNode)BTNamedLink { name = bitMember.name, data = bitMember });
5258       return bitMember;
5259    }
5260    return null;
5261 }
5262
5263 static Module Module_Load(Module fromModule, char * name, AccessMode importAccess, bool ensureCOM)
5264 {
5265    bool (stdcall * Load)(Module module) = null;
5266    bool (stdcall * Unload)(Module module) = null;
5267    Module module;
5268
5269    for(module = fromModule.application.allModules.first; module; module = module.next)
5270    {
5271       if(!strcmp(module.name, name))
5272          break;
5273    }
5274    if(ensureCOM && (!strcmp(name, "ecereCOM") || !strcmp(name, "ecere")))
5275    {
5276       for(module = fromModule.application.allModules.first; module; module = module.next)
5277       {
5278          if(!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM"))
5279             break;
5280       }
5281    }
5282    if(!module)
5283    {
5284       void * library = null;
5285
5286       if(ensureCOM && !strcmp(name, "ecereCOM"))
5287       {
5288          Load = COM_LOAD_FUNCTION;
5289          Unload = COM_UNLOAD_FUNCTION;
5290       }
5291       else
5292       {
5293          char * libLocation = null;
5294 #if defined(__ANDROID__)
5295          libLocation = AndroidInterface_GetLibLocation();
5296 #endif
5297          library = Instance_Module_Load(libLocation, name, &Load, &Unload);
5298       }
5299       if(Load)
5300       {
5301          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5302          module.application = fromModule.application;
5303          module.library = library;
5304          {
5305             char moduleName[MAX_FILENAME];
5306             char ext[MAX_EXTENSION];
5307             GetLastDirectory(name, moduleName);
5308             GetExtension(moduleName, ext);
5309             StripExtension(moduleName);
5310             if((!strcmpi(ext, "dylib") || !strcmpi(ext, "so")) && strstr(moduleName, "lib") == moduleName)
5311             {
5312                int len = (int)strlen(moduleName) - 3;
5313                memmove(moduleName, moduleName + 3, len);
5314                moduleName[len] = 0;
5315             }
5316             module.name = CopyString(moduleName);
5317          }
5318          module.Unload = Unload;
5319          module.origImportType = normalImport;
5320
5321          if(!Load(module))
5322          {
5323             eInstance_Delete((Instance)module);
5324             module = null;
5325          }
5326       }
5327       fromModule.application.allModules.Add(module);
5328    }
5329    if(ensureCOM && !strcmp(name, "ecere") && module)
5330    {
5331       name = !strcmp(module.name, "ecereCOM") ? "ecere" : "ecereCOM";
5332       if((!Load && !strcmp(module.name, "ecereCOM")) ||
5333          (Load && (!__thisModule || !__thisModule.name || !strcmp(__thisModule.name, "ecereCOM")) && Load != COM_LOAD_FUNCTION))
5334       {
5335          Module module;
5336          for(module = fromModule.application.allModules.first; module; module = module.next)
5337          {
5338             if(!strcmp(module.name, name))
5339                break;
5340          }
5341          if(!module)
5342          {
5343             Load = COM_LOAD_FUNCTION;
5344             Unload = COM_UNLOAD_FUNCTION;
5345
5346             module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5347             module.application = fromModule.application;
5348             module.library = null;
5349             module.name = CopyString(name);
5350             module.Unload = Unload;
5351
5352             if(!Load(module))
5353             {
5354                eInstance_Delete((Instance)module);
5355                module = null;
5356             }
5357
5358             fromModule.application.allModules.Add(module);
5359          }
5360          if(module)
5361          {
5362             if(fromModule)
5363             {
5364                fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5365             }
5366             incref module;
5367          }
5368       }
5369    }
5370    if(module)
5371    {
5372       if(fromModule)
5373       {
5374          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5375       }
5376       incref module;
5377    }
5378 #if defined(_DEBUG)
5379    InternalModuleLoadBreakpoint();
5380 #endif
5381    return module;
5382 }
5383
5384 public dllexport Module eModule_Load(Module fromModule, char * name, AccessMode importAccess)
5385 {
5386    return Module_Load(fromModule, name, importAccess, true);
5387 }
5388
5389 public dllexport Module eModule_LoadStrict(Module fromModule, char * name, AccessMode importAccess)
5390 {
5391    return Module_Load(fromModule, name, importAccess, false);
5392 }
5393
5394 public dllexport Module eModule_LoadStatic(Module fromModule, char * name, AccessMode importAccess, bool (* Load)(Module module), bool (* Unload)(Module module))
5395 {
5396    Module module;
5397    for(module = fromModule.application.allModules.first; module; module = module.next)
5398    {
5399       if(!strcmp(module.name, name))
5400          break;
5401    }
5402    if(!module)
5403    {
5404       if(Load)
5405       {
5406          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5407          module.application = fromModule.application;
5408          module.name = CopyString(name);
5409          module.origImportType = staticImport;
5410          module.Unload = (void *)Unload;
5411          if(!Load(module))
5412          {
5413             eInstance_Delete((Instance)module);
5414             module = null;
5415          }
5416       }
5417       fromModule.application.allModules.Add(module);
5418    }
5419    if(module)
5420    {
5421       if(fromModule)
5422       {
5423          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5424       }
5425       incref module;
5426    }
5427    return module;
5428 }
5429
5430 public dllexport void eModule_Unload(Module fromModule, Module module)
5431 {
5432    OldLink m;
5433    for(m = fromModule.modules.first; m; m = m.next)
5434    {
5435       if(m.data == module)
5436          break;
5437    }
5438    if(m)
5439    {
5440       fromModule.modules.Delete(m);
5441       delete module;
5442    }
5443 }
5444
5445 public dllexport void eEnum_AddFixedValue(Class _class, char * string, int value)
5446 {
5447    if(_class && _class.type == enumClass)
5448    {
5449       EnumClassData data = (EnumClassData)_class.data;
5450       NamedLink item;
5451
5452       for(item = data.values.first; item; item = item.next)
5453          if(!strcmp(item.name, string))
5454             break;
5455       if(!item)
5456       {
5457          data.values.Add(NamedLink { data = (void *)value, name = CopyString(string) });
5458          if(value > data.largest)
5459             data.largest = value;
5460       }
5461    }
5462 }
5463
5464 public dllexport int eEnum_AddValue(Class _class, char * string)
5465 {
5466    if(_class && _class.type == enumClass)
5467    {
5468       EnumClassData data = (EnumClassData)_class.data;
5469       int value = ((int) data.largest) + 1;
5470       NamedLink item;
5471       for(item = data.values.first; item; item = item.next)
5472          if(!strcmp(item.name, string))
5473             break;
5474       if(!item)
5475       {
5476          data.values.Add(NamedLink { data = (void *)value, name = CopyString(string) });
5477          if(value > data.largest)
5478             data.largest = value;
5479          return value;
5480       }
5481    }
5482    return -1;
5483 }
5484
5485 static void NameSpace_Free(NameSpace parentNameSpace)
5486 {
5487    NameSpace * nameSpace;
5488    delete parentNameSpace.name;
5489
5490    while((nameSpace = (NameSpace *)parentNameSpace.nameSpaces.first))
5491    {
5492       NameSpace_Free(nameSpace);
5493       parentNameSpace.nameSpaces.Delete((BTNode)nameSpace);
5494    }
5495 }
5496
5497 static void Application_Destructor(Application app)
5498 {
5499    if(app.parsedCommand)
5500    {
5501       delete app.argv;
5502       delete app.parsedCommand;
5503    }
5504 }
5505
5506 static bool Module_Constructor(Module module)
5507 {
5508    module.privateNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5509    module.privateNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5510    module.privateNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5511    module.privateNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5512
5513    module.publicNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5514    module.publicNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5515    module.publicNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5516    module.publicNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5517    return true;
5518 }
5519
5520 static void Module_Destructor(Module module)
5521 {
5522    Class _class;
5523    DefinedExpression def;
5524    GlobalFunction function;
5525    Module m;
5526    SubModule handle;
5527
5528    // printf("Destructing module %s\n", module.name);
5529
5530    // Take out references from all modules
5531    for(m = module.application.allModules.first; m; m = m.next)
5532    {
5533       SubModule next;
5534       for(handle = m.modules.first; handle; handle = next)
5535       {
5536          next = handle.next;
5537          if(handle.module == module)
5538             m.modules.Delete(handle);
5539       }
5540    }
5541
5542    if(module.Unload)
5543    {
5544       if(module.origImportType == staticImport)
5545       {
5546          bool (* Unload)(Module module) = (void *)module.Unload;
5547          Unload(module);
5548       }
5549       else
5550       {
5551          bool (stdcall * Unload)(Module module) = (void *)module.Unload;
5552          Unload(module);
5553       }
5554    }
5555
5556    // Unload dependencies
5557    {
5558       Module ourWorld = class(Class).module;
5559       void * ourHandle = null;
5560       while((handle = module.modules.last))  // STARTING WITH LAST SO THAT ecereCOM IS UNLOADED LAST...
5561       {
5562          Module depModule = handle.module;
5563          if(depModule == ourWorld)
5564          {
5565             module.modules.Remove(handle);
5566             ourHandle = handle;
5567          }
5568          else
5569          {
5570             module.modules.Delete(handle);
5571             delete depModule;
5572          }
5573       }
5574       if(ourHandle)
5575       {
5576          delete ourHandle;
5577          delete ourWorld;
5578       }
5579    }
5580
5581    // Unload classes
5582    for(;(_class = module.classes.first);)
5583    {
5584       if(_class.nameSpace)
5585       {
5586          BTNamedLink classLink = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
5587          OldLink t;
5588          for(t = _class.templatized.first; t; t = t.next)
5589          {
5590             Class template = t.data;
5591             BTNamedLink link;
5592             link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
5593
5594             template.nameSpace->classes.Delete((BTNode)link);
5595             template.nameSpace = null;
5596          }
5597          _class.nameSpace->classes.Delete((BTNode)classLink);
5598          _class.nameSpace = null;
5599       }
5600       _class.module = null;
5601       module.classes.Remove(_class);
5602       if(_class.count <= 0 || _class.type != normalClass || _class.isInstanceClass)
5603          eClass_Unregister(_class);
5604       else
5605       {
5606 #ifdef MEMINFO
5607          // printf("Delayed destruction of class %s\n", _class.name);
5608 #endif
5609       }
5610    }
5611
5612    // Unload defines
5613    for(;(def = module.defines.first);)
5614    {
5615       if(def.nameSpace)
5616       {
5617          BTNamedLink defLink;
5618          for(defLink = (BTNamedLink)def.nameSpace->defines.first; defLink; defLink = (BTNamedLink)((BTNode)defLink).next)
5619             if(defLink.data == def)
5620             {
5621                def.nameSpace->defines.Delete((BTNode)defLink);
5622                break;
5623             }
5624       }
5625       delete def.name;
5626       delete def.value;
5627       module.defines.Delete(def);
5628    }
5629
5630    // Unload functions
5631    for(;(function = module.functions.first);)
5632    {
5633       if(function.nameSpace)
5634       {
5635          BTNamedLink functionLink;
5636          for(functionLink = (BTNamedLink)function.nameSpace->functions.first; functionLink; functionLink = (BTNamedLink)((BTNode)functionLink).next)
5637             if(functionLink.data == function)
5638             {
5639                function.nameSpace->functions.Delete((BTNode)functionLink);
5640                break;
5641             }
5642       }
5643       delete function.name;
5644       delete function.dataTypeString;
5645       module.functions.Delete(function);
5646    }
5647
5648    delete module.name;
5649
5650    NameSpace_Free(module.privateNameSpace);
5651    NameSpace_Free(module.publicNameSpace);
5652
5653    if(module != module.application)
5654       module.application.allModules.Remove(module);
5655    else
5656       NameSpace_Free(module.application.systemNameSpace);
5657
5658 #ifndef MEMINFO
5659    Instance_Module_Free(module.library);
5660 #endif
5661 }
5662
5663 static int64 GetEnumSize(Class _class)
5664 {
5665    EnumClassData data = (EnumClassData)_class.data;
5666    return data.largest+1;
5667 }
5668
5669 #if defined(__GNUC__)
5670 #define strcmpi strcasecmp
5671 #define strnicmp strncasecmp
5672 #endif
5673
5674 #if defined(ECERE_BOOTSTRAP) || (defined(__GNUC__) && !defined(__DJGPP__) && !defined(__WIN32__))
5675 #undef strlwr
5676 #undef strupr
5677 default dllexport char * strlwr(char *string)
5678 {
5679    int c;
5680    for(c=0; string[c]; c++)
5681       if(string[c]>='A' && string[c]<='Z')
5682          string[c]+='a'-'A';
5683    return string;
5684 }
5685 default dllexport char * strupr(char *string)
5686 {
5687    int c;
5688    for(c=0; string[c]; c++)
5689       if(string[c]>='a' && string[c]<='z')
5690          string[c]-='a'-'A';
5691    return string;
5692 }
5693 #endif
5694
5695 public dllexport DefinedExpression eSystem_RegisterDefine(char * name, char * value, Module module, AccessMode declMode)
5696 {
5697    NameSpace * nameSpace = null;
5698
5699    int start = 0, c;
5700
5701    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5702    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5703
5704    if(declMode != staticAccess)
5705    {
5706       for(c = 0; name[c]; c++)
5707       {
5708          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5709          {
5710             NameSpace * newSpace;
5711
5712             char * spaceName = _malloc(c - start + 1);
5713             strncpy(spaceName, name + start, c - start);
5714             spaceName[c-start] = '\0';
5715
5716             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5717             if(!newSpace)
5718             {
5719                newSpace = new0 NameSpace[1];
5720                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5721                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5722                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5723                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5724                newSpace->name = spaceName;
5725                newSpace->parent = nameSpace;
5726                nameSpace->nameSpaces.Add((BTNode)newSpace);
5727             }
5728             else
5729                delete spaceName;
5730             nameSpace = newSpace;
5731             if(name[c] == ':') c++;
5732             start = c+1;
5733          }
5734       }
5735    }
5736    else
5737       c = (int)strlen(name);
5738
5739    if(c - start && !nameSpace->defines.FindString(name + start))
5740    {
5741       DefinedExpression def
5742       {
5743          name = CopyString(name);
5744          nameSpace = nameSpace;
5745          value = CopyString(value);
5746       };
5747       nameSpace->defines.Add((BTNode)BTNamedLink { name = def.name + start, data = def });
5748       // Reference the definition in the module
5749       module.defines.Add(def);
5750       return def;
5751    }
5752    return null;
5753 }
5754
5755 public dllexport GlobalFunction eSystem_RegisterFunction(char * name, char * type, void * func, Module module, AccessMode declMode)
5756 {
5757    NameSpace * nameSpace = null;
5758    int start = 0, c;
5759
5760    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5761    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5762
5763    if(declMode != staticAccess)
5764    {
5765       for(c = 0; name[c]; c++)
5766       {
5767          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5768          {
5769             NameSpace * newSpace;
5770
5771             char * spaceName = _malloc(c - start + 1);
5772             strncpy(spaceName, name + start, c - start);
5773             spaceName[c-start] = '\0';
5774
5775             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5776             if(!newSpace)
5777             {
5778                newSpace = new0 NameSpace[1];
5779                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5780                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5781                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5782                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5783                newSpace->name = spaceName;
5784                newSpace->parent = nameSpace;
5785                nameSpace->nameSpaces.Add((BTNode)newSpace);
5786             }
5787             else
5788                delete spaceName;
5789             nameSpace = newSpace;
5790             if(name[c] == ':') c++;
5791             start = c+1;
5792          }
5793       }
5794    }
5795    else
5796       c = (int)strlen(name);
5797
5798    if(c - start && !nameSpace->functions.FindString(name + start))
5799    {
5800       GlobalFunction function
5801       {
5802          name = CopyString(name);
5803          nameSpace = nameSpace;
5804          dataTypeString = CopyString(type);
5805          function = func;
5806          module = module;
5807       };
5808       nameSpace->functions.Add((BTNode)BTNamedLink { name = function.name + start, data = function });
5809       // Reference the definition in the module
5810       module.functions.Add(function);
5811       return function;
5812    }
5813    return null;
5814 }
5815
5816 public dllexport DefinedExpression eSystem_FindDefine(Module module, char * name)
5817 {
5818    if(name && module)
5819    {
5820       BTNamedLink link;
5821       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->defines);
5822       if(link) return link.data;
5823
5824       link = SearchModule(module, name, &((NameSpace *)0)->defines, true);
5825       if(link) return link.data;
5826    }
5827    return null;
5828 }
5829
5830 public dllexport GlobalFunction eSystem_FindFunction(Module module, char * name)
5831 {
5832    if(name && module)
5833    {
5834       BTNamedLink link;
5835       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->functions);
5836       if(link) return link.data;
5837
5838       link = SearchModule(module, name, &((NameSpace *)0)->functions, true);
5839       if(link) return link.data;
5840    }
5841    return null;
5842 }
5843
5844 public dllexport void * eSystem_Renew(void * memory, unsigned int size)
5845 {
5846    return _realloc(memory, size);
5847 }
5848
5849 public dllexport void * eSystem_Renew0(void * memory, unsigned int size)
5850 {
5851    return _crealloc(memory, size);
5852 }
5853
5854 public dllexport void * eSystem_New(unsigned int size)
5855 {
5856 /*#ifdef _DEBUG
5857    void * pointer = _malloc(size);
5858    memset(pointer, 0xec, size);
5859    return pointer;
5860 #else*/
5861    return _malloc(size);
5862 //#endif
5863 }
5864
5865 public dllexport void * eSystem_New0(unsigned int size)
5866 {
5867    return _calloc(1,size);
5868 }
5869
5870 public dllexport void eSystem_Delete(void * memory)
5871 {
5872    if(memory)
5873       _free(memory);
5874 }
5875
5876 // Properties
5877 public dllexport void eInstance_FireSelfWatchers(Instance instance, Property _property)
5878 {
5879    if(instance && _property && _property.selfWatchable)
5880    {
5881       Class _class;
5882       for(_class = instance._class; _class; _class = _class.base)
5883       {
5884          SelfWatcher selfWatcher, next;
5885          for(selfWatcher = _class.selfWatchers.first; selfWatcher; selfWatcher = next)
5886          {
5887             next = selfWatcher.next;
5888             if(selfWatcher._property == _property)
5889                selfWatcher.callback(instance);
5890          }
5891       }
5892    }
5893 }
5894
5895 public dllexport void eInstance_FireWatchers(Instance instance, Property _property)
5896 {
5897    if(instance && _property && _property.isWatchable)
5898    {
5899       Module module = instance._class ? instance._class.module : null;
5900       Application application = module ? module.application : null;
5901       int flags = application ? application.isGUIApp : 0;
5902       bool inCompiler = (flags & 8) ? true : false;
5903       bool force32Bits = (flags & 4) ? true : false;
5904       if(!force32Bits || !inCompiler)
5905       {
5906          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5907          Watcher watcher, next;
5908
5909          for(watcher = watchers->first; watcher; watcher = next)
5910          {
5911             next = watcher.next;
5912             watcher.callback(watcher.object, instance);
5913          }
5914       }
5915    }
5916 }
5917
5918 public dllexport void eProperty_Watchable(Property _property)
5919 {
5920    if(!_property.isWatchable)
5921    {
5922       Class _class = _property._class;
5923       if(!_class.computeSize)
5924       {
5925          _property.watcherOffset = _class.structSize;
5926          _class.structSize += sizeof(OldList);
5927
5928          // highly inefficient
5929          FixDerivativesBase(_class, _class);
5930       }
5931       _property.isWatchable = true;
5932    }
5933 }
5934
5935 public dllexport void eClass_DestructionWatchable(Class _class)
5936 {
5937    if(!_class.destructionWatchOffset)
5938    {
5939       _class.destructionWatchOffset = _class.structSize;
5940       _class.structSize += sizeof(OldList);
5941       // highly inefficient
5942       FixDerivativesBase(_class, _class);
5943    }
5944 }
5945
5946 public dllexport void eProperty_SelfWatch(Class _class, char * name, void (*callback)(void *))
5947 {
5948    if(_class)
5949    {
5950       Property _property = eClass_FindProperty(_class, name, _class.module);
5951
5952       if(!_property)
5953          _property = eClass_AddProperty(_class, name, null, null, null, baseSystemAccess /*privateAccess*/);
5954       _class.selfWatchers.Add(SelfWatcher { _property = _property, callback = callback });
5955       _property.selfWatchable = true;
5956    }
5957 }
5958
5959 public dllexport void eInstance_Watch(void * instance, Property _property, void * object, void (*callback)(void *, void *))
5960 {
5961    if(_property.isWatchable)
5962    {
5963       OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5964       watchers->Add(Watcher { callback = callback, object = object });
5965    }
5966 }
5967
5968 public dllexport void eInstance_WatchDestruction(Instance instance, Instance object, void (*callback)(Instance, Instance))
5969 {
5970    OldList * watchers = (OldList *)((byte *)instance + instance._class.destructionWatchOffset);
5971    watchers->Add(Watcher { callback = callback, object = object });
5972 }
5973
5974 public dllexport void eInstance_StopWatching(Instance instance, Property _property, Instance object)
5975 {
5976    if(instance && (!_property || _property.isWatchable))
5977    {
5978       if(_property)
5979       {
5980          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5981          Watcher watcher;
5982          for(watcher = watchers->first; watcher; watcher = watcher.next)
5983             if(watcher.object == object)
5984             {
5985                watchers->Delete(watcher);
5986                break;
5987             }
5988       }
5989       else
5990       {
5991          // Stop watching all properties as well as destruction
5992          Class _class, base;
5993          for(_class = instance._class; _class; _class = base)
5994          {
5995             if(_class.destructionWatchOffset)
5996             {
5997                OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
5998                Watcher watcher;
5999
6000                for(watcher = watchers->first; watcher; watcher = watcher.next)
6001                {
6002                   watchers->Delete(watcher);
6003                   break;
6004                }
6005             }
6006             for(_property = (Property)_class.membersAndProperties.first; _property; _property = _property.next)
6007             {
6008                if(_property.isProperty && _property.isWatchable)
6009                {
6010                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6011                   Watcher watcher;
6012                   for(watcher = watchers->first; watcher; watcher = watcher.next)
6013                      if(watcher.object == object)
6014                      {
6015                         watchers->Delete(watcher);
6016                         break;
6017                      }
6018                }
6019             }
6020             base = _class.base;
6021             if(base && (base.type == systemClass || base.isInstanceClass)) base = null;
6022          }
6023       }
6024    }
6025 }
6026
6027 public dllexport subclass(ClassDesignerBase) eClass_GetDesigner(Class _class)
6028 {
6029    for(;_class;_class = _class.base)
6030    {
6031       if(_class.designerClass)
6032          return (subclass(ClassDesignerBase))eSystem_FindClass(_class.module, _class.designerClass);
6033    }
6034    return null;
6035 }
6036
6037
6038 public dllexport subclass(ClassDesignerBase) eInstance_GetDesigner(Instance instance)
6039 {
6040    if(instance)
6041       return eClass_GetDesigner(instance._class);
6042    return null;
6043 }
6044
6045 public bool LocateModule(char * name, char * fileName)
6046 {
6047    return Instance_LocateModule(name, fileName);
6048 }
6049
6050 static void LoadCOM(Module module)
6051 {
6052    bool force64Bits = (module.application.isGUIApp & 2) ? true : false;
6053    bool force32Bits = (module.application.isGUIApp & 4) ? true : false;
6054    bool inCompiler = (module.application.isGUIApp & 8) ? true : false;
6055    int pointerSize = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
6056    Class applicationClass;
6057    Class enumClass, structClass, boolClass;
6058    Class moduleClass;
6059
6060    // Create Base Class
6061    Class baseClass = eSystem_RegisterClass(normalClass, "class", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6062    baseClass.type = systemClass;
6063    baseClass.memberOffset = 0;
6064    baseClass.offset = 0;
6065    baseClass.structSize = 0;
6066    baseClass.typeSize = 0;
6067
6068    {
6069       Class instanceClass = eSystem_RegisterClass(normalClass, "ecere::com::Instance", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6070       instanceClass.type = normalClass;
6071       instanceClass.isInstanceClass = true;
6072       instanceClass.fixed = true;
6073       instanceClass.memberOffset = 0;
6074       instanceClass.offset = 0;
6075
6076       instanceClass.memberID = -3;
6077       instanceClass.startMemberID = -3;
6078
6079       eClass_AddDataMember(instanceClass, "_vTbl", "int (**)()", pointerSize, pointerSize, publicAccess);
6080       eClass_AddDataMember(instanceClass, "_class", "ecere::com::Class", pointerSize, pointerSize, publicAccess);
6081       eClass_AddDataMember(instanceClass, "_refCount", "int", sizeof(int), sizeof(int), publicAccess);
6082    }
6083
6084    InitializeDataTypes1(module);
6085
6086    // Create Enum class
6087    enumClass = eSystem_RegisterClass(normalClass, "enum", null, 0, force64Bits ? 40 : sizeof(class EnumClassData), null, null, module, baseSystemAccess, publicAccess);
6088    eClass_AddClassProperty(enumClass, "enumSize", "int", null, GetEnumSize).constant = true;
6089    enumClass.type = systemClass;
6090
6091    delete enumClass.dataTypeString;
6092    enumClass.dataTypeString = CopyString(/*"unsigned int"*/"int");
6093
6094    // Create Struct (simple) class
6095    //structClass = eSystem_RegisterClass(structClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6096    structClass = eSystem_RegisterClass(normalClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6097    structClass.type = systemClass;
6098    structClass.memberOffset = 0;
6099    structClass.offset = 0;
6100    structClass.structSize = 0;
6101    structClass.typeSize = 0;
6102
6103    //eClass_AddMethod(enumClass, "AddValue", "int()", eEnum_AddValue);
6104    //eClass_AddMethod(enumClass, "AddFixedValue", "void()", eEnum_AddFixedValue);
6105
6106    InitializeDataTypes(module);
6107
6108    // Create bool class
6109    boolClass = eSystem_RegisterClass(ClassType::enumClass, "bool", "uint", 0, 0, null, null, module, baseSystemAccess, publicAccess);
6110    eEnum_AddFixedValue(boolClass, "true",  bool::true);
6111    eEnum_AddFixedValue(boolClass, "false", bool::false);
6112
6113    // Create Module class
6114    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) :
6115                                                                                 sizeof(struct Module), 0, (void *)Module_Constructor, (void *)Module_Destructor, module, baseSystemAccess, publicAccess);
6116    eClass_AddVirtualMethod(moduleClass, "OnLoad", "bool()", null, publicAccess);
6117    eClass_AddVirtualMethod(moduleClass, "OnUnload", "void()", null, publicAccess);
6118    eClass_AddMethod(moduleClass, "Load", "Module(char * name, AccessMode importAccess)", eModule_Load, publicAccess);
6119    eClass_AddMethod(moduleClass, "Unload", "void(Module module)", eModule_Unload, publicAccess);
6120    eClass_AddDataMember(moduleClass, "application", "Application", pointerSize, pointerSize, publicAccess);
6121    eClass_AddDataMember(moduleClass, "classes", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6122    eClass_AddDataMember(moduleClass, "defines", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6123    eClass_AddDataMember(moduleClass, "functions", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6124    eClass_AddDataMember(moduleClass, "modules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6125    eClass_AddDataMember(moduleClass, "prev", "Module", pointerSize, pointerSize, publicAccess);
6126    eClass_AddDataMember(moduleClass, "next", "Module", pointerSize, pointerSize, publicAccess);
6127    eClass_AddDataMember(moduleClass, "name", "char *", pointerSize, pointerSize, publicAccess);
6128    eClass_AddDataMember(moduleClass, "library", "void *", pointerSize, pointerSize, publicAccess);
6129    eClass_AddDataMember(moduleClass, "Unload", "void *", pointerSize, pointerSize, publicAccess);
6130    eClass_AddDataMember(moduleClass, "importType", "ImportType", sizeof(ImportType), 4, publicAccess);
6131    eClass_AddDataMember(moduleClass, "origImportType", "ImportType", sizeof(ImportType), 4, publicAccess);
6132    eClass_AddDataMember(moduleClass, "privateNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6133    eClass_AddDataMember(moduleClass, "publicNameSpace", "NameSpace",  force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6134    moduleClass.fixed = true;
6135    moduleClass.count++;
6136    if(inCompiler && force32Bits)
6137       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);
6138
6139    // Create Application class
6140    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);
6141    if(inCompiler && force32Bits)
6142    {
6143       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);
6144       applicationClass.structSize = applicationClass.offset + (4+4+4+4 + 20 + 4 + 88);
6145    }
6146    eClass_AddVirtualMethod(applicationClass, "Main", "void()", null, publicAccess);
6147    eClass_AddDataMember(applicationClass, "argc", "int", sizeof(int), 4, publicAccess);
6148    eClass_AddDataMember(applicationClass, "argv", "char **", pointerSize, pointerSize, publicAccess);
6149    eClass_AddDataMember(applicationClass, "exitCode", "int", sizeof(int), 4, publicAccess);
6150    eClass_AddDataMember(applicationClass, "isGUIApp", "bool", sizeof(bool), 4, publicAccess);
6151    eClass_AddDataMember(applicationClass, "allModules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6152    eClass_AddDataMember(applicationClass, "parsedCommand", "char *", pointerSize, pointerSize, publicAccess);
6153    eClass_AddDataMember(applicationClass, "systemNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6154    applicationClass.fixed = true;
6155    applicationClass.count++;
6156
6157    //AttachConsole(-1);
6158    //AllocConsole();
6159
6160    // --- Math ---
6161    eSystem_RegisterFunction("sin", "double sin(Angle number)", sin, module, baseSystemAccess);
6162    eSystem_RegisterFunction("sinh", "double sinh(Angle number)", sinh, module, baseSystemAccess);
6163    eSystem_RegisterFunction("cosh", "double cosh(Angle number)", cosh, module, baseSystemAccess);
6164    eSystem_RegisterFunction("tanh", "double tanh(Angle number)", tanh, module, baseSystemAccess);
6165    eSystem_RegisterFunction("sqrt", "double sqrt(double number)", sqrt, module, baseSystemAccess);
6166    eSystem_RegisterFunction("cos", "double cos(Angle number)", cos, module, baseSystemAccess);
6167    eSystem_RegisterFunction("tan", "double tan(Angle number)", tan, module, baseSystemAccess);
6168    eSystem_RegisterFunction("atan2", "Angle atan2(double y, double x)", atan2, module, baseSystemAccess);
6169    eSystem_RegisterFunction("asin", "Angle asin(double number)", asin, module, baseSystemAccess);
6170    eSystem_RegisterFunction("acos", "Angle acos(double number)", acos, module, baseSystemAccess);
6171    eSystem_RegisterFunction("atan", "Angle atan(double number)", atan, module, baseSystemAccess);
6172    eSystem_RegisterFunction("asinh", "Angle asinh(double number)", asinh, module, baseSystemAccess);
6173    eSystem_RegisterFunction("acosh", "Angle acosh(double number)", acosh, module, baseSystemAccess);
6174    eSystem_RegisterFunction("atanh", "Angle atanh(double number)", atanh, module, baseSystemAccess);
6175    eSystem_RegisterFunction("pow", "double pow(double number, double number2)", pow, module, baseSystemAccess);
6176    eSystem_RegisterFunction("fmod", "double fmod(double x, double y)", fmod, module, baseSystemAccess);
6177    eSystem_RegisterFunction("fabs", "double fabs(double number)", fabs, module, baseSystemAccess);
6178    eSystem_RegisterFunction("log", "double log(double number)", log, module, baseSystemAccess);
6179    eSystem_RegisterFunction("log10", "double log10(double number)", log10, module, baseSystemAccess);
6180    eSystem_RegisterFunction("ceil", "double ceil(double number)", ceil, module, baseSystemAccess);
6181    eSystem_RegisterFunction("floor", "double floor(double number)", floor, module, baseSystemAccess);
6182    eSystem_RegisterFunction("exp", "double exp(double number)", exp, module, baseSystemAccess);
6183
6184    // --- Stdlib ---
6185    eSystem_RegisterFunction("qsort", "void qsort(void *, uintsize, uintsize, int (*)(void *, void *))", qsort, module, baseSystemAccess);
6186    eSystem_RegisterFunction("strtod", "double strtod(char*, char**)", strtod, module, baseSystemAccess);
6187    eSystem_RegisterFunction("strtol", "int strtol(char*, char**, int base)", strtol, module, baseSystemAccess);
6188    eSystem_RegisterFunction("system", "int system(const char*)", system, module, baseSystemAccess);
6189    eSystem_RegisterFunction("atoi", "int atoi(const char*)", atoi, module, baseSystemAccess);
6190    eSystem_RegisterFunction("atof", "double atof(const char*)", atof, module, baseSystemAccess);
6191    eSystem_RegisterFunction("tolower", "int tolower(int)", tolower, module, baseSystemAccess);
6192    eSystem_RegisterFunction("toupper", "int toupper(int)", toupper, module, baseSystemAccess);
6193    eSystem_RegisterFunction("isdigit", "bool isdigit(int)", isdigit, module, baseSystemAccess);
6194    eSystem_RegisterFunction("memset", "void * memset(void * area, int value, uintsize count)", memset, module, baseSystemAccess);
6195    eSystem_RegisterFunction("getenv", "char * getenv(const char * name)", getenv, module, baseSystemAccess);
6196    eSystem_RegisterFunction("rename", "int rename(const char *oldpath, const char *newpath)", rename, module, baseSystemAccess);
6197
6198    // --- String --- (These might move to the string class)
6199    eSystem_RegisterFunction("strlen", "uintsize strlen(const char *)", strlen, module, baseSystemAccess);
6200    eSystem_RegisterFunction("strcat", "char * strcat(char *, const char *)", strcat, module, baseSystemAccess);
6201    eSystem_RegisterFunction("strncat", "char * strncat(char *, const char *, uintsize n)", strncat, module, baseSystemAccess);
6202    eSystem_RegisterFunction("strchr", "char * strchr(const char *, int)", strchr, module, baseSystemAccess);
6203    eSystem_RegisterFunction("strstr", "char * strstr(const char *, const char *)", strstr, module, baseSystemAccess);
6204    eSystem_RegisterFunction("strspn", "uintsize strspn(const char *, const char *)", strspn, module, baseSystemAccess);
6205    eSystem_RegisterFunction("strcspn", "uintsize strcspn(const char *, const char *)", strcspn, module, baseSystemAccess);
6206    eSystem_RegisterFunction("strpbrk", "char * strpbrk(const char *, const char *)", strpbrk, module, baseSystemAccess);
6207
6208    eSystem_RegisterDefine("fstrcmp", "(GetRuntimePlatform() == win32) ? strcmpi : strcmp", module, baseSystemAccess);
6209
6210 //#if defined(__GNUC__)
6211    eSystem_RegisterDefine("strcmpi", "strcasecmp", module, baseSystemAccess);
6212    eSystem_RegisterDefine("strnicmp", "strncasecmp", module, baseSystemAccess);
6213    eSystem_RegisterFunction("strcasecmp", "int strcasecmp(const char *, const char *)", strcmpi, module, baseSystemAccess);
6214    eSystem_RegisterFunction("strncasecmp", "int strncasecmp(const char *, const char *, uintsize n)", strnicmp, module, baseSystemAccess);
6215 /*
6216 #else
6217    eSystem_RegisterDefine("strcasecmp", "strcmpi", module, baseSystemAccess);
6218    eSystem_RegisterDefine("strncasecmp", "strnicmp", module, baseSystemAccess);
6219    eSystem_RegisterFunction("strcmpi", "int strcmpi(const char *, const char *)", strcmpi, module, baseSystemAccess);
6220    eSystem_RegisterFunction("strnicmp", "int strnicmp(const char *, const char *, int n)", strnicmp, module, baseSystemAccess);
6221 #endif
6222 */
6223
6224    eSystem_RegisterFunction("strcmp", "int strcmp(const char *, const char *)", strcmp, module, baseSystemAccess);
6225    eSystem_RegisterFunction("strncmp", "int strncmp(const char *, const char *, uintsize n)", strncmp, module, baseSystemAccess);
6226    eSystem_RegisterFunction("strlwr", "char * strlwr(char *)", strlwr, module, baseSystemAccess);
6227    eSystem_RegisterFunction("strupr", "char * strupr(char *)", strupr, module, baseSystemAccess);
6228    eSystem_RegisterFunction("strcpy", "char * strcpy(char *, const char *)", strcpy, module, baseSystemAccess);
6229    eSystem_RegisterFunction("strncpy", "char * strncpy(char *, const char *, uintsize n)", strncpy, module, baseSystemAccess);
6230    eSystem_RegisterFunction("memcpy", "void * memcpy(void *, const void *, uintsize size)", memcpy, module, baseSystemAccess);
6231    eSystem_RegisterFunction("memmove", "void * memmove(void *, const void *, uintsize size)", memmove, module, baseSystemAccess);
6232    eSystem_RegisterFunction("memcmp", "int memcmp(const void *, const void *, uintsize size)", memcmp, module, baseSystemAccess);
6233
6234    // --- Stdio ---
6235    eSystem_RegisterFunction("sprintf", "int sprintf(char *, char *, ...)", sprintf, module, baseSystemAccess);
6236    eSystem_RegisterFunction("snprintf", "int sprintf(char *, uintsize, char *, ...)", snprintf, module, baseSystemAccess);
6237    eSystem_RegisterFunction("printf", "int printf(char *, ...)", printf, module, baseSystemAccess);
6238    eSystem_RegisterFunction("vsprintf", "int vsprintf(char*, const char*, __builtin_va_list)", vsprintf, module, baseSystemAccess);
6239    eSystem_RegisterFunction("vsnprintf", "int vsnprintf(char*, uintsize, const char*, __builtin_va_list)", vsnprintf, module, baseSystemAccess);
6240    eSystem_RegisterFunction("puts", "int puts(char *)", puts, module, baseSystemAccess);
6241    eSystem_RegisterFunction("fputs", "int fputs(char *, void * stream)", fputs, module, baseSystemAccess);
6242
6243    // --- Ctype ---
6244    eSystem_RegisterFunction("isalnum", "int isalnum(int c)", isalnum, module, baseSystemAccess);
6245    eSystem_RegisterFunction("isspace", "int isspace(int c)", isspace, module, baseSystemAccess);
6246    eSystem_RegisterFunction("isalpha", "int isalpha(int c)", isalpha, module, baseSystemAccess);
6247    eSystem_RegisterFunction("islower", "int islower(int c)", islower, module, baseSystemAccess);
6248    eSystem_RegisterFunction("isupper", "int isupper(int c)", isupper, module, baseSystemAccess);
6249    eSystem_RegisterFunction("isprint", "int isprint(int c)", isprint, module, baseSystemAccess);
6250    eSystem_RegisterFunction("strtoul", "unsigned long strtoul(const char * nptr, char ** endptr, int base)", strtoul, module, baseSystemAccess);
6251    eSystem_RegisterFunction("strtoll", "int64 strtoll(const char * nptr, char ** endptr, int base)", strtoul, module, baseSystemAccess);
6252    eSystem_RegisterFunction("strtoull", "uint64 strtoull(const char * nptr, char ** endptr, int base)", strtoul, module, baseSystemAccess);
6253
6254 }
6255
6256 public dllexport Application __ecere_COM_Initialize(bool guiApp, int argc, char * argv[])
6257 {
6258    Application app;
6259
6260 #ifdef __ANDROID__
6261    // Clean up global variables
6262    memoryInitialized = false;
6263    pools = null;
6264 #ifdef MEMINFO
6265    memset(&memStacks, 0, sizeof(BinaryTree));
6266    memoryErrorsCount = 0;
6267    memset(&memBlocks, 0, sizeof(BinaryTree));
6268    recurse = false;
6269    blockID = 0;
6270    allocateClass = null;
6271    allocateInternal = false;
6272    TOTAL_MEM = 0;
6273    OUTSIDE_MEM = 0;
6274 #endif
6275 #endif
6276
6277 #ifdef _DEBUG
6278    // printf("Using debug ecere runtime library\n");
6279 #endif
6280    app = _calloc(1, sizeof(class Application));
6281
6282    Module_Constructor(app);
6283    app.systemNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
6284    app.systemNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
6285    app.systemNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
6286    app.systemNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
6287
6288    Instance_COM_Initialize(argc, argv, &app.parsedCommand, &app.argc, &app.argv);
6289
6290    app.application = app;
6291    app.allModules.offset = sizeof(class Instance) + (uint)(uintptr)&((struct Module *)0)->prev;
6292    app.isGUIApp = guiApp;
6293
6294    LoadCOM(app);
6295
6296    app._class = eSystem_FindClass(app, "Application");
6297
6298    return app;
6299 }
6300
6301 public dllexport ClassTemplateParameter eClass_AddTemplateParameter(Class _class, char * name, TemplateParameterType type, void * info, ClassTemplateArgument defaultArg)
6302 {
6303    if(_class && name)
6304    {
6305       ClassTemplateParameter param;
6306
6307       for(param = _class.templateParams.first; param; param = param.next)
6308       {
6309          if(!strcmp(param.name, name))
6310             return param;
6311       }
6312       param =
6313       {
6314          name = CopyString(name);
6315          type = type;
6316          (type == identifier) ? info : CopyString(info);
6317       };
6318       if(defaultArg != null)
6319       {
6320          param.defaultArg = defaultArg;
6321          CopyTemplateArg(param, param.defaultArg);
6322       }
6323       _class.templateParams.Add(param);
6324       return param;
6325    }
6326    return null;
6327 }
6328
6329 public dllexport void eClass_DoneAddingTemplateParameters(Class base)
6330 {
6331    if(base)
6332    {
6333       ClassTemplateParameter param;
6334       {
6335          void * first = base.templateParams.first;
6336          int count = base.templateParams.count;
6337
6338          FreeTemplateArgs(base);
6339          delete base.templateArgs;
6340
6341          base.templateParams.first = null;
6342          base.templateParams.count = 0;
6343
6344          FreeTemplatesDerivatives(base);
6345
6346          base.templateParams.first = first;
6347          base.templateParams.count = count;
6348       }
6349
6350       for(param = base.templateParams.first; param; param = param.next)
6351       {
6352          if(param.type == identifier && param.defaultArg.memberString)
6353          {
6354             Class memberClass = base;
6355             char * colon = strstr(param.defaultArg.memberString, "::");
6356             char * memberName;
6357             if(colon)
6358             {
6359                char className[1024];
6360                Class sClass;
6361
6362                memcpy(className, param.defaultArg.memberString, colon - param.defaultArg.memberString);
6363                className[colon - param.defaultArg.memberString] = '\0';
6364                memberName = colon + 2;
6365
6366                for(sClass = base; sClass; sClass = sClass.base)
6367                {
6368                   ClassTemplateParameter cParam;
6369                   Class nextClass;
6370                   int id = 0;
6371                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) id += nextClass.templateParams.count;
6372                   // Safety! What could cause base.templateArgs to be null?
6373                   if(sClass == base || base.templateArgs)
6374                   {
6375                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
6376                      {
6377                         if(cParam.type == type && !strcmp(cParam.name, className))
6378                            strcpy(className, (sClass == base) ? cParam.defaultArg.dataTypeString : base.templateArgs[id].dataTypeString);
6379                         id++;
6380                      }
6381                   }
6382                }
6383                memberClass = eSystem_FindClass(base.module, className);
6384                if(!memberClass)
6385                   memberClass = eSystem_FindClass(base.module.application, className);
6386             }
6387             else
6388                memberName = param.defaultArg.memberString;
6389
6390             if(memberClass)
6391             {
6392                switch(param.memberType)
6393                {
6394                   case dataMember:
6395                      param.defaultArg.member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
6396                      break;
6397                   case method:
6398                      param.defaultArg.method = eClass_FindMethod(memberClass, memberName, memberClass.module);
6399                      break;
6400                   case prop:
6401                      param.defaultArg.prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
6402                      break;
6403                }
6404             }
6405          }
6406       }
6407
6408       //ComputeClassParameters(base, null, null);
6409
6410       FixDerivativesBase(base, base);
6411    }
6412 }
6413
6414 static void FreeTemplatesDerivatives(Class base)
6415 {
6416    OldLink derivative, templateLink;
6417    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
6418    {
6419       Class _class = derivative.data;
6420       if(_class.templateArgs)
6421       {
6422          FreeTemplateArgs(_class);
6423          delete _class.templateArgs;
6424       }
6425       FreeTemplatesDerivatives(_class);
6426    }
6427
6428    for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
6429    {
6430       Class _class = templateLink.data;
6431       if(_class.templateArgs)
6432       {
6433          FreeTemplateArgs(_class);
6434          delete _class.templateArgs;
6435       }
6436       FreeTemplatesDerivatives(_class);
6437    }
6438 }
6439
6440 static const char * platformNames[Platform] = { "", "win32", "linux", "apple" }; // how to have this be accessible outside of dll/lib
6441 static const Platform firstPlatform = win32;
6442 static const Platform lastPlatform = apple;
6443
6444 public enum Platform
6445 {
6446    unknown, win32, tux, apple;
6447
6448    property char *
6449    {
6450       get { return OnGetString(null, null, null); }
6451       set
6452       {
6453          if(value)
6454          {
6455             Platform c;
6456             for(c = firstPlatform; c <= lastPlatform; c++)
6457                if(!strcmpi(value, platformNames[c]))
6458                   return c;
6459          }
6460          return unknown;
6461       }
6462    };
6463
6464    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
6465    {
6466       if(this >= firstPlatform && this <= lastPlatform)
6467       {
6468          if(tempString)
6469             strcpy(tempString, platformNames[this]);
6470          return platformNames[this];
6471       }
6472       if(tempString && tempString[0])
6473          tempString[0] = '\0';
6474       return null;
6475    }
6476
6477    bool OnGetDataFromString(char * string)
6478    {
6479       this = string;
6480       return this != unknown;
6481    }
6482 };
6483
6484 default extern Platform runtimePlatform;
6485
6486 public Platform GetRuntimePlatform()
6487 {
6488    return runtimePlatform;
6489 }
6490
6491 namespace gui;
6492
6493 class Window;
6494
6495 namespace com;
6496 // CLASS DESIGNER SUPPORT
6497
6498 public class ObjectInfo : struct
6499 {
6500 public:
6501    ObjectInfo prev, next;
6502    Instance instance;
6503    char * name;
6504    Instantiation instCode;
6505    bool deleted;
6506    ObjectInfo oClass;
6507    OldList instances;
6508    ClassDefinition classDefinition;
6509    bool modified;
6510    void * i18nStrings;
6511 };
6512
6513 public class DesignerBase : Window
6514 {
6515 public:
6516    virtual bool FindObject(Instance * instance, char * string);
6517    virtual void RenameObject(ObjectInfo object, char * name);
6518    virtual void SelectObjectFromDesigner(ObjectInfo object);
6519    virtual void CodeAddObject(Instance instance, ObjectInfo * object);
6520    virtual void SheetAddObject(ObjectInfo object);
6521    virtual void AddToolBoxClass(Class _class);
6522    virtual void AddDefaultMethod(Instance instance, Instance classInstance);
6523    virtual void DeleteObject(ObjectInfo object);
6524    virtual bool ObjectContainsCode(ObjectInfo object);
6525    virtual void ModifyCode(void);
6526    virtual void UpdateProperties(void);
6527
6528    ClassDesignerBase classDesigner;
6529    char * objectClass;
6530    bool isDragging;
6531
6532    // FIX THIS WITH PUBLIC:
6533    property ClassDesignerBase classDesigner
6534    {
6535       get { return classDesigner; }
6536       set { classDesigner = value; }
6537    };
6538    property char * objectClass
6539    {
6540       get { return objectClass; }
6541       set { objectClass = value; }
6542    };
6543    property bool isDragging
6544    {
6545       get { return isDragging; }
6546       set { isDragging = value; }
6547    };
6548 }
6549
6550 public class ClassDesignerBase : Window
6551 {
6552 public:
6553    virtual void Reset(void);
6554    virtual void AddObject(void);
6555    virtual void SelectObject(ObjectInfo object, Instance control);
6556
6557    virtual void ListToolBoxClasses(DesignerBase designer);
6558
6559    virtual void ::PrepareTestObject(DesignerBase designer, Instance test);
6560    virtual void ::CreateObject(DesignerBase designer, Instance instance, ObjectInfo object, bool isClass, Instance _class);
6561    virtual void ::PostCreateObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6562    virtual void ::DroppedObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6563    virtual void ::DestroyObject(Instance object);
6564    virtual void ::FixProperty(Property prop, Instance object);
6565    virtual void ::CreateNew(EditBox editBox, Size clientSize, char * name, char * inherit);
6566 }
6567
6568 DesignerBase activeDesigner;
6569
6570 public void SetActiveDesigner(DesignerBase designer)
6571 {
6572    activeDesigner = designer;
6573 }
6574
6575 public DesignerBase GetActiveDesigner()
6576 {
6577    return activeDesigner;
6578 }
6579
6580
6581 bool poolingDisabled;
6582
6583 public dllexport void eSystem_SetPoolingDisabled(bool disabled)
6584 {
6585    poolingDisabled = disabled;
6586 }
6587
6588 namespace sys;
6589
6590 // constants
6591 define LEAD_OFFSET      = 0xD800 - (0x10000 >> 10);
6592 define SURROGATE_OFFSET = 0x10000 - (0xD800 << 10) - 0xDC00;
6593
6594 public bool UTF8Validate(char * source)
6595 {
6596    if(source)
6597    {
6598       int c;
6599       for(c = 0; source[c];)
6600       {
6601          byte ch = source[c];
6602          unichar codePoint = 0;
6603          int numBytes = 1;
6604          int i;
6605          byte mask = 0x7F;
6606          if(ch & 0x80)
6607          {
6608             if(ch & 0x40)
6609             {
6610                mask >>= 2;
6611                numBytes++;
6612                if(ch & 0x20)
6613                {
6614                   numBytes++;
6615                   mask >>= 1;
6616                   if(ch & 0x10)
6617                   {
6618                      if(ch & 0x08)
6619                         return false;
6620                      numBytes++;
6621                      mask >>= 1;
6622                   }
6623                }
6624             }
6625             else
6626                return false;
6627          }
6628          for(i = 0; i<numBytes && (ch = source[c]); i++, c++)
6629          {
6630             codePoint <<= 6;
6631             codePoint |= ch & mask;
6632             mask = 0x3F;
6633             if(i > 1)
6634             {
6635                if(!(ch & 0x80) || (ch & 0x40))
6636                   return false;
6637             }
6638          }
6639          if(i < numBytes) return false;
6640
6641          if(codePoint > 0x10FFFF || (codePoint >= 0xD800 && codePoint <= 0xDFFF) ||
6642            (codePoint < 0x80 && numBytes > 1) ||
6643            (codePoint < 0x800 && numBytes > 2) ||
6644            (codePoint < 0x10000 && numBytes > 3))
6645             return false;
6646       }
6647    }
6648    return true;
6649 }
6650
6651 public int ISO8859_1toUTF8(char * source, char * dest, int max)
6652 {
6653    int c;
6654    int d = 0;
6655    for(c = 0; source[c]; c++)
6656    {
6657       unichar ch = ((byte *)source)[c];
6658       switch(ch)
6659       {
6660          case 150: ch = (unichar)0x2012; break;
6661       }
6662       if(ch < 0x80)
6663       {
6664          if(d + 1 >= max) break;
6665          dest[d++] = (char)ch;
6666       }
6667       else if(ch < 0x800)
6668       {
6669          if(d + 2 >= max) break;
6670          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6671          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6672       }
6673       else if(ch < 0x10000)
6674       {
6675          if(d + 3 >= max) break;
6676          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6677          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6678          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6679       }
6680       else
6681       {
6682          if(d + 4 >= max) break;
6683          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6684          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6685          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6686          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6687       }
6688    }
6689    dest[d] = 0;
6690    return d;
6691 }
6692
6693 public char * UTF16toUTF8(uint16 * source)
6694 {
6695    int c;
6696    int d = 0;
6697    int len;
6698    char * dest;
6699    uint16 u16;
6700    bool invert = false;
6701
6702    for(len = 0; source[len]; len++);
6703    dest = new char[len * 3 + 1];
6704    for(c = 0; (u16 = source[c]); c++)
6705    {
6706       unichar ch;
6707       if(!c && (u16 == 0xFFFE || u16 == 0xFEFF))
6708       {
6709          if(u16 == 0xFFFE) invert = true;
6710          continue;
6711       }
6712       if(invert) { u16 = ((u16 & 0xFF00) >> 8) | ((u16 & 0x00FF) << 8); }
6713
6714       if(u16 < 0xD800 || u16 > 0xDBFF)
6715          ch = (unichar)u16;
6716       else
6717          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
6718
6719       if(ch < 0x80)
6720       {
6721          dest[d++] = (char)ch;
6722       }
6723       else if(ch < 0x800)
6724       {
6725          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6726          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6727       }
6728       else if(ch < 0x10000)
6729       {
6730          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6731          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6732          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6733       }
6734       else
6735       {
6736          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6737          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6738          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6739          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6740       }
6741    }
6742    dest[d] = 0;
6743    dest = renew dest char[d+1];
6744    return dest;
6745 }
6746
6747 public int UTF16toUTF8Buffer(uint16 * source, byte * dest, int max)
6748 {
6749    int c;
6750    int d = 0;
6751    uint16 u16;
6752    for(c = 0; (u16 = source[c]); c++)
6753    {
6754       unichar ch;
6755       if(u16 < 0xD800 || u16 > 0xDBFF)
6756          ch = (unichar)u16;
6757       else
6758          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
6759
6760       if(ch < 0x80)
6761       {
6762          if(d + 1 >= max) break;
6763          dest[d++] = (char)ch;
6764       }
6765       else if(ch < 0x800)
6766       {
6767          if(d + 2 >= max) break;
6768          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6769          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6770       }
6771       else if(ch < 0x10000)
6772       {
6773          if(d + 3 >= max) break;
6774          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6775          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6776          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6777       }
6778       else
6779       {
6780          if(d + 4 >= max) break;
6781          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6782          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6783          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6784          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6785       }
6786    }
6787    dest[d] = 0;
6788    return d;
6789 }
6790
6791 // NOTE: UTF8GetChar now returns 0 into numBytes for the null-terminating character ('\0')
6792 public unichar UTF8GetChar(char * string, int * numBytes)
6793 {
6794    unichar ch;
6795    byte b = ((byte *)string)[0];
6796    int i;
6797    byte mask = 0x7F;
6798    int nb = b ? 1 : 0;
6799    ch = 0;
6800    if(b & 0x80)
6801    {
6802       if(b & 0x40)
6803       {
6804          mask >>= 2;
6805          nb++;
6806          if(b & 0x20)
6807          {
6808             nb++;
6809             mask >>= 1;
6810             if(b & 0x10)
6811             {
6812                if(b & 0x08) { nb = 0; }
6813                nb++;
6814                mask >>= 1;
6815             }
6816          }
6817       }
6818       else
6819          nb = 0;
6820    }
6821    for(i = 0; i<nb; i++)
6822    {
6823       ch <<= 6;
6824       ch |= (b = ((byte *)string)[i]) & mask;
6825       mask = 0x3F;
6826       if(i > 1 && (!(b & 0x80) || (b & 0x40)))
6827       {
6828          nb = 0;
6829          ch = 0;
6830       }
6831    }
6832
6833    if(i < nb ||
6834       ch > 0x10FFFF || (ch >= 0xD800 && ch <= 0xDFFF) ||
6835      (ch < 0x80 && nb > 1) ||
6836      (ch < 0x800 && nb > 2) ||
6837      (ch < 0x10000 && nb > 3))
6838    {
6839       ch = 0;
6840       nb = 0;
6841    }
6842    if(numBytes) *numBytes = nb;
6843    return ch;
6844 }
6845
6846 public int UTF8toUTF16Buffer(char * source, uint16 * dest, int max)
6847 {
6848    if(source)
6849    {
6850       int c;
6851       int d = 0;
6852       for(c = 0; source[c];)
6853       {
6854          byte ch = source[c];
6855          unichar codePoint = 0;
6856          int numBytes = 1;
6857          int i;
6858          byte mask = 0x7F;
6859          if(ch & 0x80 && ch & 0x40)
6860          {
6861             mask >>= 2;
6862             numBytes++;
6863             if(ch & 0x20)
6864             {
6865                numBytes++;
6866                mask >>= 1;
6867                if(ch & 0x10)
6868                {
6869                   numBytes++;
6870                   mask >>= 1;
6871                }
6872             }
6873          }
6874          for(i = 0; i<numBytes; i++)
6875          {
6876             codePoint <<= 6;
6877             codePoint |= source[c++] & mask;
6878             mask = 0x3F;
6879          }
6880
6881          if(codePoint > 0xFFFF)
6882          {
6883             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
6884             uint16 trail = 0xDC00 + (uint16)(codePoint & 0x3FF);
6885             if(d >= max - 1) break;
6886             dest[d++] = lead;
6887             dest[d++] = trail;
6888          }
6889          else
6890          {
6891             if(d >= max) break;
6892             dest[d++] = (uint16)codePoint;
6893          }
6894       }
6895       dest[d] = 0;
6896       return d;
6897    }
6898    return 0;
6899 }
6900
6901 public int UTF32toUTF8Len(unichar * source, int count, byte * dest, int max)
6902 {
6903    int c;
6904    int d = 0;
6905    uint32 ch;
6906    for(c = 0; c<count && (ch = source[c]); c++)
6907    {
6908       if(ch < 0x80)
6909       {
6910          if(d + 1 >= max) break;
6911          dest[d++] = (char)ch;
6912       }
6913       else if(ch < 0x800)
6914       {
6915          if(d + 2 >= max) break;
6916          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6917          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6918       }
6919       else if(ch < 0x10000)
6920       {
6921          if(d + 3 >= max) break;
6922          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6923          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6924          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6925       }
6926       else
6927       {
6928          if(d + 4 >= max) break;
6929          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6930          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6931          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6932          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6933       }
6934    }
6935    dest[d] = 0;
6936    return d;
6937 }
6938
6939 public uint16 * UTF8toUTF16(char * source, int * wordCount)
6940 {
6941    if(source)
6942    {
6943       int len = (int)strlen(source);
6944       uint16 * dest = new uint16[len + 1];
6945       int c;
6946       int d = 0;
6947       for(c = 0; source[c];)
6948       {
6949          byte ch = source[c];
6950          unichar codePoint = 0;
6951          int numBytes = 1;
6952          int i;
6953          byte mask = 0x7F;
6954          if(ch & 0x80 && ch & 0x40)
6955          {
6956             mask >>= 2;
6957             numBytes++;
6958             if(ch & 0x20)
6959             {
6960                numBytes++;
6961                mask >>= 1;
6962                if(ch & 0x10)
6963                {
6964                   numBytes++;
6965                   mask >>= 1;
6966                }
6967             }
6968          }
6969          for(i = 0; i<numBytes; i++)
6970          {
6971             codePoint <<= 6;
6972             codePoint |= source[c++] & mask;
6973             mask = 0x3F;
6974          }
6975
6976          if(codePoint > 0xFFFF)
6977          {
6978             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
6979             uint16 trail = 0xDC00 + (uint16)(codePoint & 0x3FF);
6980             dest[d++] = lead;
6981             dest[d++] = trail;
6982          }
6983          else
6984          {
6985             dest[d++] = (uint16)codePoint;
6986          }
6987       }
6988       dest[d] = 0;
6989       if(wordCount) *wordCount = d;
6990       return dest;
6991    }
6992    return null;
6993 }
6994
6995 namespace com;