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