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