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