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