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