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