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