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