ecere/com: Fixed broken serializatio of File classes
[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)();
125    int (*Get)();
126    bool (*IsSet)();
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, int);
565    int (*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 = 4;
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 = 4;
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 = 4;
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 % 4)
1159          pools[c].blockSize += 4 - (pools[c].blockSize % 4);
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 % 4;
1246          if(mod) ns += 4-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 % 4;
1294          if(mod) ns += 4-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 = (uint)((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 = (uint)((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((uint)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 = (uint)((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((uint)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 = (uint)((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((uint)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
2162    {
2163       nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
2164       if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
2165
2166       // if(declMode != staticAccess)
2167       {
2168          for(c = 0; name[c]; c++)
2169          {
2170             if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
2171             {
2172                NameSpace * newSpace;
2173
2174                char * spaceName = _malloc(c - start + 1);
2175                strncpy(spaceName, name + start, c - start);
2176                spaceName[c-start] = '\0';
2177
2178                newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
2179                if(!newSpace)
2180                {
2181                   newSpace = new0 NameSpace[1];
2182                   newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
2183                   newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
2184                   newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
2185                   newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
2186                   newSpace->name = spaceName;
2187                   newSpace->parent = nameSpace;
2188                   nameSpace->nameSpaces.Add((BTNode)newSpace);
2189                }
2190                else
2191                   delete spaceName;
2192                nameSpace = newSpace;
2193                if(name[c] == ':') c++;
2194                start = c+1;
2195             }
2196          }
2197       }
2198       /*else
2199          c = strlen(name);*/
2200    }
2201
2202    if(c - start)
2203    {
2204       int offsetClass; 
2205       int totalSizeClass;
2206       BTNamedLink classLink = null;
2207       Class _class = null;
2208       char * dataTypeString = null;
2209       Class enumBase = null;
2210       Class base = (baseName && baseName[0]) ? eSystem_FindClass(module, baseName) : null;
2211       bool refine = false;
2212
2213       if(base && !base.internalDecl && (base.type == noHeadClass || base.type == structClass || base.type == normalClass)) 
2214       {
2215          // Normal classes inheriting off simple classes should become no head classes
2216          if(base.type == structClass && type == normalClass)
2217             type = noHeadClass;
2218          else
2219             type = base.type;
2220       }
2221       if(base && (type == normalClass || type == noHeadClass || type == structClass) && 
2222          (base.type == unitClass || base.type == bitClass || base.type == enumClass))
2223       {
2224          type = base.type;
2225       }
2226       if(!base || base.type == systemClass)
2227       {
2228          if(type == enumClass)
2229          {
2230             // TO IMPROVE:
2231             if(base || !baseName || !baseName[0] ||
2232                !strcmp(baseName, "unsigned int") || 
2233                !strcmp(baseName, "uint") || 
2234                !strcmp(baseName, "unsigned int64") || 
2235                !strcmp(baseName, "uint64") || 
2236                !strcmp(baseName, "int64") || 
2237                !strcmp(baseName, "unsigned short") || 
2238                !strcmp(baseName, "short") || 
2239                !strcmp(baseName, "unsigned char") || 
2240                !strcmp(baseName, "byte") || 
2241                !strcmp(baseName, "char") || 
2242                !strcmp(baseName, "uint32") || 
2243                !strcmp(baseName, "uint16"))
2244             {
2245                base = eSystem_FindClass(module, "enum");
2246                dataTypeString = (baseName && baseName[0]) ? baseName : "int"; //"unsigned int";
2247             }
2248             else
2249             {
2250                // Undefined base
2251                base = eSystem_RegisterClass(0, baseName, null, 0,0, null, null, module, declMode, publicAccess);
2252                base.internalDecl = true;
2253
2254                enumBase = base;
2255                base = eSystem_FindClass(module, "enum");
2256                //dataTypeString = (baseName && baseName[0]) ? baseName : "unsigned int";
2257             }
2258          }
2259          else if(type == structClass && (!baseName || !baseName[0]))
2260          {
2261             base = eSystem_FindClass(module, "struct");
2262             dataTypeString = name + start;
2263          }
2264          else 
2265          {
2266             if(type == normalClass)
2267                // dataTypeString = "struct Instance";
2268                dataTypeString = "struct __ecereNameSpace__ecere__com__Instance";
2269             else if(type == noHeadClass)
2270                dataTypeString = "void *";
2271             else if(type == bitClass)
2272                dataTypeString = (baseName && baseName[0]) ? baseName : "unsigned int";
2273             else if(type == unitClass)
2274                dataTypeString = (baseName && baseName[0]) ? baseName : "int";
2275             else if(type == structClass)
2276                dataTypeString = name + start;
2277
2278             // TODO: base bit, unit or enum classes not defined yet
2279             if(base || (!baseName || !baseName[0]) || type == bitClass || type == unitClass)
2280             {
2281                // DANGEROUSLY TESTING THIS... PUT IT BACK
2282                //if(!base)
2283                if(base || !baseName || !baseName[0] ||
2284                   !strcmp(baseName, "unsigned int") || 
2285                   !strcmp(baseName, "uint") || 
2286                   !strcmp(baseName, "unsigned int64") || 
2287                   !strcmp(baseName, "uint64") || 
2288                   !strcmp(baseName, "int64") || 
2289                   !strcmp(baseName, "unsigned short") || 
2290                   !strcmp(baseName, "short") || 
2291                   !strcmp(baseName, "unsigned char") || 
2292                   !strcmp(baseName, "byte") || 
2293                   !strcmp(baseName, "char") || 
2294                   !strcmp(baseName, "uint32") || 
2295                   !strcmp(baseName, "uint16"))
2296                {
2297                   if(type == normalClass && strcmp(name, "ecere::com::Instance") && strcmp(name, "enum") && strcmp(name, "struct"))
2298                      base = eSystem_FindClass(module, "ecere::com::Instance");
2299                   else
2300                      base = eSystem_FindClass(module, "class");
2301                }
2302             }
2303             else
2304             {
2305                // Base class has not been defined yet!
2306             }
2307          }
2308       }
2309       else
2310       {
2311          if(type == enumClass)
2312          {
2313             if(base.type != enumClass)
2314             {
2315                enumBase = base;
2316                base = eSystem_FindClass(module, "enum");
2317             }
2318          }
2319          dataTypeString = enumBase ? enumBase.dataTypeString : base.dataTypeString;
2320       }
2321
2322       offsetClass = base ? base.sizeClass : (type == noHeadClass ? 0 : 0 /*sizeof(class Class)*/);
2323       totalSizeClass = offsetClass + sizeClass;
2324    
2325       if((_class = eSystem_FindClass(module, name)))
2326       {
2327          FreeTemplatesDerivatives(_class);
2328
2329          if(!_class.internalDecl)
2330          {
2331             if(declMode != baseSystemAccess)
2332                // i18n in instance.ec is more trouble than it's worth.
2333                printf("error: Redefinition of class %s\n", name);
2334             else
2335             {
2336                _class.comRedefinition = true;
2337                return _class;
2338             }
2339             return null;
2340          }
2341
2342          classLink = (BTNamedLink)_class.nameSpace->classes.FindString(name + start);
2343          _class.nameSpace->classes.Delete((BTNode)classLink);
2344          {
2345             OldLink t;
2346             for(t = _class.templatized.first; t; t = t.next)
2347             {
2348                Class template = t.data;
2349                classLink = (BTNamedLink)_class.nameSpace->classes.FindString(template.name);
2350
2351                _class.nameSpace->classes.Delete((BTNode)classLink);
2352             }
2353          }
2354          {
2355             NameSpace * ns = _class.nameSpace;
2356             while(ns->parent && 
2357                !ns->classes.first && 
2358                !ns->functions.first &&
2359                !ns->defines.first &&
2360                !ns->nameSpaces.first)
2361             {
2362                NameSpace * parent = ns->parent;
2363                NameSpace_Free(ns);
2364                parent->nameSpaces.Delete((BTNode)ns);
2365                ns = parent;
2366             }
2367          }
2368          refine = true;
2369       }
2370       else
2371       {
2372          classLink = SearchNameSpace(module.application.privateNameSpace, name, &((NameSpace *)0)->classes);
2373          if(!classLink)
2374             classLink = SearchNameSpace(module.application.publicNameSpace, name, &((NameSpace *)0)->classes);
2375
2376          if(!classLink)
2377             classLink = SearchNameSpace(module.application.privateNameSpace, name + start, &((NameSpace *)0)->classes);
2378          if(!classLink)
2379             classLink = SearchNameSpace(module.application.publicNameSpace, name + start, &((NameSpace *)0)->classes);
2380
2381          if(classLink)
2382             _class = classLink.data;
2383          if(_class && _class.internalDecl)
2384          {
2385             FreeTemplatesDerivatives(_class);
2386
2387             _class.nameSpace->classes.Delete((BTNode)classLink);
2388             {
2389                OldLink t;
2390                for(t = _class.templatized.first; t; t = t.next)
2391                {
2392                   Class template = t.data;
2393                   classLink = (BTNamedLink)_class.nameSpace->classes.FindString(template.name);
2394                   _class.nameSpace->classes.Delete((BTNode)classLink);
2395
2396                }
2397             }
2398
2399             refine = true;
2400             delete _class.fullName;
2401             _class.fullName = CopyString(name);
2402          }
2403          else
2404          {
2405             _class = _calloc(1, sizeof(class Class));
2406             _class.methods.CompareKey = (void *)BinaryTree::CompareString;
2407             _class.members.CompareKey = (void *)BinaryTree::CompareString;
2408             _class.prop.CompareKey = (void *)BinaryTree::CompareString;
2409             _class.classProperties.CompareKey = (void *)BinaryTree::CompareString;
2410
2411             _class.name = CopyString(name + start);
2412             _class.fullName = CopyString(name);
2413          }
2414       }
2415       if(nameSpace)
2416       {
2417          nameSpace->classes.Add((BTNode)BTNamedLink { name = _class.name, data = _class });
2418          {
2419             OldLink t;
2420             for(t = _class.templatized.first; t; t = t.next)
2421             {
2422                Class template = t.data;
2423                nameSpace->classes.Add((BTNode)BTNamedLink { name = template.name, data = template });
2424             }
2425          }
2426
2427       }
2428
2429       if(_class)
2430       {
2431          if(!base && baseName && strcmp(baseName, name))
2432          {
2433             // Undefined base
2434             if(strchr(baseName, '<'))
2435             {
2436                char templateClassName[1024];
2437                Class templateBase;
2438                strcpy(templateClassName, baseName);
2439                *strchr(templateClassName, '<') = '\0';
2440                templateBase = eSystem_FindClass(module, templateClassName);
2441                if(!templateBase)
2442                {
2443                   templateBase = eSystem_RegisterClass(0, templateClassName, null, 0,0, null, null, module, declMode, publicAccess);
2444                   templateBase.internalDecl = true;
2445                }
2446                base = eSystem_FindClass(module, baseName);
2447             }
2448             else
2449             {
2450                base = eSystem_RegisterClass(0, baseName, null, 0,0, null, null, module, declMode, publicAccess);
2451                base.internalDecl = true;
2452             }
2453             /*
2454             base.size = 0;
2455             base.offset = 0;
2456             base.memberOffset = 0;
2457             */
2458          }
2459          else
2460             _class.internalDecl = false;
2461
2462          if(totalSizeClass)
2463          {
2464             _class.data = renew _class.data byte[totalSizeClass];
2465             // Class Data is often not inherited... e.g. Window::pureVtbl problem
2466             // memset(_class.data, 0, totalSizeClass);
2467             if(base && base.type != systemClass && base.type != enumClass)
2468                memcpy(_class.data, base.data, offsetClass);
2469             else
2470                memset(_class.data, 0, offsetClass);
2471             memset((byte *)_class.data + offsetClass, 0, sizeClass);
2472          }
2473
2474          delete _class.dataTypeString;
2475          _class.dataTypeString = CopyString(dataTypeString);
2476          _class.defaultAlignment = base ? base.defaultAlignment : 0;
2477
2478          // Dereference the class in previous module the classed belonged to
2479          if(_class.module)
2480          {
2481             _class.module.classes.Remove(_class);
2482          }
2483
2484          if(_class.base)
2485          {
2486             //Class base = _class.base.templateClass ? _class.base.templateClass : _class.base;
2487             Class base = _class.base;
2488             OldLink deriv = base.derivatives.FindLink(_class);
2489             base.derivatives.Delete(deriv);
2490          }
2491
2492          // Reference the class in the module
2493          if(module)
2494          {
2495             module.classes.Add(_class);
2496          }
2497
2498          _class.nameSpace = nameSpace;
2499          {
2500             OldLink t;
2501             for(t = _class.templatized.first; t; t = t.next)
2502             {
2503                Class template = t.data;
2504                template.nameSpace = nameSpace;
2505             }
2506          }
2507
2508          _class.module = module;
2509          _class.base = base;
2510          if(base)
2511          {
2512             int numParams = 0;
2513             Class sClass;
2514             for(sClass = base; sClass; sClass = sClass.base)
2515             {
2516                if(sClass.templateClass) sClass = sClass.templateClass;
2517                numParams += sClass.templateParams.count;
2518             }
2519             if(numParams)
2520             {
2521                if(_class.templateArgs)
2522                {
2523                   FreeTemplateArgs(_class);
2524                }
2525                delete _class.templateArgs;
2526                _class.templateArgs = new0 ClassTemplateArgument[numParams];
2527                _class.numParams = numParams;
2528
2529                for(sClass = _class; sClass; sClass = sClass.base)
2530                {
2531                   Class prevClass;
2532                   ClassTemplateParameter param;
2533                   int id = 0;
2534                   if(sClass.templateClass) sClass = sClass.templateClass;
2535                   for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
2536                   {
2537                      if(prevClass.templateClass) prevClass = prevClass.templateClass;
2538                      id += prevClass.templateParams.count;
2539                   }
2540
2541                   if(base.templateArgs)   // Add numParams test here?
2542                   {
2543                      for(param = sClass.templateParams.first; param; param = param.next)
2544                      {
2545                         _class.templateArgs[id] = base.templateArgs[id];
2546                         CopyTemplateArg(param, _class.templateArgs[id]);
2547                         id++;
2548                      }
2549                   }
2550                }
2551             }
2552          }
2553          _class.memberID = _class.startMemberID = (base && (type == normalClass || type == noHeadClass || type == structClass)) ? base.memberID : 0;
2554          if(type == normalClass || type == noHeadClass)
2555             _class.offset = (base && base.structSize && base.type != systemClass) ? base.structSize : ((type == noHeadClass) ? 0 : sizeof(class Instance));
2556          if(type == structClass)
2557          {
2558             _class.memberOffset = (base && base.structSize && base.type != systemClass) ? base.structSize : 0;
2559             // THIS IS NEW...
2560             _class.typeSize = _class.structSize = _class.memberOffset + size;
2561          }
2562          else if(type == bitClass || type == enumClass || type == unitClass)
2563          {  
2564             Class dataTypeClass = eSystem_FindClass(_class.module, dataTypeString);
2565             if(dataTypeClass)
2566                _class.typeSize = dataTypeClass.typeSize;
2567             _class.structSize = 0;
2568          }
2569          else if(type == normalClass || type == noHeadClass)
2570          {
2571             _class.structSize = _class.offset + size;
2572             _class.typeSize = sizeof(void *);
2573          }
2574          _class.offsetClass = offsetClass;
2575          _class.sizeClass = totalSizeClass;
2576          _class.Constructor = (void *)Constructor;
2577          _class.Destructor = Destructor;
2578          if(_class.type != systemClass)
2579             _class.type = type;
2580          if(!size)
2581             _class.computeSize = true;
2582          else
2583             _class.computeSize = false;
2584          _class.inheritanceAccess = inheritanceAccess;
2585
2586          /*if(type == bitClass)
2587             _class.size = 0;*/
2588          if(type == enumClass)
2589          {
2590             if(enumBase)
2591                _class.base = base = enumBase;
2592             //else
2593             {
2594                EnumClassData data = (EnumClassData)_class.data;
2595                // TOCHECK: Trying this (if specifiers specified, no class found...)
2596                // What about bit classes, unit classes...
2597                if(base && base.type != enumClass)
2598                   data.largest = -1;//_class.base = null;
2599                else
2600                   data.largest = ((EnumClassData)(base.data)).largest;
2601             }
2602          }
2603          if(base && base.vTblSize)
2604          {
2605             _class.vTblSize = base.vTblSize;
2606             // OK to scrap existing virtual table?
2607             delete _class._vTbl;
2608             _class._vTbl = _malloc(sizeof(int(*)()) * _class.vTblSize);
2609             memcpy(_class._vTbl, base._vTbl, sizeof(int(*)()) * _class.vTblSize);
2610          }
2611
2612          if(_class.base)
2613          {
2614             OldLink link { data = _class };
2615             /*(_class.base.templateClass ? _class.base.templateClass : _class.base)*/_class.base.derivatives.Add(link);
2616          }
2617
2618          FixDerivativesBase(_class, _class);
2619          return _class;
2620       }
2621    }
2622    return null;
2623 }
2624
2625 static void DataMember_Free(DataMember parentMember)
2626 {
2627    DataMember member;
2628    BTNamedLink namedLink;
2629    delete parentMember.name;
2630    delete parentMember.dataTypeString;
2631
2632    while((member = parentMember.members.first))
2633    {
2634       DataMember_Free(member);
2635       parentMember.members.Delete(member);
2636    }
2637
2638    while((namedLink = (BTNamedLink)parentMember.membersAlpha.first))
2639    {
2640       parentMember.membersAlpha.Delete((BTNode)namedLink);
2641    }
2642 }
2643
2644 static void FreeEnumValue(NamedLink value)
2645 {
2646    delete value.name;
2647 }
2648
2649 static void FreeTemplateArg(Class template, ClassTemplateParameter param, int id)
2650 {
2651    switch(param.type)
2652    {
2653       case type:
2654          delete template.templateArgs[id].dataTypeString;
2655          break;
2656       case identifier:
2657          delete template.templateArgs[id].memberString;
2658          break;
2659       case expression:
2660          
2661          break;
2662    }
2663 }
2664
2665 static void FreeTemplateArgs(Class template)
2666 {
2667    if(template.templateArgs)
2668    {
2669       Class _class;
2670       for(_class = template; _class; _class = _class.base)
2671       {
2672          Class prevClass;
2673          ClassTemplateParameter param;
2674          int id = 0;
2675          if(_class.templateClass) _class = _class.templateClass;
2676          for(prevClass = _class.base; prevClass; prevClass = prevClass.base) 
2677          {
2678             if(prevClass.templateClass) prevClass = prevClass.templateClass;
2679             id += prevClass.templateParams.count;
2680          }
2681          if(id < template.numParams)
2682          {
2683             for(param = _class.templateParams.first; param; param = param.next)
2684             {
2685                switch(param.type)
2686                {
2687                   case type:
2688                      delete template.templateArgs[id].dataTypeString;
2689                      break;
2690                   case identifier:
2691                      delete template.templateArgs[id].memberString;
2692                      break;
2693                   case expression:
2694                      // delete template.templateArgs[id].dataTypeString;
2695                      break;
2696                }
2697                id++;
2698             }
2699          }
2700       }
2701    }
2702 }
2703
2704 static void FreeTemplate(Class template)
2705 {
2706    OldLink deriv;
2707
2708    if(template.nameSpace)
2709    {
2710       BTNamedLink link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
2711       template.nameSpace->classes.Delete((BTNode)link);
2712    }
2713    FreeTemplateArgs(template);
2714
2715    delete template.fullName;
2716    delete template.name;
2717    delete template.templateArgs;
2718
2719    while((deriv = template.derivatives.first))
2720    {
2721       ((Class)deriv.data).base = null;
2722       template.derivatives.Delete(deriv);
2723    }
2724
2725    _free(template);
2726 }
2727
2728 static void FreeTemplates(Class _class)
2729 {
2730    OldLink deriv, template;
2731
2732    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
2733    {
2734       FreeTemplates(deriv.data);
2735    }
2736
2737    FreeTemplateArgs(_class);
2738    //if(_class.templateArgs)
2739       //printf("Deleting  Template args for %s\n", _class.name);
2740    delete _class.templateArgs;
2741
2742    while((template = _class.templatized.first))
2743    {
2744       FreeTemplates(template.data);
2745       FreeTemplate(template.data);
2746       _class.templatized.Delete(template);
2747    }
2748 }
2749
2750 public dllexport void eClass_Unregister(Class _class)
2751 {
2752    BTNamedLink namedLink;
2753    DataMember member;
2754    Method method;
2755    OldLink deriv, template;
2756    ClassProperty classProp;
2757    ClassTemplateParameter param;
2758
2759    delete _class._vTbl;
2760
2761    FreeTemplates(_class);
2762    
2763    FreeTemplateArgs(_class);
2764    delete _class.templateArgs;
2765
2766    while((template = _class.templatized.first))
2767    {
2768       FreeTemplate(template.data);
2769       _class.templatized.Delete(template);
2770    }
2771
2772    while((member = _class.membersAndProperties.first))
2773    {
2774       if(!member.isProperty && (member.type == unionMember || member.type == structMember))
2775          DataMember_Free(member);
2776       delete member.name;
2777       delete member.dataTypeString;
2778       _class.membersAndProperties.Delete(member);
2779    }
2780
2781    while((member = _class.conversions.first))
2782    {
2783       delete member.name;
2784       delete member.dataTypeString;
2785       _class.conversions.Delete(member);
2786    }
2787
2788    while((namedLink = (BTNamedLink)_class.prop.first))
2789    {
2790       _class.prop.Delete((BTNode)namedLink);
2791    }
2792
2793    while((namedLink = (BTNamedLink)_class.members.first))
2794    {
2795       _class.members.Delete((BTNode)namedLink);
2796    }
2797
2798    while((classProp = (ClassProperty)_class.classProperties.first))
2799    {
2800       delete classProp.name;
2801       delete classProp.dataTypeString;
2802       _class.classProperties.Delete((BTNode)classProp);
2803    }
2804
2805    while((method = (Method)_class.methods.first))
2806    {
2807       delete method.name;
2808       delete method.dataTypeString;
2809       _class.methods.Delete((BTNode)method);
2810    }
2811
2812    if(_class.type == enumClass)
2813    {
2814       EnumClassData data = (EnumClassData)_class.data;
2815
2816       data.values.Free((void *)FreeEnumValue);
2817    }
2818    _class.delayedCPValues.Free(null);
2819
2820    _class.selfWatchers.Free(null);
2821    
2822    if(_class.base)
2823    {
2824       // Class base = _class.base.templateClass ? _class.base.templateClass : _class.base;
2825       Class base = _class.base;
2826       for(deriv = base.derivatives.first; deriv; deriv = deriv.next)
2827       {
2828          if(deriv.data == _class)
2829             break;
2830       }
2831       if(deriv)
2832          base.derivatives.Delete(deriv);
2833    }
2834    while((deriv = _class.derivatives.first))
2835    {
2836       ((Class)deriv.data).base = null;
2837       _class.derivatives.Delete(deriv);
2838    }
2839
2840    if(_class.nameSpace)
2841    {
2842       BTNamedLink link = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
2843       _class.nameSpace->classes.Delete((BTNode)link);
2844    }
2845
2846    delete _class.name;
2847    delete _class.fullName;
2848    
2849    delete _class.dataTypeString;
2850
2851    delete _class.data;
2852
2853    while((param = _class.templateParams.first))
2854    {
2855       switch(param.type)
2856       {
2857          case type:
2858             delete param.defaultArg.dataTypeString;
2859             break;
2860          case identifier:
2861             delete param.defaultArg.memberString;
2862             break;
2863          case expression:
2864             
2865             break;
2866       }
2867       if(param.type != identifier) delete param.dataTypeString;
2868       delete param.name;
2869
2870       _class.templateParams.Delete(param);
2871    }
2872
2873    //_class.nameSpace->classes.Delete(_class);
2874    _free(_class);
2875 }
2876
2877 static BTNamedLink ScanNameSpace(NameSpace nameSpace, char * name, void * listOffset)
2878 {
2879    BinaryTree * tree = (BinaryTree *)((byte *)nameSpace + (uint)listOffset);
2880    BTNamedLink link = (BTNamedLink)tree->Find((uint)name);
2881    NameSpace * child;
2882    if(!link)
2883    {
2884       for(child = (NameSpace *)nameSpace.nameSpaces.first; child; child = (NameSpace *)((BTNode)child).next)
2885       {
2886          link = ScanNameSpace(child, name, listOffset);
2887          if(link)
2888             break;
2889       }
2890    }
2891    return link;
2892 }
2893
2894 static BTNamedLink SearchNameSpace(NameSpace nameSpace, char * name, void * listOffset)
2895 {
2896    int start = 0, c;
2897    char ch;
2898    int level = 0;
2899    for(c = 0; (ch = name[c]); c++)
2900    {
2901       if(ch == '<') level++;
2902       if(ch == '>') level--;
2903       if(level == 0 && (ch == '.' || (ch == ':' && name[c+1] == ':')))
2904       {
2905          NameSpace * newSpace;
2906          char * spaceName = _malloc(c - start + 1);
2907          memcpy(spaceName, name + start, c - start);
2908          spaceName[c-start] = '\0';
2909          newSpace = (NameSpace *)nameSpace.nameSpaces.FindString(spaceName);
2910          _free(spaceName);
2911          if(!newSpace)
2912             return null;
2913          nameSpace = newSpace;
2914          if(level == 0 && ch == ':') c++;
2915          start = c+1;
2916       }
2917    }
2918    if(c - start)
2919    {
2920       return ScanNameSpace(nameSpace, name + start, listOffset);
2921    }
2922    return null;
2923 }
2924
2925 static BTNamedLink SearchModule(Module module, char * name, void * listOffset, bool searchPrivate)
2926 {
2927    SubModule subModule;
2928    BTNamedLink link;
2929
2930    if(searchPrivate)
2931    {
2932       link = SearchNameSpace(&module.privateNameSpace, name, listOffset);
2933       if(link) return link;
2934    }
2935    link = SearchNameSpace(&module.publicNameSpace, name, listOffset);
2936    if(link) return link;
2937
2938    for(subModule = module.modules.first; subModule; subModule = subModule.next)
2939    {
2940       if(searchPrivate || subModule.importMode == publicAccess)
2941       {
2942          // TOCHECK: Reverting to false to test what we were trying to fix by passing searchPrivate
2943          // Passing searchPrivate finds ALL classes private or not and thus classes clash
2944          // SearchModule here is called mainly from eSystem_FindClass, and also for Functions and Defines
2945
2946          link = SearchModule(subModule.module, name, listOffset, false);
2947          //link = SearchModule(subModule.module, name, listOffset, searchPrivate /*false*/);
2948          if(link) return link;
2949       }
2950    }
2951    return null;
2952 }
2953
2954 public int64 _strtoi64(char * string, char ** endString, int base)
2955 {
2956    int64 value = 0;
2957    int sign = 1;
2958    int c;
2959    char ch;
2960    for(c = 0; (ch = string[c]) && isspace(ch); c++);
2961    if(ch =='+') c++;
2962    else if(ch == '-') { sign = -1; c++; };
2963    if(!base)
2964    {
2965       if(ch == 0 && string[c+1] == 'x')
2966       {
2967          base = 16;
2968          c+=2;
2969       }
2970       else if(ch == '0')
2971       {
2972          base = 8;
2973          c++;
2974       }
2975       else
2976          base = 10;
2977    }
2978    for( ;(ch = string[c]); c++)
2979    {
2980       if(ch == '0')
2981          ch = 0;
2982       else if(ch >= '1' && ch <= '9')
2983          ch -= '1';
2984       else if(ch >= 'a' && ch <= 'z') 
2985          ch -= 'a'; 
2986       else if(ch >= 'A' && ch <= 'Z') 
2987          ch -= 'A';
2988       else
2989       {
2990          *endString = string + c;
2991          // Invalid character
2992          break;
2993       }
2994       if(ch < base)
2995       {
2996          value *= base;
2997          value += ch;
2998       }
2999       else
3000       {
3001          *endString = string + c;
3002          // Invalid character
3003          break;
3004       }
3005    }
3006    return sign*value;
3007 }
3008
3009 public uint64 _strtoui64(char * string, char ** endString, int base)
3010 {
3011    uint64 value = 0;
3012    int sign = 1;
3013    int c;
3014    char ch;
3015    for(c = 0; (ch = string[c]) && isspace(ch); c++);
3016    if(ch =='+') c++;
3017    else if(ch == '-') { sign = -1; c++; };
3018    if(!base)
3019    {
3020       if(ch == 0 && string[c+1] == 'x')
3021       {
3022          base = 16;
3023          c+=2;
3024       }
3025       else if(ch == '0')
3026       {
3027          base = 8;
3028          c++;
3029       }
3030       else
3031          base = 10;
3032    }
3033    for( ;(ch = string[c]); c++)
3034    {
3035       if(ch == '0')
3036          ch = 0;
3037       else if(ch >= '1' && ch <= '9')
3038          ch -= '1';
3039       else if(ch >= 'a' && ch <= 'z') 
3040          ch -= 'a'; 
3041       else if(ch >= 'A' && ch <= 'Z') 
3042          ch -= 'A';
3043       else
3044       {
3045          *endString = string + c;
3046          // Invalid character
3047          break;
3048       }
3049       if(ch < base)
3050       {
3051          value *= base;
3052          value += ch;
3053       }
3054       else
3055       {
3056          *endString = string + c;
3057          // Invalid character
3058          break;
3059       }
3060    }
3061    return sign*value;
3062 }
3063
3064 public dllexport Class eSystem_FindClass(Module module, char * name)
3065 {
3066    if(name && module)
3067    {
3068       BTNamedLink link;
3069       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->classes);
3070       if(link) return link.data;
3071
3072       link = SearchModule(module, name, &((NameSpace *)0)->classes, true);
3073       if(link) return link.data;
3074       
3075       {
3076          char noTemplateName[1024];
3077          char * templateParams = strchr(name, '<');
3078
3079          if(templateParams)
3080          {
3081             strncpy(noTemplateName, name, templateParams - name);
3082             noTemplateName[templateParams - name] = '\0';
3083          }
3084          else
3085             strcpy(noTemplateName, name);
3086
3087          link = SearchNameSpace(&module.application.systemNameSpace, noTemplateName, &((NameSpace *)0)->classes);
3088          if(!link)
3089             link = SearchModule(module, noTemplateName, &((NameSpace *)0)->classes, true);
3090          if(link)
3091          {
3092             Class _class = link.data;
3093             Class templatedClass = null;
3094             char className[1024];
3095             strcpy(className, _class.fullName);
3096             strcat(className, templateParams);
3097
3098             link = SearchNameSpace(&module.application.systemNameSpace, className, &((NameSpace *)0)->classes);
3099             if(link)
3100                return link.data;
3101
3102             link = SearchModule(module, className, &((NameSpace *)0)->classes, true);
3103             if(link)
3104                return link.data;
3105
3106             if(_class && templateParams)
3107             {
3108                // if(!numParams) return null;
3109
3110                templatedClass = Class { };
3111                *templatedClass = *_class;
3112                templatedClass.templateClass = _class;
3113                //templatedClass.fullName = CopyString(name);
3114                templatedClass.fullName = CopyString(className);
3115                templatedClass.name = CopyString(templatedClass.fullName + strlen(_class.fullName) - strlen(_class.name));
3116                templatedClass.nameSpace->classes.Add((BTNode)BTNamedLink { name = templatedClass.name, data = templatedClass });
3117                templatedClass.templateArgs = null;
3118                templatedClass.numParams = 0;
3119                templatedClass.derivatives = { };
3120                templatedClass.templatized = { };
3121
3122                ComputeClassParameters(templatedClass, templateParams, module);
3123
3124                _class.templatized.Add(OldLink { data = templatedClass });
3125             }
3126             return templatedClass;
3127          }
3128       }
3129    }
3130    return null;
3131 }
3132
3133 static void CopyTemplateArg(ClassTemplateParameter param, ClassTemplateArgument arg)
3134 {
3135    switch(param.type)
3136    {
3137       case type:
3138          arg.dataTypeString = CopyString(arg.dataTypeString);
3139          break;
3140       case expression:
3141          
3142          break;
3143       case identifier:
3144          arg.memberString = CopyString(arg.memberString);
3145          break;
3146    }
3147 }
3148
3149 static void ComputeClassParameters(Class templatedClass, char * templateParams, Module findModule)
3150 {
3151    char ch;
3152    char * nextParamStart = templateParams ? (templateParams + 1) : null;
3153    ClassTemplateParameter curParam = null;
3154    Class lastClass = null, sClass;
3155    int curParamID = 0;
3156    int numParams = 0;
3157    Class _class = templatedClass.templateClass ? templatedClass.templateClass : templatedClass;
3158
3159    for(sClass = _class; sClass; sClass = sClass.base)
3160    {
3161       if(sClass.templateClass) sClass = sClass.templateClass;
3162       numParams += sClass.templateParams.count;
3163    }
3164    
3165    if(templatedClass.templateArgs)
3166       FreeTemplateArgs(templatedClass);
3167    delete templatedClass.templateArgs;
3168    templatedClass.templateArgs = new0 ClassTemplateArgument[numParams];
3169    templatedClass.numParams = numParams;
3170
3171    if(_class != templatedClass)
3172    {
3173       /*int c;
3174       Class sClass;
3175       memcpy(templatedClass.templateArgs, _class.templateArgs, numParams * sizeof(ClassTemplateArgument));
3176       for(sClass = _class; sClass; sClass = sClass.base)
3177       {
3178          ClassTemplateParameter param;
3179          Class prevClass;
3180          int id = 0;
3181          if(sClass.templateClass) sClass = sClass.templateClass;
3182          for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
3183          {
3184             if(prevClass.templateClass) prevClass = prevClass.templateClass;
3185             id += prevClass.templateParams.count;
3186          }
3187          for(param = sClass.templateParams.first; param; param = param.next)
3188            CopyTemplateArg(param, templatedClass.templateArgs[id++]);
3189       }*/
3190    }
3191    
3192    if(templatedClass.base && templatedClass.base.templateArgs && _class == templatedClass)
3193    {
3194       Class sClass;
3195       memcpy(templatedClass.templateArgs, templatedClass.base.templateArgs, 
3196          sizeof(ClassTemplateArgument) * (numParams - templatedClass.templateParams.count));
3197       for(sClass = templatedClass.base; sClass; sClass = sClass.base)
3198       {
3199          ClassTemplateParameter param;
3200          Class prevClass;
3201          int id = 0;
3202          for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
3203          {
3204             if(prevClass.templateClass) prevClass = prevClass.templateClass;
3205             id += prevClass.templateParams.count;
3206          }
3207
3208          if(sClass.templateClass) sClass = sClass.templateClass;
3209          for(param = sClass.templateParams.first; param; param = param.next)
3210             CopyTemplateArg(param, templatedClass.templateArgs[id++]);
3211       }
3212    }
3213    
3214    while(nextParamStart)
3215    {
3216       char * paramStart = nextParamStart;
3217       char * paramEnd;
3218       int level = 0;
3219       while(*paramStart == ' ') paramStart++;
3220       paramEnd = paramStart;
3221       while((ch = *paramEnd, ch && (level > 0 || (ch != '>' && ch != ',')))) 
3222       {
3223          if(ch == '<') level++;
3224          if(ch == '>') level--;
3225
3226          paramEnd++;
3227       }
3228       nextParamStart = (ch == ',') ? (paramEnd + 1) : null;
3229       while(*paramEnd == ' ') paramEnd--;
3230       if(paramEnd > paramStart)
3231       {
3232          char * ptr, * equal = null;
3233          for(ptr = paramStart; ptr <= paramEnd; ptr++)
3234          {
3235             if(*ptr == '=')
3236             {
3237                equal = ptr;
3238                break;
3239             }
3240          }
3241          if(equal)
3242          {
3243             char * end = equal - 1;
3244             char ident[1024];
3245             
3246             while(*end == ' ') end--;
3247             strncpy(ident, paramStart, end + 1 - paramStart);
3248             ident[end + 1 - paramStart] = 0;
3249             
3250             for(sClass = _class; sClass; sClass = sClass.base)
3251             {
3252                if(sClass.templateClass) sClass = sClass.templateClass;
3253                for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
3254                {
3255                   if(!strcmp(curParam.name, ident))
3256                      break;
3257                }
3258                if(curParam)
3259                {
3260                   Class nextClass;
3261                   ClassTemplateParameter prevParam;
3262                   curParamID = 0;
3263                   for(prevParam = curParam.prev; prevParam; prevParam = prevParam.prev) curParamID++;
3264                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3265                   {
3266                      if(nextClass.templateClass) nextClass = nextClass.templateClass;
3267                      curParamID += nextClass.templateParams.count;
3268                   }
3269                   break;
3270                }
3271             }
3272             lastClass = sClass;
3273          }
3274          else
3275          {
3276             if(curParam)
3277             {
3278                curParam = curParam.next;
3279                curParamID++;
3280             }
3281
3282             if(!curParam)
3283             {
3284                for(sClass = lastClass ? lastClass.base : _class; sClass; sClass = sClass.base)
3285                {
3286                   ClassTemplateParameter param;
3287                   curParamID = 0;
3288                   if(sClass.templateClass) sClass = sClass.templateClass;
3289                   for(param = sClass.templateParams.first; param; param = param.next, curParamID++)
3290                   {
3291                      curParam = param;
3292                      break;
3293                   }
3294                   if(curParam) 
3295                   {
3296                      Class nextClass;
3297                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3298                      {
3299                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
3300                         curParamID += nextClass.templateParams.count;
3301                      }
3302                      lastClass = sClass;
3303                      break;
3304                   }
3305                }
3306                /*
3307                for(sClass = _class; sClass; sClass = sClass.base)
3308                {
3309                   if(sClass.templateParams.first)
3310                   {
3311                      Class nextClass;
3312                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3313                         if(nextClass.templateParams.first)
3314                            break;
3315                      if(nextClass != lastClass) continue;
3316
3317                      curParam = sClass.templateParams.first;
3318                      lastClass = sClass;
3319
3320                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3321                         if(nextClass.templateParams.first)
3322                         {
3323                            curParamID += nextClass.templateParams.count;
3324                            break;
3325                         } 
3326                      break;
3327                   }
3328                }
3329                */
3330             }
3331          }
3332
3333          if(curParam)
3334          {
3335             ClassTemplateArgument argument { };
3336             char value[1024];
3337             if(equal) 
3338             {
3339                equal++;
3340                while(*equal == ' ') equal++;
3341                memcpy(value, equal, paramEnd - equal);
3342                value[paramEnd - equal] = 0;
3343             }
3344             else
3345             {
3346                memcpy(value, paramStart, paramEnd - paramStart);
3347                value[paramEnd - paramStart] = 0;
3348             }
3349             TrimRSpaces(value, value);
3350
3351             switch(curParam.type)
3352             {
3353                case type:
3354                   argument.dataTypeString = CopyString(value);
3355                   argument.dataTypeClass = eSystem_FindClass(_class.module, value);
3356                   if(!argument.dataTypeClass) argument.dataTypeClass = eSystem_FindClass(_class.module.application, value);
3357                   if(!argument.dataTypeClass) argument.dataTypeClass = eSystem_FindClass(findModule, value);
3358                   break;
3359                case expression:
3360                {
3361                   Class expClass = eSystem_FindClass(_class.module, curParam.dataTypeString);
3362                   if(!expClass) expClass = eSystem_FindClass(_class.module.application, curParam.dataTypeString);
3363                   if(expClass)
3364                   {
3365                      //if(expClass.type == 
3366                      expClass._vTbl[__ecereVMethodID_class_OnGetDataFromString](expClass, &argument.expression, value);
3367                   }
3368                   // Expression should be pre simplified here
3369                   else if(value[0] == '\"')
3370                   {
3371                      char * endQuote = value + strlen(value) - 1;
3372                      if(*endQuote != '\"') endQuote++;
3373                      *endQuote = '\0';
3374                      argument.expression.p = CopyString(value + 1);
3375                   }
3376                   else if(value[0] == '\'')
3377                   {
3378                      int nb;
3379                      unichar ch = UTF8GetChar(value + 1, &nb);
3380                      argument.expression.ui = ch;
3381                   }
3382                   else if(!strcmp(curParam.dataTypeString, "uint"))
3383                   {
3384                      argument.expression.ui = strtoul(value, null, 0);
3385                   }
3386                   else if(!strcmp(curParam.dataTypeString, "char"))
3387                   {
3388                      argument.expression.c = (char)strtol(value, null, 0);
3389                   }
3390                   else if(!strcmp(curParam.dataTypeString, "byte"))
3391                   {
3392                      argument.expression.uc = (unsigned char)strtoul(value, null, 0);
3393                   }
3394                   else if(!strcmp(curParam.dataTypeString, "short"))
3395                   {
3396                      argument.expression.s = (short)strtol(value, null, 0);
3397                   }
3398                   else if(!strcmp(curParam.dataTypeString, "uint16"))
3399                   {
3400                      argument.expression.us = (unsigned short)strtoul(value, null, 0);
3401                   }
3402                   else if(!strcmp(curParam.dataTypeString, "int64"))
3403                   {
3404                      argument.expression.i64 = _strtoi64(value, null, 0);
3405                   }
3406                   else if(!strcmp(curParam.dataTypeString, "uint64"))
3407                   {
3408                      argument.expression.ui64 = _strtoui64(value, null, 0);
3409                   }
3410                   else if(!strcmp(curParam.dataTypeString, "float"))
3411                   {
3412                      argument.expression.f = (float)strtod(value, null);
3413                   }
3414                   else if(!strcmp(curParam.dataTypeString, "double"))
3415                   {
3416                      argument.expression.d = strtod(value, null);
3417                   }
3418                   else // if(!strcmp(curParam.dataTypeString, "int"))
3419                   {
3420                      argument.expression.i = strtol(value, null, 0);
3421                   }
3422                   break;
3423                } 
3424                case identifier:
3425                   argument.memberString = CopyString(value);
3426                   break;
3427             }
3428             FreeTemplateArg(templatedClass, curParam, curParamID);
3429             templatedClass.templateArgs[curParamID] = argument;
3430          }
3431       }
3432    }
3433
3434    // TESTING THIS BEFORE...
3435    if(templatedClass == _class)
3436    {
3437       Class sClass = _class;
3438       int curParamID = 0;
3439       Class nextClass;
3440       ClassTemplateParameter param;
3441       for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3442       {
3443          if(nextClass.templateClass) nextClass = nextClass.templateClass;
3444          curParamID += nextClass.templateParams.count;
3445       }
3446
3447       for(param = sClass.templateParams.first; param; param = param.next)
3448       {
3449          if(!templatedClass.templateArgs[curParamID].dataTypeString)
3450          {
3451             templatedClass.templateArgs[curParamID] = param.defaultArg;
3452             CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3453             if(param.type == type && param.defaultArg.dataTypeString)
3454             {
3455                templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3456                if(!templatedClass.templateArgs[curParamID].dataTypeClass) 
3457                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3458                if(!templatedClass.templateArgs[curParamID].dataTypeClass) 
3459                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3460             }
3461          }
3462          curParamID++;
3463       }
3464    }
3465
3466    if(templatedClass.base && templatedClass.base.templateArgs && numParams - _class.templateParams.count)
3467    {
3468       int c = numParams - _class.templateParams.count-1;
3469
3470       for(sClass = _class.base; sClass; sClass = sClass.base)
3471       {
3472          ClassTemplateParameter param;
3473          if(sClass.templateClass) sClass = sClass.templateClass;
3474          for(param = sClass.templateParams.last; param; param = param.prev)
3475          {
3476             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3477             ClassTemplateArgument * baseArg = &templatedClass.base.templateArgs[c];
3478             if(!arg->dataTypeString)
3479             {
3480                *arg = templatedClass.base.templateArgs[c];
3481                CopyTemplateArg(param, arg);
3482                if(param.type == type)
3483                {
3484                   if(arg->dataTypeClass && strchr(arg->dataTypeString, '<') && arg->dataTypeClass.templateArgs)
3485                   {
3486                      Class expClass = arg->dataTypeClass;
3487                      Class cClass = null;
3488                      int paramCount = 0;
3489                      int lastParam = -1;
3490                      
3491                      char templateString[1024];
3492                      sprintf(templateString, "%s<", expClass.templateClass.fullName);
3493                      for(cClass = expClass; cClass; cClass = cClass.base)
3494                      {
3495                         int p = 0;
3496                         ClassTemplateParameter param;
3497                         for(param = cClass.templateParams.first; param; param = param.next)
3498                         {
3499                            int id = p;
3500                            Class sClass;
3501                            ClassTemplateArgument arg;
3502                            for(sClass = expClass.base; sClass; sClass = sClass.base) id += sClass.templateParams.count;
3503                            arg = expClass.templateArgs[id];
3504
3505                            {
3506                               ClassTemplateParameter cParam;
3507                               int p = numParams - _class.templateParams.count;
3508                               for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3509                               {
3510                                  if(cParam.type == type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
3511                                  {
3512                                     arg.dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3513                                     arg.dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3514                                     break;
3515                                  }
3516                               }
3517                            }
3518
3519                            {
3520                               char argument[256];
3521                               argument[0] = '\0';
3522                               switch(param.type)
3523                               {
3524                                  case expression:
3525                                  {
3526                                     // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
3527                                     /*
3528                                     char expString[1024];
3529                                     OldList * specs = MkList();
3530                                     Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
3531                                     Expression exp;
3532                                     char * string = PrintHexUInt64(arg.expression.ui64);
3533                                     exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
3534
3535                                     ProcessExpressionType(exp);
3536                                     ComputeExpression(exp);
3537                                     expString[0] = '\0';
3538                                     PrintExpression(exp, expString);
3539                                     strcat(argument, expString);
3540                                     //delete exp;
3541                                     FreeExpression(exp);
3542                                     */
3543                                     break;
3544                                  }
3545                                  case identifier:
3546                                  {
3547                                     strcat(argument, arg.member.name);
3548                                     break;
3549                                  }
3550                                  case TemplateParameterType::type:
3551                                  {
3552                                     if(arg.dataTypeString)
3553                                        strcat(argument, arg.dataTypeString);
3554                                     break;
3555                                  }
3556                               }
3557                               if(argument[0])
3558                               {
3559                                  if(paramCount) strcat(templateString, ", ");
3560                                  if(lastParam != p - 1)
3561                                  {
3562                                     strcat(templateString, param.name);
3563                                     strcat(templateString, " = ");
3564                                  }
3565                                  strcat(templateString, argument);
3566                                  paramCount++;
3567                                  lastParam = p;
3568                               }
3569                            }
3570                            p++;
3571                         }
3572                      }
3573                      {
3574                         int len = strlen(templateString);
3575                         if(templateString[len-1] == '>') templateString[len++] = ' ';
3576                         templateString[len++] = '>';
3577                         templateString[len++] = '\0';
3578                      }
3579
3580                      FreeTemplateArg(templatedClass, param, c);
3581
3582                      arg->dataTypeString = CopyString(templateString);
3583                      arg->dataTypeClass = eSystem_FindClass(templatedClass.module, templateString);
3584                      if(!arg->dataTypeClass)
3585                         arg->dataTypeClass = eSystem_FindClass(templatedClass.module.application, templateString);
3586                   }
3587                   else
3588                   {
3589                      ClassTemplateParameter cParam;
3590                      int p = numParams - _class.templateParams.count;
3591                      for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3592                      {
3593                         // if(cParam.type == type && !strcmp(cParam.name, param.name))
3594                         if(cParam.type == type && baseArg->dataTypeString && !strcmp(cParam.name, baseArg->dataTypeString))
3595                         {
3596                            FreeTemplateArg(templatedClass, param, c);
3597
3598                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3599                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3600                            CopyTemplateArg(cParam, arg);
3601                            break;
3602                         }
3603                      }
3604                   }
3605                }
3606             }
3607             c--;                        
3608          }
3609       }
3610    }
3611
3612    {
3613       Class sClass;
3614       for(sClass = _class; sClass; sClass = sClass.base)
3615       {
3616          int curParamID = 0;
3617          Class nextClass;
3618          ClassTemplateParameter param;
3619          if(sClass.templateClass) sClass = sClass.templateClass;
3620          
3621          for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) 
3622          {
3623             if(nextClass.templateClass) nextClass = nextClass.templateClass;
3624             curParamID += nextClass.templateParams.count;
3625          }
3626
3627          for(param = sClass.templateParams.first; param; param = param.next)
3628          {
3629             if(!templatedClass.templateArgs[curParamID].dataTypeString)
3630             {
3631                templatedClass.templateArgs[curParamID] = param.defaultArg;
3632                CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3633                if(param.type == type && param.defaultArg.dataTypeString)
3634                {
3635                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3636                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3637                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3638                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3639                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3640                }
3641             }
3642             curParamID++;
3643          }
3644       }
3645    }
3646
3647    {
3648       int c = numParams - 1;
3649       for(sClass = _class; sClass; sClass = sClass.base)
3650       {
3651          ClassTemplateParameter param;
3652          if(sClass.templateClass) sClass = sClass.templateClass;
3653          for(param = sClass.templateParams.last; param; param = param.prev)
3654          {
3655             if(param.type == type)
3656             {
3657                ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3658                ClassTemplateParameter cParam;
3659                Class dClass;
3660                int p = numParams - 1;
3661                for(dClass = _class; dClass; dClass = dClass.base)
3662                {                              
3663                   if(dClass.templateClass) dClass = dClass.templateClass;
3664                   for(cParam = dClass.templateParams.last; cParam; cParam = cParam.prev, p--)
3665                   {
3666                      if(cParam.type == type && arg->dataTypeString && !strcmp(cParam.name, arg->dataTypeString))
3667                      {
3668                         if(templatedClass.templateArgs[p].dataTypeString && c != p)
3669                         {
3670                            FreeTemplateArg(templatedClass, param, c);
3671
3672                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3673                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3674                            CopyTemplateArg(cParam, arg);
3675                         }
3676                      }
3677                   }
3678                }
3679             }
3680             c--;
3681          }
3682       }
3683    }
3684
3685    {
3686       Class tClass;
3687       int c = numParams - 1;
3688       for(tClass = _class; tClass; tClass = tClass.base)
3689       {
3690          ClassTemplateParameter param;
3691          if(tClass.templateClass) tClass = tClass.templateClass;
3692          for(param = tClass.templateParams.last; param; param = param.prev)
3693          {
3694             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3695             if(param.type == identifier && arg->memberString)
3696             {
3697                Class memberClass = templatedClass;
3698                char * memberString = arg->memberString;
3699                char * colon = strstr(memberString, "::");
3700                char * memberName = memberString;
3701                if(colon) memberName = colon + 2;
3702                if(!colon)
3703                {
3704                   memberString = param.defaultArg.memberString;
3705                   colon = memberString ? strstr(memberString, "::") : null;
3706                }
3707
3708                if(colon)
3709                {
3710                   char className[1024];
3711                   Class sClass;
3712
3713                   memcpy(className, memberString, colon - memberString);
3714                   className[colon - memberString] = '\0';
3715                   
3716                   for(sClass = _class; sClass; sClass = sClass.base)
3717                   {
3718                      ClassTemplateParameter cParam;
3719                      Class nextClass;
3720                      int id = 0;
3721
3722                      if(sClass.templateClass) sClass = sClass.templateClass;
3723                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) 
3724                      {
3725                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
3726                         id += nextClass.templateParams.count;
3727                      }
3728                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
3729                      {
3730                         if(cParam.type == type && !strcmp(cParam.name, className) && templatedClass.templateArgs[id].dataTypeString)
3731                         {
3732                            strcpy(className, templatedClass.templateArgs[id].dataTypeString);
3733                         }
3734                         id++;
3735                      }                  
3736                   }
3737                   memberClass = eSystem_FindClass(templatedClass.module, className);
3738                   // TESTING: Added this here...
3739                   if(!memberClass)
3740                      memberClass = eSystem_FindClass(findModule, className);
3741                   if(!memberClass)
3742                      memberClass = eSystem_FindClass(templatedClass.module.application, className);
3743                }
3744
3745                if(memberClass)
3746                {
3747                   switch(param.memberType)
3748                   {
3749                      case dataMember:
3750                         arg->member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
3751                         break;
3752                      case method:
3753                         arg->method = eClass_FindMethod(memberClass, memberName, memberClass.module);
3754                         break;
3755                      case prop:
3756                         arg->prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
3757                         break;
3758                   }
3759                }
3760             }
3761             c--;
3762          }
3763       }
3764    }
3765 }
3766
3767 /*static */bool DefaultFunction()
3768 {
3769    return true;
3770 }
3771
3772 public dllexport bool eClass_IsDerived(Class _class, Class from)
3773 {
3774    if(!_class && !from)
3775       return true;
3776
3777    if(_class && from && (_class.templateClass || from.templateClass))
3778    {
3779       if(eClass_IsDerived(_class.templateClass ? _class.templateClass : _class, from.templateClass ? from.templateClass : from))
3780       {
3781          if(!from.templateClass)
3782             return true;
3783          else if(!_class.templateClass && _class == from.templateClass)
3784             return false;
3785          else
3786          {
3787             Class sClass;
3788             for(sClass = from; sClass; sClass = sClass.base)
3789             {
3790                if(sClass.templateParams.first)
3791                {
3792                   ClassTemplateParameter param;
3793                   Class nextClass;
3794                   int p = 0;
3795                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) p += nextClass.templateParams.count;               
3796                   for(param = sClass.templateParams.first; param; param = param.next, p++)
3797                   {
3798                      ClassTemplateArgument * arg = &_class.templateArgs[p];
3799                      ClassTemplateArgument * fArg = &from.templateArgs[p];
3800                      if(param.type == type)
3801                      {
3802                         if(arg->dataTypeString != fArg->dataTypeString && arg->dataTypeString && fArg->dataTypeString &&
3803                           strcmp(arg->dataTypeString, fArg->dataTypeString))
3804                            break;
3805                      }
3806                      else if(param.type == identifier)
3807                      {
3808                         if(arg->member != fArg->member)
3809                            break;
3810                      }
3811                      else if(param.type == expression)
3812                      {
3813                         if(arg->expression.ui64 != fArg->expression.ui64)
3814                            break;
3815                      }
3816                   }
3817                   if(param)
3818                      return false;
3819                }
3820             }
3821             return true;
3822          }
3823       }
3824    }
3825    else
3826    {
3827       for(; _class && from; _class = _class.base)
3828       {
3829          if(_class == from || _class.templateClass == from || (_class.type == systemClass && from.name && !strcmp(_class.name, from.name)))
3830             return true;
3831       }
3832    }
3833    return false;
3834 }
3835
3836 static void FixDerivativeVirtualMethod(Class base, char * name, int vid, void * origFunction, char * type)
3837 {
3838    OldLink derivative;
3839    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
3840    {
3841       Class _class = derivative.data;
3842       Method method, next;
3843       void * function = origFunction;
3844
3845       _class.vTblSize++;
3846       _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
3847       memmove(_class._vTbl + vid + 1, _class._vTbl + vid, (_class.vTblSize - vid - 1) * sizeof(void *));
3848
3849       method = (Method) _class.methods.FindString(name);
3850       if(method)
3851       {
3852          if(method.function) function = method.function;
3853
3854          if(!method.symbol)
3855          {
3856             delete method.name;
3857             delete method.dataTypeString;
3858             _class.methods.Delete((BTNode)method);
3859          }
3860          else
3861          {
3862             delete method.dataTypeString;
3863             method.type = virtualMethod;
3864             method.dataTypeString = CopyString(type);
3865             method._class = base;
3866          }
3867       }
3868       for(method = (Method)_class.methods.first; method; method = next)
3869       {
3870          next = (Method)((BTNode)method).next;
3871          if(method.type == virtualMethod)
3872             method.vid++;
3873       }
3874       _class._vTbl[vid] = function;
3875
3876       {
3877          OldLink templateLink;
3878          for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
3879          {
3880             Class template = templateLink.data;
3881             template._vTbl = _class._vTbl;
3882          }
3883       }
3884       if(_class.derivatives.first || _class.templatized.first)
3885          FixDerivativeVirtualMethod(_class, name, vid, function, type);
3886    }
3887    {
3888       OldLink templateLink;
3889       for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
3890       {
3891          Class template = templateLink.data;
3892          template._vTbl = base._vTbl;
3893          FixDerivativeVirtualMethod(template, name, vid, origFunction, type);
3894       }
3895    }
3896 }
3897
3898 public dllexport Method eClass_AddMethod(Class _class, char * name, char * type, void * function, AccessMode declMode)
3899 {
3900    if(_class && name)
3901    {
3902       Class base;
3903       for(base = _class; base; base = base.base)
3904       {
3905          Method method = (Method)base.methods.FindString(name);
3906          if(method)
3907          {
3908             // If this overides a virtual method
3909             if(method.type == virtualMethod)
3910             {
3911                OldLink deriv;
3912                void * oldFunction = _class._vTbl[method.vid];
3913                if(method.vid > _class.vTblSize)
3914                   printf("error");
3915                else
3916                   _class._vTbl[method.vid] = function ? function : DefaultFunction;
3917                for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
3918                {
3919                   Class derivClass = deriv.data;
3920                   if(derivClass._vTbl[method.vid] == oldFunction)
3921                      eClass_AddMethod(derivClass, name, type, function, declMode);
3922                }
3923                {
3924                   OldLink templateLink;
3925                   for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
3926                   {
3927                      Class template = templateLink.data;
3928                      for(deriv = template.derivatives.first; deriv; deriv = deriv.next)
3929                      {
3930                         Class derivClass = deriv.data;
3931                         if(derivClass._vTbl[method.vid] == oldFunction)
3932                            eClass_AddMethod(derivClass, name, type, function, declMode);
3933                      }
3934                   }
3935                }
3936
3937             }
3938             else
3939             {
3940                if(base == _class)
3941                {
3942                   // printf("error: Redefinition of method %s in class %s\n", name, _class.name);
3943                   break;
3944                }
3945                base = null;
3946                break;
3947             }
3948             return method;
3949          }
3950       }
3951
3952       if(!base)
3953       {
3954          Method method
3955          {
3956             name = CopyString(name),
3957             function = function ? function : DefaultFunction;
3958             _class = _class;
3959             dataTypeString = CopyString(type);
3960             memberAccess = declMode;
3961          };
3962          _class.methods.Add((BTNode)method);
3963          return method;
3964       }
3965    }
3966    return null;
3967 }
3968
3969 public dllexport Method eClass_AddVirtualMethod(Class _class, char * name, char * type, void * function, AccessMode declMode)
3970 {
3971    if(_class && name)
3972    {
3973       Class base;
3974       for(base = _class; base; base = base.base)
3975       {
3976          Method method = (Method)base.methods.FindString(name);
3977          if(method)
3978          {
3979             // If this overides a virtual method
3980             if(method.type == virtualMethod)
3981                _class._vTbl[method.vid] = function ? function : DefaultFunction;
3982             else
3983                base = null;
3984             return method;
3985          }
3986       }
3987
3988       if(!base)
3989       {
3990          Method method
3991          {
3992             name = CopyString(name);
3993             function = function ? function : DefaultFunction;
3994             type = virtualMethod;
3995             _class = _class;
3996             vid = _class.vTblSize++;
3997             dataTypeString = CopyString(type);
3998             memberAccess = declMode;
3999          };
4000          _class.methods.Add((BTNode)method);
4001          _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
4002          _class._vTbl[method.vid] = function ? function : DefaultFunction;
4003
4004          // TODO: Fix derived classes
4005          if(_class.derivatives.first || _class.templatized.first)
4006             FixDerivativeVirtualMethod(_class, name, method.vid, function ? function : (void *)DefaultFunction, type);
4007          return method;
4008       }
4009    }
4010    return null;
4011 }
4012
4013 static void FixDerivativeProperty(Class base, Property _property)
4014 {
4015    OldLink derivative;
4016    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
4017    {
4018       Class _class = derivative.data;
4019       Property prop;
4020       BTNamedLink link;
4021       link = (BTNamedLink)_class.prop.FindString(_property.name);
4022       if(link)
4023       {
4024          prop = link.data;
4025          if(!prop.Set && !prop.Get && prop.memberAccess == baseSystemAccess)
4026          {
4027             SelfWatcher watcher;
4028             for(watcher = _class.selfWatchers.first; watcher; watcher = watcher.next)
4029             {
4030                if(watcher._property == prop)
4031                   watcher._property = _property;
4032             }
4033             _property.selfWatchable = true;
4034
4035             delete prop.name;
4036             delete prop.dataTypeString;
4037             _class.membersAndProperties.Delete(prop);
4038             _class.prop.Delete((BTNode)link);
4039          }
4040       }
4041
4042       for(prop = _class.membersAndProperties.first; prop; prop = prop.next)
4043          prop.id++;
4044       _class.memberID++;
4045       _class.startMemberID++;
4046
4047       FixDerivativeProperty(_class, _property);
4048    }
4049 }
4050
4051 public dllexport Property eClass_AddProperty(Class _class, char * name, char * dataType, void * setStmt, void * getStmt, AccessMode declMode)
4052 {
4053    Property _property = null;
4054    if(_class)
4055    {
4056       if(!_class.prop.FindString((name ? name : dataType))) 
4057       {
4058          _property =
4059          {
4060             isProperty = true;
4061             name = CopyString(name ? name : dataType);
4062             id = (name && (setStmt || getStmt || dataType)) ? _class.memberID++ : 0;
4063             Set = setStmt;
4064             Get = getStmt;
4065             dataTypeString = CopyString(dataType);
4066             _class = _class;
4067             compiled = true;
4068             conversion = name ? false : true;
4069             memberAccess = declMode;
4070          };
4071          if(name)
4072             _class.membersAndProperties.Add(_property);
4073          else
4074             _class.conversions.Add(_property);
4075          _class.prop.Add((BTNode)BTNamedLink { name = _property.name, data = _property });
4076
4077          if(!_property.conversion)
4078          {
4079             FixDerivativeProperty(_class, _property);
4080          }
4081       }
4082    }
4083    return _property;
4084 }
4085
4086 static void SetDelayedCPValues(Class _class, ClassProperty _property)
4087 {
4088    OldLink deriv;
4089    NamedLink value, next;
4090
4091    for(value = _class.delayedCPValues.first; value; value = next)
4092    {
4093       next = value.next;
4094       if(!strcmp(value.name, _property.name))
4095       {
4096          // eClass_SetProperty(_class, _property.name, value.data);
4097          _property.Set(_class, (int)value.data);
4098          _class.delayedCPValues.Delete(value);
4099       }
4100    }
4101
4102    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4103    {
4104       SetDelayedCPValues(deriv.data, _property);
4105    }
4106 }
4107
4108 public dllexport ClassProperty eClass_AddClassProperty(Class _class, char * name, char * dataType, void * setStmt, void * getStmt)
4109 {
4110    if(name && !_class.classProperties.FindString(name)) 
4111    {
4112       ClassProperty _property
4113       {
4114          name = CopyString(name);
4115          Set = setStmt;
4116          Get = getStmt;
4117          dataTypeString = CopyString(dataType);
4118       };
4119       _class.classProperties.Add((BTNode)_property);
4120       SetDelayedCPValues(_class, _property);
4121       return _property;
4122    }
4123    return null;
4124 }
4125
4126 /*import "Time"
4127
4128 Time classFindTotalTime;
4129
4130 public dllexport void ResetClassFindTime()
4131 {
4132    classFindTotalTime = 0;
4133 }
4134
4135 public dllexport Time GetClassFindTime()
4136 {
4137    return classFindTotalTime;
4138 }
4139 */
4140 public dllexport ClassProperty eClass_FindClassProperty(Class _class, char * name)
4141 {
4142    //Time startTime = GetTime();
4143    ClassProperty _property = null;
4144    if(name && _class)
4145    {
4146       Class origClass = _class;
4147       for(; _class; _class = _class.base)
4148       {
4149          _property = (ClassProperty)_class.classProperties.FindString(name);
4150          if(_property)
4151             break;
4152       }
4153       // For enum class deriving off something else than enum to find enumSize...
4154       if(!_property && origClass.type == enumClass)
4155       {
4156          Class enumClass = eSystem_FindClass(origClass.module, "enum");
4157          _property = eClass_FindClassProperty(enumClass, name);
4158       }
4159    }
4160    /*if(!_property)
4161       eSystem_Logf("No such property (%s) for class %s\n", name, _class.name);*/
4162    //classFindTotalTime += GetTime() - startTime;
4163    return _property;
4164 }
4165
4166 public dllexport int eClass_GetProperty(Class _class, char * name)
4167 {
4168    ClassProperty _property = eClass_FindClassProperty(_class, name);
4169    if(_property && _property.Get && _property.Get != (void *)1)
4170    {
4171       int result = _property.Get(_class);
4172       return result;
4173    }
4174    return 0;
4175 }
4176
4177 public dllexport void eClass_SetProperty(Class _class, char * name, int value)
4178 {
4179    ClassProperty _property = eClass_FindClassProperty(_class, name);
4180    if(_property)
4181    {
4182       if(_property.Set)
4183          _property.Set(_class, value);
4184    }
4185    else
4186    {
4187       _class.delayedCPValues.Add(NamedLink { name = name, (void *)value });
4188    }
4189 }
4190
4191 public dllexport Method eClass_FindMethod(Class _class, char * name, Module module)
4192 {
4193    //Time startTime = GetTime();
4194    if(_class && name)
4195    {
4196       for(; _class; _class = _class.base)
4197       {
4198          Method method;
4199          if(_class.templateClass) _class = _class.templateClass;
4200          method = (Method)_class.methods.FindString(name);
4201          if(method && (method.memberAccess == publicAccess || _class.module == module || !method.dataTypeString))
4202          {
4203             if(!method.dataTypeString)
4204             {
4205                if(_class.module != module)
4206                {
4207                   if(method.memberAccess == publicAccess)
4208                      module = _class.module;
4209                   else
4210                   {
4211                      //classFindTotalTime += GetTime() - startTime;
4212                      return null;
4213                   }
4214                }
4215             }
4216             else
4217             {
4218                //classFindTotalTime += GetTime() - startTime;
4219                return method;
4220             }
4221          }
4222          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4223       }
4224    }
4225    //classFindTotalTime += GetTime() - startTime;
4226    return null;
4227 }
4228
4229 // Construct an instance
4230 static bool ConstructInstance(void * instance, Class _class, Class from)
4231 {
4232    if(_class.templateClass) _class = _class.templateClass;
4233    if(_class.base && from != _class.base)
4234    {
4235       if(!ConstructInstance(instance, _class.base, from))
4236          return false;
4237    }
4238    if(_class.Initialize)
4239    {
4240       void (* Initialize)(Module module) = (void *)_class.Initialize;
4241       _class.Initialize = null;
4242       Initialize(_class.module);
4243    }
4244    if(_class.Constructor)
4245    {
4246       if(!_class.Constructor(instance))
4247       {
4248          for(; _class; _class = _class.base)
4249          {
4250             if(_class.templateClass) _class = _class.templateClass;
4251             if(_class.Destructor)
4252                _class.Destructor(instance);
4253          }
4254          return false;
4255       }
4256    }
4257    (_class.templateClass ? _class.templateClass : _class).count++;
4258    return true;
4259 }
4260
4261 public dllexport void * eInstance_New(Class _class)
4262 {
4263    Instance instance = null;
4264    if(_class)
4265    {
4266       // instance = _malloc(_class.size);   
4267 #ifdef MEMINFO
4268
4269 #undef malloc
4270    memMutex.Wait();
4271       //allocateClass = _class;
4272       allocateClass = malloc(strlen(_class.name)+1);
4273       allocateInternal = _class.module == __thisModule;
4274       strcpy(allocateClass, _class.name);
4275 #ifndef MEMINFO
4276 #define malloc _mymalloc
4277 #endif
4278
4279 #endif
4280       instance = _calloc(1, _class.structSize);   
4281 #ifdef MEMINFO
4282       allocateClass = null;
4283    memMutex.Release();
4284 #endif
4285       if(_class.type == normalClass)
4286       {
4287          instance._class = _class;
4288          // Copy the virtual table initially
4289          instance._vTbl = _class._vTbl;
4290       }
4291       if(!ConstructInstance(instance, _class, null))
4292       {
4293          _free(instance);
4294          instance = null;
4295       }
4296       /*if(_class.type == normalClass && _class.count > 1000)
4297          printf("%s: %d instances\n", _class.name, _class.count);*/
4298    }
4299    return instance;
4300 }
4301
4302 public dllexport void eInstance_Evolve(Instance * instancePtr, Class _class)
4303 {
4304    if(_class && instancePtr && *instancePtr)
4305    {
4306       bool wasApp = false, wasGuiApp = false;
4307       Instance instance = (Instance)renew *instancePtr byte[_class.structSize];
4308       Class fromClass = instance._class;
4309       *instancePtr = instance;
4310       memset(((byte *)instance) + instance._class.structSize, 0, _class.structSize - instance._class.structSize);
4311       // Fix pointers to application
4312       if((wasApp = !strcmp(instance._class.name, "Application")) ||
4313          (wasGuiApp = !strcmp(instance._class.name, "GuiApplication")))
4314       {
4315          Module module;
4316          Application app = (Application) instance;
4317          BTNamedLink link;
4318          Class _class;
4319          NameSpace * nameSpace;
4320          for(module = app.allModules.first; module; module = module.next)
4321             module.application = app;
4322
4323          for(link = (BTNamedLink)app.privateNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4324          {
4325             OldLink t;
4326             ((Class)link.data).nameSpace = &app.privateNameSpace;
4327             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4328          }
4329          for(link = (BTNamedLink)app.publicNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4330          {
4331             OldLink t;
4332             ((Class)link.data).nameSpace = &app.publicNameSpace;
4333             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4334          }
4335
4336          for(link = (BTNamedLink)app.privateNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4337             ((DefinedExpression)link.data).nameSpace = &app.privateNameSpace;
4338          for(link = (BTNamedLink)app.publicNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4339             ((DefinedExpression)link.data).nameSpace = &app.publicNameSpace;
4340
4341          for(link = (BTNamedLink)app.privateNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4342             ((GlobalFunction)link.data).nameSpace = &app.privateNameSpace;
4343          for(link = (BTNamedLink)app.publicNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4344             ((GlobalFunction)link.data).nameSpace = &app.publicNameSpace;
4345
4346          for(nameSpace = (NameSpace *)app.privateNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4347             nameSpace->parent = &app.privateNameSpace;
4348          for(nameSpace = (NameSpace *)app.publicNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4349             nameSpace->parent = &app.publicNameSpace;
4350
4351          // --------------------------------------------------
4352          for(link = (BTNamedLink)app.systemNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4353          {
4354             OldLink t;
4355             ((Class)link.data).nameSpace = &app.systemNameSpace;
4356             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4357          }
4358          for(link = (BTNamedLink)app.systemNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4359             ((DefinedExpression)link.data).nameSpace = &app.systemNameSpace;
4360          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4361             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4362          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4363             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4364          for(nameSpace = (NameSpace *)app.systemNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4365             nameSpace->parent = &app.systemNameSpace;
4366          // --------------------------------------------------
4367          
4368          for(_class = app.classes.first; _class; _class = _class.next)
4369          {
4370             OldLink templateLink;
4371             _class.module = (Module) app;
4372             for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4373             {  
4374                Class template = templateLink.data;
4375                template.module = _class.module;
4376             }
4377          }
4378
4379          for(module = app.allModules.first; module; module = module.next)
4380          {
4381             for(_class = module.classes.first; _class; _class = _class.next)
4382             {
4383                OldLink templateLink;
4384                _class.module = module;
4385                for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4386                {
4387                   Class template = templateLink.data;
4388                   template.module = _class.module;
4389                }
4390             }
4391          }
4392
4393          app.application = app;
4394       }
4395
4396       {
4397          Class base;
4398          for(base = instance._class; base && base.type == normalClass && base.count; base = base.base)
4399             (base.templateClass ? base.templateClass : base).count--;
4400       }
4401
4402       instance._class = _class;
4403       // Copy the virtual table initially
4404       instance._vTbl = _class._vTbl;
4405
4406       // We don't want to reconstruct the portion already constructed...
4407       if(!ConstructInstance(instance, _class, fromClass))
4408       {
4409          _free(instance);
4410          *instancePtr = null;
4411       }
4412    }
4413 }
4414
4415 public dllexport void eInstance_Delete(Instance instance)
4416 {
4417 #ifdef MEMINFO
4418    bool checkMemory = false;
4419 #endif
4420    if(instance)
4421    {
4422       Class _class, base;
4423       bool ownVtbl;
4424
4425 #ifdef MEMINFO
4426       if(instance._class == (void *)0xecececec)
4427          _free(instance);
4428 #endif
4429
4430       ownVtbl = instance._vTbl != instance._class._vTbl;
4431
4432       for(_class = instance._class; _class; _class = base)
4433       {
4434          if(_class.templateClass) _class = _class.templateClass;
4435          if(_class.destructionWatchOffset)
4436          {
4437             OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
4438             Watcher watcher, next;
4439
4440             for(watcher = watchers->first; watcher; watcher = next)
4441             {
4442                next = watcher.next;
4443                watchers->Remove(watcher);
4444                watcher.callback(watcher.object, instance);
4445                watchers->Delete(watcher);
4446             }
4447          }
4448
4449          /*// Loop through properties to delete all watchers? Might slow down destruction...
4450          {
4451             Property _property;
4452             for(_property = _class.membersAndProperties.first; _property; _property = _property.next)
4453             {
4454                if(_property.isProperty && _property.isWatchable)
4455                {
4456                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
4457                   Watcher watcher, next;
4458                   for(watcher = watchers->first; watcher; watcher = next)
4459                   {  
4460                      next = watcher.next;
4461                      watchers->Delete(watcher);
4462                   }
4463                }
4464             }
4465          }*/
4466          
4467
4468          base = _class.base;
4469          if(base && base.type == systemClass) base = null;
4470          if(_class.Destructor)
4471             _class.Destructor(instance);
4472 #ifdef MEMINFO
4473          if(_class == class(Application))
4474             checkMemory = true;
4475 #endif
4476       }
4477
4478       for(_class = instance._class; _class; _class = base)
4479       {
4480          if(_class.templateClass) _class = _class.templateClass;
4481
4482          base = _class.base;
4483          (_class.templateClass ? _class.templateClass : _class).count--;
4484          if(_class.type == normalClass && !_class.count && !_class.module)
4485          {
4486 #ifdef MEMINFO
4487             // printf("Now Destructing class %s\n", _class.name);
4488 #endif
4489             eClass_Unregister(_class);
4490          }
4491       }
4492
4493       if(ownVtbl)
4494       {
4495          delete instance._vTbl;
4496       }
4497       //instance.prop.Free(null);
4498       _free(instance);
4499 #ifdef MEMINFO
4500       if(checkMemory) CheckMemory();
4501 #endif
4502    }
4503 }
4504
4505 public dllexport Property eClass_FindProperty(Class _class, char * name, Module module)
4506 {
4507    //Time startTime = GetTime();
4508    if(_class && name)
4509    {
4510       for(; _class; _class = _class.base)
4511       {
4512          BTNamedLink link;
4513          if(_class.templateClass) _class = _class.templateClass;
4514          link = (BTNamedLink)_class.prop.FindString(name);
4515          if(link)
4516          {
4517             Property _property = (Property)link.data;
4518             if(_property.memberAccess == publicAccess || _class.module == module || !_property.dataTypeString)
4519             {
4520                if(!_property.dataTypeString)
4521                {
4522                   if(_class.module != module)
4523                   {
4524                      if(_property.memberAccess == publicAccess)
4525                         module = _class.module;
4526                      else
4527                      {
4528                         //classFindTotalTime += GetTime() - startTime;
4529                         return null;
4530                      }
4531                   }
4532                }
4533                else
4534                {
4535                   //classFindTotalTime += GetTime() - startTime;
4536                   return _property;
4537                }
4538             }
4539          }
4540          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4541       }
4542    }
4543    //classFindTotalTime += GetTime() - startTime;
4544    return null;
4545 }
4546
4547 static DataMember FindDataMember(OldList list, BinaryTree alist, char * name, uint * offset, int * id, bool searchPrivate, DataMember * subMemberStack, int * subMemberStackPos)
4548 {
4549    BTNamedLink link;
4550    DataMember dataMember;
4551
4552    link = (BTNamedLink)alist.FindString(name);
4553    if(link)
4554    {
4555       dataMember = link.data;
4556       if(dataMember.type == normalMember && (dataMember.memberAccess == publicAccess || searchPrivate || !dataMember.dataTypeString))
4557       {
4558          if(offset)
4559             *offset += dataMember.offset;
4560          if(id) *id = dataMember.id;
4561          return dataMember;
4562       }
4563       return null;
4564    }
4565    for(dataMember = list.first; dataMember; dataMember = dataMember.next)
4566    {
4567       if(!dataMember.isProperty && (dataMember.memberAccess == publicAccess || searchPrivate) && !dataMember.name && (dataMember.type == unionMember || dataMember.type == structMember))
4568       {
4569          DataMember childMember;
4570          if(subMemberStackPos) subMemberStack[(*subMemberStackPos)++] = dataMember;
4571          childMember = FindDataMember(dataMember.members, dataMember.membersAlpha, name, offset, id, searchPrivate, subMemberStack, subMemberStackPos);
4572          if(childMember)
4573          {
4574             if(offset)
4575                *offset += dataMember.offset;
4576             if(id) *id += dataMember.id;
4577             return childMember;
4578          }
4579          if(subMemberStackPos) (*subMemberStackPos)--;
4580       }
4581    }
4582    return null;
4583 }
4584
4585 public dllexport DataMember eClass_FindDataMember(Class _class, char * name, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4586 {
4587    //Time startTime = GetTime();
4588    DataMember dataMember = null;
4589    if(subMemberStackPos) *subMemberStackPos = 0;
4590    if(_class && name)
4591    {
4592       for(; _class; _class = _class.base)
4593       {
4594          if(_class.templateClass) _class = _class.templateClass;
4595          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, null, _class.module == module, subMemberStack, subMemberStackPos);
4596          if(dataMember)
4597          {
4598             if(!dataMember.dataTypeString)
4599             {
4600                if(_class.module != module)
4601                {
4602                   if(dataMember.memberAccess == publicAccess)
4603                      module = _class.module;
4604                   else
4605                   {
4606                      //classFindTotalTime += GetTime() - startTime;
4607                      return null;
4608                   }
4609                }
4610                dataMember = null;
4611             }
4612             else
4613             {
4614                // HACK: Is this good enough? avoiding setting it when adding...
4615                dataMember._class = _class.templateClass ? _class.templateClass : _class;
4616                //classFindTotalTime += GetTime() - startTime;
4617                return dataMember;
4618             }
4619          }
4620          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4621       }
4622    }
4623    //classFindTotalTime += GetTime() - startTime;
4624    return dataMember;
4625 }
4626
4627 public dllexport DataMember eClass_FindDataMemberAndOffset(Class _class, char * name, uint * offset, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4628 {
4629    //Time startTime = GetTime();
4630    DataMember dataMember = null;
4631    if(subMemberStackPos) *subMemberStackPos = 0;
4632    if(offset) *offset = 0;
4633    if(_class)
4634    {
4635       for(; _class; _class = _class.base)
4636       {
4637          if(_class.templateClass) _class = _class.templateClass;
4638          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, offset, null, _class.module == module, subMemberStack, subMemberStackPos);
4639          if(dataMember)
4640          {
4641             if(!dataMember.dataTypeString)
4642             {
4643                if(_class.module != module)
4644                {
4645                   if(dataMember.memberAccess == publicAccess)
4646                      module = _class.module;
4647                   else
4648                   {
4649                      //classFindTotalTime += GetTime() - startTime;
4650                      return null;
4651                   }
4652                }
4653                dataMember = null;
4654             }
4655             else
4656             {
4657                // HACK: Is this good enouh? avoiding setting it when adding...
4658                dataMember._class = _class;
4659                //classFindTotalTime += GetTime() - startTime;
4660                return dataMember;
4661             }
4662          }
4663          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4664       }
4665    }
4666    //classFindTotalTime += GetTime() - startTime;
4667    return dataMember;
4668 }
4669
4670 public dllexport DataMember eClass_FindDataMemberAndId(Class _class, char * name, int * id, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4671 {
4672    //Time startTime = GetTime();
4673    DataMember dataMember = null;
4674    if(subMemberStackPos) *subMemberStackPos = 0;
4675    if(_class)
4676    {
4677       for(; _class; _class = _class.base)
4678       {
4679          if(_class.templateClass) _class = _class.templateClass;
4680          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, id, _class.module == module, subMemberStack, subMemberStackPos);  // TOCHECK: Why was this null? null, null);
4681          if(dataMember)
4682          {
4683             if(!dataMember.dataTypeString)
4684             {
4685                if(_class.module != module)
4686                {
4687                   if(dataMember.memberAccess == publicAccess)
4688                      module = _class.module;
4689                   else
4690                   {
4691                      //classFindTotalTime += GetTime() - startTime;
4692                      return null;
4693                   }
4694                }
4695                dataMember = null;
4696             }
4697             else
4698             {
4699                // HACK: Is this good enouh? avoiding setting it when adding...
4700                dataMember._class = _class;
4701                //classFindTotalTime += GetTime() - startTime;
4702                return dataMember;
4703             }
4704          }
4705          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4706       }
4707    }
4708    //classFindTotalTime += GetTime() - startTime;
4709    return dataMember;
4710 }
4711
4712 public dllexport void eClass_FindNextMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
4713 {
4714    // THIS CODE WILL FIND NEXT MEMBER... (PUBLIC MEMBERS ONLY)
4715    if(*curMember) 
4716    {
4717       *curMember = (*curMember).next;
4718
4719       if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
4720       {
4721          *curMember = subMemberStack[--(*subMemberStackPos)];
4722          *curMember = (*curMember).next;
4723       }
4724
4725       if(subMemberStackPos && *subMemberStackPos > 0)
4726       {
4727          while(*curMember && ((*curMember).memberAccess == privateAccess))
4728             *curMember = (*curMember).next;
4729       }
4730       else
4731          while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
4732          {
4733             DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
4734             if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
4735             if(dataMember && dataMember.memberAccess != privateAccess)
4736             {
4737                *curMember = dataMember;
4738                break;
4739             }
4740             else
4741                *curMember = (*curMember).next;
4742          }
4743
4744       if(subMemberStackPos)
4745       {
4746          while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
4747          {
4748             subMemberStack[(*subMemberStackPos)++] = *curMember;
4749
4750             *curMember = (*curMember).members.first;
4751             while(*curMember && ((*curMember).memberAccess == privateAccess))
4752                *curMember = (*curMember).next;                     
4753          }
4754       }
4755    }
4756    while(!*curMember)
4757    {
4758       if(!*curMember)
4759       {
4760          if(subMemberStackPos && *subMemberStackPos)
4761          {
4762             *curMember = subMemberStack[--(*subMemberStackPos)];
4763             *curMember = (*curMember).next;
4764          }
4765          else
4766          {
4767             Class lastCurClass = *curClass;
4768
4769             if(*curClass == _class) break;     // REACHED THE END
4770
4771             for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass && (*curClass).inheritanceAccess != privateAccess; *curClass = (*curClass).base);
4772             *curMember = (*curClass).membersAndProperties.first;
4773          }
4774
4775          if(subMemberStackPos && *subMemberStackPos > 0)
4776          {
4777             while(*curMember && ((*curMember).memberAccess == privateAccess))
4778                *curMember = (*curMember).next;
4779          }
4780          else
4781             while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
4782             {
4783                DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
4784                if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
4785                if(dataMember && dataMember.memberAccess != privateAccess)
4786                {
4787                   *curMember = dataMember;
4788                   break;
4789                }
4790                else
4791                   *curMember = (*curMember).next;
4792             }
4793
4794          if(subMemberStackPos)
4795          {
4796             while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
4797             {
4798                subMemberStack[(*subMemberStackPos)++] = *curMember;
4799
4800                *curMember = (*curMember).members.first;
4801                while(*curMember && (*curMember).memberAccess == privateAccess)
4802                   *curMember = (*curMember).next;                     
4803             }
4804          }
4805       }
4806    }
4807 }
4808
4809 public dllexport void eInstance_SetMethod(Instance instance, char * name, void * function)     // YET TO BE DECIDED:   , Module module)
4810 {
4811    if(instance && name)
4812    {
4813       Class _class;
4814       for(_class = instance._class; _class; _class = _class.base)
4815       {
4816          Method method = (Method)_class.methods.FindString(name);
4817          if(method && method.type == virtualMethod)
4818          {
4819             if(instance._vTbl == instance._class._vTbl)
4820             {
4821                instance._vTbl = _malloc(sizeof(void *) * instance._class.vTblSize);
4822                memcpy(instance._vTbl, instance._class._vTbl,
4823                   sizeof(int(*)()) * instance._class.vTblSize);               
4824             }
4825             instance._vTbl[method.vid] = function ? function : DefaultFunction;
4826          }
4827       }
4828    }
4829 }
4830
4831 public dllexport bool eInstance_IsDerived(Instance instance, Class from)
4832 {
4833    if(instance)
4834    {
4835       Class _class = instance._class;
4836       for(; _class; _class = _class.base)
4837       {
4838          if(_class == from)
4839             return true;
4840       }
4841    }
4842    return false;
4843 }
4844
4845 public dllexport void eInstance_IncRef(Instance instance)
4846 {
4847    if(instance)
4848       instance._refCount++;
4849 }
4850
4851 public dllexport void eInstance_DecRef(Instance instance)
4852 {
4853    if(instance)
4854    {
4855       instance._refCount--;
4856       //if(!instance._refCount)
4857       if(instance._refCount <= 0)
4858       {
4859          eInstance_Delete(instance);
4860       }
4861    }
4862 }
4863
4864 static void FixOffsets(Class _class)
4865 {
4866    OldLink deriv;
4867    _class.structSize += _class.base.structSize - _class.offset;
4868
4869    _class.offset = _class.base.structSize;   
4870
4871    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4872       FixOffsets(deriv.data);
4873 }
4874
4875 public dllexport void eClass_Resize(Class _class, int newSize)
4876 {
4877    OldLink deriv;
4878    _class.structSize = newSize;
4879    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4880       FixOffsets(deriv.data);
4881 }
4882
4883 public dllexport DataMember eClass_AddDataMember(Class _class, char * name, char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
4884 {
4885    if(_class && name)
4886    {
4887       if(!_class.members.FindString(name)) 
4888       {
4889          DataMember dataMember;
4890
4891          if(alignment)
4892          {
4893             _class.structAlignment = Max(_class.structAlignment, alignment);
4894
4895             if(_class.memberOffset % alignment)
4896                _class.memberOffset += alignment - (_class.memberOffset % alignment);
4897          }
4898          
4899          dataMember = DataMember {
4900             name = CopyString(name);
4901             dataTypeString = CopyString(type);
4902             id = _class.memberID++;
4903             _class = _class;
4904             offset = _class.memberOffset;
4905             memberOffset = size;
4906             memberAccess = declMode;
4907             membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
4908          };
4909          _class.membersAndProperties.Add(dataMember);
4910          _class.memberOffset += size;
4911
4912          _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
4913          return dataMember;
4914       }
4915    }
4916    return null;
4917 }
4918
4919 public dllexport DataMember eMember_AddDataMember(DataMember member, char * name, char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
4920 {
4921    if(name && !member.membersAlpha.FindString(name)) 
4922    {
4923       DataMember dataMember;
4924
4925       if(alignment)
4926       {
4927          member.structAlignment = Max(member.structAlignment, alignment);
4928
4929          if(member.memberOffset % alignment)
4930             member.memberOffset += alignment - (member.memberOffset % alignment);
4931       }
4932       dataMember = DataMember {
4933          name = CopyString(name);
4934          _class = member._class;
4935          dataTypeString = CopyString(type);
4936          id = member.memberID++;
4937          offset = (member.type == unionMember) ? 0 : member.memberOffset;
4938          memberAccess = declMode;
4939          membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
4940       };
4941       member.members.Add(dataMember);
4942       if(member.type == unionMember)
4943       {
4944          if(size > member.memberOffset)
4945             member.memberOffset = size;
4946       }
4947       else
4948          member.memberOffset += size;
4949       member.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
4950       return dataMember;
4951    }
4952    return null;
4953 }
4954
4955 public dllexport DataMember eMember_New(DataMemberType type, AccessMode declMode)
4956 {
4957    return DataMember { type = type, memberAccess = declMode, membersAlpha.CompareKey = (void *)BinaryTree::CompareString };
4958 }
4959
4960 static void SetMemberClass(DataMember member, Class _class)
4961 {
4962    DataMember dataMember;
4963    member._class = _class;
4964    for(dataMember = member.members.first; dataMember; dataMember = dataMember.next)
4965       SetMemberClass(dataMember, _class);      
4966 }
4967
4968 public dllexport bool eMember_AddMember(DataMember addTo, DataMember dataMember)
4969 {
4970    if(dataMember.name && addTo.membersAlpha.FindString(dataMember.name)) return false;
4971    addTo.members.Add(dataMember);
4972
4973    if(dataMember.name)
4974       addTo.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
4975
4976    dataMember._class = addTo._class;
4977    // ? SetMemberClass(dataMember, addTo._class);
4978
4979    //dataMember.id = addTo.memberID++;
4980    dataMember.id = addTo.memberID;
4981    if(dataMember.type == unionMember)
4982       addTo.memberID += 1;
4983    else
4984       addTo.memberID += dataMember.memberID;
4985
4986    addTo.structAlignment = Max(addTo.structAlignment, dataMember.structAlignment);
4987    dataMember.offset = (addTo.type == unionMember) ? 0 : addTo.memberOffset;
4988    if(addTo.type == unionMember)
4989    {
4990       if(dataMember.memberOffset > addTo.memberOffset)
4991          addTo.memberOffset = dataMember.memberOffset;
4992    }
4993    else
4994       addTo.memberOffset += dataMember.memberOffset;
4995    return true;
4996 }
4997
4998 public dllexport bool eClass_AddMember(Class _class, DataMember dataMember)
4999 {
5000    if(!_class || _class.comRedefinition || (dataMember.name && _class.members.FindString(dataMember.name)))
5001       return false;
5002    _class.membersAndProperties.Add(dataMember);
5003
5004    if(dataMember.name)
5005       _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5006
5007    //dataMember._class = _class;
5008    SetMemberClass(dataMember, _class);
5009
5010    //dataMember.id = _class.memberID++;
5011    dataMember.id = _class.memberID;
5012
5013    _class.structAlignment = Max(_class.structAlignment, dataMember.structAlignment);
5014    if(dataMember.type == unionMember)
5015       _class.memberID += 1;
5016    else
5017       _class.memberID += dataMember.memberID;
5018    dataMember.offset = _class.memberOffset;
5019    _class.memberOffset += dataMember.memberOffset;
5020    return true;
5021 }
5022
5023 public dllexport BitMember eClass_AddBitMember(Class _class, char * name, char * type, int bitSize, int bitPos, AccessMode declMode)
5024 {
5025    if(_class && name && !_class.members.FindString(name)) 
5026    {
5027       uint64 mask = 0;
5028       int c;
5029       BitMember bitMember
5030       {
5031          name = CopyString(name);
5032          _class = _class;
5033          dataTypeString = CopyString(type);
5034          id = _class.memberID++;
5035          memberAccess = declMode;
5036       };
5037       _class.membersAndProperties.Add(bitMember);
5038       if(bitSize)
5039       {
5040          bitMember.pos = (bitPos == -1) ? _class.memberOffset : bitPos;
5041          bitMember.size = bitSize;
5042          _class.memberOffset = bitMember.pos + bitMember.size;
5043          for(c = 0; c<bitSize; c++)
5044          {
5045             if(c)
5046                mask <<= 1;
5047             mask |= 1;
5048          }
5049          bitMember.mask = mask << bitMember.pos;
5050       }
5051
5052      _class.members.Add((BTNode)BTNamedLink { name = bitMember.name, data = bitMember });
5053       return bitMember;
5054    }
5055    return null;
5056 }
5057
5058 static Module Module_Load(Module fromModule, char * name, AccessMode importAccess, bool ensureCOM)
5059 {
5060    bool (stdcall * Load)(Module module) = null;
5061    bool (stdcall * Unload)(Module module) = null;
5062    Module module;
5063
5064    for(module = fromModule.application.allModules.first; module; module = module.next)
5065    {
5066       if(!strcmp(module.name, name))
5067          break;
5068    }
5069    if(ensureCOM && (!strcmp(name, "ecereCOM") || !strcmp(name, "ecere")))
5070    {
5071       for(module = fromModule.application.allModules.first; module; module = module.next)
5072       {
5073          if(!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM"))
5074             break;
5075       }
5076    }
5077    if(!module)
5078    {
5079       void * library = null;
5080
5081       if(ensureCOM && !strcmp(name, "ecereCOM"))
5082       {
5083          Load = COM_LOAD_FUNCTION;
5084          Unload = COM_UNLOAD_FUNCTION;
5085       }
5086       else
5087       {
5088          library = Instance_Module_Load(name, &Load, &Unload);
5089       }
5090       if(Load)
5091       {
5092          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5093          module.application = fromModule.application;
5094          module.library = library;
5095          module.name = CopyString(name);
5096          module.Unload = Unload;
5097          module.origImportType = normalImport;
5098          if(!Load(module))
5099          {
5100             eInstance_Delete((Instance)module);
5101             module = null;
5102          }
5103       }
5104       fromModule.application.allModules.Add(module);
5105    }
5106    if(ensureCOM && !strcmp(name, "ecere") && module)
5107    {
5108       name = !strcmp(module.name, "ecereCOM") ? "ecere" : "ecereCOM";
5109       if((!Load && !strcmp(module.name, "ecereCOM")) || 
5110          (Load && (!__thisModule || !__thisModule.name || !strcmp(__thisModule.name, "ecereCOM")) && Load != COM_LOAD_FUNCTION))
5111       {
5112          Module module;
5113          for(module = fromModule.application.allModules.first; module; module = module.next)
5114          {
5115             if(!strcmp(module.name, name))
5116                break;
5117          }
5118          if(!module)
5119          {
5120             Load = COM_LOAD_FUNCTION;
5121             Unload = COM_UNLOAD_FUNCTION;
5122
5123             module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5124             module.application = fromModule.application;
5125             module.library = null;
5126             module.name = CopyString(name);
5127             module.Unload = Unload;
5128             if(!Load(module))
5129             {
5130                eInstance_Delete((Instance)module);
5131                module = null;
5132             }
5133             fromModule.application.allModules.Add(module);
5134          }
5135          if(module)
5136          {
5137             if(fromModule)
5138             {
5139                fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5140             }
5141             incref module;
5142          }
5143       }
5144    }
5145    if(module)
5146    {
5147       if(fromModule)
5148       {
5149          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5150       }
5151       incref module;
5152    }
5153    return module;
5154 }
5155
5156 public dllexport Module eModule_Load(Module fromModule, char * name, AccessMode importAccess)
5157 {
5158    return Module_Load(fromModule, name, importAccess, true);
5159 }
5160
5161 public dllexport Module eModule_LoadStrict(Module fromModule, char * name, AccessMode importAccess)
5162 {
5163    return Module_Load(fromModule, name, importAccess, false);
5164 }
5165
5166 public dllexport Module eModule_LoadStatic(Module fromModule, char * name, AccessMode importAccess, bool (* Load)(Module module), bool (* Unload)(Module module))
5167 {
5168    Module module;
5169    for(module = fromModule.application.allModules.first; module; module = module.next)
5170    {
5171       if(!strcmp(module.name, name))
5172          break;
5173    }
5174    if(!module)
5175    {
5176       if(Load)
5177       {
5178          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5179          module.application = fromModule.application;
5180          module.name = CopyString(name);
5181          module.origImportType = staticImport;
5182          module.Unload = (void *)Unload;
5183          if(!Load(module))
5184          {
5185             eInstance_Delete((Instance)module);
5186             module = null;
5187          }
5188       }
5189       fromModule.application.allModules.Add(module);
5190    }
5191    if(module)
5192    {
5193       if(fromModule)
5194       {
5195          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5196       }
5197       incref module;
5198    }
5199    return module;
5200 }
5201
5202 public dllexport void eModule_Unload(Module fromModule, Module module)
5203 {
5204    OldLink m;
5205    for(m = fromModule.modules.first; m; m = m.next)
5206    {
5207       if(m.data == module)
5208          break;
5209    }
5210    if(m)
5211    {
5212       fromModule.modules.Delete(m);
5213       delete module;
5214    }
5215 }
5216
5217 public dllexport void eEnum_AddFixedValue(Class _class, char * string, int value)
5218 {
5219    if(_class && _class.type == enumClass)
5220    {
5221       EnumClassData data = (EnumClassData)_class.data;
5222       NamedLink item;
5223       
5224       for(item = data.values.first; item; item = item.next)
5225          if(!strcmp(item.name, string)) 
5226             break;
5227       if(!item)
5228       {
5229          data.values.Add(NamedLink { data = (void *)value, name = CopyString(string) });
5230          if(value > data.largest)
5231             data.largest = value;
5232       }
5233    }
5234 }
5235
5236 public dllexport int eEnum_AddValue(Class _class, char * string)
5237 {
5238    if(_class && _class.type == enumClass)
5239    {
5240       EnumClassData data = (EnumClassData)_class.data;
5241       int value = ((int) data.largest) + 1;
5242       NamedLink item;
5243       for(item = data.values.first; item; item = item.next)
5244          if(!strcmp(item.name, string)) 
5245             break;
5246       if(!item)
5247       {
5248          data.values.Add(NamedLink { data = (void *)value, name = CopyString(string) });
5249          if(value > data.largest)
5250             data.largest = value;
5251          return value;
5252       }
5253    }
5254    return -1;
5255 }
5256
5257 static void NameSpace_Free(NameSpace parentNameSpace)
5258 {
5259    NameSpace * nameSpace;
5260    delete parentNameSpace.name;
5261
5262    while((nameSpace = (NameSpace *)parentNameSpace.nameSpaces.first))
5263    {
5264       NameSpace_Free(nameSpace);
5265       parentNameSpace.nameSpaces.Delete((BTNode)nameSpace);
5266    }
5267 }
5268
5269 static void Application_Destructor(Application app)
5270 {
5271    if(app.parsedCommand)
5272    {
5273       delete app.argv;
5274       delete app.parsedCommand;
5275    }
5276 }
5277
5278 static bool Module_Constructor(Module module)
5279 {
5280    module.privateNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5281    module.privateNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5282    module.privateNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5283    module.privateNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5284
5285    module.publicNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5286    module.publicNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5287    module.publicNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5288    module.publicNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5289    return true;
5290 }
5291
5292 static void Module_Destructor(Module module)
5293 {
5294    Class _class;
5295    DefinedExpression def;
5296    GlobalFunction function;
5297    Module m;
5298    SubModule handle;
5299
5300    // printf("Destructing module %s\n", module.name);
5301
5302    // Take out references from all modules
5303    for(m = module.application.allModules.first; m; m = m.next)
5304    {
5305       SubModule next;
5306       for(handle = m.modules.first; handle; handle = next)
5307       {
5308          next = handle.next;
5309          if(handle.module == module)
5310             m.modules.Delete(handle);
5311       }
5312    }
5313
5314    if(module.Unload)
5315    {
5316       if(module.origImportType == staticImport)
5317       {
5318          bool (* Unload)(Module module) = (void *)module.Unload;
5319          Unload(module);
5320       }
5321       else
5322       {
5323          bool (stdcall * Unload)(Module module) = (void *)module.Unload;
5324          Unload(module);
5325       }
5326    }
5327
5328    // Unload dependencies
5329    {
5330       Module ourWorld = class(Class).module;
5331       void * ourHandle = null;
5332       while((handle = module.modules.last))  // STARTING WITH LAST SO THAT ecereCOM IS UNLOADED LAST...
5333       {
5334          Module depModule = handle.module;
5335          if(depModule == ourWorld) 
5336          {
5337             module.modules.Remove(handle);
5338             ourHandle = handle;
5339          }
5340          else
5341          {
5342             module.modules.Delete(handle);
5343             delete depModule;
5344          }         
5345       }
5346       if(ourHandle)
5347       {
5348          delete ourHandle;
5349          delete ourWorld;
5350       }
5351    }
5352
5353    // Unload classes
5354    for(;(_class = module.classes.first);)
5355    {
5356       if(_class.nameSpace)
5357       {
5358          BTNamedLink classLink = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
5359          OldLink t;
5360          for(t = _class.templatized.first; t; t = t.next)
5361          {
5362             Class template = t.data;
5363             BTNamedLink link;
5364             link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
5365
5366             template.nameSpace->classes.Delete((BTNode)link);
5367             template.nameSpace = null;
5368          }
5369          _class.nameSpace->classes.Delete((BTNode)classLink);
5370          _class.nameSpace = null;
5371       }
5372       _class.module = null;
5373       module.classes.Remove(_class);
5374       if(!_class.count || _class.type != normalClass)
5375          eClass_Unregister(_class);
5376       else
5377       {
5378 #ifdef MEMINFO
5379          // printf("Delayed destruction of class %s\n", _class.name);
5380 #endif
5381       }
5382    }
5383
5384    // Unload defines
5385    for(;(def = module.defines.first);)
5386    {
5387       if(def.nameSpace)
5388       {
5389          BTNamedLink defLink;
5390          for(defLink = (BTNamedLink)def.nameSpace->defines.first; defLink; defLink = (BTNamedLink)((BTNode)defLink).next)
5391             if(defLink.data == def)
5392             {
5393                def.nameSpace->defines.Delete((BTNode)defLink);
5394                break;
5395             }
5396       }
5397       delete def.name;
5398       delete def.value;
5399       module.defines.Delete(def);
5400    }
5401
5402    // Unload functions
5403    for(;(function = module.functions.first);)
5404    {
5405       if(function.nameSpace)
5406       {
5407          BTNamedLink functionLink;
5408          for(functionLink = (BTNamedLink)function.nameSpace->functions.first; functionLink; functionLink = (BTNamedLink)((BTNode)functionLink).next)
5409             if(functionLink.data == function)
5410             {
5411                function.nameSpace->functions.Delete((BTNode)functionLink);
5412                break;
5413             }
5414       }
5415       delete function.name;
5416       delete function.dataTypeString;
5417       module.functions.Delete(function);
5418    }
5419
5420    delete module.name;
5421
5422    NameSpace_Free(module.privateNameSpace);
5423    NameSpace_Free(module.publicNameSpace);
5424
5425    if(module != module.application)
5426       module.application.allModules.Remove(module);
5427    else
5428       NameSpace_Free(module.application.systemNameSpace);
5429
5430 #ifndef MEMINFO
5431    Instance_Module_Free(module.library);
5432 #endif
5433 }
5434
5435 static int GetEnumSize(Class _class)
5436 {
5437    EnumClassData data = (EnumClassData)_class.data;
5438    return data.largest+1;
5439 }
5440
5441 #if defined(__GNUC__)
5442 #define strcmpi strcasecmp
5443 #define strnicmp strncasecmp
5444 #endif
5445
5446 #if defined(ECERE_BOOTSTRAP) || (defined(__GNUC__) && !defined(__DJGPP__) && !defined(__WIN32__))
5447 #undef strlwr
5448 #undef strupr
5449 default dllexport char * strlwr(char *string)
5450 {
5451    int c;
5452    for(c=0; string[c]; c++)
5453       if(string[c]>='A' && string[c]<='Z')
5454          string[c]+='a'-'A';
5455    return string;
5456 }
5457 default dllexport char * strupr(char *string)
5458 {
5459    int c;
5460    for(c=0; string[c]; c++)
5461       if(string[c]>='a' && string[c]<='z')
5462          string[c]-='a'-'A';
5463    return string;
5464 }
5465 #endif
5466
5467 public dllexport DefinedExpression eSystem_RegisterDefine(char * name, char * value, Module module, AccessMode declMode)
5468 {
5469    NameSpace * nameSpace = null;
5470    
5471    int start = 0, c;
5472
5473    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5474    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5475
5476    if(declMode != staticAccess)
5477    {
5478       for(c = 0; name[c]; c++)
5479       {
5480          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5481          {
5482             NameSpace * newSpace;
5483
5484             char * spaceName = _malloc(c - start + 1);
5485             strncpy(spaceName, name + start, c - start);
5486             spaceName[c-start] = '\0';
5487
5488             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5489             if(!newSpace)
5490             {
5491                newSpace = new0 NameSpace[1];
5492                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5493                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5494                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5495                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5496                newSpace->name = spaceName;
5497                newSpace->parent = nameSpace;
5498                nameSpace->nameSpaces.Add((BTNode)newSpace);
5499             }
5500             else
5501                delete spaceName;
5502             nameSpace = newSpace;
5503             if(name[c] == ':') c++;
5504             start = c+1;         
5505          }
5506       }
5507    }
5508    else
5509       c = strlen(name);
5510
5511    if(c - start && !nameSpace->defines.FindString(name + start))
5512    {
5513       DefinedExpression def
5514       {
5515          name = CopyString(name);
5516          nameSpace = nameSpace;
5517          value = CopyString(value);
5518       };
5519       nameSpace->defines.Add((BTNode)BTNamedLink { name = def.name + start, data = def });
5520       // Reference the definition in the module
5521       module.defines.Add(def);
5522       return def;
5523    }
5524    return null;
5525 }
5526
5527 public dllexport GlobalFunction eSystem_RegisterFunction(char * name, char * type, void * func, Module module, AccessMode declMode)
5528 {
5529    NameSpace * nameSpace = null;
5530    int start = 0, c;
5531
5532    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5533    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5534
5535    if(declMode != staticAccess)
5536    {
5537       for(c = 0; name[c]; c++)
5538       {
5539          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5540          {
5541             NameSpace * newSpace;
5542
5543             char * spaceName = _malloc(c - start + 1);
5544             strncpy(spaceName, name + start, c - start);
5545             spaceName[c-start] = '\0';
5546
5547             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5548             if(!newSpace)
5549             {
5550                newSpace = new0 NameSpace[1];
5551                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5552                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5553                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5554                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5555                newSpace->name = spaceName;
5556                newSpace->parent = nameSpace;
5557                nameSpace->nameSpaces.Add((BTNode)newSpace);
5558             }
5559             else
5560                delete spaceName;
5561             nameSpace = newSpace;
5562             if(name[c] == ':') c++;
5563             start = c+1;         
5564          }
5565       }
5566    }
5567    else
5568       c = strlen(name);
5569
5570    if(c - start && !nameSpace->functions.FindString(name + start))
5571    {
5572       GlobalFunction function
5573       {
5574          name = CopyString(name);
5575          nameSpace = nameSpace;
5576          dataTypeString = CopyString(type);
5577          function = func;
5578          module = module;
5579       };
5580       nameSpace->functions.Add((BTNode)BTNamedLink { name = function.name + start, data = function });
5581       // Reference the definition in the module
5582       module.functions.Add(function);
5583       return function;
5584    }
5585    return null;
5586 }
5587
5588 public dllexport DefinedExpression eSystem_FindDefine(Module module, char * name)
5589 {
5590    if(name && module)
5591    {
5592       BTNamedLink link;
5593       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->defines);
5594       if(link) return link.data;
5595
5596       link = SearchModule(module, name, &((NameSpace *)0)->defines, true);
5597       if(link) return link.data;
5598    }
5599    return null;
5600 }
5601
5602 public dllexport GlobalFunction eSystem_FindFunction(Module module, char * name)
5603 {
5604    if(name && module)
5605    {
5606       BTNamedLink link;
5607       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->functions);
5608       if(link) return link.data;
5609
5610       link = SearchModule(module, name, &((NameSpace *)0)->functions, true);
5611       if(link) return link.data;
5612    }
5613    return null;
5614 }
5615
5616 public dllexport void * eSystem_Renew(void * memory, unsigned int size)
5617 {
5618    return _realloc(memory, size);
5619 }
5620
5621 public dllexport void * eSystem_Renew0(void * memory, unsigned int size)
5622 {
5623    return _crealloc(memory, size);
5624 }
5625
5626 public dllexport void * eSystem_New(unsigned int size)
5627 {
5628 /*#ifdef _DEBUG
5629    void * pointer = _malloc(size);
5630    memset(pointer, 0xec, size);
5631    return pointer;
5632 #else*/
5633    return _malloc(size);
5634 //#endif
5635 }
5636
5637 public dllexport void * eSystem_New0(unsigned int size)
5638 {
5639    return _calloc(1,size);
5640 }
5641
5642 public dllexport void eSystem_Delete(void * memory)
5643 {
5644    if(memory)
5645       _free(memory);
5646 }
5647
5648 // Properties
5649 public dllexport void eInstance_FireSelfWatchers(Instance instance, Property _property)
5650 {
5651    if(instance && _property && _property.selfWatchable)
5652    {
5653       Class _class;
5654       for(_class = instance._class; _class; _class = _class.base)
5655       {
5656          SelfWatcher selfWatcher, next;
5657          for(selfWatcher = _class.selfWatchers.first; selfWatcher; selfWatcher = next)
5658          {
5659             next = selfWatcher.next;
5660             if(selfWatcher._property == _property)
5661                selfWatcher.callback(instance);
5662          }
5663       }
5664    }
5665 }
5666
5667 public dllexport void eInstance_FireWatchers(Instance instance, Property _property)
5668 {
5669    if(instance && _property && _property.isWatchable)
5670    {
5671       OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5672       Watcher watcher, next;
5673
5674       for(watcher = watchers->first; watcher; watcher = next)
5675       {
5676          next = watcher.next;
5677          watcher.callback(watcher.object, instance);
5678       }
5679    }
5680 }
5681
5682 public dllexport void eProperty_Watchable(Property _property)
5683 {
5684    if(!_property.isWatchable)
5685    {
5686       Class _class = _property._class;
5687       if(!_class.computeSize)
5688       {
5689          _property.watcherOffset = _class.structSize;
5690          _class.structSize += sizeof(OldList);
5691
5692          // highly inefficient
5693          FixDerivativesBase(_class, _class);
5694       }
5695       _property.isWatchable = true;
5696    }
5697 }
5698
5699 public dllexport void eClass_DestructionWatchable(Class _class)
5700 {
5701    if(!_class.destructionWatchOffset)
5702    {
5703       _class.destructionWatchOffset = _class.structSize;
5704       _class.structSize += sizeof(OldList);
5705       // highly inefficient
5706       FixDerivativesBase(_class, _class);
5707    }
5708 }
5709
5710 public dllexport void eProperty_SelfWatch(Class _class, char * name, void (*callback)(void *))
5711 {
5712    if(_class)
5713    {
5714       Property _property = eClass_FindProperty(_class, name, _class.module);
5715       
5716       if(!_property)
5717          _property = eClass_AddProperty(_class, name, null, null, null, baseSystemAccess /*privateAccess*/);
5718       _class.selfWatchers.Add(SelfWatcher { _property = _property, callback = callback });
5719       _property.selfWatchable = true;
5720    }
5721 }
5722
5723 public dllexport void eInstance_Watch(void * instance, Property _property, void * object, void (*callback)(void *, void *))
5724 {
5725    if(_property.isWatchable)
5726    {
5727       OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5728       watchers->Add(Watcher { callback = callback, object = object });
5729    }
5730 }
5731
5732 public dllexport void eInstance_WatchDestruction(Instance instance, Instance object, void (*callback)(Instance, Instance))
5733 {
5734    OldList * watchers = (OldList *)((byte *)instance + instance._class.destructionWatchOffset);
5735    watchers->Add(Watcher { callback = callback, object = object });
5736 }
5737
5738 public dllexport void eInstance_StopWatching(Instance instance, Property _property, Instance object)
5739 {
5740    if(instance && (!_property || _property.isWatchable))
5741    {
5742       if(_property)
5743       {
5744          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5745          Watcher watcher;
5746          for(watcher = watchers->first; watcher; watcher = watcher.next)
5747             if(watcher.object == object)
5748             {
5749                watchers->Delete(watcher);
5750                break;
5751             }
5752       }
5753       else
5754       {
5755          // Stop watching all properties as well as destruction
5756          Class _class, base;
5757          for(_class = instance._class; _class; _class = base)
5758          {
5759             if(_class.destructionWatchOffset)
5760             {
5761                OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
5762                Watcher watcher;
5763
5764                for(watcher = watchers->first; watcher; watcher = watcher.next)
5765                {
5766                   watchers->Delete(watcher);
5767                   break;
5768                }
5769             }
5770             for(_property = (Property)_class.membersAndProperties.first; _property; _property = _property.next)
5771             {
5772                if(_property.isProperty && _property.isWatchable)
5773                {
5774                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5775                   Watcher watcher;
5776                   for(watcher = watchers->first; watcher; watcher = watcher.next)
5777                      if(watcher.object == object)
5778                      {
5779                         watchers->Delete(watcher);
5780                         break;
5781                      }
5782                }
5783             }
5784             base = _class.base;
5785             if(base && base.type == systemClass) base = null;
5786          }
5787       }
5788    }
5789 }
5790
5791 public dllexport subclass(ClassDesignerBase) eClass_GetDesigner(Class _class)
5792 {
5793    for(;_class;_class = _class.base)
5794    {
5795       if(_class.designerClass)
5796          return (subclass(ClassDesignerBase))eSystem_FindClass(_class.module, _class.designerClass);
5797    }
5798    return null;
5799 }
5800
5801
5802 public dllexport subclass(ClassDesignerBase) eInstance_GetDesigner(Instance instance)
5803 {
5804    if(instance)
5805       return eClass_GetDesigner(instance._class);
5806    return null;
5807 }
5808
5809 public bool LocateModule(char * name, char * fileName)
5810 {
5811    return Instance_LocateModule(name, fileName);
5812 }
5813
5814 static void LoadCOM(Module module)
5815 {
5816    Class applicationClass;
5817    Class enumClass, structClass, boolClass;
5818    Class moduleClass;
5819
5820    // Create Base Class
5821    Class baseClass = eSystem_RegisterClass(normalClass, "class", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5822    baseClass.type = systemClass;
5823    baseClass.memberOffset = 0;
5824    baseClass.offset = 0;
5825    baseClass.structSize = 0;
5826    baseClass.typeSize = 0;
5827
5828    {
5829       Class instanceClass = eSystem_RegisterClass(normalClass, "ecere::com::Instance", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5830       // Instance should really be a Normal class, but inheritance checks for systemClass to see if something has a non system ancestor
5831       instanceClass.type = systemClass;
5832       instanceClass.fixed = true;
5833       instanceClass.memberOffset = 0;
5834       instanceClass.offset = 0;
5835
5836       instanceClass.memberID = -3;
5837       instanceClass.startMemberID = -3;
5838
5839       // eClass_AddDataMember(instanceClass, "_vTbl", "void **", sizeof(int (**)()), 4, publicAccess);
5840       eClass_AddDataMember(instanceClass, "_vTbl", "int (**)()", sizeof(int (**)()), 4, publicAccess);
5841       eClass_AddDataMember(instanceClass, "_class", "ecere::com::Class", sizeof(Class), 4, publicAccess);
5842       eClass_AddDataMember(instanceClass, "_refCount", "int", sizeof(int (**)()), 4, publicAccess);
5843    }
5844
5845    InitializeDataTypes1(module);
5846
5847    // Create Enum class
5848    enumClass = eSystem_RegisterClass(normalClass, "enum", null, 0, sizeof(class EnumClassData), null, null, module, baseSystemAccess, publicAccess);
5849    eClass_AddClassProperty(enumClass, "enumSize", "int", null, GetEnumSize).constant = true;
5850    enumClass.type = systemClass;
5851    
5852    delete enumClass.dataTypeString;
5853    enumClass.dataTypeString = CopyString(/*"unsigned int"*/"int");
5854
5855    // Create Struct (simple) class
5856    //structClass = eSystem_RegisterClass(structClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5857    structClass = eSystem_RegisterClass(normalClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5858    structClass.type = systemClass;
5859    structClass.memberOffset = 0;
5860    structClass.offset = 0;
5861    structClass.structSize = 0;
5862    structClass.typeSize = 0;
5863
5864    //eClass_AddMethod(enumClass, "AddValue", "int()", eEnum_AddValue);
5865    //eClass_AddMethod(enumClass, "AddFixedValue", "void()", eEnum_AddFixedValue);
5866
5867    InitializeDataTypes(module);
5868
5869    // Create bool class
5870    boolClass = eSystem_RegisterClass(ClassType::enumClass, "bool", "uint", 0, 0, null, null, module, baseSystemAccess, publicAccess);
5871    eEnum_AddFixedValue(boolClass, "true",  bool::true);
5872    eEnum_AddFixedValue(boolClass, "false", bool::false);
5873
5874    // Create Module class
5875    moduleClass = eSystem_RegisterClass(normalClass, "ecere::com::Module", null, sizeof(struct Module), 0, (void *)Module_Constructor, (void *)Module_Destructor, module, baseSystemAccess, publicAccess);
5876    eClass_AddVirtualMethod(moduleClass, "OnLoad", "bool()", null, publicAccess);
5877    eClass_AddVirtualMethod(moduleClass, "OnUnload", "void()", null, publicAccess);
5878    eClass_AddMethod(moduleClass, "Load", "Module(char * name, AccessMode importAccess)", eModule_Load, publicAccess);
5879    eClass_AddMethod(moduleClass, "Unload", "void(Module module)", eModule_Unload, publicAccess);
5880    eClass_AddDataMember(moduleClass, "application", "Application", sizeof(Application), 4, publicAccess);
5881    eClass_AddDataMember(moduleClass, "classes", "OldList", sizeof(OldList), 4, publicAccess);
5882    eClass_AddDataMember(moduleClass, "defines", "OldList", sizeof(OldList), 4, publicAccess);
5883    eClass_AddDataMember(moduleClass, "functions", "OldList", sizeof(OldList), 4, publicAccess);
5884    eClass_AddDataMember(moduleClass, "modules", "OldList", sizeof(OldList), 4, publicAccess);
5885    eClass_AddDataMember(moduleClass, "prev", "Module", sizeof(Module), 4, publicAccess);
5886    eClass_AddDataMember(moduleClass, "next", "Module", sizeof(Module), 4, publicAccess);
5887    eClass_AddDataMember(moduleClass, "name", "char *", sizeof(char *), 4, publicAccess);
5888    eClass_AddDataMember(moduleClass, "library", "void *", sizeof(void *), 4, publicAccess);
5889    eClass_AddDataMember(moduleClass, "Unload", "void *", sizeof(void *), 4, publicAccess);
5890    eClass_AddDataMember(moduleClass, "importType", "ImportType", sizeof(ImportType), 4, publicAccess);
5891    eClass_AddDataMember(moduleClass, "origImportType", "ImportType", sizeof(ImportType), 4, publicAccess);
5892    eClass_AddDataMember(moduleClass, "privateNameSpace", "NameSpace", sizeof(NameSpace), 4, publicAccess);
5893    eClass_AddDataMember(moduleClass, "publicNameSpace", "NameSpace", sizeof(NameSpace), 4, publicAccess);
5894    moduleClass.fixed = true;
5895    moduleClass.count++;
5896    
5897    // Create Application class
5898    applicationClass = eSystem_RegisterClass(normalClass, "ecere::com::Application", "Module", sizeof(struct Application), 0, null, (void *)Application_Destructor, module, baseSystemAccess, publicAccess);
5899    eClass_AddVirtualMethod(applicationClass, "Main", "void()", null, publicAccess);
5900    eClass_AddDataMember(applicationClass, "argc", "int", sizeof(int), 4, publicAccess);
5901    eClass_AddDataMember(applicationClass, "argv", "char **", sizeof(char **), 4, publicAccess);
5902    eClass_AddDataMember(applicationClass, "exitCode", "int", sizeof(int), 4, publicAccess);
5903    eClass_AddDataMember(applicationClass, "isGUIApp", "bool", sizeof(bool), 4, publicAccess);
5904    eClass_AddDataMember(applicationClass, "allModules", "OldList", sizeof(OldList), 4, publicAccess);
5905    eClass_AddDataMember(applicationClass, "parsedCommand", "char *", sizeof(char *), 4, publicAccess);
5906    eClass_AddDataMember(applicationClass, "systemNameSpace", "NameSpace", sizeof(NameSpace), 4, publicAccess);
5907    applicationClass.fixed = true;
5908    applicationClass.count++;
5909
5910    //AttachConsole(-1);
5911    //AllocConsole();
5912
5913    // --- Math ---
5914    eSystem_RegisterFunction("sin", "double sin(Angle number)", sin, module, baseSystemAccess);
5915    eSystem_RegisterFunction("sinh", "double sinh(Angle number)", sinh, module, baseSystemAccess);
5916    eSystem_RegisterFunction("cosh", "double cosh(Angle number)", cosh, module, baseSystemAccess);
5917    eSystem_RegisterFunction("tanh", "double tanh(Angle number)", tanh, module, baseSystemAccess);
5918    eSystem_RegisterFunction("sqrt", "double sqrt(double number)", sqrt, module, baseSystemAccess);
5919    eSystem_RegisterFunction("cos", "double cos(Angle number)", cos, module, baseSystemAccess);
5920    eSystem_RegisterFunction("tan", "double tan(Angle number)", tan, module, baseSystemAccess);
5921    eSystem_RegisterFunction("atan2", "Angle atan2(double y, double x)", atan2, module, baseSystemAccess);
5922    eSystem_RegisterFunction("asin", "Angle asin(double number)", asin, module, baseSystemAccess);
5923    eSystem_RegisterFunction("acos", "Angle acos(double number)", acos, module, baseSystemAccess);
5924    eSystem_RegisterFunction("atan", "Angle atan(double number)", atan, module, baseSystemAccess);
5925    eSystem_RegisterFunction("pow", "double pow(double number, double number2)", pow, module, baseSystemAccess);
5926    eSystem_RegisterFunction("fmod", "double fmod(double x, double y)", fmod, module, baseSystemAccess);
5927    eSystem_RegisterFunction("fabs", "double fabs(double number)", fabs, module, baseSystemAccess);
5928    eSystem_RegisterFunction("log", "double log(double number)", log, module, baseSystemAccess);
5929    eSystem_RegisterFunction("log10", "double log10(double number)", log10, module, baseSystemAccess);
5930    eSystem_RegisterFunction("ceil", "double ceil(double number)", ceil, module, baseSystemAccess);
5931    eSystem_RegisterFunction("floor", "double floor(double number)", floor, module, baseSystemAccess);
5932    eSystem_RegisterFunction("exp", "double exp(double number)", exp, module, baseSystemAccess);
5933
5934    // --- Stdlib ---
5935    eSystem_RegisterFunction("qsort", "void qsort(void *, uint, uint, int (*)(void *, void *))", qsort, module, baseSystemAccess);
5936    eSystem_RegisterFunction("strtod", "double strtod(char*, char**)", strtod, module, baseSystemAccess);
5937    eSystem_RegisterFunction("strtol", "int strtol(char*, char**, int base)", strtol, module, baseSystemAccess);
5938    eSystem_RegisterFunction("system", "int system(const char*)", system, module, baseSystemAccess);
5939    eSystem_RegisterFunction("atoi", "int atoi(const char*)", atoi, module, baseSystemAccess);
5940    eSystem_RegisterFunction("atof", "float atof(const char*)", atof, module, baseSystemAccess);
5941    eSystem_RegisterFunction("tolower", "int tolower(int)", tolower, module, baseSystemAccess);
5942    eSystem_RegisterFunction("toupper", "int toupper(int)", toupper, module, baseSystemAccess);
5943    eSystem_RegisterFunction("isdigit", "bool isdigit(int)", isdigit, module, baseSystemAccess);
5944    eSystem_RegisterFunction("memset", "void memset(void * area, byte value, uint count)", memset, module, baseSystemAccess);
5945    eSystem_RegisterFunction("getenv", "char * getenv(const char * name)", getenv, module, baseSystemAccess);
5946    eSystem_RegisterFunction("rename", "int rename(const char *oldpath, const char *newpath)", rename, module, baseSystemAccess);
5947
5948    // --- String --- (These might move to the string class)
5949    eSystem_RegisterFunction("strlen", "int strlen(const char *)", strlen, module, baseSystemAccess);
5950    eSystem_RegisterFunction("strcat", "char * strcat(char *, const char *)", strcat, module, baseSystemAccess);
5951    eSystem_RegisterFunction("strncat", "char * strncat(char *, const char *, int n)", strncat, module, baseSystemAccess);
5952    eSystem_RegisterFunction("strchr", "char * strchr(char *, int)", strchr, module, baseSystemAccess);
5953    eSystem_RegisterFunction("strstr", "char * strstr(char *, const char *)", strstr, module, baseSystemAccess);
5954
5955    eSystem_RegisterDefine("fstrcmp", "(GetRuntimePlatform() == win32) ? strcmpi : strcmp", module, baseSystemAccess);
5956
5957 //#if defined(__GNUC__)
5958    eSystem_RegisterDefine("strcmpi", "strcasecmp", module, baseSystemAccess);
5959    eSystem_RegisterDefine("strnicmp", "strncasecmp", module, baseSystemAccess);
5960    eSystem_RegisterFunction("strcasecmp", "int strcasecmp(const char *, const char *)", strcmpi, module, baseSystemAccess);
5961    eSystem_RegisterFunction("strncasecmp", "int strncasecmp(const char *, const char *, int n)", strnicmp, module, baseSystemAccess);
5962 /*
5963 #else
5964    eSystem_RegisterDefine("strcasecmp", "strcmpi", module, baseSystemAccess);
5965    eSystem_RegisterDefine("strncasecmp", "strnicmp", module, baseSystemAccess);
5966    eSystem_RegisterFunction("strcmpi", "int strcmpi(const char *, const char *)", strcmpi, module, baseSystemAccess);
5967    eSystem_RegisterFunction("strnicmp", "int strnicmp(const char *, const char *, int n)", strnicmp, module, baseSystemAccess);
5968 #endif
5969 */
5970
5971    eSystem_RegisterFunction("strcmp", "int strcmp(const char *, const char *)", strcmp, module, baseSystemAccess);
5972    eSystem_RegisterFunction("strncmp", "int strncmp(const char *, const char *, int n)", strncmp, module, baseSystemAccess);
5973    eSystem_RegisterFunction("strlwr", "char * strlwr(char *)", strlwr, module, baseSystemAccess);
5974    eSystem_RegisterFunction("strupr", "char * strupr(char *)", strupr, module, baseSystemAccess);
5975    eSystem_RegisterFunction("strcpy", "char * strcpy(char *, const char *)", strcpy, module, baseSystemAccess);
5976    eSystem_RegisterFunction("strncpy", "char * strncpy(char *, const char *, int n)", strncpy, module, baseSystemAccess);
5977    eSystem_RegisterFunction("memcpy", "void * memcpy(void *, const void *, uint size)", memcpy, module, baseSystemAccess);
5978    eSystem_RegisterFunction("memmove", "void * memmove(void *, const void *, uint size)", memmove, module, baseSystemAccess);
5979
5980    // --- Stdio ---
5981    eSystem_RegisterFunction("sprintf", "int sprintf(char *, char *, ...)", sprintf, module, baseSystemAccess);
5982    // TODO: Replace int with size_t when eC recognizes it for 64 bit port
5983    eSystem_RegisterFunction("snprintf", "int sprintf(char *, int, char *, ...)", snprintf, module, baseSystemAccess);
5984    eSystem_RegisterFunction("printf", "int printf(char *, ...)", printf, module, baseSystemAccess);
5985    eSystem_RegisterFunction("vsprintf", "int vsprintf(char*, const char*, __builtin_va_list)", vsprintf, module, baseSystemAccess);
5986    // TODO: Replace int with size_t when eC recognizes it for 64 bit port
5987    eSystem_RegisterFunction("vsnprintf", "int vsnprintf(char*, int, const char*, __builtin_va_list)", vsnprintf, module, baseSystemAccess);
5988    eSystem_RegisterFunction("puts", "int puts(char *)", puts, module, baseSystemAccess);
5989    eSystem_RegisterFunction("fputs", "int fputs(char *, void * stream)", fputs, module, baseSystemAccess);
5990
5991    // --- Ctype ---
5992    eSystem_RegisterFunction("isalnum", "int isalnum(int c)", isalnum, module, baseSystemAccess);
5993    eSystem_RegisterFunction("isspace", "int isspace(int c)", isspace, module, baseSystemAccess);
5994    eSystem_RegisterFunction("isalpha", "int isalpha(int c)", isalpha, module, baseSystemAccess);
5995    eSystem_RegisterFunction("islower", "int islower(int c)", islower, module, baseSystemAccess);
5996    eSystem_RegisterFunction("isupper", "int isupper(int c)", isupper, module, baseSystemAccess);
5997    eSystem_RegisterFunction("isprint", "int isprint(int c)", isprint, module, baseSystemAccess);
5998    eSystem_RegisterFunction("strtoul", "unsigned long strtoul(const char * nptr, char ** endptr, int base)", strtoul, module, baseSystemAccess);
5999
6000 }
6001
6002 public dllexport Application __ecere_COM_Initialize(bool guiApp, int argc, char * argv[])
6003 {
6004    Application app;
6005
6006 #ifdef __ANDROID__
6007    // Clean up global variables
6008    memoryInitialized = false;
6009    pools = null;
6010 #ifdef MEMINFO
6011    memset(&memStacks, 0, sizeof(BinaryTree));
6012    memoryErrorsCount = 0;
6013    memset(&memBlocks, 0, sizeof(BinaryTree));
6014    recurse = false;
6015    blockID = 0;
6016    allocateClass = null;
6017    allocateInternal = false;
6018    TOTAL_MEM = 0;
6019    OUTSIDE_MEM = 0;
6020 #endif
6021 #endif
6022
6023 #ifdef _DEBUG
6024    // printf("Using debug ecere runtime library\n");
6025 #endif
6026    app = _calloc(1, sizeof(class Application));
6027
6028    Module_Constructor(app);
6029    app.systemNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
6030    app.systemNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
6031    app.systemNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
6032    app.systemNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
6033
6034    Instance_COM_Initialize(argc, argv, &app.parsedCommand, &app.argc, &app.argv);
6035
6036    app.application = app;
6037    app.allModules.offset = sizeof(class Instance) + (uint)&((struct Module *)0)->prev;
6038    app.isGUIApp = guiApp;
6039
6040    LoadCOM(app);
6041
6042    app._class = eSystem_FindClass(app, "Application");
6043
6044    return app;
6045 }
6046
6047 public dllexport ClassTemplateParameter eClass_AddTemplateParameter(Class _class, char * name, TemplateParameterType type, void * info, ClassTemplateArgument defaultArg)
6048 {
6049    if(_class && name)
6050    {
6051       ClassTemplateParameter param;
6052
6053       for(param = _class.templateParams.first; param; param = param.next)
6054       {
6055          if(!strcmp(param.name, name))
6056             return param;
6057       }
6058       param =
6059       {
6060          name = CopyString(name);
6061          type = type;
6062          (type == identifier) ? info : CopyString(info);
6063       };
6064       if(defaultArg != null) 
6065       {
6066          param.defaultArg = defaultArg;
6067          CopyTemplateArg(param, param.defaultArg);
6068       }
6069       _class.templateParams.Add(param);
6070       return param;
6071    }
6072    return null;
6073 }
6074
6075 public dllexport void eClass_DoneAddingTemplateParameters(Class base)
6076 {
6077    if(base)
6078    {
6079       OldLink derivative;
6080       ClassTemplateParameter param;
6081       {
6082          void * first = base.templateParams.first;
6083          int count = base.templateParams.count;
6084          base.templateParams.first = null;
6085          base.templateParams.count = 0;
6086
6087          FreeTemplateArgs(base);
6088          delete base.templateArgs;
6089          FreeTemplatesDerivatives(base);
6090
6091          base.templateParams.first = first;
6092          base.templateParams.count = count;
6093       }
6094
6095       for(param = base.templateParams.first; param; param = param.next)
6096       {
6097          if(param.type == identifier && param.defaultArg.memberString)
6098          {
6099             Class memberClass = base;
6100             char * colon = strstr(param.defaultArg.memberString, "::");
6101             char * memberName;
6102             if(colon)
6103             {
6104                char className[1024];
6105                Class sClass;
6106
6107                memcpy(className, param.defaultArg.memberString, colon - param.defaultArg.memberString);
6108                className[colon - param.defaultArg.memberString] = '\0';
6109                memberName = colon + 2;
6110
6111                for(sClass = base; sClass; sClass = sClass.base)
6112                {
6113                   ClassTemplateParameter cParam;
6114                   Class nextClass;
6115                   int id = 0;
6116                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) id += nextClass.templateParams.count;
6117                   // Safety! What could cause base.templateArgs to be null?
6118                   if(sClass == base || base.templateArgs)
6119                   {
6120                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
6121                      {
6122                         if(cParam.type == type && !strcmp(cParam.name, className))
6123                            strcpy(className, (sClass == base) ? cParam.defaultArg.dataTypeString : base.templateArgs[id].dataTypeString);
6124                         id++;
6125                      }
6126                   }
6127                }
6128                memberClass = eSystem_FindClass(base.module, className);
6129                if(!memberClass)
6130                   memberClass = eSystem_FindClass(base.module.application, className);
6131             }
6132             else
6133                memberName = param.defaultArg.memberString;
6134
6135             if(memberClass)
6136             {
6137                switch(param.memberType)
6138                {
6139                   case dataMember:
6140                      param.defaultArg.member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
6141                      break;
6142                   case method:
6143                      param.defaultArg.method = eClass_FindMethod(memberClass, memberName, memberClass.module);
6144                      break;
6145                   case prop:
6146                      param.defaultArg.prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
6147                      break;
6148                }
6149             }
6150          }
6151       }      
6152
6153       //ComputeClassParameters(base, null, null);
6154
6155       FixDerivativesBase(base, base);
6156    }
6157 }
6158
6159 static void FreeTemplatesDerivatives(Class base)
6160 {
6161    OldLink derivative, templateLink;
6162    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
6163    {
6164       Class _class = derivative.data;
6165       if(_class.templateArgs)
6166       {
6167          FreeTemplateArgs(_class);
6168          delete _class.templateArgs;
6169       }
6170       FreeTemplatesDerivatives(_class);
6171    }
6172
6173    for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
6174    {
6175       Class _class = templateLink.data;
6176       if(_class.templateArgs)
6177       {
6178          FreeTemplateArgs(_class);
6179          delete _class.templateArgs;
6180       }
6181       FreeTemplatesDerivatives(_class);
6182    }
6183 }
6184
6185 static const char * platformNames[Platform] = { "", "win32", "linux", "apple" }; // how to have this be accessible outside of dll/lib
6186 static const Platform firstPlatform = win32;
6187 static const Platform lastPlatform = apple;
6188
6189 public enum Platform
6190 {
6191    unknown, win32, tux, apple;
6192
6193    property char *
6194    {
6195       get { return OnGetString(null, null, null); }
6196       set
6197       {  
6198          if(value)
6199          {
6200             Platform c;
6201             for(c = firstPlatform; c <= lastPlatform; c++)
6202                if(!strcmpi(value, platformNames[c]))
6203                   return c;
6204          }
6205          return unknown;
6206       }
6207    };
6208
6209    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
6210    {
6211       if(this >= firstPlatform && this <= lastPlatform)
6212       {
6213          if(tempString)
6214             strcpy(tempString, platformNames[this]);
6215          return platformNames[this];
6216       }
6217       if(tempString && tempString[0])
6218          tempString[0] = '\0';
6219       return null;
6220    }
6221    
6222    bool OnGetDataFromString(char * string)
6223    {
6224       this = string;
6225       return (bool)this;
6226    }
6227 };
6228
6229 default extern Platform runtimePlatform;
6230
6231 public Platform GetRuntimePlatform()
6232 {
6233    return runtimePlatform;
6234 }
6235
6236 namespace gui;
6237
6238 class Window;
6239
6240 namespace com;
6241 // CLASS DESIGNER SUPPORT
6242
6243 public class ObjectInfo : struct
6244 {
6245 public:
6246    ObjectInfo prev, next;
6247    Instance instance;
6248    char * name;
6249    Instantiation instCode;
6250    bool deleted;
6251    ObjectInfo oClass;
6252    OldList instances;
6253    ClassDefinition classDefinition;
6254    bool modified;
6255 };
6256
6257 public class DesignerBase : Window
6258 {
6259 public:
6260    virtual bool FindObject(Instance * instance, char * string);
6261    virtual void RenameObject(ObjectInfo object, char * name);
6262    virtual void SelectObjectFromDesigner(ObjectInfo object);
6263    virtual void CodeAddObject(Instance instance, ObjectInfo * object);
6264    virtual void SheetAddObject(ObjectInfo object);
6265    virtual void AddToolBoxClass(Class _class);
6266    virtual void AddDefaultMethod(Instance instance, Instance classInstance);
6267    virtual void DeleteObject(ObjectInfo object);
6268    virtual bool ObjectContainsCode(ObjectInfo object);
6269    virtual void ModifyCode(void);
6270    virtual void UpdateProperties(void);
6271
6272    ClassDesignerBase classDesigner;
6273    char * objectClass;
6274    bool isDragging;
6275
6276    // FIX THIS WITH PUBLIC:
6277    property ClassDesignerBase classDesigner
6278    { 
6279       get { return classDesigner; }
6280       set { classDesigner = value; }
6281    };
6282    property char * objectClass
6283    { 
6284       get { return objectClass; }
6285       set { objectClass = value; }
6286    };
6287    property bool isDragging
6288    { 
6289       get { return isDragging; }
6290       set { isDragging = value; }
6291    };
6292 }
6293  
6294 public class ClassDesignerBase : Window
6295 {
6296 public:
6297    virtual void Reset(void);
6298    virtual void AddObject(void);
6299    virtual void SelectObject(ObjectInfo object, Instance control);
6300
6301    virtual void ListToolBoxClasses(DesignerBase designer);
6302
6303    virtual void ::PrepareTestObject(DesignerBase designer, Instance test);
6304    virtual void ::CreateObject(DesignerBase designer, Instance instance, ObjectInfo object, bool isClass, Instance _class);
6305    virtual void ::PostCreateObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6306    virtual void ::DroppedObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6307    virtual void ::DestroyObject(Instance object);
6308    virtual void ::FixProperty(Property prop, Instance object);
6309    virtual void ::CreateNew(EditBox editBox, Size clientSize, char * name, char * inherit);
6310 }
6311
6312 DesignerBase activeDesigner;
6313
6314 public void SetActiveDesigner(DesignerBase designer)
6315 {
6316    activeDesigner = designer;
6317 }
6318
6319 public DesignerBase GetActiveDesigner()
6320 {
6321    return activeDesigner;
6322 }
6323
6324 namespace sys;
6325
6326 // constants
6327 define LEAD_OFFSET      = 0xD800 - (0x10000 >> 10);
6328 define SURROGATE_OFFSET = 0x10000 - (0xD800 << 10) - 0xDC00;
6329
6330 public bool UTF8Validate(char * source)
6331 {
6332    if(source)
6333    {
6334       int c;
6335       for(c = 0; source[c];)
6336       {
6337          byte ch = source[c];
6338          unichar codePoint = 0;
6339          int numBytes = 1;
6340          int i;
6341          byte mask = 0x7F;
6342          if(ch & 0x80)
6343          {
6344             if(ch & 0x40)
6345             {
6346                mask >>= 2;
6347                numBytes++;
6348                if(ch & 0x20)
6349                {
6350                   numBytes++;
6351                   mask >>= 1;
6352                   if(ch & 0x10)
6353                   {
6354                      if(ch & 0x08)
6355                         return false;
6356                      numBytes++;
6357                      mask >>= 1;
6358                   }
6359                }
6360             }
6361             else
6362                return false;
6363          }
6364          for(i = 0; i<numBytes && (ch = source[c]); i++, c++)
6365          {
6366             codePoint <<= 6;
6367             codePoint |= ch & mask;
6368             mask = 0x3F;
6369             if(i > 1)
6370             {
6371                if(!(ch & 0x80) || (ch & 0x40))
6372                   return false;
6373             }
6374          }
6375          if(i < numBytes) return false;
6376
6377          if(codePoint > 0x10FFFF || (codePoint >= 0xD800 && codePoint <= 0xDFFF) || 
6378            (codePoint < 0x80 && numBytes > 1) || 
6379            (codePoint < 0x800 && numBytes > 2) || 
6380            (codePoint < 0x10000 && numBytes > 3))
6381             return false;
6382       }
6383    }
6384    return true;
6385 }
6386
6387 public int ISO8859_1toUTF8(char * source, char * dest, int max)
6388 {
6389    int c;
6390    int d = 0;
6391    for(c = 0; source[c]; c++)
6392    {
6393       unichar ch = ((byte *)source)[c];
6394       if(ch < 0x80)
6395       {
6396          if(d + 1 >= max) break;
6397          dest[d++] = (char)ch;
6398       }
6399       else if(ch < 0x800)
6400       {
6401          if(d + 2 >= max) break;
6402          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6403          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6404       }
6405       else if(ch < 0x10000)
6406       {
6407          if(d + 3 >= max) break;
6408          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6409          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6410          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6411       }
6412       else
6413       {
6414          if(d + 4 >= max) break;
6415          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6416          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6417          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6418          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6419       }
6420    }
6421    dest[d] = 0;
6422    return d;
6423 }
6424
6425 public char * UTF16toUTF8(uint16 * source)
6426 {
6427    int c;
6428    int d = 0;
6429    int len;
6430    char * dest;
6431    uint16 u16;
6432    bool invert = false;
6433
6434    for(len = 0; source[len]; len++);
6435    dest = new char[len * 3 + 1];
6436    for(c = 0; (u16 = source[c]); c++)
6437    {
6438       unichar ch;
6439       if(!c && (u16 == 0xFFFE || u16 == 0xFEFF))
6440       {
6441          if(u16 == 0xFFFE) invert = true;
6442          continue;
6443       }
6444       if(invert) { u16 = ((u16 & 0xFF00) >> 8) | ((u16 & 0x00FF) << 8); }
6445       
6446       if(u16 < 0xD800 || u16 > 0xDBFF)
6447          ch = (unichar)u16;         
6448       else
6449          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
6450                   
6451       if(ch < 0x80)
6452       {
6453          dest[d++] = (char)ch;
6454       }
6455       else if(ch < 0x800)
6456       {
6457          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6458          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6459       }
6460       else if(ch < 0x10000)
6461       {
6462          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6463          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6464          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6465       }
6466       else
6467       {
6468          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6469          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6470          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6471          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6472       }
6473    }
6474    dest[d] = 0;
6475    dest = renew dest char[d+1];
6476    return dest;
6477 }
6478
6479 public int UTF16toUTF8Buffer(uint16 * source, byte * dest, int max)
6480 {
6481    int c;
6482    int d = 0;
6483    uint16 u16;
6484    for(c = 0; (u16 = source[c]); c++)
6485    {
6486       unichar ch;
6487       if(u16 < 0xD800 || u16 > 0xDBFF)
6488          ch = (unichar)u16;         
6489       else
6490          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
6491
6492       if(ch < 0x80)
6493       {
6494          if(d + 1 >= max) break;
6495          dest[d++] = (char)ch;
6496       }
6497       else if(ch < 0x800)
6498       {
6499          if(d + 2 >= max) break;
6500          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6501          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6502       }
6503       else if(ch < 0x10000)
6504       {
6505          if(d + 3 >= max) break;
6506          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6507          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6508          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6509       }
6510       else
6511       {
6512          if(d + 4 >= max) break;
6513          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6514          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6515          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6516          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6517       }
6518    }
6519    dest[d] = 0;
6520    return d;
6521 }
6522
6523 public unichar UTF8GetChar(char * string, int * numBytes)
6524 {
6525    unichar ch;
6526    byte b = ((byte *)string)[0];
6527    int i;
6528    byte mask = 0x7F;
6529    int nb = 1;
6530    ch = 0;
6531    if(b & 0x80)
6532    {
6533       if(b & 0x40)
6534       {
6535          mask >>= 2;
6536          nb++;
6537          if(b & 0x20)
6538          {
6539             nb++;
6540             mask >>= 1;
6541             if(b & 0x10)
6542             {
6543                if(b & 0x08) { nb = 0; }
6544                nb++;
6545                mask >>= 1;
6546             }
6547          }
6548       }
6549       else
6550          nb = 0;
6551    }
6552    for(i = 0; i<nb; i++)
6553    {
6554       ch <<= 6;
6555       ch |= (b = ((byte *)string)[i]) & mask;
6556       mask = 0x3F;
6557       if(i > 1 && (!(b & 0x80) || (b & 0x40)))
6558       {
6559          nb = 0;
6560          ch = 0;
6561       }
6562    }
6563
6564    if(i < nb || 
6565       ch > 0x10FFFF || (ch >= 0xD800 && ch <= 0xDFFF) || 
6566      (ch < 0x80 && nb > 1) || 
6567      (ch < 0x800 && nb > 2) || 
6568      (ch < 0x10000 && nb > 3))
6569    {
6570       ch = 0;
6571       nb = 0;
6572    }
6573    if(numBytes) *numBytes = nb;
6574    return ch;
6575 }
6576
6577 public int UTF8toUTF16Buffer(char * source, uint16 * dest, int max)
6578 {
6579    if(source)
6580    {
6581       int c;
6582       int d = 0;
6583       for(c = 0; source[c];)
6584       {
6585          byte ch = source[c];
6586          unichar codePoint = 0;
6587          int numBytes = 1;
6588          int i;
6589          byte mask = 0x7F;
6590          if(ch & 0x80 && ch & 0x40)
6591          {
6592             mask >>= 2;
6593             numBytes++;
6594             if(ch & 0x20)
6595             {
6596                numBytes++;
6597                mask >>= 1;
6598                if(ch & 0x10)
6599                {
6600                   numBytes++;
6601                   mask >>= 1;
6602                }
6603             }
6604          }
6605          for(i = 0; i<numBytes; i++)
6606          {
6607             codePoint <<= 6;
6608             codePoint |= source[c++] & mask;
6609             mask = 0x3F;
6610          }
6611
6612          if(codePoint > 0xFFFF)
6613          {
6614             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
6615             uint16 trail = 0xDC00 + (uint16)(codePoint & 0x3FF);
6616             if(d >= max - 1) break;
6617             dest[d++] = lead;
6618             dest[d++] = trail;
6619          }
6620          else
6621          {
6622             if(d >= max) break;
6623             dest[d++] = (uint16)codePoint;
6624          }
6625       }
6626       dest[d] = 0;
6627       return d;
6628    }
6629    return 0;   
6630 }
6631
6632 public int UTF32toUTF8Len(unichar * source, int count, byte * dest, int max)
6633 {
6634    int c;
6635    int d = 0;
6636    uint32 ch;
6637    for(c = 0; c<count && (ch = source[c]); c++)
6638    {
6639       if(ch < 0x80)
6640       {
6641          if(d + 1 >= max) break;
6642          dest[d++] = (char)ch;
6643       }
6644       else if(ch < 0x800)
6645       {
6646          if(d + 2 >= max) break;
6647          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6648          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6649       }
6650       else if(ch < 0x10000)
6651       {
6652          if(d + 3 >= max) break;
6653          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6654          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6655          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6656       }
6657       else
6658       {
6659          if(d + 4 >= max) break;
6660          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6661          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6662          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6663          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6664       }
6665    }
6666    dest[d] = 0;
6667    return d;
6668 }
6669
6670 public uint16 * UTF8toUTF16(char * source, int * wordCount)
6671 {
6672    if(source)
6673    {
6674       int len = strlen(source);
6675       uint16 * dest = new uint16[len + 1];
6676       int c;
6677       int d = 0;
6678       for(c = 0; source[c];)
6679       {
6680          byte ch = source[c];
6681          unichar codePoint = 0;
6682          int numBytes = 1;
6683          int i;
6684          byte mask = 0x7F;
6685          if(ch & 0x80 && ch & 0x40)
6686          {
6687             mask >>= 2;
6688             numBytes++;
6689             if(ch & 0x20)
6690             {
6691                numBytes++;
6692                mask >>= 1;
6693                if(ch & 0x10)
6694                {
6695                   numBytes++;
6696                   mask >>= 1;
6697                }
6698             }
6699          }
6700          for(i = 0; i<numBytes; i++)
6701          {
6702             codePoint <<= 6;
6703             codePoint |= source[c++] & mask;
6704             mask = 0x3F;
6705          }
6706
6707          if(codePoint > 0xFFFF)
6708          {
6709             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
6710             uint16 trail = 0xDC00 + (uint16)(codePoint & 0x3FF);
6711             dest[d++] = lead;
6712             dest[d++] = trail;
6713          }
6714          else
6715          {
6716             dest[d++] = (uint16)codePoint;
6717          }
6718       }
6719       dest[d] = 0;
6720       if(wordCount) *wordCount = d;
6721       return dest;
6722    }
6723    return null;
6724 }
6725
6726 namespace com;