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