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