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