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