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