ecere/DataBox: Fix for prior optimization breaking cases where OnDisplay was overridden
[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       if(mod.base && mod.base.base && mod.base.vTblSize > baseClass.vTblSize && 
1967          (mod != (base.templateClass ? base.templateClass : base) || _class.vTblSize != mod.vTblSize))
1968       {
1969          Method method, next;
1970          Class b;
1971          _class.vTblSize += mod.base.vTblSize - baseClass.vTblSize;
1972          _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
1973          // memmove(_class._vTbl + mod.base.vTblSize, _class._vTbl + baseClass.vTblSize, (mod.base.vTblSize - baseClass.vTblSize) * sizeof(void *));
1974          memmove(_class._vTbl + mod.base.vTblSize, _class._vTbl + baseClass.vTblSize, (_class.vTblSize - mod.vTblSize) * sizeof(void *));
1975          
1976          for(method = (Method)_class.methods.first; method; method = next)
1977          {
1978             next = (Method)((BTNode)method).next;
1979             if(method.type == virtualMethod)
1980                method.vid += mod.base.vTblSize - baseClass.vTblSize;
1981          }
1982
1983          // TO CHECK: WHY WAS THIS baseClass? ANY PROBLEMS? CRASH WHEN DECLARING A BASE CLASS LATER (WSMS)
1984          for(b = mod.base; b && b != null; b = b.base)
1985          {
1986             Method vMethod;
1987             for(vMethod = (Method)b.methods.first; vMethod; vMethod = (Method)((BTNode)vMethod).next)
1988             {
1989                if(vMethod.type == virtualMethod)
1990                {
1991                   method = (Method)_class.methods.FindString(vMethod.name);
1992                   if(method)
1993                   {
1994                      if(method.function) _class._vTbl[vMethod.vid] = method.function;
1995                      if(!method.symbol)
1996                      {
1997                         delete method.name;
1998                         delete method.dataTypeString;
1999                         _class.methods.Delete((BTNode)method);
2000                      }
2001                      else
2002                      {
2003                         delete method.dataTypeString;
2004                         method.type = vMethod.type;
2005                         method.dataTypeString = CopyString(vMethod.dataTypeString);
2006                         method._class = vMethod._class;
2007                      }
2008                   }
2009                   else
2010                      _class._vTbl[vMethod.vid] = _class.base._vTbl[vMethod.vid];
2011                }
2012             }
2013          }
2014       }
2015
2016       // _class.defaultAlignment = base ? base.defaultAlignment : 0;
2017    
2018       if(type == normalClass || type == noHeadClass || type == structClass)
2019       {
2020          Property prop;
2021          DataMember member;
2022          Class c;
2023          for(c = mod.base; c; c = c.base)
2024          {
2025             Property _property;
2026             for(_property = c.membersAndProperties.first; _property; _property = _property.next)
2027             {
2028                if(_property.isProperty)
2029                {
2030                   BTNamedLink link = (BTNamedLink)_class.prop.FindString(_property.name);
2031                   if(link)
2032                   {
2033                      prop = link.data;
2034                      if(!prop.Set && !prop.Get && prop.memberAccess == baseSystemAccess)
2035                      {
2036                         SelfWatcher watcher;
2037                         for(watcher = _class.selfWatchers.first; watcher; watcher = watcher.next)
2038                         {
2039                            if(watcher._property == prop)
2040                               watcher._property = _property;
2041                         }
2042                         _property.selfWatchable = true;
2043                         _class.prop.Delete((BTNode)link);
2044                         delete prop.name;
2045                         delete prop.dataTypeString;
2046                         _class.membersAndProperties.Delete(prop);    // Remove only was done before?
2047                      }
2048                   }
2049                }
2050             }
2051          }
2052          // if(mod.base.memberID)
2053          {
2054             for(member = _class.membersAndProperties.first; member; member = member.next)
2055             {
2056                int offsetDiff = _class.offset - offsetBefore;
2057                if(!member.isProperty && offsetDiff > 0)
2058                {
2059                   member.offset += offsetDiff;
2060                   member.memberOffset += offsetDiff;
2061                }
2062                member.id += mod.base.memberID;
2063             }
2064
2065             _class.memberID += mod.base.memberID;
2066             _class.startMemberID += mod.base.memberID;
2067          }
2068       }
2069       // Moved this before to ensure CPValues have their data ready
2070       FixDerivativesBase(_class, mod);
2071       {
2072          Class c;
2073          for(c = mod.base; c; c = c.base)
2074          {
2075             ClassProperty _property;
2076             for(_property = (ClassProperty)c.classProperties.first; _property; _property = (ClassProperty)((BTNode)_property).next)
2077             {
2078                SetDelayedCPValues(_class, _property);
2079             }
2080          }
2081       }
2082    }
2083    
2084    {
2085       OldLink templateLink;
2086       for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
2087       {
2088          Class template = templateLink.data;
2089          char * templateParams = strchr(template.name, '<');
2090          template.base = base.base;
2091          template._vTbl = base._vTbl;
2092          //ComputeClassParameters(template, templateParams, null);
2093
2094          template.data = base.data;
2095          template.offset = base.offset;
2096          template.offsetClass = base.offsetClass;
2097          template.sizeClass = base.sizeClass;
2098          template.structSize = base.structSize;
2099          template.vTblSize = base.vTblSize;
2100          
2101          FixDerivativesBase(template, mod);
2102       }
2103    }
2104 }
2105
2106 public dllexport Class eSystem_RegisterClass(ClassType type, char * name, char * baseName, int size, int sizeClass,
2107                              bool (* Constructor)(void *),void (* Destructor)(void *),
2108                              Module module, AccessMode declMode, AccessMode inheritanceAccess)
2109 {
2110    int start = 0, c;
2111    NameSpace * nameSpace = null;
2112
2113    {
2114       nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
2115       if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
2116
2117       // if(declMode != staticAccess)
2118       {
2119          for(c = 0; name[c]; c++)
2120          {
2121             if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
2122             {
2123                NameSpace * newSpace;
2124
2125                char * spaceName = _malloc(c - start + 1);
2126                strncpy(spaceName, name + start, c - start);
2127                spaceName[c-start] = '\0';
2128
2129                newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
2130                if(!newSpace)
2131                {
2132                   newSpace = new0 NameSpace[1];
2133                   newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
2134                   newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
2135                   newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
2136                   newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
2137                   newSpace->name = spaceName;
2138                   newSpace->parent = nameSpace;
2139                   nameSpace->nameSpaces.Add((BTNode)newSpace);
2140                }
2141                else
2142                   delete spaceName;
2143                nameSpace = newSpace;
2144                if(name[c] == ':') c++;
2145                start = c+1;
2146             }
2147          }
2148       }
2149       /*else
2150          c = strlen(name);*/
2151    }
2152
2153    if(c - start)
2154    {
2155       int offsetClass; 
2156       int totalSizeClass;
2157       BTNamedLink classLink = null;
2158       Class _class = null;
2159       char * dataTypeString = null;
2160       Class enumBase = null;
2161       Class base = (baseName && baseName[0]) ? eSystem_FindClass(module, baseName) : null;
2162       bool refine = false;
2163
2164       if(base && !base.internalDecl && (base.type == noHeadClass || base.type == structClass || base.type == normalClass)) 
2165       {
2166          // Normal classes inheriting off simple classes should become no head classes
2167          if(base.type == structClass && type == normalClass)
2168             type = noHeadClass;
2169          else
2170             type = base.type;
2171       }
2172       if(base && (type == normalClass || type == noHeadClass || type == structClass) && 
2173          (base.type == unitClass || base.type == bitClass || base.type == enumClass))
2174       {
2175          type = base.type;
2176       }
2177       if(!base || base.type == systemClass)
2178       {
2179          if(type == enumClass)
2180          {
2181             // TO IMPROVE:
2182             if(base || !baseName || !baseName[0] ||
2183                !strcmp(baseName, "unsigned int") || 
2184                !strcmp(baseName, "uint") || 
2185                !strcmp(baseName, "unsigned int64") || 
2186                !strcmp(baseName, "uint64") || 
2187                !strcmp(baseName, "int64") || 
2188                !strcmp(baseName, "unsigned short") || 
2189                !strcmp(baseName, "short") || 
2190                !strcmp(baseName, "unsigned char") || 
2191                !strcmp(baseName, "byte") || 
2192                !strcmp(baseName, "char") || 
2193                !strcmp(baseName, "uint32") || 
2194                !strcmp(baseName, "uint16"))
2195             {
2196                base = eSystem_FindClass(module, "enum");
2197                dataTypeString = (baseName && baseName[0]) ? baseName : "int"; //"unsigned int";
2198             }
2199             else
2200             {
2201                // Undefined base
2202                base = eSystem_RegisterClass(0, baseName, null, 0,0, null, null, module, declMode, publicAccess);
2203                base.internalDecl = true;
2204
2205                enumBase = base;
2206                base = eSystem_FindClass(module, "enum");
2207                //dataTypeString = (baseName && baseName[0]) ? baseName : "unsigned int";
2208             }
2209          }
2210          else if(type == structClass && (!baseName || !baseName[0]))
2211          {
2212             base = eSystem_FindClass(module, "struct");
2213             dataTypeString = name + start;
2214          }
2215          else 
2216          {
2217             if(type == normalClass)
2218                // dataTypeString = "struct Instance";
2219                dataTypeString = "struct __ecereNameSpace__ecere__com__Instance";
2220             else if(type == noHeadClass)
2221                dataTypeString = "void *";
2222             else if(type == bitClass)
2223                dataTypeString = (baseName && baseName[0]) ? baseName : "unsigned int";
2224             else if(type == unitClass)
2225                dataTypeString = (baseName && baseName[0]) ? baseName : "int";
2226             else if(type == structClass)
2227                dataTypeString = name + start;
2228
2229             // TODO: base bit, unit or enum classes not defined yet
2230             if(base || (!baseName || !baseName[0]) || type == bitClass || type == unitClass)
2231             {
2232                // DANGEROUSLY TESTING THIS... PUT IT BACK
2233                //if(!base)
2234                if(base || !baseName || !baseName[0] ||
2235                   !strcmp(baseName, "unsigned int") || 
2236                   !strcmp(baseName, "uint") || 
2237                   !strcmp(baseName, "unsigned int64") || 
2238                   !strcmp(baseName, "uint64") || 
2239                   !strcmp(baseName, "int64") || 
2240                   !strcmp(baseName, "unsigned short") || 
2241                   !strcmp(baseName, "short") || 
2242                   !strcmp(baseName, "unsigned char") || 
2243                   !strcmp(baseName, "byte") || 
2244                   !strcmp(baseName, "char") || 
2245                   !strcmp(baseName, "uint32") || 
2246                   !strcmp(baseName, "uint16"))
2247                {
2248                   if(type == normalClass && strcmp(name, "ecere::com::Instance") && strcmp(name, "enum") && strcmp(name, "struct"))
2249                      base = eSystem_FindClass(module, "ecere::com::Instance");
2250                   else
2251                      base = eSystem_FindClass(module, "class");
2252                }
2253             }
2254             else
2255             {
2256                // Base class has not been defined yet!
2257             }
2258          }
2259       }
2260       else
2261       {
2262          if(type == enumClass)
2263          {
2264             if(base.type != enumClass)
2265             {
2266                enumBase = base;
2267                base = eSystem_FindClass(module, "enum");
2268             }
2269          }
2270          dataTypeString = enumBase ? enumBase.dataTypeString : base.dataTypeString;
2271       }
2272
2273       offsetClass = base ? base.sizeClass : (type == noHeadClass ? 0 : 0 /*sizeof(class Class)*/);
2274       totalSizeClass = offsetClass + sizeClass;
2275    
2276       if((_class = eSystem_FindClass(module, name)))
2277       {
2278          FreeTemplatesDerivatives(_class);
2279
2280          if(!_class.internalDecl)
2281          {
2282             if(declMode != baseSystemAccess)
2283                // i18n in instance.ec is more trouble than it's worth.
2284                printf("error: Redefinition of class %s\n", name);
2285             else
2286             {
2287                _class.comRedefinition = true;
2288                return _class;
2289             }
2290             return null;
2291          }
2292
2293          classLink = (BTNamedLink)_class.nameSpace->classes.FindString(name + start);
2294          _class.nameSpace->classes.Delete((BTNode)classLink);
2295          {
2296             OldLink t;
2297             for(t = _class.templatized.first; t; t = t.next)
2298             {
2299                Class template = t.data;
2300                classLink = (BTNamedLink)_class.nameSpace->classes.FindString(template.name);
2301
2302                _class.nameSpace->classes.Delete((BTNode)classLink);
2303             }
2304          }
2305          {
2306             NameSpace * ns = _class.nameSpace;
2307             while(ns->parent && 
2308                !ns->classes.first && 
2309                !ns->functions.first &&
2310                !ns->defines.first &&
2311                !ns->nameSpaces.first)
2312             {
2313                NameSpace * parent = ns->parent;
2314                NameSpace_Free(ns);
2315                parent->nameSpaces.Delete((BTNode)ns);
2316                ns = parent;
2317             }
2318          }
2319          refine = true;
2320       }
2321       else
2322       {
2323          classLink = SearchNameSpace(module.application.privateNameSpace, name, &((NameSpace *)0)->classes);
2324          if(!classLink)
2325             classLink = SearchNameSpace(module.application.publicNameSpace, name, &((NameSpace *)0)->classes);
2326
2327          if(!classLink)
2328             classLink = SearchNameSpace(module.application.privateNameSpace, name + start, &((NameSpace *)0)->classes);
2329          if(!classLink)
2330             classLink = SearchNameSpace(module.application.publicNameSpace, name + start, &((NameSpace *)0)->classes);
2331
2332          if(classLink)
2333             _class = classLink.data;
2334          if(_class && _class.internalDecl)
2335          {
2336             FreeTemplatesDerivatives(_class);
2337
2338             _class.nameSpace->classes.Delete((BTNode)classLink);
2339             {
2340                OldLink t;
2341                for(t = _class.templatized.first; t; t = t.next)
2342                {
2343                   Class template = t.data;
2344                   classLink = (BTNamedLink)_class.nameSpace->classes.FindString(template.name);
2345                   _class.nameSpace->classes.Delete((BTNode)classLink);
2346
2347                }
2348             }
2349
2350             refine = true;
2351             delete _class.fullName;
2352             _class.fullName = CopyString(name);
2353          }
2354          else
2355          {
2356             _class = _calloc(1, sizeof(class Class));
2357             _class.methods.CompareKey = (void *)BinaryTree::CompareString;
2358             _class.members.CompareKey = (void *)BinaryTree::CompareString;
2359             _class.prop.CompareKey = (void *)BinaryTree::CompareString;
2360             _class.classProperties.CompareKey = (void *)BinaryTree::CompareString;
2361
2362             _class.name = CopyString(name + start);
2363             _class.fullName = CopyString(name);
2364          }
2365       }
2366       if(nameSpace)
2367       {
2368          nameSpace->classes.Add((BTNode)BTNamedLink { name = _class.name, data = _class });
2369          {
2370             OldLink t;
2371             for(t = _class.templatized.first; t; t = t.next)
2372             {
2373                Class template = t.data;
2374                nameSpace->classes.Add((BTNode)BTNamedLink { name = template.name, data = template });
2375             }
2376          }
2377
2378       }
2379
2380       if(_class)
2381       {
2382          if(!base && baseName && strcmp(baseName, name))
2383          {
2384             // Undefined base
2385             if(strchr(baseName, '<'))
2386             {
2387                char templateClassName[1024];
2388                Class templateBase;
2389                strcpy(templateClassName, baseName);
2390                *strchr(templateClassName, '<') = '\0';
2391                templateBase = eSystem_FindClass(module, templateClassName);
2392                if(!templateBase)
2393                {
2394                   templateBase = eSystem_RegisterClass(0, templateClassName, null, 0,0, null, null, module, declMode, publicAccess);
2395                   templateBase.internalDecl = true;
2396                }
2397                base = eSystem_FindClass(module, baseName);
2398             }
2399             else
2400             {
2401                base = eSystem_RegisterClass(0, baseName, null, 0,0, null, null, module, declMode, publicAccess);
2402                base.internalDecl = true;
2403             }
2404             /*
2405             base.size = 0;
2406             base.offset = 0;
2407             base.memberOffset = 0;
2408             */
2409          }
2410          else
2411             _class.internalDecl = false;
2412
2413          if(totalSizeClass)
2414          {
2415             _class.data = renew _class.data byte[totalSizeClass];
2416             // memset(_class.data, 0, totalSizeClass);
2417             if(base && base.type != systemClass && base.type != enumClass)
2418                memcpy(_class.data, base.data, offsetClass);
2419             else
2420                memset(_class.data, 0, offsetClass);
2421             memset((byte *)_class.data + offsetClass, 0, sizeClass);
2422          }
2423
2424          delete _class.dataTypeString;
2425          _class.dataTypeString = CopyString(dataTypeString);
2426          _class.defaultAlignment = base ? base.defaultAlignment : 0;
2427
2428          // Dereference the class in previous module the classed belonged to
2429          if(_class.module)
2430          {
2431             _class.module.classes.Remove(_class);
2432          }
2433
2434          if(_class.base)
2435          {
2436             //Class base = _class.base.templateClass ? _class.base.templateClass : _class.base;
2437             Class base = _class.base;
2438             OldLink deriv = base.derivatives.FindLink(_class);
2439             base.derivatives.Delete(deriv);
2440          }
2441
2442          // Reference the class in the module
2443          if(module)
2444          {
2445             module.classes.Add(_class);
2446          }
2447
2448          _class.nameSpace = nameSpace;
2449          {
2450             OldLink t;
2451             for(t = _class.templatized.first; t; t = t.next)
2452             {
2453                Class template = t.data;
2454                template.nameSpace = nameSpace;
2455             }
2456          }
2457
2458          _class.module = module;
2459          _class.base = base;
2460          if(base)
2461          {
2462             int numParams = 0;
2463             Class sClass;
2464             for(sClass = base; sClass; sClass = sClass.base)
2465             {
2466                if(sClass.templateClass) sClass = sClass.templateClass;
2467                numParams += sClass.templateParams.count;
2468             }
2469             if(numParams)
2470             {
2471                if(_class.templateArgs)
2472                {
2473                   FreeTemplateArgs(_class);
2474                }
2475                delete _class.templateArgs;
2476                _class.templateArgs = new0 ClassTemplateArgument[numParams];
2477                _class.numParams = numParams;
2478
2479                for(sClass = _class; sClass; sClass = sClass.base)
2480                {
2481                   Class prevClass;
2482                   ClassTemplateParameter param;
2483                   int id = 0;
2484                   if(sClass.templateClass) sClass = sClass.templateClass;
2485                   for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
2486                   {
2487                      if(prevClass.templateClass) prevClass = prevClass.templateClass;
2488                      id += prevClass.templateParams.count;
2489                   }
2490
2491                   if(base.templateArgs)   // Add numParams test here?
2492                   {
2493                      for(param = sClass.templateParams.first; param; param = param.next)
2494                      {
2495                         _class.templateArgs[id] = base.templateArgs[id];
2496                         CopyTemplateArg(param, _class.templateArgs[id]);
2497                         id++;
2498                      }
2499                   }
2500                }
2501             }
2502          }
2503          _class.memberID = _class.startMemberID = (base && (type == normalClass || type == noHeadClass || type == structClass)) ? base.memberID : 0;
2504          if(type == normalClass || type == noHeadClass)
2505             _class.offset = (base && base.structSize && base.type != systemClass) ? base.structSize : ((type == noHeadClass) ? 0 : sizeof(class Instance));
2506          if(type == structClass)
2507          {
2508             _class.memberOffset = (base && base.structSize && base.type != systemClass) ? base.structSize : 0;
2509             // THIS IS NEW...
2510             _class.typeSize = _class.structSize = _class.memberOffset + size;
2511          }
2512          else if(type == bitClass || type == enumClass || type == unitClass)
2513          {  
2514             Class dataTypeClass = eSystem_FindClass(_class.module, dataTypeString);
2515             if(dataTypeClass)
2516                _class.typeSize = dataTypeClass.typeSize;
2517             _class.structSize = 0;
2518          }
2519          else if(type == normalClass || type == noHeadClass)
2520          {
2521             _class.structSize = _class.offset + size;
2522             _class.typeSize = sizeof(void *);
2523          }
2524          _class.offsetClass = offsetClass;
2525          _class.sizeClass = totalSizeClass;
2526          _class.Constructor = (void *)Constructor;
2527          _class.Destructor = Destructor;
2528          if(_class.type != systemClass)
2529             _class.type = type;
2530          if(!size)
2531             _class.computeSize = true;
2532          else
2533             _class.computeSize = false;
2534          _class.inheritanceAccess = inheritanceAccess;
2535
2536          /*if(type == bitClass)
2537             _class.size = 0;*/
2538          if(type == enumClass)
2539          {
2540             if(enumBase)
2541                _class.base = base = enumBase;
2542             //else
2543             {
2544                EnumClassData data = (EnumClassData)_class.data;
2545                // TOCHECK: Trying this (if specifiers specified, no class found...)
2546                // What about bit classes, unit classes...
2547                if(base && base.type != enumClass)
2548                   data.largest = -1;//_class.base = null;
2549                else
2550                   data.largest = ((EnumClassData)(base.data)).largest;
2551             }
2552          }
2553          if(base && base.vTblSize)
2554          {
2555             _class.vTblSize = base.vTblSize;
2556             // OK to scrap existing virtual table?
2557             delete _class._vTbl;
2558             _class._vTbl = _malloc(sizeof(int(*)()) * _class.vTblSize);
2559             memcpy(_class._vTbl, base._vTbl, sizeof(int(*)()) * _class.vTblSize);
2560          }
2561
2562          if(_class.base)
2563          {
2564             OldLink link { data = _class };
2565             /*(_class.base.templateClass ? _class.base.templateClass : _class.base)*/_class.base.derivatives.Add(link);
2566          }
2567
2568          FixDerivativesBase(_class, _class);
2569          return _class;
2570       }
2571    }
2572    return null;
2573 }
2574
2575 static void DataMember_Free(DataMember parentMember)
2576 {
2577    DataMember member;
2578    BTNamedLink namedLink;
2579    delete parentMember.name;
2580    delete parentMember.dataTypeString;
2581
2582    while((member = parentMember.members.first))
2583    {
2584       DataMember_Free(member);
2585       parentMember.members.Delete(member);
2586    }
2587
2588    while((namedLink = (BTNamedLink)parentMember.membersAlpha.first))
2589    {
2590       parentMember.membersAlpha.Delete((BTNode)namedLink);
2591    }
2592 }
2593
2594 static void FreeEnumValue(NamedLink value)
2595 {
2596    delete value.name;
2597 }
2598
2599 static void FreeTemplateArg(Class template, ClassTemplateParameter param, int id)
2600 {
2601    switch(param.type)
2602    {
2603       case type:
2604          delete template.templateArgs[id].dataTypeString;
2605          break;
2606       case identifier:
2607          delete template.templateArgs[id].memberString;
2608          break;
2609       case expression:
2610          
2611          break;
2612    }
2613 }
2614
2615 static void FreeTemplateArgs(Class template)
2616 {
2617    if(template.templateArgs)
2618    {
2619       Class _class;
2620       for(_class = template; _class; _class = _class.base)
2621       {
2622          Class prevClass;
2623          ClassTemplateParameter param;
2624          int id = 0;
2625          if(_class.templateClass) _class = _class.templateClass;
2626          for(prevClass = _class.base; prevClass; prevClass = prevClass.base) 
2627          {
2628             if(prevClass.templateClass) prevClass = prevClass.templateClass;
2629             id += prevClass.templateParams.count;
2630          }
2631          if(id < template.numParams)
2632          {
2633             for(param = _class.templateParams.first; param; param = param.next)
2634             {
2635                switch(param.type)
2636                {
2637                   case type:
2638                      delete template.templateArgs[id].dataTypeString;
2639                      break;
2640                   case identifier:
2641                      delete template.templateArgs[id].memberString;
2642                      break;
2643                   case expression:
2644                      // delete template.templateArgs[id].dataTypeString;
2645                      break;
2646                }
2647                id++;
2648             }
2649          }
2650       }
2651    }
2652 }
2653
2654 static void FreeTemplate(Class template)
2655 {
2656    OldLink deriv;
2657
2658    if(template.nameSpace)
2659    {
2660       BTNamedLink link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
2661       template.nameSpace->classes.Delete((BTNode)link);
2662    }
2663    FreeTemplateArgs(template);
2664
2665    delete template.fullName;
2666    delete template.name;
2667    delete template.templateArgs;
2668
2669    while((deriv = template.derivatives.first))
2670    {
2671       ((Class)deriv.data).base = null;
2672       template.derivatives.Delete(deriv);
2673    }
2674
2675    _free(template);
2676 }
2677
2678 static void FreeTemplates(Class _class)
2679 {
2680    OldLink deriv, template;
2681
2682    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
2683    {
2684       FreeTemplates(deriv.data);
2685    }
2686
2687    FreeTemplateArgs(_class);
2688    //if(_class.templateArgs)
2689       //printf("Deleting  Template args for %s\n", _class.name);
2690    delete _class.templateArgs;
2691
2692    while((template = _class.templatized.first))
2693    {
2694       FreeTemplates(template.data);
2695       FreeTemplate(template.data);
2696       _class.templatized.Delete(template);
2697    }
2698 }
2699
2700 public dllexport void eClass_Unregister(Class _class)
2701 {
2702    BTNamedLink namedLink;
2703    DataMember member;
2704    Method method;
2705    OldLink deriv, template;
2706    ClassProperty classProp;
2707    ClassTemplateParameter param;
2708
2709    delete _class._vTbl;
2710
2711    FreeTemplates(_class);
2712    
2713    FreeTemplateArgs(_class);
2714    delete _class.templateArgs;
2715
2716    while((template = _class.templatized.first))
2717    {
2718       FreeTemplate(template.data);
2719       _class.templatized.Delete(template);
2720    }
2721
2722    while((member = _class.membersAndProperties.first))
2723    {
2724       if(!member.isProperty && (member.type == unionMember || member.type == structMember))
2725          DataMember_Free(member);
2726       delete member.name;
2727       delete member.dataTypeString;
2728       _class.membersAndProperties.Delete(member);
2729    }
2730
2731    while((member = _class.conversions.first))
2732    {
2733       delete member.name;
2734       delete member.dataTypeString;
2735       _class.conversions.Delete(member);
2736    }
2737
2738    while((namedLink = (BTNamedLink)_class.prop.first))
2739    {
2740       _class.prop.Delete((BTNode)namedLink);
2741    }
2742
2743    while((namedLink = (BTNamedLink)_class.members.first))
2744    {
2745       _class.members.Delete((BTNode)namedLink);
2746    }
2747
2748    while((classProp = (ClassProperty)_class.classProperties.first))
2749    {
2750       delete classProp.name;
2751       delete classProp.dataTypeString;
2752       _class.classProperties.Delete((BTNode)classProp);
2753    }
2754
2755    while((method = (Method)_class.methods.first))
2756    {
2757       delete method.name;
2758       delete method.dataTypeString;
2759       _class.methods.Delete((BTNode)method);
2760    }
2761
2762    if(_class.type == enumClass)
2763    {
2764       EnumClassData data = (EnumClassData)_class.data;
2765
2766       data.values.Free((void *)FreeEnumValue);
2767    }
2768    _class.delayedCPValues.Free(null);
2769
2770    _class.selfWatchers.Free(null);
2771    
2772    if(_class.base)
2773    {
2774       // Class base = _class.base.templateClass ? _class.base.templateClass : _class.base;
2775       Class base = _class.base;
2776       for(deriv = base.derivatives.first; deriv; deriv = deriv.next)
2777       {
2778          if(deriv.data == _class)
2779             break;
2780       }
2781       if(deriv)
2782          base.derivatives.Delete(deriv);
2783    }
2784    while((deriv = _class.derivatives.first))
2785    {
2786       ((Class)deriv.data).base = null;
2787       _class.derivatives.Delete(deriv);
2788    }
2789
2790    if(_class.nameSpace)
2791    {
2792       BTNamedLink link = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
2793       _class.nameSpace->classes.Delete((BTNode)link);
2794    }
2795
2796    delete _class.name;
2797    delete _class.fullName;
2798    
2799    delete _class.dataTypeString;
2800
2801    delete _class.data;
2802
2803    while((param = _class.templateParams.first))
2804    {
2805       switch(param.type)
2806       {
2807          case type:
2808             delete param.defaultArg.dataTypeString;
2809             break;
2810          case identifier:
2811             delete param.defaultArg.memberString;
2812             break;
2813          case expression:
2814             
2815             break;
2816       }
2817       if(param.type != identifier) delete param.dataTypeString;
2818       delete param.name;
2819
2820       _class.templateParams.Delete(param);
2821    }
2822
2823    //_class.nameSpace->classes.Delete(_class);
2824    _free(_class);
2825 }
2826
2827 static BTNamedLink ScanNameSpace(NameSpace nameSpace, char * name, void * listOffset)
2828 {
2829    BinaryTree * tree = (BinaryTree *)((byte *)nameSpace + (uint)listOffset);
2830    BTNamedLink link = (BTNamedLink)tree->Find((uint)name);
2831    NameSpace * child;
2832    if(!link)
2833    {
2834       for(child = (NameSpace *)nameSpace.nameSpaces.first; child; child = (NameSpace *)((BTNode)child).next)
2835       {
2836          link = ScanNameSpace(child, name, listOffset);
2837          if(link)
2838             break;
2839       }
2840    }
2841    return link;
2842 }
2843
2844 static BTNamedLink SearchNameSpace(NameSpace nameSpace, char * name, void * listOffset)
2845 {
2846    int start = 0, c;
2847    char ch;
2848    int level = 0;
2849    for(c = 0; (ch = name[c]); c++)
2850    {
2851       if(ch == '<') level++;
2852       if(ch == '>') level--;
2853       if(level == 0 && (ch == '.' || (ch == ':' && name[c+1] == ':')))
2854       {
2855          NameSpace * newSpace;
2856          char * spaceName = _malloc(c - start + 1);
2857          memcpy(spaceName, name + start, c - start);
2858          spaceName[c-start] = '\0';
2859          newSpace = (NameSpace *)nameSpace.nameSpaces.FindString(spaceName);
2860          _free(spaceName);
2861          if(!newSpace)
2862             return null;
2863          nameSpace = newSpace;
2864          if(level == 0 && ch == ':') c++;
2865          start = c+1;
2866       }
2867    }
2868    if(c - start)
2869    {
2870       return ScanNameSpace(nameSpace, name + start, listOffset);
2871    }
2872    return null;
2873 }
2874
2875 static BTNamedLink SearchModule(Module module, char * name, void * listOffset, bool searchPrivate)
2876 {
2877    SubModule subModule;
2878    BTNamedLink link;
2879
2880    if(searchPrivate)
2881    {
2882       link = SearchNameSpace(&module.privateNameSpace, name, listOffset);
2883       if(link) return link;
2884    }
2885    link = SearchNameSpace(&module.publicNameSpace, name, listOffset);
2886    if(link) return link;
2887
2888    for(subModule = module.modules.first; subModule; subModule = subModule.next)
2889    {
2890       if(searchPrivate || subModule.importMode == publicAccess)
2891       {
2892          // TOCHECK: Reverting to false to test what we were trying to fix by passing searchPrivate
2893          // Passing searchPrivate finds ALL classes private or not and thus classes clash
2894          // SearchModule here is called mainly from eSystem_FindClass, and also for Functions and Defines
2895
2896          link = SearchModule(subModule.module, name, listOffset, false);
2897          //link = SearchModule(subModule.module, name, listOffset, searchPrivate /*false*/);
2898          if(link) return link;
2899       }
2900    }
2901    return null;
2902 }
2903
2904 public int64 _strtoi64(char * string, char ** endString, int base)
2905 {
2906    int64 value = 0;
2907    int sign = 1;
2908    int c;
2909    char ch;
2910    for(c = 0; (ch = string[c]) && isspace(ch); c++);
2911    if(ch =='+') c++;
2912    else if(ch == '-') { sign = -1; c++; };
2913    if(!base)
2914    {
2915       if(ch == 0 && string[c+1] == 'x')
2916       {
2917          base = 16;
2918          c+=2;
2919       }
2920       else if(ch == '0')
2921       {
2922          base = 8;
2923          c++;
2924       }
2925       else
2926          base = 10;
2927    }
2928    for( ;(ch = string[c]); c++)
2929    {
2930       if(ch == '0')
2931          ch = 0;
2932       else if(ch >= '1' && ch <= '9')
2933          ch -= '1';
2934       else if(ch >= 'a' && ch <= 'z') 
2935          ch -= 'a'; 
2936       else if(ch >= 'A' && ch <= 'Z') 
2937          ch -= 'A';
2938       else
2939       {
2940          *endString = string + c;
2941          // Invalid character
2942          break;
2943       }
2944       if(ch < base)
2945       {
2946          value *= base;
2947          value += ch;
2948       }
2949       else
2950       {
2951          *endString = string + c;
2952          // Invalid character
2953          break;
2954       }
2955    }
2956    return sign*value;
2957 }
2958
2959 public uint64 _strtoui64(char * string, char ** endString, int base)
2960 {
2961    uint64 value = 0;
2962    int sign = 1;
2963    int c;
2964    char ch;
2965    for(c = 0; (ch = string[c]) && isspace(ch); c++);
2966    if(ch =='+') c++;
2967    else if(ch == '-') { sign = -1; c++; };
2968    if(!base)
2969    {
2970       if(ch == 0 && string[c+1] == 'x')
2971       {
2972          base = 16;
2973          c+=2;
2974       }
2975       else if(ch == '0')
2976       {
2977          base = 8;
2978          c++;
2979       }
2980       else
2981          base = 10;
2982    }
2983    for( ;(ch = string[c]); c++)
2984    {
2985       if(ch == '0')
2986          ch = 0;
2987       else if(ch >= '1' && ch <= '9')
2988          ch -= '1';
2989       else if(ch >= 'a' && ch <= 'z') 
2990          ch -= 'a'; 
2991       else if(ch >= 'A' && ch <= 'Z') 
2992          ch -= 'A';
2993       else
2994       {
2995          *endString = string + c;
2996          // Invalid character
2997          break;
2998       }
2999       if(ch < base)
3000       {
3001          value *= base;
3002          value += ch;
3003       }
3004       else
3005       {
3006          *endString = string + c;
3007          // Invalid character
3008          break;
3009       }
3010    }
3011    return sign*value;
3012 }
3013
3014 public dllexport Class eSystem_FindClass(Module module, char * name)
3015 {
3016    if(name && module)
3017    {
3018       BTNamedLink link;
3019       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->classes);
3020       if(link) return link.data;
3021
3022       link = SearchModule(module, name, &((NameSpace *)0)->classes, true);
3023       if(link) return link.data;
3024       
3025       {
3026          char noTemplateName[1024];
3027          char * templateParams = strchr(name, '<');
3028
3029          if(templateParams)
3030          {
3031             strncpy(noTemplateName, name, templateParams - name);
3032             noTemplateName[templateParams - name] = '\0';
3033          }
3034          else
3035             strcpy(noTemplateName, name);
3036
3037          link = SearchNameSpace(&module.application.systemNameSpace, noTemplateName, &((NameSpace *)0)->classes);
3038          if(!link)
3039             link = SearchModule(module, noTemplateName, &((NameSpace *)0)->classes, true);
3040          if(link)
3041          {
3042             Class _class = link.data;
3043             Class templatedClass = null;
3044             char className[1024];
3045             strcpy(className, _class.fullName);
3046             strcat(className, templateParams);
3047
3048             link = SearchNameSpace(&module.application.systemNameSpace, className, &((NameSpace *)0)->classes);
3049             if(link)
3050                return link.data;
3051
3052             link = SearchModule(module, className, &((NameSpace *)0)->classes, true);
3053             if(link)
3054                return link.data;
3055
3056             if(_class && templateParams)
3057             {
3058                // if(!numParams) return null;
3059
3060                templatedClass = Class { };
3061                *templatedClass = *_class;
3062                templatedClass.templateClass = _class;
3063                //templatedClass.fullName = CopyString(name);
3064                templatedClass.fullName = CopyString(className);
3065                templatedClass.name = CopyString(templatedClass.fullName + strlen(_class.fullName) - strlen(_class.name));
3066                templatedClass.nameSpace->classes.Add((BTNode)BTNamedLink { name = templatedClass.name, data = templatedClass });
3067                templatedClass.templateArgs = null;
3068                templatedClass.numParams = 0;
3069                templatedClass.derivatives = { };
3070                templatedClass.templatized = { };
3071
3072                ComputeClassParameters(templatedClass, templateParams, module);
3073
3074                _class.templatized.Add(OldLink { data = templatedClass });
3075             }
3076             return templatedClass;
3077          }
3078       }
3079    }
3080    return null;
3081 }
3082
3083 static void CopyTemplateArg(ClassTemplateParameter param, ClassTemplateArgument arg)
3084 {
3085    switch(param.type)
3086    {
3087       case type:
3088          arg.dataTypeString = CopyString(arg.dataTypeString);
3089          break;
3090       case expression:
3091          
3092          break;
3093       case identifier:
3094          arg.memberString = CopyString(arg.memberString);
3095          break;
3096    }
3097 }
3098
3099 static void ComputeClassParameters(Class templatedClass, char * templateParams, Module findModule)
3100 {
3101    char ch;
3102    char * nextParamStart = templateParams ? (templateParams + 1) : null;
3103    ClassTemplateParameter curParam = null;
3104    Class lastClass = null, sClass;
3105    int curParamID = 0;
3106    int numParams = 0;
3107    Class _class = templatedClass.templateClass ? templatedClass.templateClass : templatedClass;
3108
3109    for(sClass = _class; sClass; sClass = sClass.base)
3110    {
3111       if(sClass.templateClass) sClass = sClass.templateClass;
3112       numParams += sClass.templateParams.count;
3113    }
3114    
3115    if(templatedClass.templateArgs)
3116       FreeTemplateArgs(templatedClass);
3117    delete templatedClass.templateArgs;
3118    templatedClass.templateArgs = new0 ClassTemplateArgument[numParams];
3119    templatedClass.numParams = numParams;
3120
3121    if(_class != templatedClass)
3122    {
3123       /*int c;
3124       Class sClass;
3125       memcpy(templatedClass.templateArgs, _class.templateArgs, numParams * sizeof(ClassTemplateArgument));
3126       for(sClass = _class; sClass; sClass = sClass.base)
3127       {
3128          ClassTemplateParameter param;
3129          Class prevClass;
3130          int id = 0;
3131          if(sClass.templateClass) sClass = sClass.templateClass;
3132          for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
3133          {
3134             if(prevClass.templateClass) prevClass = prevClass.templateClass;
3135             id += prevClass.templateParams.count;
3136          }
3137          for(param = sClass.templateParams.first; param; param = param.next)
3138            CopyTemplateArg(param, templatedClass.templateArgs[id++]);
3139       }*/
3140    }
3141    
3142    if(templatedClass.base && templatedClass.base.templateArgs && _class == templatedClass)
3143    {
3144       Class sClass;
3145       memcpy(templatedClass.templateArgs, templatedClass.base.templateArgs, 
3146          sizeof(ClassTemplateArgument) * (numParams - templatedClass.templateParams.count));
3147       for(sClass = templatedClass.base; sClass; sClass = sClass.base)
3148       {
3149          ClassTemplateParameter param;
3150          Class prevClass;
3151          int id = 0;
3152          for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
3153          {
3154             if(prevClass.templateClass) prevClass = prevClass.templateClass;
3155             id += prevClass.templateParams.count;
3156          }
3157
3158          if(sClass.templateClass) sClass = sClass.templateClass;
3159          for(param = sClass.templateParams.first; param; param = param.next)
3160             CopyTemplateArg(param, templatedClass.templateArgs[id++]);
3161       }
3162    }
3163    
3164    while(nextParamStart)
3165    {
3166       char * paramStart = nextParamStart;
3167       char * paramEnd;
3168       int level = 0;
3169       while(*paramStart == ' ') paramStart++;
3170       paramEnd = paramStart;
3171       while((ch = *paramEnd, ch && (level > 0 || (ch != '>' && ch != ',')))) 
3172       {
3173          if(ch == '<') level++;
3174          if(ch == '>') level--;
3175
3176          paramEnd++;
3177       }
3178       nextParamStart = (ch == ',') ? (paramEnd + 1) : null;
3179       while(*paramEnd == ' ') paramEnd--;
3180       if(paramEnd > paramStart)
3181       {
3182          char * ptr, * equal = null;
3183          for(ptr = paramStart; ptr <= paramEnd; ptr++)
3184          {
3185             if(*ptr == '=')
3186             {
3187                equal = ptr;
3188                break;
3189             }
3190          }
3191          if(equal)
3192          {
3193             char * end = equal - 1;
3194             char ident[1024];
3195             
3196             while(*end == ' ') end--;
3197             strncpy(ident, paramStart, end + 1 - paramStart);
3198             ident[end + 1 - paramStart] = 0;
3199             
3200             for(sClass = _class; sClass; sClass = sClass.base)
3201             {
3202                if(sClass.templateClass) sClass = sClass.templateClass;
3203                for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
3204                {
3205                   if(!strcmp(curParam.name, ident))
3206                      break;
3207                }
3208                if(curParam)
3209                {
3210                   Class nextClass;
3211                   ClassTemplateParameter prevParam;
3212                   curParamID = 0;
3213                   for(prevParam = curParam.prev; prevParam; prevParam = prevParam.prev) curParamID++;
3214                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3215                   {
3216                      if(nextClass.templateClass) nextClass = nextClass.templateClass;
3217                      curParamID += nextClass.templateParams.count;
3218                   }
3219                   break;
3220                }
3221             }
3222             lastClass = sClass;
3223          }
3224          else
3225          {
3226             if(curParam)
3227             {
3228                curParam = curParam.next;
3229                curParamID++;
3230             }
3231
3232             if(!curParam)
3233             {
3234                for(sClass = lastClass ? lastClass.base : _class; sClass; sClass = sClass.base)
3235                {
3236                   ClassTemplateParameter param;
3237                   curParamID = 0;
3238                   if(sClass.templateClass) sClass = sClass.templateClass;
3239                   for(param = sClass.templateParams.first; param; param = param.next, curParamID++)
3240                   {
3241                      curParam = param;
3242                      break;
3243                   }
3244                   if(curParam) 
3245                   {
3246                      Class nextClass;
3247                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3248                      {
3249                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
3250                         curParamID += nextClass.templateParams.count;
3251                      }
3252                      lastClass = sClass;
3253                      break;
3254                   }
3255                }
3256                /*
3257                for(sClass = _class; sClass; sClass = sClass.base)
3258                {
3259                   if(sClass.templateParams.first)
3260                   {
3261                      Class nextClass;
3262                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3263                         if(nextClass.templateParams.first)
3264                            break;
3265                      if(nextClass != lastClass) continue;
3266
3267                      curParam = sClass.templateParams.first;
3268                      lastClass = sClass;
3269
3270                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3271                         if(nextClass.templateParams.first)
3272                         {
3273                            curParamID += nextClass.templateParams.count;
3274                            break;
3275                         } 
3276                      break;
3277                   }
3278                }
3279                */
3280             }
3281          }
3282
3283          if(curParam)
3284          {
3285             ClassTemplateArgument argument { };
3286             char value[1024];
3287             if(equal) 
3288             {
3289                equal++;
3290                while(*equal == ' ') equal++;
3291                memcpy(value, equal, paramEnd - equal);
3292                value[paramEnd - equal] = 0;
3293             }
3294             else
3295             {
3296                memcpy(value, paramStart, paramEnd - paramStart);
3297                value[paramEnd - paramStart] = 0;
3298             }
3299             TrimRSpaces(value, value);
3300
3301             switch(curParam.type)
3302             {
3303                case type:
3304                   argument.dataTypeString = CopyString(value);
3305                   argument.dataTypeClass = eSystem_FindClass(_class.module, value);
3306                   if(!argument.dataTypeClass) argument.dataTypeClass = eSystem_FindClass(_class.module.application, value);
3307                   if(!argument.dataTypeClass) argument.dataTypeClass = eSystem_FindClass(findModule, value);
3308                   break;
3309                case expression:
3310                {
3311                   Class expClass = eSystem_FindClass(_class.module, curParam.dataTypeString);
3312                   if(!expClass) expClass = eSystem_FindClass(_class.module.application, curParam.dataTypeString);
3313                   if(expClass)
3314                   {
3315                      //if(expClass.type == 
3316                      expClass._vTbl[__ecereVMethodID_class_OnGetDataFromString](expClass, &argument.expression, value);
3317                   }
3318                   // Expression should be pre simplified here
3319                   else if(value[0] == '\"')
3320                   {
3321                      char * endQuote = value + strlen(value) - 1;
3322                      if(*endQuote != '\"') endQuote++;
3323                      *endQuote = '\0';
3324                      argument.expression.p = CopyString(value + 1);
3325                   }
3326                   else if(value[0] == '\'')
3327                   {
3328                      int nb;
3329                      unichar ch = UTF8GetChar(value + 1, &nb);
3330                      argument.expression.ui = ch;
3331                   }
3332                   else if(!strcmp(curParam.dataTypeString, "uint"))
3333                   {
3334                      argument.expression.ui = strtoul(value, null, 0);
3335                   }
3336                   else if(!strcmp(curParam.dataTypeString, "char"))
3337                   {
3338                      argument.expression.c = (char)strtol(value, null, 0);
3339                   }
3340                   else if(!strcmp(curParam.dataTypeString, "byte"))
3341                   {
3342                      argument.expression.uc = (unsigned char)strtoul(value, null, 0);
3343                   }
3344                   else if(!strcmp(curParam.dataTypeString, "short"))
3345                   {
3346                      argument.expression.s = (short)strtol(value, null, 0);
3347                   }
3348                   else if(!strcmp(curParam.dataTypeString, "uint16"))
3349                   {
3350                      argument.expression.us = (unsigned short)strtoul(value, null, 0);
3351                   }
3352                   else if(!strcmp(curParam.dataTypeString, "int64"))
3353                   {
3354                      argument.expression.i64 = _strtoi64(value, null, 0);
3355                   }
3356                   else if(!strcmp(curParam.dataTypeString, "uint64"))
3357                   {
3358                      argument.expression.ui64 = _strtoui64(value, null, 0);
3359                   }
3360                   else if(!strcmp(curParam.dataTypeString, "float"))
3361                   {
3362                      argument.expression.f = (float)strtod(value, null);
3363                   }
3364                   else if(!strcmp(curParam.dataTypeString, "double"))
3365                   {
3366                      argument.expression.d = strtod(value, null);
3367                   }
3368                   else // if(!strcmp(curParam.dataTypeString, "int"))
3369                   {
3370                      argument.expression.i = strtol(value, null, 0);
3371                   }
3372                   break;
3373                } 
3374                case identifier:
3375                   argument.memberString = CopyString(value);
3376                   break;
3377             }
3378             FreeTemplateArg(templatedClass, curParam, curParamID);
3379             templatedClass.templateArgs[curParamID] = argument;
3380          }
3381       }
3382    }
3383
3384    // TESTING THIS BEFORE...
3385    if(templatedClass == _class)
3386    {
3387       Class sClass = _class;
3388       int curParamID = 0;
3389       Class nextClass;
3390       ClassTemplateParameter param;
3391       for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3392       {
3393          if(nextClass.templateClass) nextClass = nextClass.templateClass;
3394          curParamID += nextClass.templateParams.count;
3395       }
3396
3397       for(param = sClass.templateParams.first; param; param = param.next)
3398       {
3399          if(!templatedClass.templateArgs[curParamID].dataTypeString)
3400          {
3401             templatedClass.templateArgs[curParamID] = param.defaultArg;
3402             CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3403             if(param.type == type && param.defaultArg.dataTypeString)
3404             {
3405                templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3406                if(!templatedClass.templateArgs[curParamID].dataTypeClass) 
3407                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3408                if(!templatedClass.templateArgs[curParamID].dataTypeClass) 
3409                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3410             }
3411          }
3412          curParamID++;
3413       }
3414    }
3415
3416    if(templatedClass.base && templatedClass.base.templateArgs && numParams - _class.templateParams.count)
3417    {
3418       int c = numParams - _class.templateParams.count-1;
3419
3420       for(sClass = _class.base; sClass; sClass = sClass.base)
3421       {
3422          ClassTemplateParameter param;
3423          if(sClass.templateClass) sClass = sClass.templateClass;
3424          for(param = sClass.templateParams.last; param; param = param.prev)
3425          {
3426             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3427             ClassTemplateArgument * baseArg = &templatedClass.base.templateArgs[c];
3428             if(!arg->dataTypeString)
3429             {
3430                *arg = templatedClass.base.templateArgs[c];
3431                CopyTemplateArg(param, arg);
3432                if(param.type == type)
3433                {
3434                   if(arg->dataTypeClass && strchr(arg->dataTypeString, '<') && arg->dataTypeClass.templateArgs)
3435                   {
3436                      Class expClass = arg->dataTypeClass;
3437                      Class cClass = null;
3438                      int paramCount = 0;
3439                      int lastParam = -1;
3440                      
3441                      char templateString[1024];
3442                      sprintf(templateString, "%s<", expClass.templateClass.fullName);
3443                      for(cClass = expClass; cClass; cClass = cClass.base)
3444                      {
3445                         int p = 0;
3446                         ClassTemplateParameter param;
3447                         for(param = cClass.templateParams.first; param; param = param.next)
3448                         {
3449                            int id = p;
3450                            Class sClass;
3451                            ClassTemplateArgument arg;
3452                            for(sClass = expClass.base; sClass; sClass = sClass.base) id += sClass.templateParams.count;
3453                            arg = expClass.templateArgs[id];
3454
3455                            {
3456                               ClassTemplateParameter cParam;
3457                               int p = numParams - _class.templateParams.count;
3458                               for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3459                               {
3460                                  if(cParam.type == type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
3461                                  {
3462                                     arg.dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3463                                     arg.dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3464                                     break;
3465                                  }
3466                               }
3467                            }
3468
3469                            {
3470                               char argument[256];
3471                               argument[0] = '\0';
3472                               switch(param.type)
3473                               {
3474                                  case expression:
3475                                  {
3476                                     // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
3477                                     /*
3478                                     char expString[1024];
3479                                     OldList * specs = MkList();
3480                                     Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
3481                                     Expression exp;
3482                                     char * string = PrintHexUInt64(arg.expression.ui64);
3483                                     exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
3484
3485                                     ProcessExpressionType(exp);
3486                                     ComputeExpression(exp);
3487                                     expString[0] = '\0';
3488                                     PrintExpression(exp, expString);
3489                                     strcat(argument, expString);
3490                                     //delete exp;
3491                                     FreeExpression(exp);
3492                                     */
3493                                     break;
3494                                  }
3495                                  case identifier:
3496                                  {
3497                                     strcat(argument, arg.member.name);
3498                                     break;
3499                                  }
3500                                  case TemplateParameterType::type:
3501                                  {
3502                                     if(arg.dataTypeString)
3503                                        strcat(argument, arg.dataTypeString);
3504                                     break;
3505                                  }
3506                               }
3507                               if(argument[0])
3508                               {
3509                                  if(paramCount) strcat(templateString, ", ");
3510                                  if(lastParam != p - 1)
3511                                  {
3512                                     strcat(templateString, param.name);
3513                                     strcat(templateString, " = ");
3514                                  }
3515                                  strcat(templateString, argument);
3516                                  paramCount++;
3517                                  lastParam = p;
3518                               }
3519                            }
3520                            p++;
3521                         }
3522                      }
3523                      {
3524                         int len = strlen(templateString);
3525                         if(templateString[len-1] == '>') templateString[len++] = ' ';
3526                         templateString[len++] = '>';
3527                         templateString[len++] = '\0';
3528                      }
3529
3530                      FreeTemplateArg(templatedClass, param, c);
3531
3532                      arg->dataTypeString = CopyString(templateString);
3533                      arg->dataTypeClass = eSystem_FindClass(templatedClass.module, templateString);
3534                      if(!arg->dataTypeClass)
3535                         arg->dataTypeClass = eSystem_FindClass(templatedClass.module.application, templateString);
3536                   }
3537                   else
3538                   {
3539                      ClassTemplateParameter cParam;
3540                      int p = numParams - _class.templateParams.count;
3541                      for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3542                      {
3543                         // if(cParam.type == type && !strcmp(cParam.name, param.name))
3544                         if(cParam.type == type && baseArg->dataTypeString && !strcmp(cParam.name, baseArg->dataTypeString))
3545                         {
3546                            FreeTemplateArg(templatedClass, param, c);
3547
3548                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3549                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3550                            CopyTemplateArg(cParam, arg);
3551                            break;
3552                         }
3553                      }
3554                   }
3555                }
3556             }
3557             c--;                        
3558          }
3559       }
3560    }
3561
3562    {
3563       Class sClass;
3564       for(sClass = _class; sClass; sClass = sClass.base)
3565       {
3566          int curParamID = 0;
3567          Class nextClass;
3568          ClassTemplateParameter param;
3569          if(sClass.templateClass) sClass = sClass.templateClass;
3570          
3571          for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) 
3572          {
3573             if(nextClass.templateClass) nextClass = nextClass.templateClass;
3574             curParamID += nextClass.templateParams.count;
3575          }
3576
3577          for(param = sClass.templateParams.first; param; param = param.next)
3578          {
3579             if(!templatedClass.templateArgs[curParamID].dataTypeString)
3580             {
3581                templatedClass.templateArgs[curParamID] = param.defaultArg;
3582                CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3583                if(param.type == type && param.defaultArg.dataTypeString)
3584                {
3585                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3586                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3587                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3588                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3589                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3590                }
3591             }
3592             curParamID++;
3593          }
3594       }
3595    }
3596
3597    {
3598       int c = numParams - 1;
3599       for(sClass = _class; sClass; sClass = sClass.base)
3600       {
3601          ClassTemplateParameter param;
3602          if(sClass.templateClass) sClass = sClass.templateClass;
3603          for(param = sClass.templateParams.last; param; param = param.prev)
3604          {
3605             if(param.type == type)
3606             {
3607                ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3608                ClassTemplateParameter cParam;
3609                Class dClass;
3610                int p = numParams - 1;
3611                for(dClass = _class; dClass; dClass = dClass.base)
3612                {                              
3613                   if(dClass.templateClass) dClass = dClass.templateClass;
3614                   for(cParam = dClass.templateParams.last; cParam; cParam = cParam.prev, p--)
3615                   {
3616                      if(cParam.type == type && arg->dataTypeString && !strcmp(cParam.name, arg->dataTypeString))
3617                      {
3618                         if(templatedClass.templateArgs[p].dataTypeString && c != p)
3619                         {
3620                            FreeTemplateArg(templatedClass, param, c);
3621
3622                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3623                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3624                            CopyTemplateArg(cParam, arg);
3625                         }
3626                      }
3627                   }
3628                }
3629             }
3630             c--;
3631          }
3632       }
3633    }
3634
3635    {
3636       Class tClass;
3637       int c = numParams - 1;
3638       for(tClass = _class; tClass; tClass = tClass.base)
3639       {
3640          ClassTemplateParameter param;
3641          if(tClass.templateClass) tClass = tClass.templateClass;
3642          for(param = tClass.templateParams.last; param; param = param.prev)
3643          {
3644             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3645             if(param.type == identifier && arg->memberString)
3646             {
3647                Class memberClass = templatedClass;
3648                char * memberString = arg->memberString;
3649                char * colon = strstr(memberString, "::");
3650                char * memberName = memberString;
3651                if(colon) memberName = colon + 2;
3652                if(!colon)
3653                {
3654                   memberString = param.defaultArg.memberString;
3655                   colon = memberString ? strstr(memberString, "::") : null;
3656                }
3657
3658                if(colon)
3659                {
3660                   char className[1024];
3661                   Class sClass;
3662
3663                   memcpy(className, memberString, colon - memberString);
3664                   className[colon - memberString] = '\0';
3665                   
3666                   for(sClass = _class; sClass; sClass = sClass.base)
3667                   {
3668                      ClassTemplateParameter cParam;
3669                      Class nextClass;
3670                      int id = 0;
3671
3672                      if(sClass.templateClass) sClass = sClass.templateClass;
3673                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) 
3674                      {
3675                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
3676                         id += nextClass.templateParams.count;
3677                      }
3678                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
3679                      {
3680                         if(cParam.type == type && !strcmp(cParam.name, className) && templatedClass.templateArgs[id].dataTypeString)
3681                         {
3682                            strcpy(className, templatedClass.templateArgs[id].dataTypeString);
3683                         }
3684                         id++;
3685                      }                  
3686                   }
3687                   memberClass = eSystem_FindClass(templatedClass.module, className);
3688                   // TESTING: Added this here...
3689                   if(!memberClass)
3690                      memberClass = eSystem_FindClass(findModule, className);
3691                   if(!memberClass)
3692                      memberClass = eSystem_FindClass(templatedClass.module.application, className);
3693                }
3694
3695                if(memberClass)
3696                {
3697                   switch(param.memberType)
3698                   {
3699                      case dataMember:
3700                         arg->member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
3701                         break;
3702                      case method:
3703                         arg->method = eClass_FindMethod(memberClass, memberName, memberClass.module);
3704                         break;
3705                      case prop:
3706                         arg->prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
3707                         break;
3708                   }
3709                }
3710             }
3711             c--;
3712          }
3713       }
3714    }
3715 }
3716
3717 /*static */bool DefaultFunction()
3718 {
3719    return true;
3720 }
3721
3722 public dllexport bool eClass_IsDerived(Class _class, Class from)
3723 {
3724    if(!_class && !from)
3725       return true;
3726
3727    if(_class && from && (_class.templateClass || from.templateClass))
3728    {
3729       if(eClass_IsDerived(_class.templateClass ? _class.templateClass : _class, from.templateClass ? from.templateClass : from))
3730       {
3731          if(!from.templateClass)
3732             return true;
3733          else if(!_class.templateClass && _class == from.templateClass)
3734             return false;
3735          else
3736          {
3737             Class sClass;
3738             for(sClass = from; sClass; sClass = sClass.base)
3739             {
3740                if(sClass.templateParams.first)
3741                {
3742                   ClassTemplateParameter param;
3743                   Class nextClass;
3744                   int p = 0;
3745                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) p += nextClass.templateParams.count;               
3746                   for(param = sClass.templateParams.first; param; param = param.next, p++)
3747                   {
3748                      ClassTemplateArgument * arg = &_class.templateArgs[p];
3749                      ClassTemplateArgument * fArg = &from.templateArgs[p];
3750                      if(param.type == type)
3751                      {
3752                         if(arg->dataTypeString != fArg->dataTypeString && arg->dataTypeString && fArg->dataTypeString &&
3753                           strcmp(arg->dataTypeString, fArg->dataTypeString))
3754                            break;
3755                      }
3756                      else if(param.type == identifier)
3757                      {
3758                         if(arg->member != fArg->member)
3759                            break;
3760                      }
3761                      else if(param.type == expression)
3762                      {
3763                         if(arg->expression.ui64 != fArg->expression.ui64)
3764                            break;
3765                      }
3766                   }
3767                   if(param)
3768                      return false;
3769                }
3770             }
3771             return true;
3772          }
3773       }
3774    }
3775    else
3776    {
3777       for(; _class && from; _class = _class.base)
3778       {
3779          if(_class == from || _class.templateClass == from || (_class.type == systemClass && from.name && !strcmp(_class.name, from.name)))
3780             return true;
3781       }
3782    }
3783    return false;
3784 }
3785
3786 static void FixDerivativeVirtualMethod(Class base, char * name, int vid, void * origFunction, char * type)
3787 {
3788    OldLink derivative;
3789    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
3790    {
3791       Class _class = derivative.data;
3792       Method method, next;
3793       void * function = origFunction;
3794
3795       _class.vTblSize++;
3796       _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
3797       memmove(_class._vTbl + vid + 1, _class._vTbl + vid, (_class.vTblSize - vid - 1) * sizeof(void *));
3798
3799       method = (Method) _class.methods.FindString(name);
3800       if(method)
3801       {
3802          if(method.function) function = method.function;
3803
3804          if(!method.symbol)
3805          {
3806             delete method.name;
3807             delete method.dataTypeString;
3808             _class.methods.Delete((BTNode)method);
3809          }
3810          else
3811          {
3812             delete method.dataTypeString;
3813             method.type = virtualMethod;
3814             method.dataTypeString = CopyString(type);
3815             method._class = base;
3816          }
3817       }
3818       for(method = (Method)_class.methods.first; method; method = next)
3819       {
3820          next = (Method)((BTNode)method).next;
3821          if(method.type == virtualMethod)
3822             method.vid++;
3823       }
3824       _class._vTbl[vid] = function;
3825
3826       {
3827          OldLink templateLink;
3828          for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
3829          {
3830             Class template = templateLink.data;
3831             template._vTbl = _class._vTbl;
3832          }
3833       }
3834       if(_class.derivatives.first || _class.templatized.first)
3835          FixDerivativeVirtualMethod(_class, name, vid, function, type);
3836    }
3837    {
3838       OldLink templateLink;
3839       for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
3840       {
3841          Class template = templateLink.data;
3842          template._vTbl = base._vTbl;
3843          FixDerivativeVirtualMethod(template, name, vid, origFunction, type);
3844       }
3845    }
3846 }
3847
3848 public dllexport Method eClass_AddMethod(Class _class, char * name, char * type, void * function, AccessMode declMode)
3849 {
3850    if(_class && name)
3851    {
3852       Class base;
3853       for(base = _class; base; base = base.base)
3854       {
3855          Method method = (Method)base.methods.FindString(name);
3856          if(method)
3857          {
3858             // If this overides a virtual method
3859             if(method.type == virtualMethod)
3860             {
3861                OldLink deriv;
3862                void * oldFunction = _class._vTbl[method.vid];
3863                if(method.vid > _class.vTblSize)
3864                   printf("error");
3865                else
3866                   _class._vTbl[method.vid] = function ? function : DefaultFunction;
3867                for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
3868                {
3869                   Class derivClass = deriv.data;
3870                   if(derivClass._vTbl[method.vid] == oldFunction)
3871                      eClass_AddMethod(derivClass, name, type, function, declMode);
3872                }
3873                {
3874                   OldLink templateLink;
3875                   for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
3876                   {
3877                      Class template = templateLink.data;
3878                      for(deriv = template.derivatives.first; deriv; deriv = deriv.next)
3879                      {
3880                         Class derivClass = deriv.data;
3881                         if(derivClass._vTbl[method.vid] == oldFunction)
3882                            eClass_AddMethod(derivClass, name, type, function, declMode);
3883                      }
3884                   }
3885                }
3886
3887             }
3888             else
3889             {
3890                if(base == _class)
3891                {
3892                   // printf("error: Redefinition of method %s in class %s\n", name, _class.name);
3893                   break;
3894                }
3895                base = null;
3896                break;
3897             }
3898             return method;
3899          }
3900       }
3901
3902       if(!base)
3903       {
3904          Method method
3905          {
3906             name = CopyString(name),
3907             function = function ? function : DefaultFunction;
3908             _class = _class;
3909             dataTypeString = CopyString(type);
3910             memberAccess = declMode;
3911          };
3912          _class.methods.Add((BTNode)method);
3913          return method;
3914       }
3915    }
3916    return null;
3917 }
3918
3919 public dllexport Method eClass_AddVirtualMethod(Class _class, char * name, char * type, void * function, AccessMode declMode)
3920 {
3921    if(_class && name)
3922    {
3923       Class base;
3924       for(base = _class; base; base = base.base)
3925       {
3926          Method method = (Method)base.methods.FindString(name);
3927          if(method)
3928          {
3929             // If this overides a virtual method
3930             if(method.type == virtualMethod)
3931                _class._vTbl[method.vid] = function ? function : DefaultFunction;
3932             else
3933                base = null;
3934             return method;
3935          }
3936       }
3937
3938       if(!base)
3939       {
3940          Method method
3941          {
3942             name = CopyString(name);
3943             function = function ? function : DefaultFunction;
3944             type = virtualMethod;
3945             _class = _class;
3946             vid = _class.vTblSize++;
3947             dataTypeString = CopyString(type);
3948             memberAccess = declMode;
3949          };
3950          _class.methods.Add((BTNode)method);
3951          _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
3952          _class._vTbl[method.vid] = function ? function : DefaultFunction;
3953
3954          // TODO: Fix derived classes
3955          if(_class.derivatives.first || _class.templatized.first)
3956             FixDerivativeVirtualMethod(_class, name, method.vid, function ? function : (void *)DefaultFunction, type);
3957          return method;
3958       }
3959    }
3960    return null;
3961 }
3962
3963 static void FixDerivativeProperty(Class base, Property _property)
3964 {
3965    OldLink derivative;
3966    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
3967    {
3968       Class _class = derivative.data;
3969       Property prop;
3970       BTNamedLink link;
3971       link = (BTNamedLink)_class.prop.FindString(_property.name);
3972       if(link)
3973       {
3974          prop = link.data;
3975          if(!prop.Set && !prop.Get && prop.memberAccess == baseSystemAccess)
3976          {
3977             SelfWatcher watcher;
3978             for(watcher = _class.selfWatchers.first; watcher; watcher = watcher.next)
3979             {
3980                if(watcher._property == prop)
3981                   watcher._property = _property;
3982             }
3983             _property.selfWatchable = true;
3984
3985             delete prop.name;
3986             delete prop.dataTypeString;
3987             _class.membersAndProperties.Delete(prop);
3988             _class.prop.Delete((BTNode)link);
3989          }
3990       }
3991
3992       for(prop = _class.membersAndProperties.first; prop; prop = prop.next)
3993          prop.id++;
3994       _class.memberID++;
3995       _class.startMemberID++;
3996
3997       FixDerivativeProperty(_class, _property);
3998    }
3999 }
4000
4001 public dllexport Property eClass_AddProperty(Class _class, char * name, char * dataType, void * setStmt, void * getStmt, AccessMode declMode)
4002 {
4003    Property _property = null;
4004    if(_class)
4005    {
4006       if(!_class.prop.FindString((name ? name : dataType))) 
4007       {
4008          _property =
4009          {
4010             isProperty = true;
4011             name = CopyString(name ? name : dataType);
4012             id = (name && (setStmt || getStmt || dataType)) ? _class.memberID++ : 0;
4013             Set = setStmt;
4014             Get = getStmt;
4015             dataTypeString = CopyString(dataType);
4016             _class = _class;
4017             compiled = true;
4018             conversion = name ? false : true;
4019             memberAccess = declMode;
4020          };
4021          if(name)
4022             _class.membersAndProperties.Add(_property);
4023          else
4024             _class.conversions.Add(_property);
4025          _class.prop.Add((BTNode)BTNamedLink { name = _property.name, data = _property });
4026
4027          if(!_property.conversion)
4028          {
4029             FixDerivativeProperty(_class, _property);
4030          }
4031       }
4032    }
4033    return _property;
4034 }
4035
4036 static void SetDelayedCPValues(Class _class, ClassProperty _property)
4037 {
4038    OldLink deriv;
4039    NamedLink value, next;
4040
4041    for(value = _class.delayedCPValues.first; value; value = next)
4042    {
4043       next = value.next;
4044       if(!strcmp(value.name, _property.name))
4045       {
4046          // eClass_SetProperty(_class, _property.name, value.data);
4047          _property.Set(_class, (int)value.data);
4048          _class.delayedCPValues.Delete(value);
4049       }
4050    }
4051
4052    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4053    {
4054       SetDelayedCPValues(deriv.data, _property);
4055    }
4056 }
4057
4058 public dllexport ClassProperty eClass_AddClassProperty(Class _class, char * name, char * dataType, void * setStmt, void * getStmt)
4059 {
4060    if(name && !_class.classProperties.FindString(name)) 
4061    {
4062       ClassProperty _property
4063       {
4064          name = CopyString(name);
4065          Set = setStmt;
4066          Get = getStmt;
4067          dataTypeString = CopyString(dataType);
4068       };
4069       _class.classProperties.Add((BTNode)_property);
4070       SetDelayedCPValues(_class, _property);
4071       return _property;
4072    }
4073    return null;
4074 }
4075
4076 /*import "Time"
4077
4078 Time classFindTotalTime;
4079
4080 public dllexport void ResetClassFindTime()
4081 {
4082    classFindTotalTime = 0;
4083 }
4084
4085 public dllexport Time GetClassFindTime()
4086 {
4087    return classFindTotalTime;
4088 }
4089 */
4090 public dllexport ClassProperty eClass_FindClassProperty(Class _class, char * name)
4091 {
4092    //Time startTime = GetTime();
4093    ClassProperty _property = null;
4094    if(name && _class)
4095    {
4096       Class origClass = _class;
4097       for(; _class; _class = _class.base)
4098       {
4099          _property = (ClassProperty)_class.classProperties.FindString(name);
4100          if(_property)
4101             break;
4102       }
4103       // For enum class deriving off something else than enum to find enumSize...
4104       if(!_property && origClass.type == enumClass)
4105       {
4106          Class enumClass = eSystem_FindClass(origClass.module, "enum");
4107          _property = eClass_FindClassProperty(enumClass, name);
4108       }
4109    }
4110    /*if(!_property)
4111       eSystem_Logf("No such property (%s) for class %s\n", name, _class.name);*/
4112    //classFindTotalTime += GetTime() - startTime;
4113    return _property;
4114 }
4115
4116 public dllexport int eClass_GetProperty(Class _class, char * name)
4117 {
4118    ClassProperty _property = eClass_FindClassProperty(_class, name);
4119    if(_property && _property.Get && _property.Get != (void *)1)
4120    {
4121       int result = _property.Get(_class);
4122       return result;
4123    }
4124    return 0;
4125 }
4126
4127 public dllexport void eClass_SetProperty(Class _class, char * name, int value)
4128 {
4129    ClassProperty _property = eClass_FindClassProperty(_class, name);
4130    if(_property)
4131    {
4132       if(_property.Set)
4133          _property.Set(_class, value);
4134    }
4135    else
4136    {
4137       _class.delayedCPValues.Add(NamedLink { name = name, (void *)value });
4138    }
4139 }
4140
4141 public dllexport Method eClass_FindMethod(Class _class, char * name, Module module)
4142 {
4143    //Time startTime = GetTime();
4144    if(_class && name)
4145    {
4146       for(; _class; _class = _class.base)
4147       {
4148          Method method;
4149          if(_class.templateClass) _class = _class.templateClass;
4150          method = (Method)_class.methods.FindString(name);
4151          if(method && (method.memberAccess == publicAccess || _class.module == module || !method.dataTypeString))
4152          {
4153             if(!method.dataTypeString)
4154             {
4155                if(_class.module != module)
4156                {
4157                   if(method.memberAccess == publicAccess)
4158                      module = _class.module;
4159                   else
4160                   {
4161                      //classFindTotalTime += GetTime() - startTime;
4162                      return null;
4163                   }
4164                }
4165             }
4166             else
4167             {
4168                //classFindTotalTime += GetTime() - startTime;
4169                return method;
4170             }
4171          }
4172          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4173       }
4174    }
4175    //classFindTotalTime += GetTime() - startTime;
4176    return null;
4177 }
4178
4179 // Construct an instance
4180 static bool ConstructInstance(void * instance, Class _class)
4181 {
4182    if(_class.templateClass) _class = _class.templateClass;
4183    if(_class.base)
4184    {
4185       if(!ConstructInstance(instance, _class.base))
4186          return false;
4187    }
4188    if(_class.Initialize)
4189    {
4190       void (* Initialize)(Module module) = (void *)_class.Initialize;
4191       _class.Initialize = null;
4192       Initialize(_class.module);
4193    }
4194    if(_class.Constructor)
4195    {
4196       if(!_class.Constructor(instance))
4197       {
4198          for(; _class; _class = _class.base)
4199          {
4200             if(_class.templateClass) _class = _class.templateClass;
4201             if(_class.Destructor)
4202                _class.Destructor(instance);
4203          }
4204          return false;
4205       }
4206    }
4207    (_class.templateClass ? _class.templateClass : _class).count++;
4208    return true;
4209 }
4210
4211 public dllexport void * eInstance_New(Class _class)
4212 {
4213    Instance instance = null;
4214    if(_class)
4215    {
4216       // instance = _malloc(_class.size);   
4217 #ifdef MEMINFO
4218
4219 #undef malloc
4220    memMutex.Wait();
4221       //allocateClass = _class;
4222       allocateClass = malloc(strlen(_class.name)+1);
4223       allocateInternal = _class.module == __thisModule;
4224       strcpy(allocateClass, _class.name);
4225 #ifndef MEMINFO
4226 #define malloc _mymalloc
4227 #endif
4228
4229 #endif
4230       instance = _calloc(1, _class.structSize);   
4231 #ifdef MEMINFO
4232       allocateClass = null;
4233    memMutex.Release();
4234 #endif
4235       if(_class.type == normalClass)
4236       {
4237          instance._class = _class;
4238          // Copy the virtual table initially
4239          instance._vTbl = _class._vTbl;
4240       }
4241       if(!ConstructInstance(instance, _class))
4242       {
4243          _free(instance);
4244          instance = null;
4245       }
4246       /*if(_class.type == normalClass && _class.count > 1000)
4247          printf("%s: %d instances\n", _class.name, _class.count);*/
4248    }
4249    return instance;
4250 }
4251
4252 public dllexport void eInstance_Evolve(Instance * instancePtr, Class _class)
4253 {
4254    if(_class && instancePtr && *instancePtr)
4255    {
4256       Instance instance = (Instance)renew *instancePtr byte[_class.structSize];
4257       *instancePtr = instance;
4258       memset(((byte *)instance) + instance._class.structSize, 0, _class.structSize - instance._class.structSize);
4259       // Fix pointers to application
4260       if(!strcmp(instance._class.name, "Application"))
4261       {
4262          Module module;
4263          Application app = (Application) instance;
4264          BTNamedLink link;
4265          Class _class;
4266          NameSpace * nameSpace;
4267          for(module = app.allModules.first; module; module = module.next)
4268             module.application = app;
4269
4270          for(link = (BTNamedLink)app.privateNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4271          {
4272             OldLink t;
4273             ((Class)link.data).nameSpace = &app.privateNameSpace;
4274             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4275          }
4276          for(link = (BTNamedLink)app.publicNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4277          {
4278             OldLink t;
4279             ((Class)link.data).nameSpace = &app.publicNameSpace;
4280             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4281          }
4282
4283          for(link = (BTNamedLink)app.privateNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4284             ((DefinedExpression)link.data).nameSpace = &app.privateNameSpace;
4285          for(link = (BTNamedLink)app.publicNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4286             ((DefinedExpression)link.data).nameSpace = &app.publicNameSpace;
4287
4288          for(link = (BTNamedLink)app.privateNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4289             ((GlobalFunction)link.data).nameSpace = &app.privateNameSpace;
4290          for(link = (BTNamedLink)app.publicNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4291             ((GlobalFunction)link.data).nameSpace = &app.publicNameSpace;
4292
4293          for(nameSpace = (NameSpace *)app.privateNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4294             nameSpace->parent = &app.privateNameSpace;
4295          for(nameSpace = (NameSpace *)app.publicNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4296             nameSpace->parent = &app.publicNameSpace;
4297
4298          // --------------------------------------------------
4299          for(link = (BTNamedLink)app.systemNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4300          {
4301             OldLink t;
4302             ((Class)link.data).nameSpace = &app.systemNameSpace;
4303             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4304          }
4305          for(link = (BTNamedLink)app.systemNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4306             ((DefinedExpression)link.data).nameSpace = &app.systemNameSpace;
4307          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4308             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4309          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4310             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4311          for(nameSpace = (NameSpace *)app.systemNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4312             nameSpace->parent = &app.systemNameSpace;
4313          // --------------------------------------------------
4314          
4315          for(_class = app.classes.first; _class; _class = _class.next)
4316          {
4317             OldLink templateLink;
4318             _class.module = (Module) app;
4319             for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4320             {  
4321                Class template = templateLink.data;
4322                template.module = _class.module;
4323             }
4324          }
4325          app.application = app;
4326       }
4327
4328       {
4329          Class base;
4330          for(base = instance._class; base && base.type == normalClass && base.count; base = base.base)
4331             (base.templateClass ? base.templateClass : base).count--;
4332       }
4333
4334       instance._class = _class;
4335       // Copy the virtual table initially
4336       instance._vTbl = _class._vTbl;
4337
4338       if(!ConstructInstance(instance, _class))
4339       {
4340          _free(instance);
4341          *instancePtr = null;
4342       }
4343    }
4344 }
4345
4346 public dllexport void eInstance_Delete(Instance instance)
4347 {
4348 #ifdef MEMINFO
4349    bool checkMemory = false;
4350 #endif
4351    if(instance)
4352    {
4353       Class _class, base;
4354       bool ownVtbl;
4355
4356 #ifdef MEMINFO
4357       if(instance._class == (void *)0xecececec)
4358          _free(instance);
4359 #endif
4360
4361       ownVtbl = instance._vTbl != instance._class._vTbl;
4362
4363       for(_class = instance._class; _class; _class = base)
4364       {
4365          if(_class.templateClass) _class = _class.templateClass;
4366          if(_class.destructionWatchOffset)
4367          {
4368             OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
4369             Watcher watcher, next;
4370
4371             for(watcher = watchers->first; watcher; watcher = next)
4372             {
4373                next = watcher.next;
4374                watchers->Remove(watcher);
4375                watcher.callback(watcher.object, instance);
4376                watchers->Delete(watcher);
4377             }
4378          }
4379
4380          /*// Loop through properties to delete all watchers? Might slow down destruction...
4381          {
4382             Property _property;
4383             for(_property = _class.membersAndProperties.first; _property; _property = _property.next)
4384             {
4385                if(_property.isProperty && _property.isWatchable)
4386                {
4387                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
4388                   Watcher watcher, next;
4389                   for(watcher = watchers->first; watcher; watcher = next)
4390                   {  
4391                      next = watcher.next;
4392                      watchers->Delete(watcher);
4393                   }
4394                }
4395             }
4396          }*/
4397          
4398
4399          base = _class.base;
4400          if(base && base.type == systemClass) base = null;
4401          if(_class.Destructor)
4402             _class.Destructor(instance);
4403 #ifdef MEMINFO
4404          if(_class == class(Application))
4405             checkMemory = true;
4406 #endif
4407       }
4408
4409       for(_class = instance._class; _class; _class = base)
4410       {
4411          if(_class.templateClass) _class = _class.templateClass;
4412
4413          base = _class.base;
4414          (_class.templateClass ? _class.templateClass : _class).count--;
4415          if(_class.type == normalClass && !_class.count && !_class.module)
4416          {
4417 #ifdef MEMINFO
4418             // printf("Now Destructing class %s\n", _class.name);
4419 #endif
4420             eClass_Unregister(_class);
4421          }
4422       }
4423
4424       if(ownVtbl)
4425       {
4426          delete instance._vTbl;
4427       }
4428       //instance.prop.Free(null);
4429       _free(instance);
4430 #ifdef MEMINFO
4431       if(checkMemory) CheckMemory();
4432 #endif
4433    }
4434 }
4435
4436 public dllexport Property eClass_FindProperty(Class _class, char * name, Module module)
4437 {
4438    //Time startTime = GetTime();
4439    if(_class && name)
4440    {
4441       for(; _class; _class = _class.base)
4442       {
4443          BTNamedLink link;
4444          if(_class.templateClass) _class = _class.templateClass;
4445          link = (BTNamedLink)_class.prop.FindString(name);
4446          if(link)
4447          {
4448             Property _property = (Property)link.data;
4449             if(_property.memberAccess == publicAccess || _class.module == module || !_property.dataTypeString)
4450             {
4451                if(!_property.dataTypeString)
4452                {
4453                   if(_class.module != module)
4454                   {
4455                      if(_property.memberAccess == publicAccess)
4456                         module = _class.module;
4457                      else
4458                      {
4459                         //classFindTotalTime += GetTime() - startTime;
4460                         return null;
4461                      }
4462                   }
4463                }
4464                else
4465                {
4466                   //classFindTotalTime += GetTime() - startTime;
4467                   return _property;
4468                }
4469             }
4470          }
4471          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4472       }
4473    }
4474    //classFindTotalTime += GetTime() - startTime;
4475    return null;
4476 }
4477
4478 static DataMember FindDataMember(OldList list, BinaryTree alist, char * name, uint * offset, int * id, bool searchPrivate, DataMember * subMemberStack, int * subMemberStackPos)
4479 {
4480    BTNamedLink link;
4481    DataMember dataMember;
4482
4483    link = (BTNamedLink)alist.FindString(name);
4484    if(link)
4485    {
4486       dataMember = link.data;
4487       if(dataMember.type == normalMember && (dataMember.memberAccess == publicAccess || searchPrivate || !dataMember.dataTypeString))
4488       {
4489          if(offset)
4490             *offset += dataMember.offset;
4491          if(id) *id = dataMember.id;
4492          return dataMember;
4493       }
4494       return null;
4495    }
4496    for(dataMember = list.first; dataMember; dataMember = dataMember.next)
4497    {
4498       if(!dataMember.isProperty && (dataMember.memberAccess == publicAccess || searchPrivate) && !dataMember.name && (dataMember.type == unionMember || dataMember.type == structMember))
4499       {
4500          DataMember childMember;
4501          if(subMemberStackPos) subMemberStack[(*subMemberStackPos)++] = dataMember;
4502          childMember = FindDataMember(dataMember.members, dataMember.membersAlpha, name, offset, id, searchPrivate, subMemberStack, subMemberStackPos);
4503          if(childMember)
4504          {
4505             if(offset)
4506                *offset += dataMember.offset;
4507             if(id) *id += dataMember.id;
4508             return childMember;
4509          }
4510          if(subMemberStackPos) (*subMemberStackPos)--;
4511       }
4512    }
4513    return null;
4514 }
4515
4516 public dllexport DataMember eClass_FindDataMember(Class _class, char * name, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4517 {
4518    //Time startTime = GetTime();
4519    DataMember dataMember = null;
4520    if(subMemberStackPos) *subMemberStackPos = 0;
4521    if(_class && name)
4522    {
4523       for(; _class; _class = _class.base)
4524       {
4525          if(_class.templateClass) _class = _class.templateClass;
4526          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, null, _class.module == module, subMemberStack, subMemberStackPos);
4527          if(dataMember)
4528          {
4529             if(!dataMember.dataTypeString)
4530             {
4531                if(_class.module != module)
4532                {
4533                   if(dataMember.memberAccess == publicAccess)
4534                      module = _class.module;
4535                   else
4536                   {
4537                      //classFindTotalTime += GetTime() - startTime;
4538                      return null;
4539                   }
4540                }
4541                dataMember = null;
4542             }
4543             else
4544             {
4545                // HACK: Is this good enough? avoiding setting it when adding...
4546                dataMember._class = _class.templateClass ? _class.templateClass : _class;
4547                //classFindTotalTime += GetTime() - startTime;
4548                return dataMember;
4549             }
4550          }
4551          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4552       }
4553    }
4554    //classFindTotalTime += GetTime() - startTime;
4555    return dataMember;
4556 }
4557
4558 public dllexport DataMember eClass_FindDataMemberAndOffset(Class _class, char * name, uint * offset, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4559 {
4560    //Time startTime = GetTime();
4561    DataMember dataMember = null;
4562    if(subMemberStackPos) *subMemberStackPos = 0;
4563    if(offset) *offset = 0;
4564    if(_class)
4565    {
4566       for(; _class; _class = _class.base)
4567       {
4568          if(_class.templateClass) _class = _class.templateClass;
4569          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, offset, null, _class.module == module, subMemberStack, subMemberStackPos);
4570          if(dataMember)
4571          {
4572             if(!dataMember.dataTypeString)
4573             {
4574                if(_class.module != module)
4575                {
4576                   if(dataMember.memberAccess == publicAccess)
4577                      module = _class.module;
4578                   else
4579                   {
4580                      //classFindTotalTime += GetTime() - startTime;
4581                      return null;
4582                   }
4583                }
4584                dataMember = null;
4585             }
4586             else
4587             {
4588                // HACK: Is this good enouh? avoiding setting it when adding...
4589                dataMember._class = _class;
4590                //classFindTotalTime += GetTime() - startTime;
4591                return dataMember;
4592             }
4593          }
4594          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4595       }
4596    }
4597    //classFindTotalTime += GetTime() - startTime;
4598    return dataMember;
4599 }
4600
4601 public dllexport DataMember eClass_FindDataMemberAndId(Class _class, char * name, int * id, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4602 {
4603    //Time startTime = GetTime();
4604    DataMember dataMember = null;
4605    if(subMemberStackPos) *subMemberStackPos = 0;
4606    if(_class)
4607    {
4608       for(; _class; _class = _class.base)
4609       {
4610          if(_class.templateClass) _class = _class.templateClass;
4611          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, id, _class.module == module, subMemberStack, subMemberStackPos);  // TOCHECK: Why was this null? null, null);
4612          if(dataMember)
4613          {
4614             if(!dataMember.dataTypeString)
4615             {
4616                if(_class.module != module)
4617                {
4618                   if(dataMember.memberAccess == publicAccess)
4619                      module = _class.module;
4620                   else
4621                   {
4622                      //classFindTotalTime += GetTime() - startTime;
4623                      return null;
4624                   }
4625                }
4626                dataMember = null;
4627             }
4628             else
4629             {
4630                // HACK: Is this good enouh? avoiding setting it when adding...
4631                dataMember._class = _class;
4632                //classFindTotalTime += GetTime() - startTime;
4633                return dataMember;
4634             }
4635          }
4636          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4637       }
4638    }
4639    //classFindTotalTime += GetTime() - startTime;
4640    return dataMember;
4641 }
4642
4643 public dllexport void eClass_FindNextMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
4644 {
4645    // THIS CODE WILL FIND NEXT MEMBER... (PUBLIC MEMBERS ONLY)
4646    if(*curMember) 
4647    {
4648       *curMember = (*curMember).next;
4649
4650       if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
4651       {
4652          *curMember = subMemberStack[--(*subMemberStackPos)];
4653          *curMember = (*curMember).next;
4654       }
4655
4656       if(subMemberStackPos && *subMemberStackPos > 0)
4657       {
4658          while(*curMember && ((*curMember).memberAccess == privateAccess))
4659             *curMember = (*curMember).next;
4660       }
4661       else
4662          while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
4663          {
4664             DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
4665             if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
4666             if(dataMember && dataMember.memberAccess != privateAccess)
4667             {
4668                *curMember = dataMember;
4669                break;
4670             }
4671             else
4672                *curMember = (*curMember).next;
4673          }
4674
4675       if(subMemberStackPos)
4676       {
4677          while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
4678          {
4679             subMemberStack[(*subMemberStackPos)++] = *curMember;
4680
4681             *curMember = (*curMember).members.first;
4682             while(*curMember && ((*curMember).memberAccess == privateAccess))
4683                *curMember = (*curMember).next;                     
4684          }
4685       }
4686    }
4687    while(!*curMember)
4688    {
4689       if(!*curMember)
4690       {
4691          if(subMemberStackPos && *subMemberStackPos)
4692          {
4693             *curMember = subMemberStack[--(*subMemberStackPos)];
4694             *curMember = (*curMember).next;
4695          }
4696          else
4697          {
4698             Class lastCurClass = *curClass;
4699
4700             if(*curClass == _class) break;     // REACHED THE END
4701
4702             for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass && (*curClass).inheritanceAccess != privateAccess; *curClass = (*curClass).base);
4703             *curMember = (*curClass).membersAndProperties.first;
4704          }
4705
4706          if(subMemberStackPos && *subMemberStackPos > 0)
4707          {
4708             while(*curMember && ((*curMember).memberAccess == privateAccess))
4709                *curMember = (*curMember).next;
4710          }
4711          else
4712             while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
4713             {
4714                DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
4715                if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
4716                if(dataMember && dataMember.memberAccess != privateAccess)
4717                {
4718                   *curMember = dataMember;
4719                   break;
4720                }
4721                else
4722                   *curMember = (*curMember).next;
4723             }
4724
4725          if(subMemberStackPos)
4726          {
4727             while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
4728             {
4729                subMemberStack[(*subMemberStackPos)++] = *curMember;
4730
4731                *curMember = (*curMember).members.first;
4732                while(*curMember && (*curMember).memberAccess == privateAccess)
4733                   *curMember = (*curMember).next;                     
4734             }
4735          }
4736       }
4737    }
4738 }
4739
4740 public dllexport void eInstance_SetMethod(Instance instance, char * name, void * function)     // YET TO BE DECIDED:   , Module module)
4741 {
4742    if(instance && name)
4743    {
4744       Class _class;
4745       for(_class = instance._class; _class; _class = _class.base)
4746       {
4747          Method method = (Method)_class.methods.FindString(name);
4748          if(method && method.type == virtualMethod)
4749          {
4750             if(instance._vTbl == instance._class._vTbl)
4751             {
4752                instance._vTbl = _malloc(sizeof(void *) * instance._class.vTblSize);
4753                memcpy(instance._vTbl, instance._class._vTbl,
4754                   sizeof(int(*)()) * instance._class.vTblSize);               
4755             }
4756             instance._vTbl[method.vid] = function ? function : DefaultFunction;
4757          }
4758       }
4759    }
4760 }
4761
4762 public dllexport bool eInstance_IsDerived(Instance instance, Class from)
4763 {
4764    if(instance)
4765    {
4766       Class _class = instance._class;
4767       for(; _class; _class = _class.base)
4768       {
4769          if(_class == from)
4770             return true;
4771       }
4772    }
4773    return false;
4774 }
4775
4776 public dllexport void eInstance_IncRef(Instance instance)
4777 {
4778    if(instance)
4779       instance._refCount++;
4780 }
4781
4782 public dllexport void eInstance_DecRef(Instance instance)
4783 {
4784    if(instance)
4785    {
4786       instance._refCount--;
4787       //if(!instance._refCount)
4788       if(instance._refCount <= 0)
4789       {
4790          eInstance_Delete(instance);
4791       }
4792    }
4793 }
4794
4795 static void FixOffsets(Class _class)
4796 {
4797    OldLink deriv;
4798    _class.structSize += _class.base.structSize - _class.offset;
4799
4800    _class.offset = _class.base.structSize;   
4801
4802    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4803       FixOffsets(deriv.data);
4804 }
4805
4806 public dllexport void eClass_Resize(Class _class, int newSize)
4807 {
4808    OldLink deriv;
4809    _class.structSize = newSize;
4810    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4811       FixOffsets(deriv.data);
4812 }
4813
4814 public dllexport DataMember eClass_AddDataMember(Class _class, char * name, char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
4815 {
4816    if(_class && name)
4817    {
4818       if(!_class.members.FindString(name)) 
4819       {
4820          DataMember dataMember;
4821
4822          if(alignment)
4823          {
4824             _class.structAlignment = Max(_class.structAlignment, alignment);
4825
4826             if(_class.memberOffset % alignment)
4827                _class.memberOffset += alignment - (_class.memberOffset % alignment);
4828          }
4829          
4830          dataMember = DataMember {
4831             name = CopyString(name);
4832             dataTypeString = CopyString(type);
4833             id = _class.memberID++;
4834             _class = _class;
4835             offset = _class.memberOffset;
4836             memberOffset = size;
4837             memberAccess = declMode;
4838             membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
4839          };
4840          _class.membersAndProperties.Add(dataMember);
4841          _class.memberOffset += size;
4842
4843          _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
4844          return dataMember;
4845       }
4846    }
4847    return null;
4848 }
4849
4850 public dllexport DataMember eMember_AddDataMember(DataMember member, char * name, char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
4851 {
4852    if(name && !member.membersAlpha.FindString(name)) 
4853    {
4854       DataMember dataMember;
4855
4856       if(alignment)
4857       {
4858          member.structAlignment = Max(member.structAlignment, alignment);
4859
4860          if(member.memberOffset % alignment)
4861             member.memberOffset += alignment - (member.memberOffset % alignment);
4862       }
4863       dataMember = DataMember {
4864          name = CopyString(name);
4865          _class = member._class;
4866          dataTypeString = CopyString(type);
4867          id = member.memberID++;
4868          offset = (member.type == unionMember) ? 0 : member.memberOffset;
4869          memberAccess = declMode;
4870          membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
4871       };
4872       member.members.Add(dataMember);
4873       if(member.type == unionMember)
4874       {
4875          if(size > member.memberOffset)
4876             member.memberOffset = size;
4877       }
4878       else
4879          member.memberOffset += size;
4880       member.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
4881       return dataMember;
4882    }
4883    return null;
4884 }
4885
4886 public dllexport DataMember eMember_New(DataMemberType type, AccessMode declMode)
4887 {
4888    return DataMember { type = type, memberAccess = declMode, membersAlpha.CompareKey = (void *)BinaryTree::CompareString };
4889 }
4890
4891 static void SetMemberClass(DataMember member, Class _class)
4892 {
4893    DataMember dataMember;
4894    member._class = _class;
4895    for(dataMember = member.members.first; dataMember; dataMember = dataMember.next)
4896       SetMemberClass(dataMember, _class);      
4897 }
4898
4899 public dllexport bool eMember_AddMember(DataMember addTo, DataMember dataMember)
4900 {
4901    if(dataMember.name && addTo.membersAlpha.FindString(dataMember.name)) return false;
4902    addTo.members.Add(dataMember);
4903
4904    if(dataMember.name)
4905       addTo.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
4906
4907    dataMember._class = addTo._class;
4908    // ? SetMemberClass(dataMember, addTo._class);
4909
4910    //dataMember.id = addTo.memberID++;
4911    dataMember.id = addTo.memberID;
4912    if(dataMember.type == unionMember)
4913       addTo.memberID += 1;
4914    else
4915       addTo.memberID += dataMember.memberID;
4916
4917    addTo.structAlignment = Max(addTo.structAlignment, dataMember.structAlignment);
4918    dataMember.offset = (addTo.type == unionMember) ? 0 : addTo.memberOffset;
4919    if(addTo.type == unionMember)
4920    {
4921       if(dataMember.memberOffset > addTo.memberOffset)
4922          addTo.memberOffset = dataMember.memberOffset;
4923    }
4924    else
4925       addTo.memberOffset += dataMember.memberOffset;
4926    return true;
4927 }
4928
4929 public dllexport bool eClass_AddMember(Class _class, DataMember dataMember)
4930 {
4931    if(!_class || _class.comRedefinition || (dataMember.name && _class.members.FindString(dataMember.name)))
4932       return false;
4933    _class.membersAndProperties.Add(dataMember);
4934
4935    if(dataMember.name)
4936       _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
4937
4938    //dataMember._class = _class;
4939    SetMemberClass(dataMember, _class);
4940
4941    //dataMember.id = _class.memberID++;
4942    dataMember.id = _class.memberID;
4943
4944    _class.structAlignment = Max(_class.structAlignment, dataMember.structAlignment);
4945    if(dataMember.type == unionMember)
4946       _class.memberID += 1;
4947    else
4948       _class.memberID += dataMember.memberID;
4949    dataMember.offset = _class.memberOffset;
4950    _class.memberOffset += dataMember.memberOffset;
4951    return true;
4952 }
4953
4954 public dllexport BitMember eClass_AddBitMember(Class _class, char * name, char * type, int bitSize, int bitPos, AccessMode declMode)
4955 {
4956    if(_class && name && !_class.members.FindString(name)) 
4957    {
4958       uint64 mask = 0;
4959       int c;
4960       BitMember bitMember
4961       {
4962          name = CopyString(name);
4963          _class = _class;
4964          dataTypeString = CopyString(type);
4965          id = _class.memberID++;
4966          memberAccess = declMode;
4967       };
4968       _class.membersAndProperties.Add(bitMember);
4969       if(bitSize)
4970       {
4971          bitMember.pos = (bitPos == -1) ? _class.memberOffset : bitPos;
4972          bitMember.size = bitSize;
4973          _class.memberOffset = bitMember.pos + bitMember.size;
4974          for(c = 0; c<bitSize; c++)
4975          {
4976             if(c)
4977                mask <<= 1;
4978             mask |= 1;
4979          }
4980          bitMember.mask = mask << bitMember.pos;
4981       }
4982
4983      _class.members.Add((BTNode)BTNamedLink { name = bitMember.name, data = bitMember });
4984       return bitMember;
4985    }
4986    return null;
4987 }
4988
4989 static Module Module_Load(Module fromModule, char * name, AccessMode importAccess, bool ensureCOM)
4990 {
4991    bool (stdcall * Load)(Module module) = null;
4992    bool (stdcall * Unload)(Module module) = null;
4993    Module module;
4994
4995    for(module = fromModule.application.allModules.first; module; module = module.next)
4996    {
4997       if(!strcmp(module.name, name))
4998          break;
4999    }
5000    if(ensureCOM && (!strcmp(name, "ecereCOM") || !strcmp(name, "ecere")))
5001    {
5002       for(module = fromModule.application.allModules.first; module; module = module.next)
5003       {
5004          if(!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM"))
5005             break;
5006       }
5007    }
5008    if(!module)
5009    {
5010       void * library = null;
5011
5012       if(ensureCOM && !strcmp(name, "ecereCOM"))
5013       {
5014          Load = COM_LOAD_FUNCTION;
5015          Unload = COM_UNLOAD_FUNCTION;
5016       }
5017       else
5018       {
5019          library = Instance_Module_Load(name, &Load, &Unload);
5020       }
5021       if(Load)
5022       {
5023          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5024          module.application = fromModule.application;
5025          module.library = library;
5026          module.name = CopyString(name);
5027          module.Unload = Unload;
5028          module.origImportType = normalImport;
5029          if(!Load(module))
5030          {
5031             eInstance_Delete((Instance)module);
5032             module = null;
5033          }
5034       }
5035       fromModule.application.allModules.Add(module);
5036    }
5037    if(ensureCOM && !strcmp(name, "ecere") && module)
5038    {
5039       name = !strcmp(module.name, "ecereCOM") ? "ecere" : "ecereCOM";
5040       if((!Load && !strcmp(module.name, "ecereCOM")) || 
5041          (Load && (!__thisModule || !__thisModule.name || !strcmp(__thisModule.name, "ecereCOM")) && Load != COM_LOAD_FUNCTION))
5042       {
5043          Module module;
5044          for(module = fromModule.application.allModules.first; module; module = module.next)
5045          {
5046             if(!strcmp(module.name, name))
5047                break;
5048          }
5049          if(!module)
5050          {
5051             Load = COM_LOAD_FUNCTION;
5052             Unload = COM_UNLOAD_FUNCTION;
5053
5054             module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5055             module.application = fromModule.application;
5056             module.library = null;
5057             module.name = CopyString(name);
5058             module.Unload = Unload;
5059             if(!Load(module))
5060             {
5061                eInstance_Delete((Instance)module);
5062                module = null;
5063             }
5064             fromModule.application.allModules.Add(module);
5065          }
5066          if(module)
5067          {
5068             if(fromModule)
5069             {
5070                fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5071             }
5072             incref module;
5073          }
5074       }
5075    }
5076    if(module)
5077    {
5078       if(fromModule)
5079       {
5080          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5081       }
5082       incref module;
5083    }
5084    return module;
5085 }
5086
5087 public dllexport Module eModule_Load(Module fromModule, char * name, AccessMode importAccess)
5088 {
5089    return Module_Load(fromModule, name, importAccess, true);
5090 }
5091
5092 public dllexport Module eModule_LoadStrict(Module fromModule, char * name, AccessMode importAccess)
5093 {
5094    return Module_Load(fromModule, name, importAccess, false);
5095 }
5096
5097 public dllexport Module eModule_LoadStatic(Module fromModule, char * name, AccessMode importAccess, bool (* Load)(Module module), bool (* Unload)(Module module))
5098 {
5099    Module module;
5100    for(module = fromModule.application.allModules.first; module; module = module.next)
5101    {
5102       if(!strcmp(module.name, name))
5103          break;
5104    }
5105    if(!module)
5106    {
5107       if(Load)
5108       {
5109          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5110          module.application = fromModule.application;
5111          module.name = CopyString(name);
5112          module.origImportType = staticImport;
5113          module.Unload = (void *)Unload;
5114          if(!Load(module))
5115          {
5116             eInstance_Delete((Instance)module);
5117             module = null;
5118          }
5119       }
5120       fromModule.application.allModules.Add(module);
5121    }
5122    if(module)
5123    {
5124       if(fromModule)
5125       {
5126          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5127       }
5128       incref module;
5129    }
5130    return module;
5131 }
5132
5133 public dllexport void eModule_Unload(Module fromModule, Module module)
5134 {
5135    OldLink m;
5136    for(m = fromModule.modules.first; m; m = m.next)
5137    {
5138       if(m.data == module)
5139          break;
5140    }
5141    if(m)
5142    {
5143       fromModule.modules.Delete(m);
5144       delete module;
5145    }
5146 }
5147
5148 public dllexport void eEnum_AddFixedValue(Class _class, char * string, int value)
5149 {
5150    if(_class && _class.type == enumClass)
5151    {
5152       EnumClassData data = (EnumClassData)_class.data;
5153       NamedLink item;
5154       
5155       for(item = data.values.first; item; item = item.next)
5156          if(!strcmp(item.name, string)) 
5157             break;
5158       if(!item)
5159       {
5160          data.values.Add(NamedLink { data = (void *)value, name = CopyString(string) });
5161          if(value > data.largest)
5162             data.largest = value;
5163       }
5164    }
5165 }
5166
5167 public dllexport int eEnum_AddValue(Class _class, char * string)
5168 {
5169    if(_class && _class.type == enumClass)
5170    {
5171       EnumClassData data = (EnumClassData)_class.data;
5172       int value = ((int) data.largest) + 1;
5173       NamedLink item;
5174       for(item = data.values.first; item; item = item.next)
5175          if(!strcmp(item.name, string)) 
5176             break;
5177       if(!item)
5178       {
5179          data.values.Add(NamedLink { data = (void *)value, name = CopyString(string) });
5180          if(value > data.largest)
5181             data.largest = value;
5182          return value;
5183       }
5184    }
5185    return -1;
5186 }
5187
5188 static void NameSpace_Free(NameSpace parentNameSpace)
5189 {
5190    NameSpace * nameSpace;
5191    delete parentNameSpace.name;
5192
5193    while((nameSpace = (NameSpace *)parentNameSpace.nameSpaces.first))
5194    {
5195       NameSpace_Free(nameSpace);
5196       parentNameSpace.nameSpaces.Delete((BTNode)nameSpace);
5197    }
5198 }
5199
5200 static void Application_Destructor(Application app)
5201 {
5202    if(app.parsedCommand)
5203    {
5204       delete app.argv;
5205       delete app.parsedCommand;
5206    }
5207 }
5208
5209 static bool Module_Constructor(Module module)
5210 {
5211    module.privateNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5212    module.privateNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5213    module.privateNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5214    module.privateNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5215
5216    module.publicNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5217    module.publicNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5218    module.publicNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5219    module.publicNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5220    return true;
5221 }
5222
5223 static void Module_Destructor(Module module)
5224 {
5225    Class _class;
5226    DefinedExpression def;
5227    GlobalFunction function;
5228    Module m;
5229    SubModule handle;
5230
5231    // printf("Destructing module %s\n", module.name);
5232
5233    // Take out references from all modules
5234    for(m = module.application.allModules.first; m; m = m.next)
5235    {
5236       SubModule next;
5237       for(handle = m.modules.first; handle; handle = next)
5238       {
5239          next = handle.next;
5240          if(handle.module == module)
5241             m.modules.Delete(handle);
5242       }
5243    }
5244
5245    if(module.Unload)
5246    {
5247       if(module.origImportType == staticImport)
5248       {
5249          bool (* Unload)(Module module) = (void *)module.Unload;
5250          Unload(module);
5251       }
5252       else
5253       {
5254          bool (stdcall * Unload)(Module module) = (void *)module.Unload;
5255          Unload(module);
5256       }
5257    }
5258
5259    // Unload dependencies
5260    {
5261       Module ourWorld = class(Class).module;
5262       void * ourHandle = null;
5263       while((handle = module.modules.last))  // STARTING WITH LAST SO THAT ecereCOM IS UNLOADED LAST...
5264       {
5265          Module depModule = handle.module;
5266          if(depModule == ourWorld) 
5267          {
5268             module.modules.Remove(handle);
5269             ourHandle = handle;
5270          }
5271          else
5272          {
5273             module.modules.Delete(handle);
5274             delete depModule;
5275          }         
5276       }
5277       if(ourHandle)
5278       {
5279          delete ourHandle;
5280          delete ourWorld;
5281       }
5282    }
5283
5284    // Unload classes
5285    for(;(_class = module.classes.first);)
5286    {
5287       if(_class.nameSpace)
5288       {
5289          BTNamedLink classLink = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
5290          OldLink t;
5291          for(t = _class.templatized.first; t; t = t.next)
5292          {
5293             Class template = t.data;
5294             BTNamedLink link;
5295             link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
5296
5297             template.nameSpace->classes.Delete((BTNode)link);
5298             template.nameSpace = null;
5299          }
5300          _class.nameSpace->classes.Delete((BTNode)classLink);
5301          _class.nameSpace = null;
5302       }
5303       _class.module = null;
5304       module.classes.Remove(_class);
5305       if(!_class.count || _class.type != normalClass)
5306          eClass_Unregister(_class);
5307       else
5308       {
5309 #ifdef MEMINFO
5310          // printf("Delayed destruction of class %s\n", _class.name);
5311 #endif
5312       }
5313    }
5314
5315    // Unload defines
5316    for(;(def = module.defines.first);)
5317    {
5318       if(def.nameSpace)
5319       {
5320          BTNamedLink defLink;
5321          for(defLink = (BTNamedLink)def.nameSpace->defines.first; defLink; defLink = (BTNamedLink)((BTNode)defLink).next)
5322             if(defLink.data == def)
5323             {
5324                def.nameSpace->defines.Delete((BTNode)defLink);
5325                break;
5326             }
5327       }
5328       delete def.name;
5329       delete def.value;
5330       module.defines.Delete(def);
5331    }
5332
5333    // Unload functions
5334    for(;(function = module.functions.first);)
5335    {
5336       if(function.nameSpace)
5337       {
5338          BTNamedLink functionLink;
5339          for(functionLink = (BTNamedLink)function.nameSpace->functions.first; functionLink; functionLink = (BTNamedLink)((BTNode)functionLink).next)
5340             if(functionLink.data == function)
5341             {
5342                function.nameSpace->functions.Delete((BTNode)functionLink);
5343                break;
5344             }
5345       }
5346       delete function.name;
5347       delete function.dataTypeString;
5348       module.functions.Delete(function);
5349    }
5350
5351    delete module.name;
5352
5353    NameSpace_Free(module.privateNameSpace);
5354    NameSpace_Free(module.publicNameSpace);
5355
5356    if(module != module.application)
5357       module.application.allModules.Remove(module);
5358    else
5359       NameSpace_Free(module.application.systemNameSpace);
5360
5361 #ifndef MEMINFO
5362    Instance_Module_Free(module.library);
5363 #endif
5364 }
5365
5366 static int GetEnumSize(Class _class)
5367 {
5368    EnumClassData data = (EnumClassData)_class.data;
5369    return data.largest+1;
5370 }
5371
5372 #if defined(__GNUC__)
5373 #define strcmpi strcasecmp
5374 #define strnicmp strncasecmp
5375 #endif
5376
5377 #if defined(ECERE_BOOTSTRAP) || (defined(__GNUC__) && !defined(__DJGPP__) && !defined(__WIN32__))
5378 #undef strlwr
5379 #undef strupr
5380 default dllexport char * strlwr(char *string)
5381 {
5382    int c;
5383    for(c=0; string[c]; c++)
5384       if(string[c]>='A' && string[c]<='Z')
5385          string[c]+='a'-'A';
5386    return string;
5387 }
5388 default dllexport char * strupr(char *string)
5389 {
5390    int c;
5391    for(c=0; string[c]; c++)
5392       if(string[c]>='a' && string[c]<='z')
5393          string[c]-='a'-'A';
5394    return string;
5395 }
5396 #endif
5397
5398 public dllexport DefinedExpression eSystem_RegisterDefine(char * name, char * value, Module module, AccessMode declMode)
5399 {
5400    NameSpace * nameSpace = null;
5401    
5402    int start = 0, c;
5403
5404    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5405    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5406
5407    if(declMode != staticAccess)
5408    {
5409       for(c = 0; name[c]; c++)
5410       {
5411          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5412          {
5413             NameSpace * newSpace;
5414
5415             char * spaceName = _malloc(c - start + 1);
5416             strncpy(spaceName, name + start, c - start);
5417             spaceName[c-start] = '\0';
5418
5419             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5420             if(!newSpace)
5421             {
5422                newSpace = new0 NameSpace[1];
5423                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5424                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5425                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5426                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5427                newSpace->name = spaceName;
5428                newSpace->parent = nameSpace;
5429                nameSpace->nameSpaces.Add((BTNode)newSpace);
5430             }
5431             else
5432                delete spaceName;
5433             nameSpace = newSpace;
5434             if(name[c] == ':') c++;
5435             start = c+1;         
5436          }
5437       }
5438    }
5439    else
5440       c = strlen(name);
5441
5442    if(c - start && !nameSpace->defines.FindString(name + start))
5443    {
5444       DefinedExpression def
5445       {
5446          name = CopyString(name);
5447          nameSpace = nameSpace;
5448          value = CopyString(value);
5449       };
5450       nameSpace->defines.Add((BTNode)BTNamedLink { name = def.name + start, data = def });
5451       // Reference the definition in the module
5452       module.defines.Add(def);
5453       return def;
5454    }
5455    return null;
5456 }
5457
5458 public dllexport GlobalFunction eSystem_RegisterFunction(char * name, char * type, void * func, Module module, AccessMode declMode)
5459 {
5460    NameSpace * nameSpace = null;
5461    int start = 0, c;
5462
5463    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5464    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5465
5466    if(declMode != staticAccess)
5467    {
5468       for(c = 0; name[c]; c++)
5469       {
5470          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5471          {
5472             NameSpace * newSpace;
5473
5474             char * spaceName = _malloc(c - start + 1);
5475             strncpy(spaceName, name + start, c - start);
5476             spaceName[c-start] = '\0';
5477
5478             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5479             if(!newSpace)
5480             {
5481                newSpace = new0 NameSpace[1];
5482                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5483                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5484                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5485                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5486                newSpace->name = spaceName;
5487                newSpace->parent = nameSpace;
5488                nameSpace->nameSpaces.Add((BTNode)newSpace);
5489             }
5490             else
5491                delete spaceName;
5492             nameSpace = newSpace;
5493             if(name[c] == ':') c++;
5494             start = c+1;         
5495          }
5496       }
5497    }
5498    else
5499       c = strlen(name);
5500
5501    if(c - start && !nameSpace->functions.FindString(name + start))
5502    {
5503       GlobalFunction function
5504       {
5505          name = CopyString(name);
5506          nameSpace = nameSpace;
5507          dataTypeString = CopyString(type);
5508          function = func;
5509          module = module;
5510       };
5511       nameSpace->functions.Add((BTNode)BTNamedLink { name = function.name + start, data = function });
5512       // Reference the definition in the module
5513       module.functions.Add(function);
5514       return function;
5515    }
5516    return null;
5517 }
5518
5519 public dllexport DefinedExpression eSystem_FindDefine(Module module, char * name)
5520 {
5521    if(name && module)
5522    {
5523       BTNamedLink link;
5524       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->defines);
5525       if(link) return link.data;
5526
5527       link = SearchModule(module, name, &((NameSpace *)0)->defines, true);
5528       if(link) return link.data;
5529    }
5530    return null;
5531 }
5532
5533 public dllexport GlobalFunction eSystem_FindFunction(Module module, char * name)
5534 {
5535    if(name && module)
5536    {
5537       BTNamedLink link;
5538       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->functions);
5539       if(link) return link.data;
5540
5541       link = SearchModule(module, name, &((NameSpace *)0)->functions, true);
5542       if(link) return link.data;
5543    }
5544    return null;
5545 }
5546
5547 public dllexport void * eSystem_Renew(void * memory, unsigned int size)
5548 {
5549    return _realloc(memory, size);
5550 }
5551
5552 public dllexport void * eSystem_Renew0(void * memory, unsigned int size)
5553 {
5554    return _crealloc(memory, size);
5555 }
5556
5557 public dllexport void * eSystem_New(unsigned int size)
5558 {
5559 /*#ifdef _DEBUG
5560    void * pointer = _malloc(size);
5561    memset(pointer, 0xec, size);
5562    return pointer;
5563 #else*/
5564    return _malloc(size);
5565 //#endif
5566 }
5567
5568 public dllexport void * eSystem_New0(unsigned int size)
5569 {
5570    return _calloc(1,size);
5571 }
5572
5573 public dllexport void eSystem_Delete(void * memory)
5574 {
5575    if(memory)
5576       _free(memory);
5577 }
5578
5579 // Properties
5580 public dllexport void eInstance_FireSelfWatchers(Instance instance, Property _property)
5581 {
5582    if(instance && _property && _property.selfWatchable)
5583    {
5584       Class _class;
5585       for(_class = instance._class; _class; _class = _class.base)
5586       {
5587          SelfWatcher selfWatcher, next;
5588          for(selfWatcher = _class.selfWatchers.first; selfWatcher; selfWatcher = next)
5589          {
5590             next = selfWatcher.next;
5591             if(selfWatcher._property == _property)
5592                selfWatcher.callback(instance);
5593          }
5594       }
5595    }
5596 }
5597
5598 public dllexport void eInstance_FireWatchers(Instance instance, Property _property)
5599 {
5600    if(instance && _property && _property.isWatchable)
5601    {
5602       OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5603       Watcher watcher, next;
5604
5605       for(watcher = watchers->first; watcher; watcher = next)
5606       {
5607          next = watcher.next;
5608          watcher.callback(watcher.object, instance);
5609       }
5610    }
5611 }
5612
5613 public dllexport void eProperty_Watchable(Property _property)
5614 {
5615    if(!_property.isWatchable)
5616    {
5617       Class _class = _property._class;
5618       if(!_class.computeSize)
5619       {
5620          _property.watcherOffset = _class.structSize;
5621          _class.structSize += sizeof(OldList);
5622
5623          // highly inefficient
5624          FixDerivativesBase(_class, _class);
5625       }
5626       _property.isWatchable = true;
5627    }
5628 }
5629
5630 public dllexport void eClass_DestructionWatchable(Class _class)
5631 {
5632    if(!_class.destructionWatchOffset)
5633    {
5634       _class.destructionWatchOffset = _class.structSize;
5635       _class.structSize += sizeof(OldList);
5636       // highly inefficient
5637       FixDerivativesBase(_class, _class);
5638    }
5639 }
5640
5641 public dllexport void eProperty_SelfWatch(Class _class, char * name, void (*callback)(void *))
5642 {
5643    if(_class)
5644    {
5645       Property _property = eClass_FindProperty(_class, name, _class.module);
5646       
5647       if(!_property)
5648          _property = eClass_AddProperty(_class, name, null, null, null, baseSystemAccess /*privateAccess*/);
5649       _class.selfWatchers.Add(SelfWatcher { _property = _property, callback = callback });
5650       _property.selfWatchable = true;
5651    }
5652 }
5653
5654 public dllexport void eInstance_Watch(void * instance, Property _property, void * object, void (*callback)(void *, void *))
5655 {
5656    if(_property.isWatchable)
5657    {
5658       OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5659       watchers->Add(Watcher { callback = callback, object = object });
5660    }
5661 }
5662
5663 public dllexport void eInstance_WatchDestruction(Instance instance, Instance object, void (*callback)(Instance, Instance))
5664 {
5665    OldList * watchers = (OldList *)((byte *)instance + instance._class.destructionWatchOffset);
5666    watchers->Add(Watcher { callback = callback, object = object });
5667 }
5668
5669 public dllexport void eInstance_StopWatching(Instance instance, Property _property, Instance object)
5670 {
5671    if(instance && (!_property || _property.isWatchable))
5672    {
5673       if(_property)
5674       {
5675          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5676          Watcher watcher;
5677          for(watcher = watchers->first; watcher; watcher = watcher.next)
5678             if(watcher.object == object)
5679             {
5680                watchers->Delete(watcher);
5681                break;
5682             }
5683       }
5684       else
5685       {
5686          // Stop watching all properties as well as destruction
5687          Class _class, base;
5688          for(_class = instance._class; _class; _class = base)
5689          {
5690             if(_class.destructionWatchOffset)
5691             {
5692                OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
5693                Watcher watcher;
5694
5695                for(watcher = watchers->first; watcher; watcher = watcher.next)
5696                {
5697                   watchers->Delete(watcher);
5698                   break;
5699                }
5700             }
5701             for(_property = (Property)_class.membersAndProperties.first; _property; _property = _property.next)
5702             {
5703                if(_property.isProperty && _property.isWatchable)
5704                {
5705                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5706                   Watcher watcher;
5707                   for(watcher = watchers->first; watcher; watcher = watcher.next)
5708                      if(watcher.object == object)
5709                      {
5710                         watchers->Delete(watcher);
5711                         break;
5712                      }
5713                }
5714             }
5715             base = _class.base;
5716             if(base && base.type == systemClass) base = null;
5717          }
5718       }
5719    }
5720 }
5721
5722 public dllexport subclass(ClassDesignerBase) eClass_GetDesigner(Class _class)
5723 {
5724    for(;_class;_class = _class.base)
5725    {
5726       if(_class.designerClass)
5727          return (subclass(ClassDesignerBase))eSystem_FindClass(_class.module, _class.designerClass);
5728    }
5729    return null;
5730 }
5731
5732
5733 public dllexport subclass(ClassDesignerBase) eInstance_GetDesigner(Instance instance)
5734 {
5735    if(instance)
5736       return eClass_GetDesigner(instance._class);
5737    return null;
5738 }
5739
5740 public bool LocateModule(char * name, char * fileName)
5741 {
5742    return Instance_LocateModule(name, fileName);
5743 }
5744
5745 static void LoadCOM(Module module)
5746 {
5747    Class applicationClass;
5748    Class enumClass, structClass, boolClass;
5749    Class moduleClass;
5750
5751    // Create Base Class
5752    Class baseClass = eSystem_RegisterClass(normalClass, "class", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5753    baseClass.type = systemClass;
5754    baseClass.memberOffset = 0;
5755    baseClass.offset = 0;
5756    baseClass.structSize = 0;
5757    baseClass.typeSize = 0;
5758
5759    {
5760       Class instanceClass = eSystem_RegisterClass(normalClass, "ecere::com::Instance", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5761       // Instance should really be a Normal class, but inheritance checks for systemClass to see if something has a non system ancestor
5762       instanceClass.type = systemClass;
5763       instanceClass.fixed = true;
5764       instanceClass.memberOffset = 0;
5765       instanceClass.offset = 0;
5766
5767       instanceClass.memberID = -3;
5768       instanceClass.startMemberID = -3;
5769
5770       // eClass_AddDataMember(instanceClass, "_vTbl", "void **", sizeof(int (**)()), 4, publicAccess);
5771       eClass_AddDataMember(instanceClass, "_vTbl", "int (**)()", sizeof(int (**)()), 4, publicAccess);
5772       eClass_AddDataMember(instanceClass, "_class", "ecere::com::Class", sizeof(Class), 4, publicAccess);
5773       eClass_AddDataMember(instanceClass, "_refCount", "int", sizeof(int (**)()), 4, publicAccess);
5774    }
5775
5776    InitializeDataTypes1(module);
5777
5778    // Create Enum class
5779    enumClass = eSystem_RegisterClass(normalClass, "enum", null, 0, sizeof(class EnumClassData), null, null, module, baseSystemAccess, publicAccess);
5780    eClass_AddClassProperty(enumClass, "enumSize", "int", null, GetEnumSize).constant = true;
5781    enumClass.type = systemClass;
5782    
5783    delete enumClass.dataTypeString;
5784    enumClass.dataTypeString = CopyString(/*"unsigned int"*/"int");
5785
5786    // Create Struct (simple) class
5787    //structClass = eSystem_RegisterClass(structClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5788    structClass = eSystem_RegisterClass(normalClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5789    structClass.type = systemClass;
5790    structClass.memberOffset = 0;
5791    structClass.offset = 0;
5792    structClass.structSize = 0;
5793    structClass.typeSize = 0;
5794
5795    //eClass_AddMethod(enumClass, "AddValue", "int()", eEnum_AddValue);
5796    //eClass_AddMethod(enumClass, "AddFixedValue", "void()", eEnum_AddFixedValue);
5797
5798    InitializeDataTypes(module);
5799
5800    // Create bool class
5801    boolClass = eSystem_RegisterClass(ClassType::enumClass, "bool", "uint", 0, 0, null, null, module, baseSystemAccess, publicAccess);
5802    eEnum_AddFixedValue(boolClass, "true",  bool::true);
5803    eEnum_AddFixedValue(boolClass, "false", bool::false);
5804
5805    // Create Module class
5806    moduleClass = eSystem_RegisterClass(normalClass, "ecere::com::Module", null, sizeof(struct Module), 0, (void *)Module_Constructor, (void *)Module_Destructor, module, baseSystemAccess, publicAccess);
5807    eClass_AddVirtualMethod(moduleClass, "OnLoad", "bool()", null, publicAccess);
5808    eClass_AddVirtualMethod(moduleClass, "OnUnload", "void()", null, publicAccess);
5809    eClass_AddMethod(moduleClass, "Load", "Module(char * name, AccessMode importAccess)", eModule_Load, publicAccess);
5810    eClass_AddMethod(moduleClass, "Unload", "void(Module module)", eModule_Unload, publicAccess);
5811    eClass_AddDataMember(moduleClass, "application", "Application", sizeof(Application), 4, publicAccess);
5812    eClass_AddDataMember(moduleClass, "classes", "OldList", sizeof(OldList), 4, publicAccess);
5813    eClass_AddDataMember(moduleClass, "defines", "OldList", sizeof(OldList), 4, publicAccess);
5814    eClass_AddDataMember(moduleClass, "functions", "OldList", sizeof(OldList), 4, publicAccess);
5815    eClass_AddDataMember(moduleClass, "modules", "OldList", sizeof(OldList), 4, publicAccess);
5816    eClass_AddDataMember(moduleClass, "prev", "Module", sizeof(Module), 4, publicAccess);
5817    eClass_AddDataMember(moduleClass, "next", "Module", sizeof(Module), 4, publicAccess);
5818    eClass_AddDataMember(moduleClass, "name", "char *", sizeof(char *), 4, publicAccess);
5819    eClass_AddDataMember(moduleClass, "library", "void *", sizeof(void *), 4, publicAccess);
5820    eClass_AddDataMember(moduleClass, "Unload", "void *", sizeof(void *), 4, publicAccess);
5821    eClass_AddDataMember(moduleClass, "importType", "ImportType", sizeof(ImportType), 4, publicAccess);
5822    eClass_AddDataMember(moduleClass, "origImportType", "ImportType", sizeof(ImportType), 4, publicAccess);
5823    eClass_AddDataMember(moduleClass, "privateNameSpace", "NameSpace", sizeof(NameSpace), 4, publicAccess);
5824    eClass_AddDataMember(moduleClass, "publicNameSpace", "NameSpace", sizeof(NameSpace), 4, publicAccess);
5825    moduleClass.fixed = true;
5826    moduleClass.count++;
5827    
5828    // Create Application class
5829    applicationClass = eSystem_RegisterClass(normalClass, "ecere::com::Application", "Module", sizeof(struct Application), 0, null, (void *)Application_Destructor, module, baseSystemAccess, publicAccess);
5830    eClass_AddVirtualMethod(applicationClass, "Main", "void()", null, publicAccess);
5831    eClass_AddDataMember(applicationClass, "argc", "int", sizeof(int), 4, publicAccess);
5832    eClass_AddDataMember(applicationClass, "argv", "char **", sizeof(char **), 4, publicAccess);
5833    eClass_AddDataMember(applicationClass, "exitCode", "int", sizeof(int), 4, publicAccess);
5834    eClass_AddDataMember(applicationClass, "isGUIApp", "bool", sizeof(bool), 4, publicAccess);
5835    eClass_AddDataMember(applicationClass, "allModules", "OldList", sizeof(OldList), 4, publicAccess);
5836    eClass_AddDataMember(applicationClass, "parsedCommand", "char *", sizeof(char *), 4, publicAccess);
5837    eClass_AddDataMember(applicationClass, "systemNameSpace", "NameSpace", sizeof(NameSpace), 4, publicAccess);
5838    applicationClass.fixed = true;
5839    applicationClass.count++;
5840
5841    //AttachConsole(-1);
5842    //AllocConsole();
5843
5844    // --- Math ---
5845    eSystem_RegisterFunction("sin", "double sin(Angle number)", sin, module, baseSystemAccess);
5846    eSystem_RegisterFunction("sinh", "double sinh(Angle number)", sinh, module, baseSystemAccess);
5847    eSystem_RegisterFunction("cosh", "double cosh(Angle number)", cosh, module, baseSystemAccess);
5848    eSystem_RegisterFunction("tanh", "double tanh(Angle number)", tanh, module, baseSystemAccess);
5849    eSystem_RegisterFunction("sqrt", "double sqrt(double number)", sqrt, module, baseSystemAccess);
5850    eSystem_RegisterFunction("cos", "double cos(Angle number)", cos, module, baseSystemAccess);
5851    eSystem_RegisterFunction("tan", "double tan(Angle number)", tan, module, baseSystemAccess);
5852    eSystem_RegisterFunction("atan2", "Angle atan2(double y, double x)", atan2, module, baseSystemAccess);
5853    eSystem_RegisterFunction("asin", "Angle asin(double number)", asin, module, baseSystemAccess);
5854    eSystem_RegisterFunction("acos", "Angle acos(double number)", acos, module, baseSystemAccess);
5855    eSystem_RegisterFunction("atan", "Angle atan(double number)", atan, module, baseSystemAccess);
5856    eSystem_RegisterFunction("pow", "double pow(double number, double number2)", pow, module, baseSystemAccess);
5857    eSystem_RegisterFunction("fmod", "double fmod(double x, double y)", fmod, module, baseSystemAccess);
5858    eSystem_RegisterFunction("fabs", "double fabs(double number)", fabs, module, baseSystemAccess);
5859    eSystem_RegisterFunction("log", "double log(double number)", log, module, baseSystemAccess);
5860    eSystem_RegisterFunction("log10", "double log10(double number)", log10, module, baseSystemAccess);
5861    eSystem_RegisterFunction("ceil", "double ceil(double number)", ceil, module, baseSystemAccess);
5862    eSystem_RegisterFunction("floor", "double floor(double number)", floor, module, baseSystemAccess);
5863    eSystem_RegisterFunction("exp", "double exp(double number)", exp, module, baseSystemAccess);
5864
5865    // --- Stdlib ---
5866    eSystem_RegisterFunction("qsort", "void qsort(void *, uint, uint, int (*)(void *, void *))", qsort, module, baseSystemAccess);
5867    eSystem_RegisterFunction("strtod", "double strtod(char*, char**)", strtod, module, baseSystemAccess);
5868    eSystem_RegisterFunction("strtol", "int strtol(char*, char**, int base)", strtol, module, baseSystemAccess);
5869    eSystem_RegisterFunction("system", "int system(const char*)", system, module, baseSystemAccess);
5870    eSystem_RegisterFunction("atoi", "int atoi(const char*)", atoi, module, baseSystemAccess);
5871    eSystem_RegisterFunction("atof", "float atof(const char*)", atof, module, baseSystemAccess);
5872    eSystem_RegisterFunction("tolower", "int tolower(int)", tolower, module, baseSystemAccess);
5873    eSystem_RegisterFunction("toupper", "int toupper(int)", toupper, module, baseSystemAccess);
5874    eSystem_RegisterFunction("isdigit", "bool isdigit(int)", isdigit, module, baseSystemAccess);
5875    eSystem_RegisterFunction("memset", "void memset(void * area, byte value, uint count)", memset, module, baseSystemAccess);
5876    eSystem_RegisterFunction("getenv", "char * getenv(const char * name)", getenv, module, baseSystemAccess);
5877    eSystem_RegisterFunction("rename", "int rename(const char *oldpath, const char *newpath)", rename, module, baseSystemAccess);
5878
5879    // --- String --- (These might move to the string class)
5880    eSystem_RegisterFunction("strlen", "int strlen(const char *)", strlen, module, baseSystemAccess);
5881    eSystem_RegisterFunction("strcat", "char * strcat(char *, const char *)", strcat, module, baseSystemAccess);
5882    eSystem_RegisterFunction("strncat", "char * strncat(char *, const char *, int n)", strncat, module, baseSystemAccess);
5883    eSystem_RegisterFunction("strchr", "char * strchr(char *, int)", strchr, module, baseSystemAccess);
5884    eSystem_RegisterFunction("strstr", "char * strstr(char *, const char *)", strstr, module, baseSystemAccess);
5885
5886    eSystem_RegisterDefine("fstrcmp", "(GetRuntimePlatform() == win32) ? strcmpi : strcmp", module, baseSystemAccess);
5887
5888 //#if defined(__GNUC__)
5889    eSystem_RegisterDefine("strcmpi", "strcasecmp", module, baseSystemAccess);
5890    eSystem_RegisterDefine("strnicmp", "strncasecmp", module, baseSystemAccess);
5891    eSystem_RegisterFunction("strcasecmp", "int strcasecmp(const char *, const char *)", strcmpi, module, baseSystemAccess);
5892    eSystem_RegisterFunction("strncasecmp", "int strncasecmp(const char *, const char *, int n)", strnicmp, module, baseSystemAccess);
5893 /*
5894 #else
5895    eSystem_RegisterDefine("strcasecmp", "strcmpi", module, baseSystemAccess);
5896    eSystem_RegisterDefine("strncasecmp", "strnicmp", module, baseSystemAccess);
5897    eSystem_RegisterFunction("strcmpi", "int strcmpi(const char *, const char *)", strcmpi, module, baseSystemAccess);
5898    eSystem_RegisterFunction("strnicmp", "int strnicmp(const char *, const char *, int n)", strnicmp, module, baseSystemAccess);
5899 #endif
5900 */
5901
5902    eSystem_RegisterFunction("strcmp", "int strcmp(const char *, const char *)", strcmp, module, baseSystemAccess);
5903    eSystem_RegisterFunction("strncmp", "int strncmp(const char *, const char *, int n)", strncmp, module, baseSystemAccess);
5904    eSystem_RegisterFunction("strlwr", "char * strlwr(char *)", strlwr, module, baseSystemAccess);
5905    eSystem_RegisterFunction("strupr", "char * strupr(char *)", strupr, module, baseSystemAccess);
5906    eSystem_RegisterFunction("strcpy", "char * strcpy(char *, const char *)", strcpy, module, baseSystemAccess);
5907    eSystem_RegisterFunction("strncpy", "char * strncpy(char *, const char *, int n)", strncpy, module, baseSystemAccess);
5908    eSystem_RegisterFunction("memcpy", "void * memcpy(void *, const void *, uint size)", memcpy, module, baseSystemAccess);
5909    eSystem_RegisterFunction("memmove", "void * memmove(void *, const void *, uint size)", memmove, module, baseSystemAccess);
5910
5911    // --- Stdio ---
5912    eSystem_RegisterFunction("sprintf", "int sprintf(char *, char *, ...)", sprintf, module, baseSystemAccess);
5913    eSystem_RegisterFunction("printf", "int printf(char *, ...)", printf, module, baseSystemAccess);
5914    eSystem_RegisterFunction("vsprintf", "int vsprintf(char*, const char*, __builtin_va_list)", vsprintf, module, baseSystemAccess);
5915    eSystem_RegisterFunction("puts", "int puts(char *)", puts, module, baseSystemAccess);
5916    eSystem_RegisterFunction("fputs", "int fputs(char *, void * stream)", fputs, module, baseSystemAccess);
5917
5918    // --- Ctype ---
5919    eSystem_RegisterFunction("isalnum", "int isalnum(int c)", isalnum, module, baseSystemAccess);
5920    eSystem_RegisterFunction("isspace", "int isspace(int c)", isspace, module, baseSystemAccess);
5921    eSystem_RegisterFunction("isalpha", "int isalpha(int c)", isalpha, module, baseSystemAccess);
5922    eSystem_RegisterFunction("islower", "int islower(int c)", islower, module, baseSystemAccess);
5923    eSystem_RegisterFunction("isupper", "int isupper(int c)", isupper, module, baseSystemAccess);
5924    eSystem_RegisterFunction("isprint", "int isprint(int c)", isprint, module, baseSystemAccess);
5925    eSystem_RegisterFunction("strtoul", "unsigned long strtoul(const char * nptr, char ** endptr, int base)", strtoul, module, baseSystemAccess);
5926
5927 }
5928
5929 public dllexport Application __ecere_COM_Initialize(bool guiApp, int argc, char * argv[])
5930 {
5931    Application app;
5932
5933 #ifdef _DEBUG
5934    // printf("Using debug ecere runtime library\n");
5935 #endif
5936    app = _calloc(1, sizeof(class Application));
5937
5938    Module_Constructor(app);
5939    app.systemNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5940    app.systemNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5941    app.systemNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5942    app.systemNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5943
5944    Instance_COM_Initialize(argc, argv, &app.parsedCommand, &app.argc, &app.argv);
5945
5946    app.application = app;
5947    app.allModules.offset = sizeof(class Instance) + (uint)&((struct Module *)0)->prev;
5948    app.isGUIApp = guiApp;
5949
5950    LoadCOM(app);
5951
5952    app._class = eSystem_FindClass(app, "Application");
5953
5954    return app;
5955 }
5956
5957 public dllexport ClassTemplateParameter eClass_AddTemplateParameter(Class _class, char * name, TemplateParameterType type, void * info, ClassTemplateArgument defaultArg)
5958 {
5959    if(_class && name)
5960    {
5961       ClassTemplateParameter param;
5962
5963       for(param = _class.templateParams.first; param; param = param.next)
5964       {
5965          if(!strcmp(param.name, name))
5966             return param;
5967       }
5968       param =
5969       {
5970          name = CopyString(name);
5971          type = type;
5972          (type == identifier) ? info : CopyString(info);
5973       };
5974       if(defaultArg != null) 
5975       {
5976          param.defaultArg = defaultArg;
5977          CopyTemplateArg(param, param.defaultArg);
5978       }
5979       _class.templateParams.Add(param);
5980       return param;
5981    }
5982    return null;
5983 }
5984
5985 public dllexport void eClass_DoneAddingTemplateParameters(Class base)
5986 {
5987    if(base)
5988    {
5989       OldLink derivative;
5990       ClassTemplateParameter param;
5991       {
5992          void * first = base.templateParams.first;
5993          int count = base.templateParams.count;
5994          base.templateParams.first = null;
5995          base.templateParams.count = 0;
5996
5997          FreeTemplateArgs(base);
5998          delete base.templateArgs;
5999          FreeTemplatesDerivatives(base);
6000
6001          base.templateParams.first = first;
6002          base.templateParams.count = count;
6003       }
6004
6005       for(param = base.templateParams.first; param; param = param.next)
6006       {
6007          if(param.type == identifier && param.defaultArg.memberString)
6008          {
6009             Class memberClass = base;
6010             char * colon = strstr(param.defaultArg.memberString, "::");
6011             char * memberName;
6012             if(colon)
6013             {
6014                char className[1024];
6015                Class sClass;
6016
6017                memcpy(className, param.defaultArg.memberString, colon - param.defaultArg.memberString);
6018                className[colon - param.defaultArg.memberString] = '\0';
6019                memberName = colon + 2;
6020
6021                for(sClass = base; sClass; sClass = sClass.base)
6022                {
6023                   ClassTemplateParameter cParam;
6024                   Class nextClass;
6025                   int id = 0;
6026                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) id += nextClass.templateParams.count;
6027                   // Safety! What could cause base.templateArgs to be null?
6028                   if(sClass == base || base.templateArgs)
6029                   {
6030                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
6031                      {
6032                         if(cParam.type == type && !strcmp(cParam.name, className))
6033                            strcpy(className, (sClass == base) ? cParam.defaultArg.dataTypeString : base.templateArgs[id].dataTypeString);
6034                         id++;
6035                      }
6036                   }
6037                }
6038                memberClass = eSystem_FindClass(base.module, className);
6039                if(!memberClass)
6040                   memberClass = eSystem_FindClass(base.module.application, className);
6041             }
6042             else
6043                memberName = param.defaultArg.memberString;
6044
6045             if(memberClass)
6046             {
6047                switch(param.memberType)
6048                {
6049                   case dataMember:
6050                      param.defaultArg.member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
6051                      break;
6052                   case method:
6053                      param.defaultArg.method = eClass_FindMethod(memberClass, memberName, memberClass.module);
6054                      break;
6055                   case prop:
6056                      param.defaultArg.prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
6057                      break;
6058                }
6059             }
6060          }
6061       }      
6062
6063       //ComputeClassParameters(base, null, null);
6064
6065       FixDerivativesBase(base, base);
6066    }
6067 }
6068
6069 static void FreeTemplatesDerivatives(Class base)
6070 {
6071    OldLink derivative, templateLink;
6072    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
6073    {
6074       Class _class = derivative.data;
6075       if(_class.templateArgs)
6076       {
6077          FreeTemplateArgs(_class);
6078          delete _class.templateArgs;
6079       }
6080       FreeTemplatesDerivatives(_class);
6081    }
6082
6083    for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
6084    {
6085       Class _class = templateLink.data;
6086       if(_class.templateArgs)
6087       {
6088          FreeTemplateArgs(_class);
6089          delete _class.templateArgs;
6090       }
6091       FreeTemplatesDerivatives(_class);
6092    }
6093 }
6094
6095 static const char * platformNames[Platform] = { "", "win32", "linux", "apple" }; // how to have this be accessible outside of dll/lib
6096 static const Platform firstPlatform = win32;
6097 static const Platform lastPlatform = apple;
6098
6099 public enum Platform
6100 {
6101    unknown, win32, tux, apple;
6102
6103    property char *
6104    {
6105       get { return OnGetString(null, null, null); }
6106       set
6107       {  
6108          if(value)
6109          {
6110             Platform c;
6111             for(c = firstPlatform; c <= lastPlatform; c++)
6112                if(!strcmpi(value, platformNames[c]))
6113                   return c;
6114          }
6115          return unknown;
6116       }
6117    };
6118
6119    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
6120    {
6121       if(this >= firstPlatform && this <= lastPlatform)
6122       {
6123          if(tempString)
6124             strcpy(tempString, platformNames[this]);
6125          return platformNames[this];
6126       }
6127       if(tempString && tempString[0])
6128          tempString[0] = '\0';
6129       return null;
6130    }
6131    
6132    bool OnGetDataFromString(char * string)
6133    {
6134       this = string;
6135       return (bool)this;
6136    }
6137 };
6138
6139 default extern Platform runtimePlatform;
6140
6141 public Platform GetRuntimePlatform()
6142 {
6143    return runtimePlatform;
6144 }
6145
6146 namespace gui;
6147
6148 class Window;
6149
6150 namespace com;
6151 // CLASS DESIGNER SUPPORT
6152
6153 public class ObjectInfo : struct
6154 {
6155 public:
6156    ObjectInfo prev, next;
6157    Instance instance;
6158    char * name;
6159    Instantiation instCode;
6160    bool deleted;
6161    ObjectInfo oClass;
6162    OldList instances;
6163    ClassDefinition classDefinition;
6164    bool modified;
6165 };
6166
6167 public class DesignerBase : Window
6168 {
6169 public:
6170    virtual bool FindObject(Instance * instance, char * string);
6171    virtual void RenameObject(ObjectInfo object, char * name);
6172    virtual void SelectObjectFromDesigner(ObjectInfo object);
6173    virtual void CodeAddObject(Instance instance, ObjectInfo * object);
6174    virtual void SheetAddObject(ObjectInfo object);
6175    virtual void AddToolBoxClass(Class _class);
6176    virtual void AddDefaultMethod(Instance instance, Instance classInstance);
6177    virtual void DeleteObject(ObjectInfo object);
6178    virtual bool ObjectContainsCode(ObjectInfo object);
6179    virtual void ModifyCode(void);
6180    virtual void UpdateProperties(void);
6181
6182    ClassDesignerBase classDesigner;
6183    char * objectClass;
6184    bool isDragging;
6185
6186    // FIX THIS WITH PUBLIC:
6187    property ClassDesignerBase classDesigner
6188    { 
6189       get { return classDesigner; }
6190       set { classDesigner = value; }
6191    };
6192    property char * objectClass
6193    { 
6194       get { return objectClass; }
6195       set { objectClass = value; }
6196    };
6197    property bool isDragging
6198    { 
6199       get { return isDragging; }
6200       set { isDragging = value; }
6201    };
6202 }
6203  
6204 public class ClassDesignerBase : Window
6205 {
6206 public:
6207    virtual void Reset(void);
6208    virtual void AddObject(void);
6209    virtual void SelectObject(ObjectInfo object, Instance control);
6210
6211    virtual void ListToolBoxClasses(DesignerBase designer);
6212
6213    virtual void ::PrepareTestObject(DesignerBase designer, Instance test);
6214    virtual void ::CreateObject(DesignerBase designer, Instance instance, ObjectInfo object, bool isClass, Instance _class);
6215    virtual void ::PostCreateObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6216    virtual void ::DroppedObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6217    virtual void ::DestroyObject(Instance object);
6218    virtual void ::FixProperty(Property prop, Instance object);
6219    virtual void ::CreateNew(EditBox editBox, Size clientSize, char * name, char * inherit);
6220 }
6221
6222 DesignerBase activeDesigner;
6223
6224 public void SetActiveDesigner(DesignerBase designer)
6225 {
6226    activeDesigner = designer;
6227 }
6228
6229 public DesignerBase GetActiveDesigner()
6230 {
6231    return activeDesigner;
6232 }
6233
6234 namespace sys;
6235
6236 // constants
6237 define LEAD_OFFSET      = 0xD800 - (0x10000 >> 10);
6238 define SURROGATE_OFFSET = 0x10000 - (0xD800 << 10) - 0xDC00;
6239
6240 public bool UTF8Validate(char * source)
6241 {
6242    if(source)
6243    {
6244       int c;
6245       for(c = 0; source[c];)
6246       {
6247          byte ch = source[c];
6248          unichar codePoint = 0;
6249          int numBytes = 1;
6250          int i;
6251          byte mask = 0x7F;
6252          if(ch & 0x80)
6253          {
6254             if(ch & 0x40)
6255             {
6256                mask >>= 2;
6257                numBytes++;
6258                if(ch & 0x20)
6259                {
6260                   numBytes++;
6261                   mask >>= 1;
6262                   if(ch & 0x10)
6263                   {
6264                      if(ch & 0x08)
6265                         return false;
6266                      numBytes++;
6267                      mask >>= 1;
6268                   }
6269                }
6270             }
6271             else
6272                return false;
6273          }
6274          for(i = 0; i<numBytes && (ch = source[c]); i++, c++)
6275          {
6276             codePoint <<= 6;
6277             codePoint |= ch & mask;
6278             mask = 0x3F;
6279             if(i > 1)
6280             {
6281                if(!(ch & 0x80) || (ch & 0x40))
6282                   return false;
6283             }
6284          }
6285          if(i < numBytes) return false;
6286
6287          if(codePoint > 0x10FFFF || (codePoint >= 0xD800 && codePoint <= 0xDFFF) || 
6288            (codePoint < 0x80 && numBytes > 1) || 
6289            (codePoint < 0x800 && numBytes > 2) || 
6290            (codePoint < 0x10000 && numBytes > 3))
6291             return false;
6292       }
6293    }
6294    return true;
6295 }
6296
6297 public int ISO8859_1toUTF8(char * source, char * dest, int max)
6298 {
6299    int c;
6300    int d = 0;
6301    for(c = 0; source[c]; c++)
6302    {
6303       unichar ch = ((byte *)source)[c];
6304       if(ch < 0x80)
6305       {
6306          if(d + 1 >= max) break;
6307          dest[d++] = (char)ch;
6308       }
6309       else if(ch < 0x800)
6310       {
6311          if(d + 2 >= max) break;
6312          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6313          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6314       }
6315       else if(ch < 0x10000)
6316       {
6317          if(d + 3 >= max) break;
6318          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6319          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6320          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6321       }
6322       else
6323       {
6324          if(d + 4 >= max) break;
6325          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6326          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6327          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6328          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6329       }
6330    }
6331    dest[d] = 0;
6332    return d;
6333 }
6334
6335 public char * UTF16toUTF8(uint16 * source)
6336 {
6337    int c;
6338    int d = 0;
6339    int len;
6340    char * dest;
6341    uint16 u16;
6342    bool invert = false;
6343
6344    for(len = 0; source[len]; len++);
6345    dest = new char[len * 3 + 1];
6346    for(c = 0; (u16 = source[c]); c++)
6347    {
6348       unichar ch;
6349       if(!c && (u16 == 0xFFFE || u16 == 0xFEFF))
6350       {
6351          if(u16 == 0xFFFE) invert = true;
6352          continue;
6353       }
6354       if(invert) { u16 = ((u16 & 0xFF00) >> 8) | ((u16 & 0x00FF) << 8); }
6355       
6356       if(u16 < 0xD800 || u16 > 0xDBFF)
6357          ch = (unichar)u16;         
6358       else
6359          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
6360                   
6361       if(ch < 0x80)
6362       {
6363          dest[d++] = (char)ch;
6364       }
6365       else if(ch < 0x800)
6366       {
6367          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6368          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6369       }
6370       else if(ch < 0x10000)
6371       {
6372          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6373          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6374          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6375       }
6376       else
6377       {
6378          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6379          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6380          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6381          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6382       }
6383    }
6384    dest[d] = 0;
6385    dest = renew dest char[d+1];
6386    return dest;
6387 }
6388
6389 public int UTF16toUTF8Buffer(uint16 * source, byte * dest, int max)
6390 {
6391    int c;
6392    int d = 0;
6393    uint16 u16;
6394    for(c = 0; (u16 = source[c]); c++)
6395    {
6396       unichar ch;
6397       if(u16 < 0xD800 || u16 > 0xDBFF)
6398          ch = (unichar)u16;         
6399       else
6400          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
6401
6402       if(ch < 0x80)
6403       {
6404          if(d + 1 >= max) break;
6405          dest[d++] = (char)ch;
6406       }
6407       else if(ch < 0x800)
6408       {
6409          if(d + 2 >= max) break;
6410          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6411          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6412       }
6413       else if(ch < 0x10000)
6414       {
6415          if(d + 3 >= max) break;
6416          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6417          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6418          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6419       }
6420       else
6421       {
6422          if(d + 4 >= max) break;
6423          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6424          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6425          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6426          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6427       }
6428    }
6429    dest[d] = 0;
6430    return d;
6431 }
6432
6433 public unichar UTF8GetChar(char * string, int * numBytes)
6434 {
6435    unichar ch;
6436    byte b = ((byte *)string)[0];
6437    int i;
6438    byte mask = 0x7F;
6439    int nb = 1;
6440    ch = 0;
6441    if(b & 0x80)
6442    {
6443       if(b & 0x40)
6444       {
6445          mask >>= 2;
6446          nb++;
6447          if(b & 0x20)
6448          {
6449             nb++;
6450             mask >>= 1;
6451             if(b & 0x10)
6452             {
6453                if(b & 0x08) { nb = 0; }
6454                nb++;
6455                mask >>= 1;
6456             }
6457          }
6458       }
6459       else
6460          nb = 0;
6461    }
6462    for(i = 0; i<nb; i++)
6463    {
6464       ch <<= 6;
6465       ch |= (b = ((byte *)string)[i]) & mask;
6466       mask = 0x3F;
6467       if(i > 1 && (!(b & 0x80) || (b & 0x40)))
6468       {
6469          nb = 0;
6470          ch = 0;
6471       }
6472    }
6473
6474    if(i < nb || 
6475       ch > 0x10FFFF || (ch >= 0xD800 && ch <= 0xDFFF) || 
6476      (ch < 0x80 && nb > 1) || 
6477      (ch < 0x800 && nb > 2) || 
6478      (ch < 0x10000 && nb > 3))
6479    {
6480       ch = 0;
6481       nb = 0;
6482    }
6483    if(numBytes) *numBytes = nb;
6484    return ch;
6485 }
6486
6487 public int UTF8toUTF16Buffer(char * source, uint16 * dest, int max)
6488 {
6489    if(source)
6490    {
6491       int c;
6492       int d = 0;
6493       for(c = 0; source[c];)
6494       {
6495          byte ch = source[c];
6496          unichar codePoint = 0;
6497          int numBytes = 1;
6498          int i;
6499          byte mask = 0x7F;
6500          if(ch & 0x80 && ch & 0x40)
6501          {
6502             mask >>= 2;
6503             numBytes++;
6504             if(ch & 0x20)
6505             {
6506                numBytes++;
6507                mask >>= 1;
6508                if(ch & 0x10)
6509                {
6510                   numBytes++;
6511                   mask >>= 1;
6512                }
6513             }
6514          }
6515          for(i = 0; i<numBytes; i++)
6516          {
6517             codePoint <<= 6;
6518             codePoint |= source[c++] & mask;
6519             mask = 0x3F;
6520          }
6521
6522          if(codePoint > 0xFFFF)
6523          {
6524             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
6525             uint16 trail = 0xDC00 + (uint16)(codePoint & 0x3FF);
6526             if(d >= max - 1) break;
6527             dest[d++] = lead;
6528             dest[d++] = trail;
6529          }
6530          else
6531          {
6532             if(d >= max) break;
6533             dest[d++] = (uint16)codePoint;
6534          }
6535       }
6536       dest[d] = 0;
6537       return d;
6538    }
6539    return 0;   
6540 }
6541
6542 public int UTF32toUTF8Len(unichar * source, int count, byte * dest, int max)
6543 {
6544    int c;
6545    int d = 0;
6546    uint32 ch;
6547    for(c = 0; c<count && (ch = source[c]); c++)
6548    {
6549       if(ch < 0x80)
6550       {
6551          if(d + 1 >= max) break;
6552          dest[d++] = (char)ch;
6553       }
6554       else if(ch < 0x800)
6555       {
6556          if(d + 2 >= max) break;
6557          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6558          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6559       }
6560       else if(ch < 0x10000)
6561       {
6562          if(d + 3 >= max) break;
6563          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6564          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6565          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6566       }
6567       else
6568       {
6569          if(d + 4 >= max) break;
6570          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6571          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6572          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6573          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6574       }
6575    }
6576    dest[d] = 0;
6577    return d;
6578 }
6579
6580 public uint16 * UTF8toUTF16(char * source, int * wordCount)
6581 {
6582    if(source)
6583    {
6584       int len = strlen(source);
6585       uint16 * dest = new uint16[len + 1];
6586       int c;
6587       int d = 0;
6588       for(c = 0; source[c];)
6589       {
6590          byte ch = source[c];
6591          unichar codePoint = 0;
6592          int numBytes = 1;
6593          int i;
6594          byte mask = 0x7F;
6595          if(ch & 0x80 && ch & 0x40)
6596          {
6597             mask >>= 2;
6598             numBytes++;
6599             if(ch & 0x20)
6600             {
6601                numBytes++;
6602                mask >>= 1;
6603                if(ch & 0x10)
6604                {
6605                   numBytes++;
6606                   mask >>= 1;
6607                }
6608             }
6609          }
6610          for(i = 0; i<numBytes; i++)
6611          {
6612             codePoint <<= 6;
6613             codePoint |= source[c++] & mask;
6614             mask = 0x3F;
6615          }
6616
6617          if(codePoint > 0xFFFF)
6618          {
6619             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
6620             uint16 trail = 0xDC00 + (uint16)(codePoint & 0x3FF);
6621             dest[d++] = lead;
6622             dest[d++] = trail;
6623          }
6624          else
6625          {
6626             dest[d++] = (uint16)codePoint;
6627          }
6628       }
6629       dest[d] = 0;
6630       if(wordCount) *wordCount = d;
6631       return dest;
6632    }
6633    return null;
6634 }
6635
6636 namespace com;