ecere/com; compiler/bootstrap: Fixed leaks occuring when importing ecere within ecere...
[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 && _class.vTblSize < 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 = (BTNamedLink)_class.prop.FindString(_property.name);
4127       if(link)
4128       {
4129          prop = link.data;
4130          if(!prop.Set && !prop.Get && prop.memberAccess == baseSystemAccess)
4131          {
4132             SelfWatcher watcher;
4133             for(watcher = _class.selfWatchers.first; watcher; watcher = watcher.next)
4134             {
4135                if(watcher._property == prop)
4136                   watcher._property = _property;
4137             }
4138             _property.selfWatchable = true;
4139
4140             delete prop.name;
4141             delete prop.dataTypeString;
4142             _class.membersAndProperties.Delete(prop);
4143             _class.prop.Delete((BTNode)link);
4144          }
4145       }
4146
4147       for(prop = _class.membersAndProperties.first; prop; prop = prop.next)
4148          prop.id++;
4149       _class.memberID++;
4150       _class.startMemberID++;
4151
4152       FixDerivativeProperty(_class, _property);
4153    }
4154 }
4155
4156 public dllexport Property eClass_AddProperty(Class _class, char * name, char * dataType, void * setStmt, void * getStmt, AccessMode declMode)
4157 {
4158    Property _property = null;
4159    if(_class)
4160    {
4161       BTNamedLink link = (BTNamedLink)_class.prop.FindString(name ? name : dataType);
4162       if(link)
4163          _property = link.data;
4164       if(!_property)
4165       {
4166          _property =
4167          {
4168             isProperty = true;
4169             name = CopyString(name ? name : dataType);
4170             id = (name && (setStmt || getStmt || dataType)) ? _class.memberID++ : 0;
4171             Set = setStmt;
4172             Get = getStmt;
4173             dataTypeString = CopyString(dataType);
4174             _class = _class;
4175             compiled = true;
4176             conversion = name ? false : true;
4177             memberAccess = declMode;
4178          };
4179          if(name)
4180             _class.membersAndProperties.Add(_property);
4181          else
4182             _class.conversions.Add(_property);
4183          _class.prop.Add((BTNode)BTNamedLink { name = _property.name, data = _property });
4184
4185          if(!_property.conversion)
4186          {
4187             FixDerivativeProperty(_class, _property);
4188          }
4189       }
4190    }
4191    return _property;
4192 }
4193
4194 static void SetDelayedCPValues(Class _class, ClassProperty _property)
4195 {
4196    OldLink deriv;
4197    NamedLink64 value, next;
4198
4199    for(value = _class.delayedCPValues.first; value; value = next)
4200    {
4201       next = value.next;
4202       if(!strcmp(value.name, _property.name))
4203       {
4204          // eClass_SetProperty(_class, _property.name, value.data);
4205          _property.Set(_class, value.data);
4206          _class.delayedCPValues.Delete(value);
4207       }
4208    }
4209
4210    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4211    {
4212       SetDelayedCPValues(deriv.data, _property);
4213    }
4214 }
4215
4216 public dllexport ClassProperty eClass_AddClassProperty(Class _class, char * name, char * dataType, void * setStmt, void * getStmt)
4217 {
4218    if(name && !_class.classProperties.FindString(name)) 
4219    {
4220       ClassProperty _property
4221       {
4222          name = CopyString(name);
4223          Set = setStmt;
4224          Get = getStmt;
4225          dataTypeString = CopyString(dataType);
4226       };
4227       _class.classProperties.Add((BTNode)_property);
4228       SetDelayedCPValues(_class, _property);
4229       return _property;
4230    }
4231    return null;
4232 }
4233
4234 /*import "Time"
4235
4236 Time classFindTotalTime;
4237
4238 public dllexport void ResetClassFindTime()
4239 {
4240    classFindTotalTime = 0;
4241 }
4242
4243 public dllexport Time GetClassFindTime()
4244 {
4245    return classFindTotalTime;
4246 }
4247 */
4248 public dllexport ClassProperty eClass_FindClassProperty(Class _class, char * name)
4249 {
4250    //Time startTime = GetTime();
4251    ClassProperty _property = null;
4252    if(name && _class)
4253    {
4254       Class origClass = _class;
4255       for(; _class; _class = _class.base)
4256       {
4257          _property = (ClassProperty)_class.classProperties.FindString(name);
4258          if(_property)
4259             break;
4260       }
4261       // For enum class deriving off something else than enum to find enumSize...
4262       if(!_property && origClass.type == enumClass)
4263       {
4264          Class enumClass = eSystem_FindClass(origClass.module, "enum");
4265          _property = eClass_FindClassProperty(enumClass, name);
4266       }
4267    }
4268    /*if(!_property)
4269       eSystem_Logf("No such property (%s) for class %s\n", name, _class.name);*/
4270    //classFindTotalTime += GetTime() - startTime;
4271    return _property;
4272 }
4273
4274 public dllexport int64 eClass_GetProperty(Class _class, char * name)
4275 {
4276    ClassProperty _property = eClass_FindClassProperty(_class, name);
4277    if(_property && _property.Get && _property.Get != (void *)1)
4278    {
4279       int64 result = _property.Get(_class);
4280       return result;
4281    }
4282    return 0;
4283 }
4284
4285 public dllexport void eClass_SetProperty(Class _class, char * name, int64 value)
4286 {
4287    ClassProperty _property = eClass_FindClassProperty(_class, name);
4288    if(_property)
4289    {
4290       if(_property.Set)
4291          ((void(*)(void *, int64))_property.Set)(_class, value);
4292    }
4293    else
4294    {
4295       _class.delayedCPValues.Add(NamedLink64 { name = name, value });
4296    }
4297 }
4298
4299 public dllexport Method eClass_FindMethod(Class _class, char * name, Module module)
4300 {
4301    //Time startTime = GetTime();
4302    if(_class && name)
4303    {
4304       for(; _class; _class = _class.base)
4305       {
4306          Method method;
4307          if(_class.templateClass) _class = _class.templateClass;
4308          method = (Method)_class.methods.FindString(name);
4309          if(method && (method.memberAccess == publicAccess || _class.module == module || !method.dataTypeString))
4310          {
4311             if(!method.dataTypeString)
4312             {
4313                if(_class.module != module)
4314                {
4315                   if(method.memberAccess == publicAccess)
4316                      module = _class.module;
4317                   else
4318                   {
4319                      //classFindTotalTime += GetTime() - startTime;
4320                      return null;
4321                   }
4322                }
4323             }
4324             else
4325             {
4326                //classFindTotalTime += GetTime() - startTime;
4327                return method;
4328             }
4329          }
4330          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4331       }
4332    }
4333    //classFindTotalTime += GetTime() - startTime;
4334    return null;
4335 }
4336
4337 // Construct an instance
4338 static bool ConstructInstance(void * instance, Class _class, Class from)
4339 {
4340    if(_class.templateClass) _class = _class.templateClass;
4341    if(_class.base && from != _class.base)
4342    {
4343       if(!ConstructInstance(instance, _class.base, from))
4344          return false;
4345    }
4346    if(_class.Initialize)
4347    {
4348       void (* Initialize)(Module module) = (void *)_class.Initialize;
4349       _class.Initialize = null;
4350       Initialize(_class.module);
4351    }
4352    if(_class.Constructor)
4353    {
4354       if(!_class.Constructor(instance))
4355       {
4356          for(; _class; _class = _class.base)
4357          {
4358             if(_class.templateClass) _class = _class.templateClass;
4359             if(_class.Destructor)
4360                _class.Destructor(instance);
4361          }
4362          return false;
4363       }
4364    }
4365    (_class.templateClass ? _class.templateClass : _class).count++;
4366    return true;
4367 }
4368
4369 public dllexport void * eInstance_New(Class _class)
4370 {
4371    Instance instance = null;
4372    if(_class)
4373    {
4374       // instance = _malloc(_class.size);   
4375 #ifdef MEMINFO
4376
4377 #undef malloc
4378    memMutex.Wait();
4379       //allocateClass = _class;
4380       allocateClass = malloc(strlen(_class.name)+1);
4381       allocateInternal = _class.module == __thisModule;
4382       strcpy(allocateClass, _class.name);
4383 #ifndef MEMINFO
4384 #define malloc _mymalloc
4385 #endif
4386
4387 #endif
4388       {
4389          int size = _class.structSize;
4390          int flags = _class.module.application.isGUIApp;
4391          bool inCompiler = (flags & 8) ? true : false;
4392          bool force32Bits = (flags & 4) ? true : false;
4393          if(force32Bits && inCompiler)
4394          {
4395             // Allocate 64 bit sizes for these when cross-compiling for 32 bit to allow loaded libraries to work properly
4396             if(!strcmp(_class.name, "Module"))
4397                size = 560;
4398             else if(_class.templateClass && !strcmp(_class.templateClass.name, "Map"))
4399                size = 40;
4400             else
4401                size *= 3;
4402          }
4403          instance = _calloc(1, size);
4404       }
4405 #ifdef MEMINFO
4406       allocateClass = null;
4407    memMutex.Release();
4408 #endif
4409       if(_class.type == normalClass)
4410       {
4411          instance._class = _class;
4412          // Copy the virtual table initially
4413          instance._vTbl = _class._vTbl;
4414       }
4415       if(!ConstructInstance(instance, _class, null))
4416       {
4417          _free(instance);
4418          instance = null;
4419       }
4420       /*if(_class.type == normalClass && _class.count > 1000)
4421          printf("%s: %d instances\n", _class.name, _class.count);*/
4422    }
4423    return instance;
4424 }
4425
4426 public dllexport void eInstance_Evolve(Instance * instancePtr, Class _class)
4427 {
4428    if(_class && instancePtr && *instancePtr)
4429    {
4430       bool wasApp = false, wasGuiApp = false;
4431       Instance instance = (Instance)renew *instancePtr byte[_class.structSize];
4432       Class fromClass = instance._class;
4433       *instancePtr = instance;
4434       memset(((byte *)instance) + instance._class.structSize, 0, _class.structSize - instance._class.structSize);
4435       // Fix pointers to application
4436       if((wasApp = !strcmp(instance._class.name, "Application")) ||
4437          (wasGuiApp = !strcmp(instance._class.name, "GuiApplication")))
4438       {
4439          Module module;
4440          Application app = (Application) instance;
4441          BTNamedLink link;
4442          Class _class;
4443          NameSpace * nameSpace;
4444          for(module = app.allModules.first; module; module = module.next)
4445             module.application = app;
4446
4447          for(link = (BTNamedLink)app.privateNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4448          {
4449             OldLink t;
4450             ((Class)link.data).nameSpace = &app.privateNameSpace;
4451             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4452          }
4453          for(link = (BTNamedLink)app.publicNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4454          {
4455             OldLink t;
4456             ((Class)link.data).nameSpace = &app.publicNameSpace;
4457             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4458          }
4459
4460          for(link = (BTNamedLink)app.privateNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4461             ((DefinedExpression)link.data).nameSpace = &app.privateNameSpace;
4462          for(link = (BTNamedLink)app.publicNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4463             ((DefinedExpression)link.data).nameSpace = &app.publicNameSpace;
4464
4465          for(link = (BTNamedLink)app.privateNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4466             ((GlobalFunction)link.data).nameSpace = &app.privateNameSpace;
4467          for(link = (BTNamedLink)app.publicNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4468             ((GlobalFunction)link.data).nameSpace = &app.publicNameSpace;
4469
4470          for(nameSpace = (NameSpace *)app.privateNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4471             nameSpace->parent = &app.privateNameSpace;
4472          for(nameSpace = (NameSpace *)app.publicNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4473             nameSpace->parent = &app.publicNameSpace;
4474
4475          // --------------------------------------------------
4476          for(link = (BTNamedLink)app.systemNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4477          {
4478             OldLink t;
4479             ((Class)link.data).nameSpace = &app.systemNameSpace;
4480             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4481          }
4482          for(link = (BTNamedLink)app.systemNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4483             ((DefinedExpression)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(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4487             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4488          for(nameSpace = (NameSpace *)app.systemNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4489             nameSpace->parent = &app.systemNameSpace;
4490          // --------------------------------------------------
4491          
4492          for(_class = app.classes.first; _class; _class = _class.next)
4493          {
4494             OldLink templateLink;
4495             _class.module = (Module) app;
4496             for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4497             {  
4498                Class template = templateLink.data;
4499                template.module = _class.module;
4500             }
4501          }
4502
4503          for(module = app.allModules.first; module; module = module.next)
4504          {
4505             for(_class = module.classes.first; _class; _class = _class.next)
4506             {
4507                OldLink templateLink;
4508                _class.module = module;
4509                for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4510                {
4511                   Class template = templateLink.data;
4512                   template.module = _class.module;
4513                }
4514             }
4515          }
4516
4517          app.application = app;
4518       }
4519
4520       {
4521          Class base;
4522          for(base = instance._class; base && base.type == normalClass && base.count; base = base.base)
4523             (base.templateClass ? base.templateClass : base).count--;
4524       }
4525
4526       instance._class = _class;
4527       // Copy the virtual table initially
4528       instance._vTbl = _class._vTbl;
4529
4530       // We don't want to reconstruct the portion already constructed...
4531       if(!ConstructInstance(instance, _class, fromClass))
4532       {
4533          _free(instance);
4534          *instancePtr = null;
4535       }
4536    }
4537 }
4538
4539 public dllexport void eInstance_Delete(Instance instance)
4540 {
4541 #ifdef MEMINFO
4542    bool checkMemory = false;
4543 #endif
4544    if(instance)
4545    {
4546       Class _class, base;
4547       bool ownVtbl;
4548
4549 #ifdef MEMINFO
4550       if(instance._class == (void *)0xecececec)
4551          _free(instance);
4552 #endif
4553
4554       ownVtbl = instance._vTbl != instance._class._vTbl;
4555
4556       for(_class = instance._class; _class; _class = base)
4557       {
4558          if(_class.templateClass) _class = _class.templateClass;
4559          if(_class.destructionWatchOffset)
4560          {
4561             OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
4562             Watcher watcher, next;
4563
4564             for(watcher = watchers->first; watcher; watcher = next)
4565             {
4566                next = watcher.next;
4567                watchers->Remove(watcher);
4568                watcher.callback(watcher.object, instance);
4569                watchers->Delete(watcher);
4570             }
4571          }
4572
4573          /*// Loop through properties to delete all watchers? Might slow down destruction...
4574          {
4575             Property _property;
4576             for(_property = _class.membersAndProperties.first; _property; _property = _property.next)
4577             {
4578                if(_property.isProperty && _property.isWatchable)
4579                {
4580                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
4581                   Watcher watcher, next;
4582                   for(watcher = watchers->first; watcher; watcher = next)
4583                   {  
4584                      next = watcher.next;
4585                      watchers->Delete(watcher);
4586                   }
4587                }
4588             }
4589          }*/
4590          
4591
4592          base = _class.base;
4593          if(base && (base.type == systemClass || base.isInstanceClass)) base = null;
4594          if(_class.Destructor)
4595             _class.Destructor(instance);
4596 #ifdef MEMINFO
4597          if(_class == class(Application))
4598             checkMemory = true;
4599 #endif
4600       }
4601
4602       for(_class = instance._class; _class; _class = base)
4603       {
4604          if(_class.templateClass) _class = _class.templateClass;
4605
4606          base = _class.base;
4607          (_class.templateClass ? _class.templateClass : _class).count--;
4608          if(_class.type == normalClass && !_class.count && !_class.module)
4609          {
4610 #ifdef MEMINFO
4611             // printf("Now Destructing class %s\n", _class.name);
4612 #endif
4613             eClass_Unregister(_class);
4614          }
4615       }
4616
4617       if(ownVtbl)
4618       {
4619          delete instance._vTbl;
4620       }
4621       //instance.prop.Free(null);
4622       _free(instance);
4623 #ifdef MEMINFO
4624       if(checkMemory) CheckMemory();
4625 #endif
4626    }
4627 }
4628
4629 public dllexport Property eClass_FindProperty(Class _class, char * name, Module module)
4630 {
4631    //Time startTime = GetTime();
4632    if(_class && name)
4633    {
4634       for(; _class; _class = _class.base)
4635       {
4636          BTNamedLink link;
4637          if(_class.templateClass) _class = _class.templateClass;
4638          link = (BTNamedLink)_class.prop.FindString(name);
4639          if(link)
4640          {
4641             Property _property = (Property)link.data;
4642             if(_property.memberAccess == publicAccess || _class.module == module || !_property.dataTypeString)
4643             {
4644                if(!_property.dataTypeString)
4645                {
4646                   if(_class.module != module)
4647                   {
4648                      if(_property.memberAccess == publicAccess)
4649                         module = _class.module;
4650                      else
4651                      {
4652                         //classFindTotalTime += GetTime() - startTime;
4653                         return null;
4654                      }
4655                   }
4656                }
4657                else
4658                {
4659                   //classFindTotalTime += GetTime() - startTime;
4660                   return _property;
4661                }
4662             }
4663          }
4664          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4665       }
4666    }
4667    //classFindTotalTime += GetTime() - startTime;
4668    return null;
4669 }
4670
4671 static DataMember FindDataMember(OldList list, BinaryTree alist, char * name, uint * offset, int * id, bool searchPrivate, DataMember * subMemberStack, int * subMemberStackPos)
4672 {
4673    BTNamedLink link;
4674    DataMember dataMember;
4675
4676    link = (BTNamedLink)alist.FindString(name);
4677    if(link)
4678    {
4679       dataMember = link.data;
4680       if(dataMember.type == normalMember && (dataMember.memberAccess == publicAccess || searchPrivate || !dataMember.dataTypeString))
4681       {
4682          if(offset)
4683             *offset += dataMember.offset;
4684          if(id) *id = dataMember.id;
4685          return dataMember;
4686       }
4687       return null;
4688    }
4689    for(dataMember = list.first; dataMember; dataMember = dataMember.next)
4690    {
4691       if(!dataMember.isProperty && (dataMember.memberAccess == publicAccess || searchPrivate) && !dataMember.name && (dataMember.type == unionMember || dataMember.type == structMember))
4692       {
4693          DataMember childMember;
4694          if(subMemberStackPos) subMemberStack[(*subMemberStackPos)++] = dataMember;
4695          childMember = FindDataMember(dataMember.members, dataMember.membersAlpha, name, offset, id, searchPrivate, subMemberStack, subMemberStackPos);
4696          if(childMember)
4697          {
4698             if(offset)
4699                *offset += dataMember.offset;
4700             if(id) *id += dataMember.id;
4701             return childMember;
4702          }
4703          if(subMemberStackPos) (*subMemberStackPos)--;
4704       }
4705    }
4706    return null;
4707 }
4708
4709 public dllexport DataMember eClass_FindDataMember(Class _class, char * name, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4710 {
4711    //Time startTime = GetTime();
4712    DataMember dataMember = null;
4713    if(subMemberStackPos) *subMemberStackPos = 0;
4714    if(_class && name)
4715    {
4716       for(; _class; _class = _class.base)
4717       {
4718          if(_class.templateClass) _class = _class.templateClass;
4719          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, null, _class.module == module, subMemberStack, subMemberStackPos);
4720          if(dataMember)
4721          {
4722             if(!dataMember.dataTypeString)
4723             {
4724                if(_class.module != module)
4725                {
4726                   if(dataMember.memberAccess == publicAccess)
4727                      module = _class.module;
4728                   else
4729                   {
4730                      //classFindTotalTime += GetTime() - startTime;
4731                      return null;
4732                   }
4733                }
4734                dataMember = null;
4735             }
4736             else
4737             {
4738                // HACK: Is this good enough? avoiding setting it when adding...
4739                dataMember._class = _class.templateClass ? _class.templateClass : _class;
4740                //classFindTotalTime += GetTime() - startTime;
4741                return dataMember;
4742             }
4743          }
4744          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4745       }
4746    }
4747    //classFindTotalTime += GetTime() - startTime;
4748    return dataMember;
4749 }
4750
4751 public dllexport DataMember eClass_FindDataMemberAndOffset(Class _class, char * name, uint * offset, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4752 {
4753    //Time startTime = GetTime();
4754    DataMember dataMember = null;
4755    if(subMemberStackPos) *subMemberStackPos = 0;
4756    if(offset) *offset = 0;
4757    if(_class)
4758    {
4759       for(; _class; _class = _class.base)
4760       {
4761          if(_class.templateClass) _class = _class.templateClass;
4762          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, offset, null, _class.module == module, subMemberStack, subMemberStackPos);
4763          if(dataMember)
4764          {
4765             if(!dataMember.dataTypeString)
4766             {
4767                if(_class.module != module)
4768                {
4769                   if(dataMember.memberAccess == publicAccess)
4770                      module = _class.module;
4771                   else
4772                   {
4773                      //classFindTotalTime += GetTime() - startTime;
4774                      return null;
4775                   }
4776                }
4777                dataMember = null;
4778             }
4779             else
4780             {
4781                // HACK: Is this good enouh? avoiding setting it when adding...
4782                dataMember._class = _class;
4783                //classFindTotalTime += GetTime() - startTime;
4784                return dataMember;
4785             }
4786          }
4787          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4788       }
4789    }
4790    //classFindTotalTime += GetTime() - startTime;
4791    return dataMember;
4792 }
4793
4794 public dllexport DataMember eClass_FindDataMemberAndId(Class _class, char * name, int * id, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4795 {
4796    //Time startTime = GetTime();
4797    DataMember dataMember = null;
4798    if(subMemberStackPos) *subMemberStackPos = 0;
4799    if(_class)
4800    {
4801       for(; _class; _class = _class.base)
4802       {
4803          if(_class.templateClass) _class = _class.templateClass;
4804          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, id, _class.module == module, subMemberStack, subMemberStackPos);  // TOCHECK: Why was this null? null, null);
4805          if(dataMember)
4806          {
4807             if(!dataMember.dataTypeString)
4808             {
4809                if(_class.module != module)
4810                {
4811                   if(dataMember.memberAccess == publicAccess)
4812                      module = _class.module;
4813                   else
4814                   {
4815                      //classFindTotalTime += GetTime() - startTime;
4816                      return null;
4817                   }
4818                }
4819                dataMember = null;
4820             }
4821             else
4822             {
4823                // HACK: Is this good enouh? avoiding setting it when adding...
4824                dataMember._class = _class;
4825                //classFindTotalTime += GetTime() - startTime;
4826                return dataMember;
4827             }
4828          }
4829          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4830       }
4831    }
4832    //classFindTotalTime += GetTime() - startTime;
4833    return dataMember;
4834 }
4835
4836 public dllexport void eClass_FindNextMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
4837 {
4838    // THIS CODE WILL FIND NEXT MEMBER... (PUBLIC MEMBERS ONLY)
4839    if(*curMember) 
4840    {
4841       *curMember = (*curMember).next;
4842
4843       if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
4844       {
4845          *curMember = subMemberStack[--(*subMemberStackPos)];
4846          *curMember = (*curMember).next;
4847       }
4848
4849       if(subMemberStackPos && *subMemberStackPos > 0)
4850       {
4851          while(*curMember && ((*curMember).memberAccess == privateAccess))
4852             *curMember = (*curMember).next;
4853       }
4854       else
4855          while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
4856          {
4857             DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
4858             if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
4859             if(dataMember && dataMember.memberAccess != privateAccess)
4860             {
4861                *curMember = dataMember;
4862                break;
4863             }
4864             else
4865                *curMember = (*curMember).next;
4866          }
4867
4868       if(subMemberStackPos)
4869       {
4870          while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
4871          {
4872             subMemberStack[(*subMemberStackPos)++] = *curMember;
4873
4874             *curMember = (*curMember).members.first;
4875             while(*curMember && ((*curMember).memberAccess == privateAccess))
4876                *curMember = (*curMember).next;                     
4877          }
4878       }
4879    }
4880    while(!*curMember)
4881    {
4882       if(!*curMember)
4883       {
4884          if(subMemberStackPos && *subMemberStackPos)
4885          {
4886             *curMember = subMemberStack[--(*subMemberStackPos)];
4887             *curMember = (*curMember).next;
4888          }
4889          else
4890          {
4891             Class lastCurClass = *curClass;
4892
4893             if(*curClass == _class) break;     // REACHED THE END
4894
4895             for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass && (*curClass).inheritanceAccess != privateAccess; *curClass = (*curClass).base);
4896             *curMember = (*curClass).membersAndProperties.first;
4897          }
4898
4899          if(subMemberStackPos && *subMemberStackPos > 0)
4900          {
4901             while(*curMember && ((*curMember).memberAccess == privateAccess))
4902                *curMember = (*curMember).next;
4903          }
4904          else
4905             while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
4906             {
4907                DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
4908                if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
4909                if(dataMember && dataMember.memberAccess != privateAccess && dataMember.id >= 0) // Skip _vTbl, _refCount and _class in Instance
4910                {
4911                   *curMember = dataMember;
4912                   break;
4913                }
4914                else
4915                   *curMember = (*curMember).next;
4916             }
4917
4918          if(subMemberStackPos)
4919          {
4920             while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
4921             {
4922                subMemberStack[(*subMemberStackPos)++] = *curMember;
4923
4924                *curMember = (*curMember).members.first;
4925                while(*curMember && (*curMember).memberAccess == privateAccess)
4926                   *curMember = (*curMember).next;                     
4927             }
4928          }
4929       }
4930    }
4931 }
4932
4933 public dllexport void eInstance_SetMethod(Instance instance, char * name, void * function)     // YET TO BE DECIDED:   , Module module)
4934 {
4935    if(instance && name)
4936    {
4937       Class _class;
4938       for(_class = instance._class; _class; _class = _class.base)
4939       {
4940          Method method = (Method)_class.methods.FindString(name);
4941          if(method && method.type == virtualMethod)
4942          {
4943             if(instance._vTbl == instance._class._vTbl)
4944             {
4945                instance._vTbl = _malloc(sizeof(void *) * instance._class.vTblSize);
4946                memcpy(instance._vTbl, instance._class._vTbl,
4947                   sizeof(int(*)()) * instance._class.vTblSize);               
4948             }
4949             instance._vTbl[method.vid] = function ? function : DefaultFunction;
4950          }
4951       }
4952    }
4953 }
4954
4955 public dllexport bool eInstance_IsDerived(Instance instance, Class from)
4956 {
4957    if(instance)
4958    {
4959       Class _class = instance._class;
4960       for(; _class; _class = _class.base)
4961       {
4962          if(_class == from)
4963             return true;
4964       }
4965    }
4966    return false;
4967 }
4968
4969 public dllexport void eInstance_IncRef(Instance instance)
4970 {
4971    if(instance)
4972       instance._refCount++;
4973 }
4974
4975 public dllexport void eInstance_DecRef(Instance instance)
4976 {
4977    if(instance)
4978    {
4979       instance._refCount--;
4980       //if(!instance._refCount)
4981       if(instance._refCount <= 0)
4982       {
4983          eInstance_Delete(instance);
4984       }
4985    }
4986 }
4987
4988 static void FixOffsets(Class _class)
4989 {
4990    OldLink deriv;
4991    _class.structSize += _class.base.structSize - _class.offset;
4992
4993    _class.offset = _class.base.structSize;   
4994
4995    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4996       FixOffsets(deriv.data);
4997 }
4998
4999 public dllexport void eClass_Resize(Class _class, int newSize)
5000 {
5001    OldLink deriv;
5002    _class.structSize = newSize;
5003    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
5004       FixOffsets(deriv.data);
5005 }
5006
5007 public dllexport DataMember eClass_AddDataMember(Class _class, char * name, char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
5008 {
5009    if(_class && name)
5010    {
5011       if(!_class.members.FindString(name)) 
5012       {
5013          DataMember dataMember;
5014
5015          if(alignment)
5016          {
5017             _class.structAlignment = Max(_class.structAlignment, alignment);
5018
5019             if(_class.memberOffset % alignment)
5020                _class.memberOffset += alignment - (_class.memberOffset % alignment);
5021          }
5022          
5023          dataMember = DataMember {
5024             name = CopyString(name);
5025             dataTypeString = CopyString(type);
5026             id = _class.memberID++;
5027             _class = _class;
5028             offset = _class.memberOffset;
5029             memberOffset = size;
5030             memberAccess = declMode;
5031             membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5032          };
5033          _class.membersAndProperties.Add(dataMember);
5034          _class.memberOffset += size;
5035
5036          _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5037          return dataMember;
5038       }
5039    }
5040    return null;
5041 }
5042
5043 public dllexport DataMember eMember_AddDataMember(DataMember member, char * name, char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
5044 {
5045    if(name && !member.membersAlpha.FindString(name)) 
5046    {
5047       DataMember dataMember;
5048
5049       if(alignment)
5050       {
5051          member.structAlignment = Max(member.structAlignment, alignment);
5052
5053          if(member.memberOffset % alignment)
5054             member.memberOffset += alignment - (member.memberOffset % alignment);
5055       }
5056       dataMember = DataMember {
5057          name = CopyString(name);
5058          _class = member._class;
5059          dataTypeString = CopyString(type);
5060          id = member.memberID++;
5061          offset = (member.type == unionMember) ? 0 : member.memberOffset;
5062          memberAccess = declMode;
5063          membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5064       };
5065       member.members.Add(dataMember);
5066       if(member.type == unionMember)
5067       {
5068          if(size > member.memberOffset)
5069             member.memberOffset = size;
5070       }
5071       else
5072          member.memberOffset += size;
5073       member.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5074       return dataMember;
5075    }
5076    return null;
5077 }
5078
5079 public dllexport DataMember eMember_New(DataMemberType type, AccessMode declMode)
5080 {
5081    return DataMember { type = type, memberAccess = declMode, membersAlpha.CompareKey = (void *)BinaryTree::CompareString };
5082 }
5083
5084 static void SetMemberClass(DataMember member, Class _class)
5085 {
5086    DataMember dataMember;
5087    member._class = _class;
5088    for(dataMember = member.members.first; dataMember; dataMember = dataMember.next)
5089       SetMemberClass(dataMember, _class);      
5090 }
5091
5092 public dllexport bool eMember_AddMember(DataMember addTo, DataMember dataMember)
5093 {
5094    if(dataMember.name && addTo.membersAlpha.FindString(dataMember.name))
5095    {
5096       DataMember_Free(dataMember);
5097       delete dataMember;
5098       return false;
5099    }
5100    addTo.members.Add(dataMember);
5101
5102    if(dataMember.name)
5103       addTo.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5104
5105    dataMember._class = addTo._class;
5106    // ? SetMemberClass(dataMember, addTo._class);
5107
5108    //dataMember.id = addTo.memberID++;
5109    dataMember.id = addTo.memberID;
5110    if(dataMember.type == unionMember)
5111       addTo.memberID += 1;
5112    else
5113       addTo.memberID += dataMember.memberID;
5114
5115    addTo.structAlignment = Max(addTo.structAlignment, dataMember.structAlignment);
5116    dataMember.offset = (addTo.type == unionMember) ? 0 : addTo.memberOffset;
5117    if(addTo.type == unionMember)
5118    {
5119       if(dataMember.memberOffset > addTo.memberOffset)
5120          addTo.memberOffset = dataMember.memberOffset;
5121    }
5122    else
5123       addTo.memberOffset += dataMember.memberOffset;
5124    return true;
5125 }
5126
5127 public dllexport bool eClass_AddMember(Class _class, DataMember dataMember)
5128 {
5129    if(!_class || _class.comRedefinition || (dataMember.name && _class.members.FindString(dataMember.name)))
5130    {
5131       DataMember_Free(dataMember);
5132       delete dataMember;
5133       return false;
5134    }
5135    _class.membersAndProperties.Add(dataMember);
5136
5137    if(dataMember.name)
5138       _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5139
5140    //dataMember._class = _class;
5141    SetMemberClass(dataMember, _class);
5142
5143    //dataMember.id = _class.memberID++;
5144    dataMember.id = _class.memberID;
5145
5146    _class.structAlignment = Max(_class.structAlignment, dataMember.structAlignment);
5147    if(dataMember.type == unionMember)
5148       _class.memberID += 1;
5149    else
5150       _class.memberID += dataMember.memberID;
5151    dataMember.offset = _class.memberOffset;
5152    _class.memberOffset += dataMember.memberOffset;
5153    return true;
5154 }
5155
5156 public dllexport BitMember eClass_AddBitMember(Class _class, char * name, char * type, int bitSize, int bitPos, AccessMode declMode)
5157 {
5158    if(_class && name && !_class.members.FindString(name)) 
5159    {
5160       uint64 mask = 0;
5161       int c;
5162       BitMember bitMember
5163       {
5164          name = CopyString(name);
5165          _class = _class;
5166          dataTypeString = CopyString(type);
5167          id = _class.memberID++;
5168          memberAccess = declMode;
5169       };
5170       _class.membersAndProperties.Add(bitMember);
5171       if(bitSize)
5172       {
5173          bitMember.pos = (bitPos == -1) ? _class.memberOffset : bitPos;
5174          bitMember.size = bitSize;
5175          _class.memberOffset = bitMember.pos + bitMember.size;
5176          for(c = 0; c<bitSize; c++)
5177          {
5178             if(c)
5179                mask <<= 1;
5180             mask |= 1;
5181          }
5182          bitMember.mask = mask << bitMember.pos;
5183       }
5184
5185      _class.members.Add((BTNode)BTNamedLink { name = bitMember.name, data = bitMember });
5186       return bitMember;
5187    }
5188    return null;
5189 }
5190
5191 static Module Module_Load(Module fromModule, char * name, AccessMode importAccess, bool ensureCOM)
5192 {
5193    bool (stdcall * Load)(Module module) = null;
5194    bool (stdcall * Unload)(Module module) = null;
5195    Module module;
5196
5197    for(module = fromModule.application.allModules.first; module; module = module.next)
5198    {
5199       if(!strcmp(module.name, name))
5200          break;
5201    }
5202    if(ensureCOM && (!strcmp(name, "ecereCOM") || !strcmp(name, "ecere")))
5203    {
5204       for(module = fromModule.application.allModules.first; module; module = module.next)
5205       {
5206          if(!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM"))
5207             break;
5208       }
5209    }
5210    if(!module)
5211    {
5212       void * library = null;
5213
5214       if(ensureCOM && !strcmp(name, "ecereCOM"))
5215       {
5216          Load = COM_LOAD_FUNCTION;
5217          Unload = COM_UNLOAD_FUNCTION;
5218       }
5219       else
5220       {
5221          char * libLocation = null;
5222 #if defined(__ANDROID__)
5223          libLocation = AndroidInterface_GetLibLocation();
5224 #endif
5225          library = Instance_Module_Load(libLocation, name, &Load, &Unload);
5226       }
5227       if(Load)
5228       {
5229          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5230          module.application = fromModule.application;
5231          module.library = library;
5232          module.name = CopyString(name);
5233          module.Unload = Unload;
5234          module.origImportType = normalImport;
5235
5236          if(!Load(module))
5237          {
5238             eInstance_Delete((Instance)module);
5239             module = null;
5240          }
5241       }
5242       fromModule.application.allModules.Add(module);
5243    }
5244    if(ensureCOM && !strcmp(name, "ecere") && module)
5245    {
5246       name = !strcmp(module.name, "ecereCOM") ? "ecere" : "ecereCOM";
5247       if((!Load && !strcmp(module.name, "ecereCOM")) || 
5248          (Load && (!__thisModule || !__thisModule.name || !strcmp(__thisModule.name, "ecereCOM")) && Load != COM_LOAD_FUNCTION))
5249       {
5250          Module module;
5251          for(module = fromModule.application.allModules.first; module; module = module.next)
5252          {
5253             if(!strcmp(module.name, name))
5254                break;
5255          }
5256          if(!module)
5257          {
5258             Load = COM_LOAD_FUNCTION;
5259             Unload = COM_UNLOAD_FUNCTION;
5260
5261             module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5262             module.application = fromModule.application;
5263             module.library = null;
5264             module.name = CopyString(name);
5265             module.Unload = Unload;
5266
5267             if(!Load(module))
5268             {
5269                eInstance_Delete((Instance)module);
5270                module = null;
5271             }
5272
5273             fromModule.application.allModules.Add(module);
5274          }
5275          if(module)
5276          {
5277             if(fromModule)
5278             {
5279                fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5280             }
5281             incref module;
5282          }
5283       }
5284    }
5285    if(module)
5286    {
5287       if(fromModule)
5288       {
5289          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5290       }
5291       incref module;
5292    }
5293 #if defined(_DEBUG)
5294    InternalModuleLoadBreakpoint();
5295 #endif
5296    return module;
5297 }
5298
5299 public dllexport Module eModule_Load(Module fromModule, char * name, AccessMode importAccess)
5300 {
5301    return Module_Load(fromModule, name, importAccess, true);
5302 }
5303
5304 public dllexport Module eModule_LoadStrict(Module fromModule, char * name, AccessMode importAccess)
5305 {
5306    return Module_Load(fromModule, name, importAccess, false);
5307 }
5308
5309 public dllexport Module eModule_LoadStatic(Module fromModule, char * name, AccessMode importAccess, bool (* Load)(Module module), bool (* Unload)(Module module))
5310 {
5311    Module module;
5312    for(module = fromModule.application.allModules.first; module; module = module.next)
5313    {
5314       if(!strcmp(module.name, name))
5315          break;
5316    }
5317    if(!module)
5318    {
5319       if(Load)
5320       {
5321          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5322          module.application = fromModule.application;
5323          module.name = CopyString(name);
5324          module.origImportType = staticImport;
5325          module.Unload = (void *)Unload;
5326          if(!Load(module))
5327          {
5328             eInstance_Delete((Instance)module);
5329             module = null;
5330          }
5331       }
5332       fromModule.application.allModules.Add(module);
5333    }
5334    if(module)
5335    {
5336       if(fromModule)
5337       {
5338          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5339       }
5340       incref module;
5341    }
5342    return module;
5343 }
5344
5345 public dllexport void eModule_Unload(Module fromModule, Module module)
5346 {
5347    OldLink m;
5348    for(m = fromModule.modules.first; m; m = m.next)
5349    {
5350       if(m.data == module)
5351          break;
5352    }
5353    if(m)
5354    {
5355       fromModule.modules.Delete(m);
5356       delete module;
5357    }
5358 }
5359
5360 public dllexport void eEnum_AddFixedValue(Class _class, char * string, int value)
5361 {
5362    if(_class && _class.type == enumClass)
5363    {
5364       EnumClassData data = (EnumClassData)_class.data;
5365       NamedLink item;
5366       
5367       for(item = data.values.first; item; item = item.next)
5368          if(!strcmp(item.name, string)) 
5369             break;
5370       if(!item)
5371       {
5372          data.values.Add(NamedLink { data = (void *)value, name = CopyString(string) });
5373          if(value > data.largest)
5374             data.largest = value;
5375       }
5376    }
5377 }
5378
5379 public dllexport int eEnum_AddValue(Class _class, char * string)
5380 {
5381    if(_class && _class.type == enumClass)
5382    {
5383       EnumClassData data = (EnumClassData)_class.data;
5384       int value = ((int) data.largest) + 1;
5385       NamedLink item;
5386       for(item = data.values.first; item; item = item.next)
5387          if(!strcmp(item.name, string)) 
5388             break;
5389       if(!item)
5390       {
5391          data.values.Add(NamedLink { data = (void *)value, name = CopyString(string) });
5392          if(value > data.largest)
5393             data.largest = value;
5394          return value;
5395       }
5396    }
5397    return -1;
5398 }
5399
5400 static void NameSpace_Free(NameSpace parentNameSpace)
5401 {
5402    NameSpace * nameSpace;
5403    delete parentNameSpace.name;
5404
5405    while((nameSpace = (NameSpace *)parentNameSpace.nameSpaces.first))
5406    {
5407       NameSpace_Free(nameSpace);
5408       parentNameSpace.nameSpaces.Delete((BTNode)nameSpace);
5409    }
5410 }
5411
5412 static void Application_Destructor(Application app)
5413 {
5414    if(app.parsedCommand)
5415    {
5416       delete app.argv;
5417       delete app.parsedCommand;
5418    }
5419 }
5420
5421 static bool Module_Constructor(Module module)
5422 {
5423    module.privateNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5424    module.privateNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5425    module.privateNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5426    module.privateNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5427
5428    module.publicNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5429    module.publicNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5430    module.publicNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5431    module.publicNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5432    return true;
5433 }
5434
5435 static void Module_Destructor(Module module)
5436 {
5437    Class _class;
5438    DefinedExpression def;
5439    GlobalFunction function;
5440    Module m;
5441    SubModule handle;
5442
5443    // printf("Destructing module %s\n", module.name);
5444
5445    // Take out references from all modules
5446    for(m = module.application.allModules.first; m; m = m.next)
5447    {
5448       SubModule next;
5449       for(handle = m.modules.first; handle; handle = next)
5450       {
5451          next = handle.next;
5452          if(handle.module == module)
5453             m.modules.Delete(handle);
5454       }
5455    }
5456
5457    if(module.Unload)
5458    {
5459       if(module.origImportType == staticImport)
5460       {
5461          bool (* Unload)(Module module) = (void *)module.Unload;
5462          Unload(module);
5463       }
5464       else
5465       {
5466          bool (stdcall * Unload)(Module module) = (void *)module.Unload;
5467          Unload(module);
5468       }
5469    }
5470
5471    // Unload dependencies
5472    {
5473       Module ourWorld = class(Class).module;
5474       void * ourHandle = null;
5475       while((handle = module.modules.last))  // STARTING WITH LAST SO THAT ecereCOM IS UNLOADED LAST...
5476       {
5477          Module depModule = handle.module;
5478          if(depModule == ourWorld) 
5479          {
5480             module.modules.Remove(handle);
5481             ourHandle = handle;
5482          }
5483          else
5484          {
5485             module.modules.Delete(handle);
5486             delete depModule;
5487          }         
5488       }
5489       if(ourHandle)
5490       {
5491          delete ourHandle;
5492          delete ourWorld;
5493       }
5494    }
5495
5496    // Unload classes
5497    for(;(_class = module.classes.first);)
5498    {
5499       if(_class.nameSpace)
5500       {
5501          BTNamedLink classLink = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
5502          OldLink t;
5503          for(t = _class.templatized.first; t; t = t.next)
5504          {
5505             Class template = t.data;
5506             BTNamedLink link;
5507             link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
5508
5509             template.nameSpace->classes.Delete((BTNode)link);
5510             template.nameSpace = null;
5511          }
5512          _class.nameSpace->classes.Delete((BTNode)classLink);
5513          _class.nameSpace = null;
5514       }
5515       _class.module = null;
5516       module.classes.Remove(_class);
5517       if(_class.count <= 0 || _class.type != normalClass || _class.isInstanceClass)
5518          eClass_Unregister(_class);
5519       else
5520       {
5521 #ifdef MEMINFO
5522          // printf("Delayed destruction of class %s\n", _class.name);
5523 #endif
5524       }
5525    }
5526
5527    // Unload defines
5528    for(;(def = module.defines.first);)
5529    {
5530       if(def.nameSpace)
5531       {
5532          BTNamedLink defLink;
5533          for(defLink = (BTNamedLink)def.nameSpace->defines.first; defLink; defLink = (BTNamedLink)((BTNode)defLink).next)
5534             if(defLink.data == def)
5535             {
5536                def.nameSpace->defines.Delete((BTNode)defLink);
5537                break;
5538             }
5539       }
5540       delete def.name;
5541       delete def.value;
5542       module.defines.Delete(def);
5543    }
5544
5545    // Unload functions
5546    for(;(function = module.functions.first);)
5547    {
5548       if(function.nameSpace)
5549       {
5550          BTNamedLink functionLink;
5551          for(functionLink = (BTNamedLink)function.nameSpace->functions.first; functionLink; functionLink = (BTNamedLink)((BTNode)functionLink).next)
5552             if(functionLink.data == function)
5553             {
5554                function.nameSpace->functions.Delete((BTNode)functionLink);
5555                break;
5556             }
5557       }
5558       delete function.name;
5559       delete function.dataTypeString;
5560       module.functions.Delete(function);
5561    }
5562
5563    delete module.name;
5564
5565    NameSpace_Free(module.privateNameSpace);
5566    NameSpace_Free(module.publicNameSpace);
5567
5568    if(module != module.application)
5569       module.application.allModules.Remove(module);
5570    else
5571       NameSpace_Free(module.application.systemNameSpace);
5572
5573 #ifndef MEMINFO
5574    Instance_Module_Free(module.library);
5575 #endif
5576 }
5577
5578 static int64 GetEnumSize(Class _class)
5579 {
5580    EnumClassData data = (EnumClassData)_class.data;
5581    return data.largest+1;
5582 }
5583
5584 #if defined(__GNUC__)
5585 #define strcmpi strcasecmp
5586 #define strnicmp strncasecmp
5587 #endif
5588
5589 #if defined(ECERE_BOOTSTRAP) || (defined(__GNUC__) && !defined(__DJGPP__) && !defined(__WIN32__))
5590 #undef strlwr
5591 #undef strupr
5592 default dllexport char * strlwr(char *string)
5593 {
5594    int c;
5595    for(c=0; string[c]; c++)
5596       if(string[c]>='A' && string[c]<='Z')
5597          string[c]+='a'-'A';
5598    return string;
5599 }
5600 default dllexport char * strupr(char *string)
5601 {
5602    int c;
5603    for(c=0; string[c]; c++)
5604       if(string[c]>='a' && string[c]<='z')
5605          string[c]-='a'-'A';
5606    return string;
5607 }
5608 #endif
5609
5610 public dllexport DefinedExpression eSystem_RegisterDefine(char * name, char * value, Module module, AccessMode declMode)
5611 {
5612    NameSpace * nameSpace = null;
5613    
5614    int start = 0, c;
5615
5616    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5617    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5618
5619    if(declMode != staticAccess)
5620    {
5621       for(c = 0; name[c]; c++)
5622       {
5623          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5624          {
5625             NameSpace * newSpace;
5626
5627             char * spaceName = _malloc(c - start + 1);
5628             strncpy(spaceName, name + start, c - start);
5629             spaceName[c-start] = '\0';
5630
5631             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5632             if(!newSpace)
5633             {
5634                newSpace = new0 NameSpace[1];
5635                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5636                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5637                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5638                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5639                newSpace->name = spaceName;
5640                newSpace->parent = nameSpace;
5641                nameSpace->nameSpaces.Add((BTNode)newSpace);
5642             }
5643             else
5644                delete spaceName;
5645             nameSpace = newSpace;
5646             if(name[c] == ':') c++;
5647             start = c+1;         
5648          }
5649       }
5650    }
5651    else
5652       c = strlen(name);
5653
5654    if(c - start && !nameSpace->defines.FindString(name + start))
5655    {
5656       DefinedExpression def
5657       {
5658          name = CopyString(name);
5659          nameSpace = nameSpace;
5660          value = CopyString(value);
5661       };
5662       nameSpace->defines.Add((BTNode)BTNamedLink { name = def.name + start, data = def });
5663       // Reference the definition in the module
5664       module.defines.Add(def);
5665       return def;
5666    }
5667    return null;
5668 }
5669
5670 public dllexport GlobalFunction eSystem_RegisterFunction(char * name, char * type, void * func, Module module, AccessMode declMode)
5671 {
5672    NameSpace * nameSpace = null;
5673    int start = 0, c;
5674
5675    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5676    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5677
5678    if(declMode != staticAccess)
5679    {
5680       for(c = 0; name[c]; c++)
5681       {
5682          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5683          {
5684             NameSpace * newSpace;
5685
5686             char * spaceName = _malloc(c - start + 1);
5687             strncpy(spaceName, name + start, c - start);
5688             spaceName[c-start] = '\0';
5689
5690             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5691             if(!newSpace)
5692             {
5693                newSpace = new0 NameSpace[1];
5694                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5695                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5696                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5697                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5698                newSpace->name = spaceName;
5699                newSpace->parent = nameSpace;
5700                nameSpace->nameSpaces.Add((BTNode)newSpace);
5701             }
5702             else
5703                delete spaceName;
5704             nameSpace = newSpace;
5705             if(name[c] == ':') c++;
5706             start = c+1;         
5707          }
5708       }
5709    }
5710    else
5711       c = strlen(name);
5712
5713    if(c - start && !nameSpace->functions.FindString(name + start))
5714    {
5715       GlobalFunction function
5716       {
5717          name = CopyString(name);
5718          nameSpace = nameSpace;
5719          dataTypeString = CopyString(type);
5720          function = func;
5721          module = module;
5722       };
5723       nameSpace->functions.Add((BTNode)BTNamedLink { name = function.name + start, data = function });
5724       // Reference the definition in the module
5725       module.functions.Add(function);
5726       return function;
5727    }
5728    return null;
5729 }
5730
5731 public dllexport DefinedExpression eSystem_FindDefine(Module module, char * name)
5732 {
5733    if(name && module)
5734    {
5735       BTNamedLink link;
5736       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->defines);
5737       if(link) return link.data;
5738
5739       link = SearchModule(module, name, &((NameSpace *)0)->defines, true);
5740       if(link) return link.data;
5741    }
5742    return null;
5743 }
5744
5745 public dllexport GlobalFunction eSystem_FindFunction(Module module, char * name)
5746 {
5747    if(name && module)
5748    {
5749       BTNamedLink link;
5750       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->functions);
5751       if(link) return link.data;
5752
5753       link = SearchModule(module, name, &((NameSpace *)0)->functions, true);
5754       if(link) return link.data;
5755    }
5756    return null;
5757 }
5758
5759 public dllexport void * eSystem_Renew(void * memory, unsigned int size)
5760 {
5761    return _realloc(memory, size);
5762 }
5763
5764 public dllexport void * eSystem_Renew0(void * memory, unsigned int size)
5765 {
5766    return _crealloc(memory, size);
5767 }
5768
5769 public dllexport void * eSystem_New(unsigned int size)
5770 {
5771 /*#ifdef _DEBUG
5772    void * pointer = _malloc(size);
5773    memset(pointer, 0xec, size);
5774    return pointer;
5775 #else*/
5776    return _malloc(size);
5777 //#endif
5778 }
5779
5780 public dllexport void * eSystem_New0(unsigned int size)
5781 {
5782    return _calloc(1,size);
5783 }
5784
5785 public dllexport void eSystem_Delete(void * memory)
5786 {
5787    if(memory)
5788       _free(memory);
5789 }
5790
5791 // Properties
5792 public dllexport void eInstance_FireSelfWatchers(Instance instance, Property _property)
5793 {
5794    if(instance && _property && _property.selfWatchable)
5795    {
5796       Class _class;
5797       for(_class = instance._class; _class; _class = _class.base)
5798       {
5799          SelfWatcher selfWatcher, next;
5800          for(selfWatcher = _class.selfWatchers.first; selfWatcher; selfWatcher = next)
5801          {
5802             next = selfWatcher.next;
5803             if(selfWatcher._property == _property)
5804                selfWatcher.callback(instance);
5805          }
5806       }
5807    }
5808 }
5809
5810 public dllexport void eInstance_FireWatchers(Instance instance, Property _property)
5811 {
5812    if(instance && _property && _property.isWatchable)
5813    {
5814       Module module = instance._class ? instance._class.module : null;
5815       Application application = module ? module.application : null;
5816       int flags = application ? application.isGUIApp : 0;
5817       bool inCompiler = (flags & 8) ? true : false;
5818       bool force32Bits = (flags & 4) ? true : false;
5819       if(!force32Bits || !inCompiler)
5820       {
5821          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5822          Watcher watcher, next;
5823
5824          for(watcher = watchers->first; watcher; watcher = next)
5825          {
5826             next = watcher.next;
5827             watcher.callback(watcher.object, instance);
5828          }
5829       }
5830    }
5831 }
5832
5833 public dllexport void eProperty_Watchable(Property _property)
5834 {
5835    if(!_property.isWatchable)
5836    {
5837       Class _class = _property._class;
5838       if(!_class.computeSize)
5839       {
5840          _property.watcherOffset = _class.structSize;
5841          _class.structSize += sizeof(OldList);
5842
5843          // highly inefficient
5844          FixDerivativesBase(_class, _class);
5845       }
5846       _property.isWatchable = true;
5847    }
5848 }
5849
5850 public dllexport void eClass_DestructionWatchable(Class _class)
5851 {
5852    if(!_class.destructionWatchOffset)
5853    {
5854       _class.destructionWatchOffset = _class.structSize;
5855       _class.structSize += sizeof(OldList);
5856       // highly inefficient
5857       FixDerivativesBase(_class, _class);
5858    }
5859 }
5860
5861 public dllexport void eProperty_SelfWatch(Class _class, char * name, void (*callback)(void *))
5862 {
5863    if(_class)
5864    {
5865       Property _property = eClass_FindProperty(_class, name, _class.module);
5866       
5867       if(!_property)
5868          _property = eClass_AddProperty(_class, name, null, null, null, baseSystemAccess /*privateAccess*/);
5869       _class.selfWatchers.Add(SelfWatcher { _property = _property, callback = callback });
5870       _property.selfWatchable = true;
5871    }
5872 }
5873
5874 public dllexport void eInstance_Watch(void * instance, Property _property, void * object, void (*callback)(void *, void *))
5875 {
5876    if(_property.isWatchable)
5877    {
5878       OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5879       watchers->Add(Watcher { callback = callback, object = object });
5880    }
5881 }
5882
5883 public dllexport void eInstance_WatchDestruction(Instance instance, Instance object, void (*callback)(Instance, Instance))
5884 {
5885    OldList * watchers = (OldList *)((byte *)instance + instance._class.destructionWatchOffset);
5886    watchers->Add(Watcher { callback = callback, object = object });
5887 }
5888
5889 public dllexport void eInstance_StopWatching(Instance instance, Property _property, Instance object)
5890 {
5891    if(instance && (!_property || _property.isWatchable))
5892    {
5893       if(_property)
5894       {
5895          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5896          Watcher watcher;
5897          for(watcher = watchers->first; watcher; watcher = watcher.next)
5898             if(watcher.object == object)
5899             {
5900                watchers->Delete(watcher);
5901                break;
5902             }
5903       }
5904       else
5905       {
5906          // Stop watching all properties as well as destruction
5907          Class _class, base;
5908          for(_class = instance._class; _class; _class = base)
5909          {
5910             if(_class.destructionWatchOffset)
5911             {
5912                OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
5913                Watcher watcher;
5914
5915                for(watcher = watchers->first; watcher; watcher = watcher.next)
5916                {
5917                   watchers->Delete(watcher);
5918                   break;
5919                }
5920             }
5921             for(_property = (Property)_class.membersAndProperties.first; _property; _property = _property.next)
5922             {
5923                if(_property.isProperty && _property.isWatchable)
5924                {
5925                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5926                   Watcher watcher;
5927                   for(watcher = watchers->first; watcher; watcher = watcher.next)
5928                      if(watcher.object == object)
5929                      {
5930                         watchers->Delete(watcher);
5931                         break;
5932                      }
5933                }
5934             }
5935             base = _class.base;
5936             if(base && (base.type == systemClass || base.isInstanceClass)) base = null;
5937          }
5938       }
5939    }
5940 }
5941
5942 public dllexport subclass(ClassDesignerBase) eClass_GetDesigner(Class _class)
5943 {
5944    for(;_class;_class = _class.base)
5945    {
5946       if(_class.designerClass)
5947          return (subclass(ClassDesignerBase))eSystem_FindClass(_class.module, _class.designerClass);
5948    }
5949    return null;
5950 }
5951
5952
5953 public dllexport subclass(ClassDesignerBase) eInstance_GetDesigner(Instance instance)
5954 {
5955    if(instance)
5956       return eClass_GetDesigner(instance._class);
5957    return null;
5958 }
5959
5960 public bool LocateModule(char * name, char * fileName)
5961 {
5962    return Instance_LocateModule(name, fileName);
5963 }
5964
5965 static void LoadCOM(Module module)
5966 {
5967    bool force64Bits = (module.application.isGUIApp & 2) ? true : false;
5968    bool force32Bits = (module.application.isGUIApp & 4) ? true : false;
5969    bool inCompiler = (module.application.isGUIApp & 8) ? true : false;
5970    int pointerSize = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
5971    Class applicationClass;
5972    Class enumClass, structClass, boolClass;
5973    Class moduleClass;
5974
5975    // Create Base Class
5976    Class baseClass = eSystem_RegisterClass(normalClass, "class", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5977    baseClass.type = systemClass;
5978    baseClass.memberOffset = 0;
5979    baseClass.offset = 0;
5980    baseClass.structSize = 0;
5981    baseClass.typeSize = 0;
5982
5983    {
5984       Class instanceClass = eSystem_RegisterClass(normalClass, "ecere::com::Instance", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5985       instanceClass.type = normalClass;
5986       instanceClass.isInstanceClass = true;
5987       instanceClass.fixed = true;
5988       instanceClass.memberOffset = 0;
5989       instanceClass.offset = 0;
5990
5991       instanceClass.memberID = -3;
5992       instanceClass.startMemberID = -3;
5993
5994       eClass_AddDataMember(instanceClass, "_vTbl", "int (**)()", pointerSize, pointerSize, publicAccess);
5995       eClass_AddDataMember(instanceClass, "_class", "ecere::com::Class", pointerSize, pointerSize, publicAccess);
5996       eClass_AddDataMember(instanceClass, "_refCount", "int", sizeof(int), sizeof(int), publicAccess);
5997    }
5998
5999    InitializeDataTypes1(module);
6000
6001    // Create Enum class
6002    enumClass = eSystem_RegisterClass(normalClass, "enum", null, 0, force64Bits ? 40 : sizeof(class EnumClassData), null, null, module, baseSystemAccess, publicAccess);
6003    eClass_AddClassProperty(enumClass, "enumSize", "int", null, GetEnumSize).constant = true;
6004    enumClass.type = systemClass;
6005    
6006    delete enumClass.dataTypeString;
6007    enumClass.dataTypeString = CopyString(/*"unsigned int"*/"int");
6008
6009    // Create Struct (simple) class
6010    //structClass = eSystem_RegisterClass(structClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6011    structClass = eSystem_RegisterClass(normalClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6012    structClass.type = systemClass;
6013    structClass.memberOffset = 0;
6014    structClass.offset = 0;
6015    structClass.structSize = 0;
6016    structClass.typeSize = 0;
6017
6018    //eClass_AddMethod(enumClass, "AddValue", "int()", eEnum_AddValue);
6019    //eClass_AddMethod(enumClass, "AddFixedValue", "void()", eEnum_AddFixedValue);
6020
6021    InitializeDataTypes(module);
6022
6023    // Create bool class
6024    boolClass = eSystem_RegisterClass(ClassType::enumClass, "bool", "uint", 0, 0, null, null, module, baseSystemAccess, publicAccess);
6025    eEnum_AddFixedValue(boolClass, "true",  bool::true);
6026    eEnum_AddFixedValue(boolClass, "false", bool::false);
6027
6028    // Create Module class
6029    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) :
6030                                                                                 sizeof(struct Module), 0, (void *)Module_Constructor, (void *)Module_Destructor, module, baseSystemAccess, publicAccess);
6031    eClass_AddVirtualMethod(moduleClass, "OnLoad", "bool()", null, publicAccess);
6032    eClass_AddVirtualMethod(moduleClass, "OnUnload", "void()", null, publicAccess);
6033    eClass_AddMethod(moduleClass, "Load", "Module(char * name, AccessMode importAccess)", eModule_Load, publicAccess);
6034    eClass_AddMethod(moduleClass, "Unload", "void(Module module)", eModule_Unload, publicAccess);
6035    eClass_AddDataMember(moduleClass, "application", "Application", pointerSize, pointerSize, publicAccess);
6036    eClass_AddDataMember(moduleClass, "classes", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6037    eClass_AddDataMember(moduleClass, "defines", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6038    eClass_AddDataMember(moduleClass, "functions", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6039    eClass_AddDataMember(moduleClass, "modules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6040    eClass_AddDataMember(moduleClass, "prev", "Module", pointerSize, pointerSize, publicAccess);
6041    eClass_AddDataMember(moduleClass, "next", "Module", pointerSize, pointerSize, publicAccess);
6042    eClass_AddDataMember(moduleClass, "name", "char *", pointerSize, pointerSize, publicAccess);
6043    eClass_AddDataMember(moduleClass, "library", "void *", pointerSize, pointerSize, publicAccess);
6044    eClass_AddDataMember(moduleClass, "Unload", "void *", pointerSize, pointerSize, publicAccess);
6045    eClass_AddDataMember(moduleClass, "importType", "ImportType", sizeof(ImportType), 4, publicAccess);
6046    eClass_AddDataMember(moduleClass, "origImportType", "ImportType", sizeof(ImportType), 4, publicAccess);
6047    eClass_AddDataMember(moduleClass, "privateNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6048    eClass_AddDataMember(moduleClass, "publicNameSpace", "NameSpace",  force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6049    moduleClass.fixed = true;
6050    moduleClass.count++;
6051    if(inCompiler && force32Bits)
6052       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);
6053    
6054    // Create Application class
6055    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);
6056    if(inCompiler && force32Bits)
6057    {
6058       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);
6059       applicationClass.structSize = applicationClass.offset + (4+4+4+4 + 20 + 4 + 88);
6060    }
6061    eClass_AddVirtualMethod(applicationClass, "Main", "void()", null, publicAccess);
6062    eClass_AddDataMember(applicationClass, "argc", "int", sizeof(int), 4, publicAccess);
6063    eClass_AddDataMember(applicationClass, "argv", "char **", pointerSize, pointerSize, publicAccess);
6064    eClass_AddDataMember(applicationClass, "exitCode", "int", sizeof(int), 4, publicAccess);
6065    eClass_AddDataMember(applicationClass, "isGUIApp", "bool", sizeof(bool), 4, publicAccess);
6066    eClass_AddDataMember(applicationClass, "allModules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6067    eClass_AddDataMember(applicationClass, "parsedCommand", "char *", pointerSize, pointerSize, publicAccess);
6068    eClass_AddDataMember(applicationClass, "systemNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6069    applicationClass.fixed = true;
6070    applicationClass.count++;
6071
6072    //AttachConsole(-1);
6073    //AllocConsole();
6074
6075    // --- Math ---
6076    eSystem_RegisterFunction("sin", "double sin(Angle number)", sin, module, baseSystemAccess);
6077    eSystem_RegisterFunction("sinh", "double sinh(Angle number)", sinh, module, baseSystemAccess);
6078    eSystem_RegisterFunction("cosh", "double cosh(Angle number)", cosh, module, baseSystemAccess);
6079    eSystem_RegisterFunction("tanh", "double tanh(Angle number)", tanh, module, baseSystemAccess);
6080    eSystem_RegisterFunction("sqrt", "double sqrt(double number)", sqrt, module, baseSystemAccess);
6081    eSystem_RegisterFunction("cos", "double cos(Angle number)", cos, module, baseSystemAccess);
6082    eSystem_RegisterFunction("tan", "double tan(Angle number)", tan, module, baseSystemAccess);
6083    eSystem_RegisterFunction("atan2", "Angle atan2(double y, double x)", atan2, module, baseSystemAccess);
6084    eSystem_RegisterFunction("asin", "Angle asin(double number)", asin, module, baseSystemAccess);
6085    eSystem_RegisterFunction("acos", "Angle acos(double number)", acos, module, baseSystemAccess);
6086    eSystem_RegisterFunction("atan", "Angle atan(double number)", atan, module, baseSystemAccess);
6087    eSystem_RegisterFunction("pow", "double pow(double number, double number2)", pow, module, baseSystemAccess);
6088    eSystem_RegisterFunction("fmod", "double fmod(double x, double y)", fmod, module, baseSystemAccess);
6089    eSystem_RegisterFunction("fabs", "double fabs(double number)", fabs, module, baseSystemAccess);
6090    eSystem_RegisterFunction("log", "double log(double number)", log, module, baseSystemAccess);
6091    eSystem_RegisterFunction("log10", "double log10(double number)", log10, module, baseSystemAccess);
6092    eSystem_RegisterFunction("ceil", "double ceil(double number)", ceil, module, baseSystemAccess);
6093    eSystem_RegisterFunction("floor", "double floor(double number)", floor, module, baseSystemAccess);
6094    eSystem_RegisterFunction("exp", "double exp(double number)", exp, module, baseSystemAccess);
6095
6096    // --- Stdlib ---
6097    eSystem_RegisterFunction("qsort", "void qsort(void *, uintsize, uintsize, int (*)(void *, void *))", qsort, module, baseSystemAccess);
6098    eSystem_RegisterFunction("strtod", "double strtod(char*, char**)", strtod, module, baseSystemAccess);
6099    eSystem_RegisterFunction("strtol", "int strtol(char*, char**, int base)", strtol, module, baseSystemAccess);
6100    eSystem_RegisterFunction("system", "int system(const char*)", system, module, baseSystemAccess);
6101    eSystem_RegisterFunction("atoi", "int atoi(const char*)", atoi, module, baseSystemAccess);
6102    eSystem_RegisterFunction("atof", "double atof(const char*)", atof, module, baseSystemAccess);
6103    eSystem_RegisterFunction("tolower", "int tolower(int)", tolower, module, baseSystemAccess);
6104    eSystem_RegisterFunction("toupper", "int toupper(int)", toupper, module, baseSystemAccess);
6105    eSystem_RegisterFunction("isdigit", "bool isdigit(int)", isdigit, module, baseSystemAccess);
6106    eSystem_RegisterFunction("memset", "void * memset(void * area, int value, uintsize count)", memset, module, baseSystemAccess);
6107    eSystem_RegisterFunction("getenv", "char * getenv(const char * name)", getenv, module, baseSystemAccess);
6108    eSystem_RegisterFunction("rename", "int rename(const char *oldpath, const char *newpath)", rename, module, baseSystemAccess);
6109
6110    // --- String --- (These might move to the string class)
6111    eSystem_RegisterFunction("strlen", "uintsize strlen(const char *)", strlen, module, baseSystemAccess);
6112    eSystem_RegisterFunction("strcat", "char * strcat(char *, const char *)", strcat, module, baseSystemAccess);
6113    eSystem_RegisterFunction("strncat", "char * strncat(char *, const char *, uintsize n)", strncat, module, baseSystemAccess);
6114    eSystem_RegisterFunction("strchr", "char * strchr(const char *, int)", strchr, module, baseSystemAccess);
6115    eSystem_RegisterFunction("strstr", "char * strstr(const char *, const char *)", strstr, module, baseSystemAccess);
6116
6117    eSystem_RegisterDefine("fstrcmp", "(GetRuntimePlatform() == win32) ? strcmpi : strcmp", module, baseSystemAccess);
6118
6119 //#if defined(__GNUC__)
6120    eSystem_RegisterDefine("strcmpi", "strcasecmp", module, baseSystemAccess);
6121    eSystem_RegisterDefine("strnicmp", "strncasecmp", module, baseSystemAccess);
6122    eSystem_RegisterFunction("strcasecmp", "int strcasecmp(const char *, const char *)", strcmpi, module, baseSystemAccess);
6123    eSystem_RegisterFunction("strncasecmp", "int strncasecmp(const char *, const char *, uintsize n)", strnicmp, module, baseSystemAccess);
6124 /*
6125 #else
6126    eSystem_RegisterDefine("strcasecmp", "strcmpi", module, baseSystemAccess);
6127    eSystem_RegisterDefine("strncasecmp", "strnicmp", module, baseSystemAccess);
6128    eSystem_RegisterFunction("strcmpi", "int strcmpi(const char *, const char *)", strcmpi, module, baseSystemAccess);
6129    eSystem_RegisterFunction("strnicmp", "int strnicmp(const char *, const char *, int n)", strnicmp, module, baseSystemAccess);
6130 #endif
6131 */
6132
6133    eSystem_RegisterFunction("strcmp", "int strcmp(const char *, const char *)", strcmp, module, baseSystemAccess);
6134    eSystem_RegisterFunction("strncmp", "int strncmp(const char *, const char *, uintsize n)", strncmp, module, baseSystemAccess);
6135    eSystem_RegisterFunction("strlwr", "char * strlwr(char *)", strlwr, module, baseSystemAccess);
6136    eSystem_RegisterFunction("strupr", "char * strupr(char *)", strupr, module, baseSystemAccess);
6137    eSystem_RegisterFunction("strcpy", "char * strcpy(char *, const char *)", strcpy, module, baseSystemAccess);
6138    eSystem_RegisterFunction("strncpy", "char * strncpy(char *, const char *, uintsize n)", strncpy, module, baseSystemAccess);
6139    eSystem_RegisterFunction("memcpy", "void * memcpy(void *, const void *, uintsize size)", memcpy, module, baseSystemAccess);
6140    eSystem_RegisterFunction("memmove", "void * memmove(void *, const void *, uintsize size)", memmove, module, baseSystemAccess);
6141
6142    // --- Stdio ---
6143    eSystem_RegisterFunction("sprintf", "int sprintf(char *, char *, ...)", sprintf, module, baseSystemAccess);
6144    eSystem_RegisterFunction("snprintf", "int sprintf(char *, uintsize, char *, ...)", snprintf, module, baseSystemAccess);
6145    eSystem_RegisterFunction("printf", "int printf(char *, ...)", printf, module, baseSystemAccess);
6146    eSystem_RegisterFunction("vsprintf", "int vsprintf(char*, const char*, __builtin_va_list)", vsprintf, module, baseSystemAccess);
6147    eSystem_RegisterFunction("vsnprintf", "int vsnprintf(char*, uintsize, const char*, __builtin_va_list)", vsnprintf, module, baseSystemAccess);
6148    eSystem_RegisterFunction("puts", "int puts(char *)", puts, module, baseSystemAccess);
6149    eSystem_RegisterFunction("fputs", "int fputs(char *, void * stream)", fputs, module, baseSystemAccess);
6150
6151    // --- Ctype ---
6152    eSystem_RegisterFunction("isalnum", "int isalnum(int c)", isalnum, module, baseSystemAccess);
6153    eSystem_RegisterFunction("isspace", "int isspace(int c)", isspace, module, baseSystemAccess);
6154    eSystem_RegisterFunction("isalpha", "int isalpha(int c)", isalpha, module, baseSystemAccess);
6155    eSystem_RegisterFunction("islower", "int islower(int c)", islower, module, baseSystemAccess);
6156    eSystem_RegisterFunction("isupper", "int isupper(int c)", isupper, module, baseSystemAccess);
6157    eSystem_RegisterFunction("isprint", "int isprint(int c)", isprint, module, baseSystemAccess);
6158    eSystem_RegisterFunction("strtoul", "unsigned long strtoul(const char * nptr, char ** endptr, int base)", strtoul, module, baseSystemAccess);
6159
6160 }
6161
6162 public dllexport Application __ecere_COM_Initialize(bool guiApp, int argc, char * argv[])
6163 {
6164    Application app;
6165
6166 #ifdef __ANDROID__
6167    // Clean up global variables
6168    memoryInitialized = false;
6169    pools = null;
6170 #ifdef MEMINFO
6171    memset(&memStacks, 0, sizeof(BinaryTree));
6172    memoryErrorsCount = 0;
6173    memset(&memBlocks, 0, sizeof(BinaryTree));
6174    recurse = false;
6175    blockID = 0;
6176    allocateClass = null;
6177    allocateInternal = false;
6178    TOTAL_MEM = 0;
6179    OUTSIDE_MEM = 0;
6180 #endif
6181 #endif
6182
6183 #ifdef _DEBUG
6184    // printf("Using debug ecere runtime library\n");
6185 #endif
6186    app = _calloc(1, sizeof(class Application));
6187
6188    Module_Constructor(app);
6189    app.systemNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
6190    app.systemNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
6191    app.systemNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
6192    app.systemNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
6193
6194    Instance_COM_Initialize(argc, argv, &app.parsedCommand, &app.argc, &app.argv);
6195
6196    app.application = app;
6197    app.allModules.offset = sizeof(class Instance) + (uint)&((struct Module *)0)->prev;
6198    app.isGUIApp = guiApp;
6199
6200    LoadCOM(app);
6201
6202    app._class = eSystem_FindClass(app, "Application");
6203
6204    return app;
6205 }
6206
6207 public dllexport ClassTemplateParameter eClass_AddTemplateParameter(Class _class, char * name, TemplateParameterType type, void * info, ClassTemplateArgument defaultArg)
6208 {
6209    if(_class && name)
6210    {
6211       ClassTemplateParameter param;
6212
6213       for(param = _class.templateParams.first; param; param = param.next)
6214       {
6215          if(!strcmp(param.name, name))
6216             return param;
6217       }
6218       param =
6219       {
6220          name = CopyString(name);
6221          type = type;
6222          (type == identifier) ? info : CopyString(info);
6223       };
6224       if(defaultArg != null) 
6225       {
6226          param.defaultArg = defaultArg;
6227          CopyTemplateArg(param, param.defaultArg);
6228       }
6229       _class.templateParams.Add(param);
6230       return param;
6231    }
6232    return null;
6233 }
6234
6235 public dllexport void eClass_DoneAddingTemplateParameters(Class base)
6236 {
6237    if(base)
6238    {
6239       OldLink derivative;
6240       ClassTemplateParameter param;
6241       {
6242          void * first = base.templateParams.first;
6243          int count = base.templateParams.count;
6244
6245          FreeTemplateArgs(base);
6246          delete base.templateArgs;
6247
6248          base.templateParams.first = null;
6249          base.templateParams.count = 0;
6250
6251          FreeTemplatesDerivatives(base);
6252
6253          base.templateParams.first = first;
6254          base.templateParams.count = count;
6255       }
6256
6257       for(param = base.templateParams.first; param; param = param.next)
6258       {
6259          if(param.type == identifier && param.defaultArg.memberString)
6260          {
6261             Class memberClass = base;
6262             char * colon = strstr(param.defaultArg.memberString, "::");
6263             char * memberName;
6264             if(colon)
6265             {
6266                char className[1024];
6267                Class sClass;
6268
6269                memcpy(className, param.defaultArg.memberString, colon - param.defaultArg.memberString);
6270                className[colon - param.defaultArg.memberString] = '\0';
6271                memberName = colon + 2;
6272
6273                for(sClass = base; sClass; sClass = sClass.base)
6274                {
6275                   ClassTemplateParameter cParam;
6276                   Class nextClass;
6277                   int id = 0;
6278                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) id += nextClass.templateParams.count;
6279                   // Safety! What could cause base.templateArgs to be null?
6280                   if(sClass == base || base.templateArgs)
6281                   {
6282                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
6283                      {
6284                         if(cParam.type == type && !strcmp(cParam.name, className))
6285                            strcpy(className, (sClass == base) ? cParam.defaultArg.dataTypeString : base.templateArgs[id].dataTypeString);
6286                         id++;
6287                      }
6288                   }
6289                }
6290                memberClass = eSystem_FindClass(base.module, className);
6291                if(!memberClass)
6292                   memberClass = eSystem_FindClass(base.module.application, className);
6293             }
6294             else
6295                memberName = param.defaultArg.memberString;
6296
6297             if(memberClass)
6298             {
6299                switch(param.memberType)
6300                {
6301                   case dataMember:
6302                      param.defaultArg.member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
6303                      break;
6304                   case method:
6305                      param.defaultArg.method = eClass_FindMethod(memberClass, memberName, memberClass.module);
6306                      break;
6307                   case prop:
6308                      param.defaultArg.prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
6309                      break;
6310                }
6311             }
6312          }
6313       }      
6314
6315       //ComputeClassParameters(base, null, null);
6316
6317       FixDerivativesBase(base, base);
6318    }
6319 }
6320
6321 static void FreeTemplatesDerivatives(Class base)
6322 {
6323    OldLink derivative, templateLink;
6324    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
6325    {
6326       Class _class = derivative.data;
6327       if(_class.templateArgs)
6328       {
6329          FreeTemplateArgs(_class);
6330          delete _class.templateArgs;
6331       }
6332       FreeTemplatesDerivatives(_class);
6333    }
6334
6335    for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
6336    {
6337       Class _class = templateLink.data;
6338       if(_class.templateArgs)
6339       {
6340          FreeTemplateArgs(_class);
6341          delete _class.templateArgs;
6342       }
6343       FreeTemplatesDerivatives(_class);
6344    }
6345 }
6346
6347 static const char * platformNames[Platform] = { "", "win32", "linux", "apple" }; // how to have this be accessible outside of dll/lib
6348 static const Platform firstPlatform = win32;
6349 static const Platform lastPlatform = apple;
6350
6351 public enum Platform
6352 {
6353    unknown, win32, tux, apple;
6354
6355    property char *
6356    {
6357       get { return OnGetString(null, null, null); }
6358       set
6359       {  
6360          if(value)
6361          {
6362             Platform c;
6363             for(c = firstPlatform; c <= lastPlatform; c++)
6364                if(!strcmpi(value, platformNames[c]))
6365                   return c;
6366          }
6367          return unknown;
6368       }
6369    };
6370
6371    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
6372    {
6373       if(this >= firstPlatform && this <= lastPlatform)
6374       {
6375          if(tempString)
6376             strcpy(tempString, platformNames[this]);
6377          return platformNames[this];
6378       }
6379       if(tempString && tempString[0])
6380          tempString[0] = '\0';
6381       return null;
6382    }
6383    
6384    bool OnGetDataFromString(char * string)
6385    {
6386       this = string;
6387       return (bool)this;
6388    }
6389 };
6390
6391 default extern Platform runtimePlatform;
6392
6393 public Platform GetRuntimePlatform()
6394 {
6395    return runtimePlatform;
6396 }
6397
6398 namespace gui;
6399
6400 class Window;
6401
6402 namespace com;
6403 // CLASS DESIGNER SUPPORT
6404
6405 public class ObjectInfo : struct
6406 {
6407 public:
6408    ObjectInfo prev, next;
6409    Instance instance;
6410    char * name;
6411    Instantiation instCode;
6412    bool deleted;
6413    ObjectInfo oClass;
6414    OldList instances;
6415    ClassDefinition classDefinition;
6416    bool modified;
6417 };
6418
6419 public class DesignerBase : Window
6420 {
6421 public:
6422    virtual bool FindObject(Instance * instance, char * string);
6423    virtual void RenameObject(ObjectInfo object, char * name);
6424    virtual void SelectObjectFromDesigner(ObjectInfo object);
6425    virtual void CodeAddObject(Instance instance, ObjectInfo * object);
6426    virtual void SheetAddObject(ObjectInfo object);
6427    virtual void AddToolBoxClass(Class _class);
6428    virtual void AddDefaultMethod(Instance instance, Instance classInstance);
6429    virtual void DeleteObject(ObjectInfo object);
6430    virtual bool ObjectContainsCode(ObjectInfo object);
6431    virtual void ModifyCode(void);
6432    virtual void UpdateProperties(void);
6433
6434    ClassDesignerBase classDesigner;
6435    char * objectClass;
6436    bool isDragging;
6437
6438    // FIX THIS WITH PUBLIC:
6439    property ClassDesignerBase classDesigner
6440    { 
6441       get { return classDesigner; }
6442       set { classDesigner = value; }
6443    };
6444    property char * objectClass
6445    { 
6446       get { return objectClass; }
6447       set { objectClass = value; }
6448    };
6449    property bool isDragging
6450    { 
6451       get { return isDragging; }
6452       set { isDragging = value; }
6453    };
6454 }
6455  
6456 public class ClassDesignerBase : Window
6457 {
6458 public:
6459    virtual void Reset(void);
6460    virtual void AddObject(void);
6461    virtual void SelectObject(ObjectInfo object, Instance control);
6462
6463    virtual void ListToolBoxClasses(DesignerBase designer);
6464
6465    virtual void ::PrepareTestObject(DesignerBase designer, Instance test);
6466    virtual void ::CreateObject(DesignerBase designer, Instance instance, ObjectInfo object, bool isClass, Instance _class);
6467    virtual void ::PostCreateObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6468    virtual void ::DroppedObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6469    virtual void ::DestroyObject(Instance object);
6470    virtual void ::FixProperty(Property prop, Instance object);
6471    virtual void ::CreateNew(EditBox editBox, Size clientSize, char * name, char * inherit);
6472 }
6473
6474 DesignerBase activeDesigner;
6475
6476 public void SetActiveDesigner(DesignerBase designer)
6477 {
6478    activeDesigner = designer;
6479 }
6480
6481 public DesignerBase GetActiveDesigner()
6482 {
6483    return activeDesigner;
6484 }
6485
6486 namespace sys;
6487
6488 // constants
6489 define LEAD_OFFSET      = 0xD800 - (0x10000 >> 10);
6490 define SURROGATE_OFFSET = 0x10000 - (0xD800 << 10) - 0xDC00;
6491
6492 public bool UTF8Validate(char * source)
6493 {
6494    if(source)
6495    {
6496       int c;
6497       for(c = 0; source[c];)
6498       {
6499          byte ch = source[c];
6500          unichar codePoint = 0;
6501          int numBytes = 1;
6502          int i;
6503          byte mask = 0x7F;
6504          if(ch & 0x80)
6505          {
6506             if(ch & 0x40)
6507             {
6508                mask >>= 2;
6509                numBytes++;
6510                if(ch & 0x20)
6511                {
6512                   numBytes++;
6513                   mask >>= 1;
6514                   if(ch & 0x10)
6515                   {
6516                      if(ch & 0x08)
6517                         return false;
6518                      numBytes++;
6519                      mask >>= 1;
6520                   }
6521                }
6522             }
6523             else
6524                return false;
6525          }
6526          for(i = 0; i<numBytes && (ch = source[c]); i++, c++)
6527          {
6528             codePoint <<= 6;
6529             codePoint |= ch & mask;
6530             mask = 0x3F;
6531             if(i > 1)
6532             {
6533                if(!(ch & 0x80) || (ch & 0x40))
6534                   return false;
6535             }
6536          }
6537          if(i < numBytes) return false;
6538
6539          if(codePoint > 0x10FFFF || (codePoint >= 0xD800 && codePoint <= 0xDFFF) || 
6540            (codePoint < 0x80 && numBytes > 1) || 
6541            (codePoint < 0x800 && numBytes > 2) || 
6542            (codePoint < 0x10000 && numBytes > 3))
6543             return false;
6544       }
6545    }
6546    return true;
6547 }
6548
6549 public int ISO8859_1toUTF8(char * source, char * dest, int max)
6550 {
6551    int c;
6552    int d = 0;
6553    for(c = 0; source[c]; c++)
6554    {
6555       unichar ch = ((byte *)source)[c];
6556       if(ch < 0x80)
6557       {
6558          if(d + 1 >= max) break;
6559          dest[d++] = (char)ch;
6560       }
6561       else if(ch < 0x800)
6562       {
6563          if(d + 2 >= max) break;
6564          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6565          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6566       }
6567       else if(ch < 0x10000)
6568       {
6569          if(d + 3 >= max) break;
6570          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6571          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6572          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6573       }
6574       else
6575       {
6576          if(d + 4 >= max) break;
6577          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6578          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6579          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6580          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6581       }
6582    }
6583    dest[d] = 0;
6584    return d;
6585 }
6586
6587 public char * UTF16toUTF8(uint16 * source)
6588 {
6589    int c;
6590    int d = 0;
6591    int len;
6592    char * dest;
6593    uint16 u16;
6594    bool invert = false;
6595
6596    for(len = 0; source[len]; len++);
6597    dest = new char[len * 3 + 1];
6598    for(c = 0; (u16 = source[c]); c++)
6599    {
6600       unichar ch;
6601       if(!c && (u16 == 0xFFFE || u16 == 0xFEFF))
6602       {
6603          if(u16 == 0xFFFE) invert = true;
6604          continue;
6605       }
6606       if(invert) { u16 = ((u16 & 0xFF00) >> 8) | ((u16 & 0x00FF) << 8); }
6607       
6608       if(u16 < 0xD800 || u16 > 0xDBFF)
6609          ch = (unichar)u16;         
6610       else
6611          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
6612                   
6613       if(ch < 0x80)
6614       {
6615          dest[d++] = (char)ch;
6616       }
6617       else if(ch < 0x800)
6618       {
6619          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6620          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6621       }
6622       else if(ch < 0x10000)
6623       {
6624          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6625          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6626          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6627       }
6628       else
6629       {
6630          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6631          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6632          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6633          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6634       }
6635    }
6636    dest[d] = 0;
6637    dest = renew dest char[d+1];
6638    return dest;
6639 }
6640
6641 public int UTF16toUTF8Buffer(uint16 * source, byte * dest, int max)
6642 {
6643    int c;
6644    int d = 0;
6645    uint16 u16;
6646    for(c = 0; (u16 = source[c]); c++)
6647    {
6648       unichar ch;
6649       if(u16 < 0xD800 || u16 > 0xDBFF)
6650          ch = (unichar)u16;         
6651       else
6652          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
6653
6654       if(ch < 0x80)
6655       {
6656          if(d + 1 >= max) break;
6657          dest[d++] = (char)ch;
6658       }
6659       else if(ch < 0x800)
6660       {
6661          if(d + 2 >= max) break;
6662          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6663          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6664       }
6665       else if(ch < 0x10000)
6666       {
6667          if(d + 3 >= max) break;
6668          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6669          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6670          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6671       }
6672       else
6673       {
6674          if(d + 4 >= max) break;
6675          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6676          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6677          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6678          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6679       }
6680    }
6681    dest[d] = 0;
6682    return d;
6683 }
6684
6685 // NOTE: UTF8GetChar now returns 0 into numBytes for the null-terminating character ('\0')
6686 public unichar UTF8GetChar(char * string, int * numBytes)
6687 {
6688    unichar ch;
6689    byte b = ((byte *)string)[0];
6690    int i;
6691    byte mask = 0x7F;
6692    int nb = b ? 1 : 0;
6693    ch = 0;
6694    if(b & 0x80)
6695    {
6696       if(b & 0x40)
6697       {
6698          mask >>= 2;
6699          nb++;
6700          if(b & 0x20)
6701          {
6702             nb++;
6703             mask >>= 1;
6704             if(b & 0x10)
6705             {
6706                if(b & 0x08) { nb = 0; }
6707                nb++;
6708                mask >>= 1;
6709             }
6710          }
6711       }
6712       else
6713          nb = 0;
6714    }
6715    for(i = 0; i<nb; i++)
6716    {
6717       ch <<= 6;
6718       ch |= (b = ((byte *)string)[i]) & mask;
6719       mask = 0x3F;
6720       if(i > 1 && (!(b & 0x80) || (b & 0x40)))
6721       {
6722          nb = 0;
6723          ch = 0;
6724       }
6725    }
6726
6727    if(i < nb || 
6728       ch > 0x10FFFF || (ch >= 0xD800 && ch <= 0xDFFF) || 
6729      (ch < 0x80 && nb > 1) || 
6730      (ch < 0x800 && nb > 2) || 
6731      (ch < 0x10000 && nb > 3))
6732    {
6733       ch = 0;
6734       nb = 0;
6735    }
6736    if(numBytes) *numBytes = nb;
6737    return ch;
6738 }
6739
6740 public int UTF8toUTF16Buffer(char * source, uint16 * dest, int max)
6741 {
6742    if(source)
6743    {
6744       int c;
6745       int d = 0;
6746       for(c = 0; source[c];)
6747       {
6748          byte ch = source[c];
6749          unichar codePoint = 0;
6750          int numBytes = 1;
6751          int i;
6752          byte mask = 0x7F;
6753          if(ch & 0x80 && ch & 0x40)
6754          {
6755             mask >>= 2;
6756             numBytes++;
6757             if(ch & 0x20)
6758             {
6759                numBytes++;
6760                mask >>= 1;
6761                if(ch & 0x10)
6762                {
6763                   numBytes++;
6764                   mask >>= 1;
6765                }
6766             }
6767          }
6768          for(i = 0; i<numBytes; i++)
6769          {
6770             codePoint <<= 6;
6771             codePoint |= source[c++] & mask;
6772             mask = 0x3F;
6773          }
6774
6775          if(codePoint > 0xFFFF)
6776          {
6777             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
6778             uint16 trail = 0xDC00 + (uint16)(codePoint & 0x3FF);
6779             if(d >= max - 1) break;
6780             dest[d++] = lead;
6781             dest[d++] = trail;
6782          }
6783          else
6784          {
6785             if(d >= max) break;
6786             dest[d++] = (uint16)codePoint;
6787          }
6788       }
6789       dest[d] = 0;
6790       return d;
6791    }
6792    return 0;   
6793 }
6794
6795 public int UTF32toUTF8Len(unichar * source, int count, byte * dest, int max)
6796 {
6797    int c;
6798    int d = 0;
6799    uint32 ch;
6800    for(c = 0; c<count && (ch = source[c]); c++)
6801    {
6802       if(ch < 0x80)
6803       {
6804          if(d + 1 >= max) break;
6805          dest[d++] = (char)ch;
6806       }
6807       else if(ch < 0x800)
6808       {
6809          if(d + 2 >= max) break;
6810          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6811          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6812       }
6813       else if(ch < 0x10000)
6814       {
6815          if(d + 3 >= max) break;
6816          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6817          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6818          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6819       }
6820       else
6821       {
6822          if(d + 4 >= max) break;
6823          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6824          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6825          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6826          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6827       }
6828    }
6829    dest[d] = 0;
6830    return d;
6831 }
6832
6833 public uint16 * UTF8toUTF16(char * source, int * wordCount)
6834 {
6835    if(source)
6836    {
6837       int len = strlen(source);
6838       uint16 * dest = new uint16[len + 1];
6839       int c;
6840       int d = 0;
6841       for(c = 0; source[c];)
6842       {
6843          byte ch = source[c];
6844          unichar codePoint = 0;
6845          int numBytes = 1;
6846          int i;
6847          byte mask = 0x7F;
6848          if(ch & 0x80 && ch & 0x40)
6849          {
6850             mask >>= 2;
6851             numBytes++;
6852             if(ch & 0x20)
6853             {
6854                numBytes++;
6855                mask >>= 1;
6856                if(ch & 0x10)
6857                {
6858                   numBytes++;
6859                   mask >>= 1;
6860                }
6861             }
6862          }
6863          for(i = 0; i<numBytes; i++)
6864          {
6865             codePoint <<= 6;
6866             codePoint |= source[c++] & mask;
6867             mask = 0x3F;
6868          }
6869
6870          if(codePoint > 0xFFFF)
6871          {
6872             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
6873             uint16 trail = 0xDC00 + (uint16)(codePoint & 0x3FF);
6874             dest[d++] = lead;
6875             dest[d++] = trail;
6876          }
6877          else
6878          {
6879             dest[d++] = (uint16)codePoint;
6880          }
6881       }
6882       dest[d] = 0;
6883       if(wordCount) *wordCount = d;
6884       return dest;
6885    }
6886    return null;
6887 }
6888
6889 namespace com;