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