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