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