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