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