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