ecere/com: Improved on virtual table protection 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: virtual methods overriding failure\n");
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             {
4067                if(method.vid >= _class.vTblSize)
4068                   printf("error: virtual methods overriding failure\n");
4069                else
4070                   _class._vTbl[method.vid] = function ? function : DefaultFunction;
4071             }
4072             else
4073                base = null;
4074             return method;
4075          }
4076       }
4077
4078       if(!base)
4079       {
4080          Method method
4081          {
4082             name = CopyString(name);
4083             function = function ? function : DefaultFunction;
4084             type = virtualMethod;
4085             _class = _class;
4086             vid = _class.vTblSize++;
4087             dataTypeString = CopyString(type);
4088             memberAccess = declMode;
4089          };
4090          _class.methods.Add((BTNode)method);
4091          _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
4092          _class._vTbl[method.vid] = function ? function : DefaultFunction;
4093
4094          // TODO: Fix derived classes
4095          if(_class.derivatives.first || _class.templatized.first)
4096             FixDerivativeVirtualMethod(_class, name, method.vid, function ? function : (void *)DefaultFunction, type);
4097          return method;
4098       }
4099    }
4100    return null;
4101 }
4102
4103 static void FixDerivativeProperty(Class base, Property _property)
4104 {
4105    OldLink derivative;
4106    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
4107    {
4108       Class _class = derivative.data;
4109       Property prop;
4110       BTNamedLink link;
4111       link = (BTNamedLink)_class.prop.FindString(_property.name);
4112       if(link)
4113       {
4114          prop = link.data;
4115          if(!prop.Set && !prop.Get && prop.memberAccess == baseSystemAccess)
4116          {
4117             SelfWatcher watcher;
4118             for(watcher = _class.selfWatchers.first; watcher; watcher = watcher.next)
4119             {
4120                if(watcher._property == prop)
4121                   watcher._property = _property;
4122             }
4123             _property.selfWatchable = true;
4124
4125             delete prop.name;
4126             delete prop.dataTypeString;
4127             _class.membersAndProperties.Delete(prop);
4128             _class.prop.Delete((BTNode)link);
4129          }
4130       }
4131
4132       for(prop = _class.membersAndProperties.first; prop; prop = prop.next)
4133          prop.id++;
4134       _class.memberID++;
4135       _class.startMemberID++;
4136
4137       FixDerivativeProperty(_class, _property);
4138    }
4139 }
4140
4141 public dllexport Property eClass_AddProperty(Class _class, char * name, char * dataType, void * setStmt, void * getStmt, AccessMode declMode)
4142 {
4143    Property _property = null;
4144    if(_class)
4145    {
4146       if(!_class.prop.FindString((name ? name : dataType))) 
4147       {
4148          _property =
4149          {
4150             isProperty = true;
4151             name = CopyString(name ? name : dataType);
4152             id = (name && (setStmt || getStmt || dataType)) ? _class.memberID++ : 0;
4153             Set = setStmt;
4154             Get = getStmt;
4155             dataTypeString = CopyString(dataType);
4156             _class = _class;
4157             compiled = true;
4158             conversion = name ? false : true;
4159             memberAccess = declMode;
4160          };
4161          if(name)
4162             _class.membersAndProperties.Add(_property);
4163          else
4164             _class.conversions.Add(_property);
4165          _class.prop.Add((BTNode)BTNamedLink { name = _property.name, data = _property });
4166
4167          if(!_property.conversion)
4168          {
4169             FixDerivativeProperty(_class, _property);
4170          }
4171       }
4172    }
4173    return _property;
4174 }
4175
4176 static void SetDelayedCPValues(Class _class, ClassProperty _property)
4177 {
4178    OldLink deriv;
4179    NamedLink64 value, next;
4180
4181    for(value = _class.delayedCPValues.first; value; value = next)
4182    {
4183       next = value.next;
4184       if(!strcmp(value.name, _property.name))
4185       {
4186          // eClass_SetProperty(_class, _property.name, value.data);
4187          _property.Set(_class, value.data);
4188          _class.delayedCPValues.Delete(value);
4189       }
4190    }
4191
4192    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4193    {
4194       SetDelayedCPValues(deriv.data, _property);
4195    }
4196 }
4197
4198 public dllexport ClassProperty eClass_AddClassProperty(Class _class, char * name, char * dataType, void * setStmt, void * getStmt)
4199 {
4200    if(name && !_class.classProperties.FindString(name)) 
4201    {
4202       ClassProperty _property
4203       {
4204          name = CopyString(name);
4205          Set = setStmt;
4206          Get = getStmt;
4207          dataTypeString = CopyString(dataType);
4208       };
4209       _class.classProperties.Add((BTNode)_property);
4210       SetDelayedCPValues(_class, _property);
4211       return _property;
4212    }
4213    return null;
4214 }
4215
4216 /*import "Time"
4217
4218 Time classFindTotalTime;
4219
4220 public dllexport void ResetClassFindTime()
4221 {
4222    classFindTotalTime = 0;
4223 }
4224
4225 public dllexport Time GetClassFindTime()
4226 {
4227    return classFindTotalTime;
4228 }
4229 */
4230 public dllexport ClassProperty eClass_FindClassProperty(Class _class, char * name)
4231 {
4232    //Time startTime = GetTime();
4233    ClassProperty _property = null;
4234    if(name && _class)
4235    {
4236       Class origClass = _class;
4237       for(; _class; _class = _class.base)
4238       {
4239          _property = (ClassProperty)_class.classProperties.FindString(name);
4240          if(_property)
4241             break;
4242       }
4243       // For enum class deriving off something else than enum to find enumSize...
4244       if(!_property && origClass.type == enumClass)
4245       {
4246          Class enumClass = eSystem_FindClass(origClass.module, "enum");
4247          _property = eClass_FindClassProperty(enumClass, name);
4248       }
4249    }
4250    /*if(!_property)
4251       eSystem_Logf("No such property (%s) for class %s\n", name, _class.name);*/
4252    //classFindTotalTime += GetTime() - startTime;
4253    return _property;
4254 }
4255
4256 public dllexport int64 eClass_GetProperty(Class _class, char * name)
4257 {
4258    ClassProperty _property = eClass_FindClassProperty(_class, name);
4259    if(_property && _property.Get && _property.Get != (void *)1)
4260    {
4261       int64 result = _property.Get(_class);
4262       return result;
4263    }
4264    return 0;
4265 }
4266
4267 public dllexport void eClass_SetProperty(Class _class, char * name, int64 value)
4268 {
4269    ClassProperty _property = eClass_FindClassProperty(_class, name);
4270    if(_property)
4271    {
4272       if(_property.Set)
4273          ((void(*)(void *, int64))_property.Set)(_class, value);
4274    }
4275    else
4276    {
4277       _class.delayedCPValues.Add(NamedLink64 { name = name, value });
4278    }
4279 }
4280
4281 public dllexport Method eClass_FindMethod(Class _class, char * name, Module module)
4282 {
4283    //Time startTime = GetTime();
4284    if(_class && name)
4285    {
4286       for(; _class; _class = _class.base)
4287       {
4288          Method method;
4289          if(_class.templateClass) _class = _class.templateClass;
4290          method = (Method)_class.methods.FindString(name);
4291          if(method && (method.memberAccess == publicAccess || _class.module == module || !method.dataTypeString))
4292          {
4293             if(!method.dataTypeString)
4294             {
4295                if(_class.module != module)
4296                {
4297                   if(method.memberAccess == publicAccess)
4298                      module = _class.module;
4299                   else
4300                   {
4301                      //classFindTotalTime += GetTime() - startTime;
4302                      return null;
4303                   }
4304                }
4305             }
4306             else
4307             {
4308                //classFindTotalTime += GetTime() - startTime;
4309                return method;
4310             }
4311          }
4312          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4313       }
4314    }
4315    //classFindTotalTime += GetTime() - startTime;
4316    return null;
4317 }
4318
4319 // Construct an instance
4320 static bool ConstructInstance(void * instance, Class _class, Class from)
4321 {
4322    if(_class.templateClass) _class = _class.templateClass;
4323    if(_class.base && from != _class.base)
4324    {
4325       if(!ConstructInstance(instance, _class.base, from))
4326          return false;
4327    }
4328    if(_class.Initialize)
4329    {
4330       void (* Initialize)(Module module) = (void *)_class.Initialize;
4331       _class.Initialize = null;
4332       Initialize(_class.module);
4333    }
4334    if(_class.Constructor)
4335    {
4336       if(!_class.Constructor(instance))
4337       {
4338          for(; _class; _class = _class.base)
4339          {
4340             if(_class.templateClass) _class = _class.templateClass;
4341             if(_class.Destructor)
4342                _class.Destructor(instance);
4343          }
4344          return false;
4345       }
4346    }
4347    (_class.templateClass ? _class.templateClass : _class).count++;
4348    return true;
4349 }
4350
4351 public dllexport void * eInstance_New(Class _class)
4352 {
4353    Instance instance = null;
4354    if(_class)
4355    {
4356       // instance = _malloc(_class.size);   
4357 #ifdef MEMINFO
4358
4359 #undef malloc
4360    memMutex.Wait();
4361       //allocateClass = _class;
4362       allocateClass = malloc(strlen(_class.name)+1);
4363       allocateInternal = _class.module == __thisModule;
4364       strcpy(allocateClass, _class.name);
4365 #ifndef MEMINFO
4366 #define malloc _mymalloc
4367 #endif
4368
4369 #endif
4370       {
4371          int size = _class.structSize;
4372          int flags = _class.module.application.isGUIApp;
4373          bool inCompiler = (flags & 8) ? true : false;
4374          bool force32Bits = (flags & 4) ? true : false;
4375          if(force32Bits && inCompiler)
4376          {
4377             // Allocate 64 bit sizes for these when cross-compiling for 32 bit to allow loaded libraries to work properly
4378             if(!strcmp(_class.name, "Module"))
4379                size = 560;
4380             else if(_class.templateClass && !strcmp(_class.templateClass.name, "Map"))
4381                size = 40;
4382             else
4383                size *= 3;
4384          }
4385          instance = _calloc(1, size);
4386       }
4387 #ifdef MEMINFO
4388       allocateClass = null;
4389    memMutex.Release();
4390 #endif
4391       if(_class.type == normalClass)
4392       {
4393          instance._class = _class;
4394          // Copy the virtual table initially
4395          instance._vTbl = _class._vTbl;
4396       }
4397       if(!ConstructInstance(instance, _class, null))
4398       {
4399          _free(instance);
4400          instance = null;
4401       }
4402       /*if(_class.type == normalClass && _class.count > 1000)
4403          printf("%s: %d instances\n", _class.name, _class.count);*/
4404    }
4405    return instance;
4406 }
4407
4408 public dllexport void eInstance_Evolve(Instance * instancePtr, Class _class)
4409 {
4410    if(_class && instancePtr && *instancePtr)
4411    {
4412       bool wasApp = false, wasGuiApp = false;
4413       Instance instance = (Instance)renew *instancePtr byte[_class.structSize];
4414       Class fromClass = instance._class;
4415       *instancePtr = instance;
4416       memset(((byte *)instance) + instance._class.structSize, 0, _class.structSize - instance._class.structSize);
4417       // Fix pointers to application
4418       if((wasApp = !strcmp(instance._class.name, "Application")) ||
4419          (wasGuiApp = !strcmp(instance._class.name, "GuiApplication")))
4420       {
4421          Module module;
4422          Application app = (Application) instance;
4423          BTNamedLink link;
4424          Class _class;
4425          NameSpace * nameSpace;
4426          for(module = app.allModules.first; module; module = module.next)
4427             module.application = app;
4428
4429          for(link = (BTNamedLink)app.privateNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4430          {
4431             OldLink t;
4432             ((Class)link.data).nameSpace = &app.privateNameSpace;
4433             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4434          }
4435          for(link = (BTNamedLink)app.publicNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4436          {
4437             OldLink t;
4438             ((Class)link.data).nameSpace = &app.publicNameSpace;
4439             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4440          }
4441
4442          for(link = (BTNamedLink)app.privateNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4443             ((DefinedExpression)link.data).nameSpace = &app.privateNameSpace;
4444          for(link = (BTNamedLink)app.publicNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4445             ((DefinedExpression)link.data).nameSpace = &app.publicNameSpace;
4446
4447          for(link = (BTNamedLink)app.privateNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4448             ((GlobalFunction)link.data).nameSpace = &app.privateNameSpace;
4449          for(link = (BTNamedLink)app.publicNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4450             ((GlobalFunction)link.data).nameSpace = &app.publicNameSpace;
4451
4452          for(nameSpace = (NameSpace *)app.privateNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4453             nameSpace->parent = &app.privateNameSpace;
4454          for(nameSpace = (NameSpace *)app.publicNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4455             nameSpace->parent = &app.publicNameSpace;
4456
4457          // --------------------------------------------------
4458          for(link = (BTNamedLink)app.systemNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4459          {
4460             OldLink t;
4461             ((Class)link.data).nameSpace = &app.systemNameSpace;
4462             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4463          }
4464          for(link = (BTNamedLink)app.systemNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4465             ((DefinedExpression)link.data).nameSpace = &app.systemNameSpace;
4466          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4467             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4468          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4469             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4470          for(nameSpace = (NameSpace *)app.systemNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4471             nameSpace->parent = &app.systemNameSpace;
4472          // --------------------------------------------------
4473          
4474          for(_class = app.classes.first; _class; _class = _class.next)
4475          {
4476             OldLink templateLink;
4477             _class.module = (Module) app;
4478             for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4479             {  
4480                Class template = templateLink.data;
4481                template.module = _class.module;
4482             }
4483          }
4484
4485          for(module = app.allModules.first; module; module = module.next)
4486          {
4487             for(_class = module.classes.first; _class; _class = _class.next)
4488             {
4489                OldLink templateLink;
4490                _class.module = module;
4491                for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4492                {
4493                   Class template = templateLink.data;
4494                   template.module = _class.module;
4495                }
4496             }
4497          }
4498
4499          app.application = app;
4500       }
4501
4502       {
4503          Class base;
4504          for(base = instance._class; base && base.type == normalClass && base.count; base = base.base)
4505             (base.templateClass ? base.templateClass : base).count--;
4506       }
4507
4508       instance._class = _class;
4509       // Copy the virtual table initially
4510       instance._vTbl = _class._vTbl;
4511
4512       // We don't want to reconstruct the portion already constructed...
4513       if(!ConstructInstance(instance, _class, fromClass))
4514       {
4515          _free(instance);
4516          *instancePtr = null;
4517       }
4518    }
4519 }
4520
4521 public dllexport void eInstance_Delete(Instance instance)
4522 {
4523 #ifdef MEMINFO
4524    bool checkMemory = false;
4525 #endif
4526    if(instance)
4527    {
4528       Class _class, base;
4529       bool ownVtbl;
4530
4531 #ifdef MEMINFO
4532       if(instance._class == (void *)0xecececec)
4533          _free(instance);
4534 #endif
4535
4536       ownVtbl = instance._vTbl != instance._class._vTbl;
4537
4538       for(_class = instance._class; _class; _class = base)
4539       {
4540          if(_class.templateClass) _class = _class.templateClass;
4541          if(_class.destructionWatchOffset)
4542          {
4543             OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
4544             Watcher watcher, next;
4545
4546             for(watcher = watchers->first; watcher; watcher = next)
4547             {
4548                next = watcher.next;
4549                watchers->Remove(watcher);
4550                watcher.callback(watcher.object, instance);
4551                watchers->Delete(watcher);
4552             }
4553          }
4554
4555          /*// Loop through properties to delete all watchers? Might slow down destruction...
4556          {
4557             Property _property;
4558             for(_property = _class.membersAndProperties.first; _property; _property = _property.next)
4559             {
4560                if(_property.isProperty && _property.isWatchable)
4561                {
4562                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
4563                   Watcher watcher, next;
4564                   for(watcher = watchers->first; watcher; watcher = next)
4565                   {  
4566                      next = watcher.next;
4567                      watchers->Delete(watcher);
4568                   }
4569                }
4570             }
4571          }*/
4572          
4573
4574          base = _class.base;
4575          if(base && base.type == systemClass) base = null;
4576          if(_class.Destructor)
4577             _class.Destructor(instance);
4578 #ifdef MEMINFO
4579          if(_class == class(Application))
4580             checkMemory = true;
4581 #endif
4582       }
4583
4584       for(_class = instance._class; _class; _class = base)
4585       {
4586          if(_class.templateClass) _class = _class.templateClass;
4587
4588          base = _class.base;
4589          (_class.templateClass ? _class.templateClass : _class).count--;
4590          if(_class.type == normalClass && !_class.count && !_class.module)
4591          {
4592 #ifdef MEMINFO
4593             // printf("Now Destructing class %s\n", _class.name);
4594 #endif
4595             eClass_Unregister(_class);
4596          }
4597       }
4598
4599       if(ownVtbl)
4600       {
4601          delete instance._vTbl;
4602       }
4603       //instance.prop.Free(null);
4604       _free(instance);
4605 #ifdef MEMINFO
4606       if(checkMemory) CheckMemory();
4607 #endif
4608    }
4609 }
4610
4611 public dllexport Property eClass_FindProperty(Class _class, char * name, Module module)
4612 {
4613    //Time startTime = GetTime();
4614    if(_class && name)
4615    {
4616       for(; _class; _class = _class.base)
4617       {
4618          BTNamedLink link;
4619          if(_class.templateClass) _class = _class.templateClass;
4620          link = (BTNamedLink)_class.prop.FindString(name);
4621          if(link)
4622          {
4623             Property _property = (Property)link.data;
4624             if(_property.memberAccess == publicAccess || _class.module == module || !_property.dataTypeString)
4625             {
4626                if(!_property.dataTypeString)
4627                {
4628                   if(_class.module != module)
4629                   {
4630                      if(_property.memberAccess == publicAccess)
4631                         module = _class.module;
4632                      else
4633                      {
4634                         //classFindTotalTime += GetTime() - startTime;
4635                         return null;
4636                      }
4637                   }
4638                }
4639                else
4640                {
4641                   //classFindTotalTime += GetTime() - startTime;
4642                   return _property;
4643                }
4644             }
4645          }
4646          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4647       }
4648    }
4649    //classFindTotalTime += GetTime() - startTime;
4650    return null;
4651 }
4652
4653 static DataMember FindDataMember(OldList list, BinaryTree alist, char * name, uint * offset, int * id, bool searchPrivate, DataMember * subMemberStack, int * subMemberStackPos)
4654 {
4655    BTNamedLink link;
4656    DataMember dataMember;
4657
4658    link = (BTNamedLink)alist.FindString(name);
4659    if(link)
4660    {
4661       dataMember = link.data;
4662       if(dataMember.type == normalMember && (dataMember.memberAccess == publicAccess || searchPrivate || !dataMember.dataTypeString))
4663       {
4664          if(offset)
4665             *offset += dataMember.offset;
4666          if(id) *id = dataMember.id;
4667          return dataMember;
4668       }
4669       return null;
4670    }
4671    for(dataMember = list.first; dataMember; dataMember = dataMember.next)
4672    {
4673       if(!dataMember.isProperty && (dataMember.memberAccess == publicAccess || searchPrivate) && !dataMember.name && (dataMember.type == unionMember || dataMember.type == structMember))
4674       {
4675          DataMember childMember;
4676          if(subMemberStackPos) subMemberStack[(*subMemberStackPos)++] = dataMember;
4677          childMember = FindDataMember(dataMember.members, dataMember.membersAlpha, name, offset, id, searchPrivate, subMemberStack, subMemberStackPos);
4678          if(childMember)
4679          {
4680             if(offset)
4681                *offset += dataMember.offset;
4682             if(id) *id += dataMember.id;
4683             return childMember;
4684          }
4685          if(subMemberStackPos) (*subMemberStackPos)--;
4686       }
4687    }
4688    return null;
4689 }
4690
4691 public dllexport DataMember eClass_FindDataMember(Class _class, char * name, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4692 {
4693    //Time startTime = GetTime();
4694    DataMember dataMember = null;
4695    if(subMemberStackPos) *subMemberStackPos = 0;
4696    if(_class && name)
4697    {
4698       for(; _class; _class = _class.base)
4699       {
4700          if(_class.templateClass) _class = _class.templateClass;
4701          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, null, _class.module == module, subMemberStack, subMemberStackPos);
4702          if(dataMember)
4703          {
4704             if(!dataMember.dataTypeString)
4705             {
4706                if(_class.module != module)
4707                {
4708                   if(dataMember.memberAccess == publicAccess)
4709                      module = _class.module;
4710                   else
4711                   {
4712                      //classFindTotalTime += GetTime() - startTime;
4713                      return null;
4714                   }
4715                }
4716                dataMember = null;
4717             }
4718             else
4719             {
4720                // HACK: Is this good enough? avoiding setting it when adding...
4721                dataMember._class = _class.templateClass ? _class.templateClass : _class;
4722                //classFindTotalTime += GetTime() - startTime;
4723                return dataMember;
4724             }
4725          }
4726          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4727       }
4728    }
4729    //classFindTotalTime += GetTime() - startTime;
4730    return dataMember;
4731 }
4732
4733 public dllexport DataMember eClass_FindDataMemberAndOffset(Class _class, char * name, uint * offset, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4734 {
4735    //Time startTime = GetTime();
4736    DataMember dataMember = null;
4737    if(subMemberStackPos) *subMemberStackPos = 0;
4738    if(offset) *offset = 0;
4739    if(_class)
4740    {
4741       for(; _class; _class = _class.base)
4742       {
4743          if(_class.templateClass) _class = _class.templateClass;
4744          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, offset, null, _class.module == module, subMemberStack, subMemberStackPos);
4745          if(dataMember)
4746          {
4747             if(!dataMember.dataTypeString)
4748             {
4749                if(_class.module != module)
4750                {
4751                   if(dataMember.memberAccess == publicAccess)
4752                      module = _class.module;
4753                   else
4754                   {
4755                      //classFindTotalTime += GetTime() - startTime;
4756                      return null;
4757                   }
4758                }
4759                dataMember = null;
4760             }
4761             else
4762             {
4763                // HACK: Is this good enouh? avoiding setting it when adding...
4764                dataMember._class = _class;
4765                //classFindTotalTime += GetTime() - startTime;
4766                return dataMember;
4767             }
4768          }
4769          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4770       }
4771    }
4772    //classFindTotalTime += GetTime() - startTime;
4773    return dataMember;
4774 }
4775
4776 public dllexport DataMember eClass_FindDataMemberAndId(Class _class, char * name, int * id, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4777 {
4778    //Time startTime = GetTime();
4779    DataMember dataMember = null;
4780    if(subMemberStackPos) *subMemberStackPos = 0;
4781    if(_class)
4782    {
4783       for(; _class; _class = _class.base)
4784       {
4785          if(_class.templateClass) _class = _class.templateClass;
4786          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, id, _class.module == module, subMemberStack, subMemberStackPos);  // TOCHECK: Why was this null? null, null);
4787          if(dataMember)
4788          {
4789             if(!dataMember.dataTypeString)
4790             {
4791                if(_class.module != module)
4792                {
4793                   if(dataMember.memberAccess == publicAccess)
4794                      module = _class.module;
4795                   else
4796                   {
4797                      //classFindTotalTime += GetTime() - startTime;
4798                      return null;
4799                   }
4800                }
4801                dataMember = null;
4802             }
4803             else
4804             {
4805                // HACK: Is this good enouh? avoiding setting it when adding...
4806                dataMember._class = _class;
4807                //classFindTotalTime += GetTime() - startTime;
4808                return dataMember;
4809             }
4810          }
4811          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4812       }
4813    }
4814    //classFindTotalTime += GetTime() - startTime;
4815    return dataMember;
4816 }
4817
4818 public dllexport void eClass_FindNextMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
4819 {
4820    // THIS CODE WILL FIND NEXT MEMBER... (PUBLIC MEMBERS ONLY)
4821    if(*curMember) 
4822    {
4823       *curMember = (*curMember).next;
4824
4825       if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
4826       {
4827          *curMember = subMemberStack[--(*subMemberStackPos)];
4828          *curMember = (*curMember).next;
4829       }
4830
4831       if(subMemberStackPos && *subMemberStackPos > 0)
4832       {
4833          while(*curMember && ((*curMember).memberAccess == privateAccess))
4834             *curMember = (*curMember).next;
4835       }
4836       else
4837          while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
4838          {
4839             DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
4840             if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
4841             if(dataMember && dataMember.memberAccess != privateAccess)
4842             {
4843                *curMember = dataMember;
4844                break;
4845             }
4846             else
4847                *curMember = (*curMember).next;
4848          }
4849
4850       if(subMemberStackPos)
4851       {
4852          while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
4853          {
4854             subMemberStack[(*subMemberStackPos)++] = *curMember;
4855
4856             *curMember = (*curMember).members.first;
4857             while(*curMember && ((*curMember).memberAccess == privateAccess))
4858                *curMember = (*curMember).next;                     
4859          }
4860       }
4861    }
4862    while(!*curMember)
4863    {
4864       if(!*curMember)
4865       {
4866          if(subMemberStackPos && *subMemberStackPos)
4867          {
4868             *curMember = subMemberStack[--(*subMemberStackPos)];
4869             *curMember = (*curMember).next;
4870          }
4871          else
4872          {
4873             Class lastCurClass = *curClass;
4874
4875             if(*curClass == _class) break;     // REACHED THE END
4876
4877             for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass && (*curClass).inheritanceAccess != privateAccess; *curClass = (*curClass).base);
4878             *curMember = (*curClass).membersAndProperties.first;
4879          }
4880
4881          if(subMemberStackPos && *subMemberStackPos > 0)
4882          {
4883             while(*curMember && ((*curMember).memberAccess == privateAccess))
4884                *curMember = (*curMember).next;
4885          }
4886          else
4887             while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
4888             {
4889                DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
4890                if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
4891                if(dataMember && dataMember.memberAccess != privateAccess)
4892                {
4893                   *curMember = dataMember;
4894                   break;
4895                }
4896                else
4897                   *curMember = (*curMember).next;
4898             }
4899
4900          if(subMemberStackPos)
4901          {
4902             while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
4903             {
4904                subMemberStack[(*subMemberStackPos)++] = *curMember;
4905
4906                *curMember = (*curMember).members.first;
4907                while(*curMember && (*curMember).memberAccess == privateAccess)
4908                   *curMember = (*curMember).next;                     
4909             }
4910          }
4911       }
4912    }
4913 }
4914
4915 public dllexport void eInstance_SetMethod(Instance instance, char * name, void * function)     // YET TO BE DECIDED:   , Module module)
4916 {
4917    if(instance && name)
4918    {
4919       Class _class;
4920       for(_class = instance._class; _class; _class = _class.base)
4921       {
4922          Method method = (Method)_class.methods.FindString(name);
4923          if(method && method.type == virtualMethod)
4924          {
4925             if(instance._vTbl == instance._class._vTbl)
4926             {
4927                instance._vTbl = _malloc(sizeof(void *) * instance._class.vTblSize);
4928                memcpy(instance._vTbl, instance._class._vTbl,
4929                   sizeof(int(*)()) * instance._class.vTblSize);               
4930             }
4931             instance._vTbl[method.vid] = function ? function : DefaultFunction;
4932          }
4933       }
4934    }
4935 }
4936
4937 public dllexport bool eInstance_IsDerived(Instance instance, Class from)
4938 {
4939    if(instance)
4940    {
4941       Class _class = instance._class;
4942       for(; _class; _class = _class.base)
4943       {
4944          if(_class == from)
4945             return true;
4946       }
4947    }
4948    return false;
4949 }
4950
4951 public dllexport void eInstance_IncRef(Instance instance)
4952 {
4953    if(instance)
4954       instance._refCount++;
4955 }
4956
4957 public dllexport void eInstance_DecRef(Instance instance)
4958 {
4959    if(instance)
4960    {
4961       instance._refCount--;
4962       //if(!instance._refCount)
4963       if(instance._refCount <= 0)
4964       {
4965          eInstance_Delete(instance);
4966       }
4967    }
4968 }
4969
4970 static void FixOffsets(Class _class)
4971 {
4972    OldLink deriv;
4973    _class.structSize += _class.base.structSize - _class.offset;
4974
4975    _class.offset = _class.base.structSize;   
4976
4977    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4978       FixOffsets(deriv.data);
4979 }
4980
4981 public dllexport void eClass_Resize(Class _class, int newSize)
4982 {
4983    OldLink deriv;
4984    _class.structSize = newSize;
4985    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4986       FixOffsets(deriv.data);
4987 }
4988
4989 public dllexport DataMember eClass_AddDataMember(Class _class, char * name, char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
4990 {
4991    if(_class && name)
4992    {
4993       if(!_class.members.FindString(name)) 
4994       {
4995          DataMember dataMember;
4996
4997          if(alignment)
4998          {
4999             _class.structAlignment = Max(_class.structAlignment, alignment);
5000
5001             if(_class.memberOffset % alignment)
5002                _class.memberOffset += alignment - (_class.memberOffset % alignment);
5003          }
5004          
5005          dataMember = DataMember {
5006             name = CopyString(name);
5007             dataTypeString = CopyString(type);
5008             id = _class.memberID++;
5009             _class = _class;
5010             offset = _class.memberOffset;
5011             memberOffset = size;
5012             memberAccess = declMode;
5013             membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5014          };
5015          _class.membersAndProperties.Add(dataMember);
5016          _class.memberOffset += size;
5017
5018          _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5019          return dataMember;
5020       }
5021    }
5022    return null;
5023 }
5024
5025 public dllexport DataMember eMember_AddDataMember(DataMember member, char * name, char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
5026 {
5027    if(name && !member.membersAlpha.FindString(name)) 
5028    {
5029       DataMember dataMember;
5030
5031       if(alignment)
5032       {
5033          member.structAlignment = Max(member.structAlignment, alignment);
5034
5035          if(member.memberOffset % alignment)
5036             member.memberOffset += alignment - (member.memberOffset % alignment);
5037       }
5038       dataMember = DataMember {
5039          name = CopyString(name);
5040          _class = member._class;
5041          dataTypeString = CopyString(type);
5042          id = member.memberID++;
5043          offset = (member.type == unionMember) ? 0 : member.memberOffset;
5044          memberAccess = declMode;
5045          membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5046       };
5047       member.members.Add(dataMember);
5048       if(member.type == unionMember)
5049       {
5050          if(size > member.memberOffset)
5051             member.memberOffset = size;
5052       }
5053       else
5054          member.memberOffset += size;
5055       member.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5056       return dataMember;
5057    }
5058    return null;
5059 }
5060
5061 public dllexport DataMember eMember_New(DataMemberType type, AccessMode declMode)
5062 {
5063    return DataMember { type = type, memberAccess = declMode, membersAlpha.CompareKey = (void *)BinaryTree::CompareString };
5064 }
5065
5066 static void SetMemberClass(DataMember member, Class _class)
5067 {
5068    DataMember dataMember;
5069    member._class = _class;
5070    for(dataMember = member.members.first; dataMember; dataMember = dataMember.next)
5071       SetMemberClass(dataMember, _class);      
5072 }
5073
5074 public dllexport bool eMember_AddMember(DataMember addTo, DataMember dataMember)
5075 {
5076    if(dataMember.name && addTo.membersAlpha.FindString(dataMember.name)) return false;
5077    addTo.members.Add(dataMember);
5078
5079    if(dataMember.name)
5080       addTo.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5081
5082    dataMember._class = addTo._class;
5083    // ? SetMemberClass(dataMember, addTo._class);
5084
5085    //dataMember.id = addTo.memberID++;
5086    dataMember.id = addTo.memberID;
5087    if(dataMember.type == unionMember)
5088       addTo.memberID += 1;
5089    else
5090       addTo.memberID += dataMember.memberID;
5091
5092    addTo.structAlignment = Max(addTo.structAlignment, dataMember.structAlignment);
5093    dataMember.offset = (addTo.type == unionMember) ? 0 : addTo.memberOffset;
5094    if(addTo.type == unionMember)
5095    {
5096       if(dataMember.memberOffset > addTo.memberOffset)
5097          addTo.memberOffset = dataMember.memberOffset;
5098    }
5099    else
5100       addTo.memberOffset += dataMember.memberOffset;
5101    return true;
5102 }
5103
5104 public dllexport bool eClass_AddMember(Class _class, DataMember dataMember)
5105 {
5106    if(!_class || _class.comRedefinition || (dataMember.name && _class.members.FindString(dataMember.name)))
5107       return false;
5108    _class.membersAndProperties.Add(dataMember);
5109
5110    if(dataMember.name)
5111       _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5112
5113    //dataMember._class = _class;
5114    SetMemberClass(dataMember, _class);
5115
5116    //dataMember.id = _class.memberID++;
5117    dataMember.id = _class.memberID;
5118
5119    _class.structAlignment = Max(_class.structAlignment, dataMember.structAlignment);
5120    if(dataMember.type == unionMember)
5121       _class.memberID += 1;
5122    else
5123       _class.memberID += dataMember.memberID;
5124    dataMember.offset = _class.memberOffset;
5125    _class.memberOffset += dataMember.memberOffset;
5126    return true;
5127 }
5128
5129 public dllexport BitMember eClass_AddBitMember(Class _class, char * name, char * type, int bitSize, int bitPos, AccessMode declMode)
5130 {
5131    if(_class && name && !_class.members.FindString(name)) 
5132    {
5133       uint64 mask = 0;
5134       int c;
5135       BitMember bitMember
5136       {
5137          name = CopyString(name);
5138          _class = _class;
5139          dataTypeString = CopyString(type);
5140          id = _class.memberID++;
5141          memberAccess = declMode;
5142       };
5143       _class.membersAndProperties.Add(bitMember);
5144       if(bitSize)
5145       {
5146          bitMember.pos = (bitPos == -1) ? _class.memberOffset : bitPos;
5147          bitMember.size = bitSize;
5148          _class.memberOffset = bitMember.pos + bitMember.size;
5149          for(c = 0; c<bitSize; c++)
5150          {
5151             if(c)
5152                mask <<= 1;
5153             mask |= 1;
5154          }
5155          bitMember.mask = mask << bitMember.pos;
5156       }
5157
5158      _class.members.Add((BTNode)BTNamedLink { name = bitMember.name, data = bitMember });
5159       return bitMember;
5160    }
5161    return null;
5162 }
5163
5164 static Module Module_Load(Module fromModule, char * name, AccessMode importAccess, bool ensureCOM)
5165 {
5166    bool (stdcall * Load)(Module module) = null;
5167    bool (stdcall * Unload)(Module module) = null;
5168    Module module;
5169
5170    for(module = fromModule.application.allModules.first; module; module = module.next)
5171    {
5172       if(!strcmp(module.name, name))
5173          break;
5174    }
5175    if(ensureCOM && (!strcmp(name, "ecereCOM") || !strcmp(name, "ecere")))
5176    {
5177       for(module = fromModule.application.allModules.first; module; module = module.next)
5178       {
5179          if(!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM"))
5180             break;
5181       }
5182    }
5183    if(!module)
5184    {
5185       void * library = null;
5186
5187       if(ensureCOM && !strcmp(name, "ecereCOM"))
5188       {
5189          Load = COM_LOAD_FUNCTION;
5190          Unload = COM_UNLOAD_FUNCTION;
5191       }
5192       else
5193       {
5194          char * libLocation = null;
5195 #if defined(__ANDROID__)
5196          libLocation = AndroidInterface_GetLibLocation();
5197 #endif
5198          library = Instance_Module_Load(libLocation, name, &Load, &Unload);
5199       }
5200       if(Load)
5201       {
5202          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5203          module.application = fromModule.application;
5204          module.library = library;
5205          module.name = CopyString(name);
5206          module.Unload = Unload;
5207          module.origImportType = normalImport;
5208
5209          if(!Load(module))
5210          {
5211             eInstance_Delete((Instance)module);
5212             module = null;
5213          }
5214       }
5215       fromModule.application.allModules.Add(module);
5216    }
5217    if(ensureCOM && !strcmp(name, "ecere") && module)
5218    {
5219       name = !strcmp(module.name, "ecereCOM") ? "ecere" : "ecereCOM";
5220       if((!Load && !strcmp(module.name, "ecereCOM")) || 
5221          (Load && (!__thisModule || !__thisModule.name || !strcmp(__thisModule.name, "ecereCOM")) && Load != COM_LOAD_FUNCTION))
5222       {
5223          Module module;
5224          for(module = fromModule.application.allModules.first; module; module = module.next)
5225          {
5226             if(!strcmp(module.name, name))
5227                break;
5228          }
5229          if(!module)
5230          {
5231             Load = COM_LOAD_FUNCTION;
5232             Unload = COM_UNLOAD_FUNCTION;
5233
5234             module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5235             module.application = fromModule.application;
5236             module.library = null;
5237             module.name = CopyString(name);
5238             module.Unload = Unload;
5239
5240             if(!Load(module))
5241             {
5242                eInstance_Delete((Instance)module);
5243                module = null;
5244             }
5245
5246             fromModule.application.allModules.Add(module);
5247          }
5248          if(module)
5249          {
5250             if(fromModule)
5251             {
5252                fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5253             }
5254             incref module;
5255          }
5256       }
5257    }
5258    if(module)
5259    {
5260       if(fromModule)
5261       {
5262          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5263       }
5264       incref module;
5265    }
5266 #if defined(_DEBUG)
5267    InternalModuleLoadBreakpoint();
5268 #endif
5269    return module;
5270 }
5271
5272 public dllexport Module eModule_Load(Module fromModule, char * name, AccessMode importAccess)
5273 {
5274    return Module_Load(fromModule, name, importAccess, true);
5275 }
5276
5277 public dllexport Module eModule_LoadStrict(Module fromModule, char * name, AccessMode importAccess)
5278 {
5279    return Module_Load(fromModule, name, importAccess, false);
5280 }
5281
5282 public dllexport Module eModule_LoadStatic(Module fromModule, char * name, AccessMode importAccess, bool (* Load)(Module module), bool (* Unload)(Module module))
5283 {
5284    Module module;
5285    for(module = fromModule.application.allModules.first; module; module = module.next)
5286    {
5287       if(!strcmp(module.name, name))
5288          break;
5289    }
5290    if(!module)
5291    {
5292       if(Load)
5293       {
5294          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5295          module.application = fromModule.application;
5296          module.name = CopyString(name);
5297          module.origImportType = staticImport;
5298          module.Unload = (void *)Unload;
5299          if(!Load(module))
5300          {
5301             eInstance_Delete((Instance)module);
5302             module = null;
5303          }
5304       }
5305       fromModule.application.allModules.Add(module);
5306    }
5307    if(module)
5308    {
5309       if(fromModule)
5310       {
5311          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5312       }
5313       incref module;
5314    }
5315    return module;
5316 }
5317
5318 public dllexport void eModule_Unload(Module fromModule, Module module)
5319 {
5320    OldLink m;
5321    for(m = fromModule.modules.first; m; m = m.next)
5322    {
5323       if(m.data == module)
5324          break;
5325    }
5326    if(m)
5327    {
5328       fromModule.modules.Delete(m);
5329       delete module;
5330    }
5331 }
5332
5333 public dllexport void eEnum_AddFixedValue(Class _class, char * string, int value)
5334 {
5335    if(_class && _class.type == enumClass)
5336    {
5337       EnumClassData data = (EnumClassData)_class.data;
5338       NamedLink item;
5339       
5340       for(item = data.values.first; item; item = item.next)
5341          if(!strcmp(item.name, string)) 
5342             break;
5343       if(!item)
5344       {
5345          data.values.Add(NamedLink { data = (void *)value, name = CopyString(string) });
5346          if(value > data.largest)
5347             data.largest = value;
5348       }
5349    }
5350 }
5351
5352 public dllexport int eEnum_AddValue(Class _class, char * string)
5353 {
5354    if(_class && _class.type == enumClass)
5355    {
5356       EnumClassData data = (EnumClassData)_class.data;
5357       int value = ((int) data.largest) + 1;
5358       NamedLink item;
5359       for(item = data.values.first; item; item = item.next)
5360          if(!strcmp(item.name, string)) 
5361             break;
5362       if(!item)
5363       {
5364          data.values.Add(NamedLink { data = (void *)value, name = CopyString(string) });
5365          if(value > data.largest)
5366             data.largest = value;
5367          return value;
5368       }
5369    }
5370    return -1;
5371 }
5372
5373 static void NameSpace_Free(NameSpace parentNameSpace)
5374 {
5375    NameSpace * nameSpace;
5376    delete parentNameSpace.name;
5377
5378    while((nameSpace = (NameSpace *)parentNameSpace.nameSpaces.first))
5379    {
5380       NameSpace_Free(nameSpace);
5381       parentNameSpace.nameSpaces.Delete((BTNode)nameSpace);
5382    }
5383 }
5384
5385 static void Application_Destructor(Application app)
5386 {
5387    if(app.parsedCommand)
5388    {
5389       delete app.argv;
5390       delete app.parsedCommand;
5391    }
5392 }
5393
5394 static bool Module_Constructor(Module module)
5395 {
5396    module.privateNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5397    module.privateNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5398    module.privateNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5399    module.privateNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5400
5401    module.publicNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5402    module.publicNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5403    module.publicNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5404    module.publicNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5405    return true;
5406 }
5407
5408 static void Module_Destructor(Module module)
5409 {
5410    Class _class;
5411    DefinedExpression def;
5412    GlobalFunction function;
5413    Module m;
5414    SubModule handle;
5415
5416    // printf("Destructing module %s\n", module.name);
5417
5418    // Take out references from all modules
5419    for(m = module.application.allModules.first; m; m = m.next)
5420    {
5421       SubModule next;
5422       for(handle = m.modules.first; handle; handle = next)
5423       {
5424          next = handle.next;
5425          if(handle.module == module)
5426             m.modules.Delete(handle);
5427       }
5428    }
5429
5430    if(module.Unload)
5431    {
5432       if(module.origImportType == staticImport)
5433       {
5434          bool (* Unload)(Module module) = (void *)module.Unload;
5435          Unload(module);
5436       }
5437       else
5438       {
5439          bool (stdcall * Unload)(Module module) = (void *)module.Unload;
5440          Unload(module);
5441       }
5442    }
5443
5444    // Unload dependencies
5445    {
5446       Module ourWorld = class(Class).module;
5447       void * ourHandle = null;
5448       while((handle = module.modules.last))  // STARTING WITH LAST SO THAT ecereCOM IS UNLOADED LAST...
5449       {
5450          Module depModule = handle.module;
5451          if(depModule == ourWorld) 
5452          {
5453             module.modules.Remove(handle);
5454             ourHandle = handle;
5455          }
5456          else
5457          {
5458             module.modules.Delete(handle);
5459             delete depModule;
5460          }         
5461       }
5462       if(ourHandle)
5463       {
5464          delete ourHandle;
5465          delete ourWorld;
5466       }
5467    }
5468
5469    // Unload classes
5470    for(;(_class = module.classes.first);)
5471    {
5472       if(_class.nameSpace)
5473       {
5474          BTNamedLink classLink = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
5475          OldLink t;
5476          for(t = _class.templatized.first; t; t = t.next)
5477          {
5478             Class template = t.data;
5479             BTNamedLink link;
5480             link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
5481
5482             template.nameSpace->classes.Delete((BTNode)link);
5483             template.nameSpace = null;
5484          }
5485          _class.nameSpace->classes.Delete((BTNode)classLink);
5486          _class.nameSpace = null;
5487       }
5488       _class.module = null;
5489       module.classes.Remove(_class);
5490       if(!_class.count || _class.type != normalClass)
5491          eClass_Unregister(_class);
5492       else
5493       {
5494 #ifdef MEMINFO
5495          // printf("Delayed destruction of class %s\n", _class.name);
5496 #endif
5497       }
5498    }
5499
5500    // Unload defines
5501    for(;(def = module.defines.first);)
5502    {
5503       if(def.nameSpace)
5504       {
5505          BTNamedLink defLink;
5506          for(defLink = (BTNamedLink)def.nameSpace->defines.first; defLink; defLink = (BTNamedLink)((BTNode)defLink).next)
5507             if(defLink.data == def)
5508             {
5509                def.nameSpace->defines.Delete((BTNode)defLink);
5510                break;
5511             }
5512       }
5513       delete def.name;
5514       delete def.value;
5515       module.defines.Delete(def);
5516    }
5517
5518    // Unload functions
5519    for(;(function = module.functions.first);)
5520    {
5521       if(function.nameSpace)
5522       {
5523          BTNamedLink functionLink;
5524          for(functionLink = (BTNamedLink)function.nameSpace->functions.first; functionLink; functionLink = (BTNamedLink)((BTNode)functionLink).next)
5525             if(functionLink.data == function)
5526             {
5527                function.nameSpace->functions.Delete((BTNode)functionLink);
5528                break;
5529             }
5530       }
5531       delete function.name;
5532       delete function.dataTypeString;
5533       module.functions.Delete(function);
5534    }
5535
5536    delete module.name;
5537
5538    NameSpace_Free(module.privateNameSpace);
5539    NameSpace_Free(module.publicNameSpace);
5540
5541    if(module != module.application)
5542       module.application.allModules.Remove(module);
5543    else
5544       NameSpace_Free(module.application.systemNameSpace);
5545
5546 #ifndef MEMINFO
5547    Instance_Module_Free(module.library);
5548 #endif
5549 }
5550
5551 static int64 GetEnumSize(Class _class)
5552 {
5553    EnumClassData data = (EnumClassData)_class.data;
5554    return data.largest+1;
5555 }
5556
5557 #if defined(__GNUC__)
5558 #define strcmpi strcasecmp
5559 #define strnicmp strncasecmp
5560 #endif
5561
5562 #if defined(ECERE_BOOTSTRAP) || (defined(__GNUC__) && !defined(__DJGPP__) && !defined(__WIN32__))
5563 #undef strlwr
5564 #undef strupr
5565 default dllexport char * strlwr(char *string)
5566 {
5567    int c;
5568    for(c=0; string[c]; c++)
5569       if(string[c]>='A' && string[c]<='Z')
5570          string[c]+='a'-'A';
5571    return string;
5572 }
5573 default dllexport char * strupr(char *string)
5574 {
5575    int c;
5576    for(c=0; string[c]; c++)
5577       if(string[c]>='a' && string[c]<='z')
5578          string[c]-='a'-'A';
5579    return string;
5580 }
5581 #endif
5582
5583 public dllexport DefinedExpression eSystem_RegisterDefine(char * name, char * value, Module module, AccessMode declMode)
5584 {
5585    NameSpace * nameSpace = null;
5586    
5587    int start = 0, c;
5588
5589    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5590    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5591
5592    if(declMode != staticAccess)
5593    {
5594       for(c = 0; name[c]; c++)
5595       {
5596          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5597          {
5598             NameSpace * newSpace;
5599
5600             char * spaceName = _malloc(c - start + 1);
5601             strncpy(spaceName, name + start, c - start);
5602             spaceName[c-start] = '\0';
5603
5604             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5605             if(!newSpace)
5606             {
5607                newSpace = new0 NameSpace[1];
5608                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5609                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5610                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5611                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5612                newSpace->name = spaceName;
5613                newSpace->parent = nameSpace;
5614                nameSpace->nameSpaces.Add((BTNode)newSpace);
5615             }
5616             else
5617                delete spaceName;
5618             nameSpace = newSpace;
5619             if(name[c] == ':') c++;
5620             start = c+1;         
5621          }
5622       }
5623    }
5624    else
5625       c = strlen(name);
5626
5627    if(c - start && !nameSpace->defines.FindString(name + start))
5628    {
5629       DefinedExpression def
5630       {
5631          name = CopyString(name);
5632          nameSpace = nameSpace;
5633          value = CopyString(value);
5634       };
5635       nameSpace->defines.Add((BTNode)BTNamedLink { name = def.name + start, data = def });
5636       // Reference the definition in the module
5637       module.defines.Add(def);
5638       return def;
5639    }
5640    return null;
5641 }
5642
5643 public dllexport GlobalFunction eSystem_RegisterFunction(char * name, char * type, void * func, Module module, AccessMode declMode)
5644 {
5645    NameSpace * nameSpace = null;
5646    int start = 0, c;
5647
5648    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5649    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5650
5651    if(declMode != staticAccess)
5652    {
5653       for(c = 0; name[c]; c++)
5654       {
5655          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5656          {
5657             NameSpace * newSpace;
5658
5659             char * spaceName = _malloc(c - start + 1);
5660             strncpy(spaceName, name + start, c - start);
5661             spaceName[c-start] = '\0';
5662
5663             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5664             if(!newSpace)
5665             {
5666                newSpace = new0 NameSpace[1];
5667                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5668                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5669                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5670                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5671                newSpace->name = spaceName;
5672                newSpace->parent = nameSpace;
5673                nameSpace->nameSpaces.Add((BTNode)newSpace);
5674             }
5675             else
5676                delete spaceName;
5677             nameSpace = newSpace;
5678             if(name[c] == ':') c++;
5679             start = c+1;         
5680          }
5681       }
5682    }
5683    else
5684       c = strlen(name);
5685
5686    if(c - start && !nameSpace->functions.FindString(name + start))
5687    {
5688       GlobalFunction function
5689       {
5690          name = CopyString(name);
5691          nameSpace = nameSpace;
5692          dataTypeString = CopyString(type);
5693          function = func;
5694          module = module;
5695       };
5696       nameSpace->functions.Add((BTNode)BTNamedLink { name = function.name + start, data = function });
5697       // Reference the definition in the module
5698       module.functions.Add(function);
5699       return function;
5700    }
5701    return null;
5702 }
5703
5704 public dllexport DefinedExpression eSystem_FindDefine(Module module, char * name)
5705 {
5706    if(name && module)
5707    {
5708       BTNamedLink link;
5709       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->defines);
5710       if(link) return link.data;
5711
5712       link = SearchModule(module, name, &((NameSpace *)0)->defines, true);
5713       if(link) return link.data;
5714    }
5715    return null;
5716 }
5717
5718 public dllexport GlobalFunction eSystem_FindFunction(Module module, char * name)
5719 {
5720    if(name && module)
5721    {
5722       BTNamedLink link;
5723       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->functions);
5724       if(link) return link.data;
5725
5726       link = SearchModule(module, name, &((NameSpace *)0)->functions, true);
5727       if(link) return link.data;
5728    }
5729    return null;
5730 }
5731
5732 public dllexport void * eSystem_Renew(void * memory, unsigned int size)
5733 {
5734    return _realloc(memory, size);
5735 }
5736
5737 public dllexport void * eSystem_Renew0(void * memory, unsigned int size)
5738 {
5739    return _crealloc(memory, size);
5740 }
5741
5742 public dllexport void * eSystem_New(unsigned int size)
5743 {
5744 /*#ifdef _DEBUG
5745    void * pointer = _malloc(size);
5746    memset(pointer, 0xec, size);
5747    return pointer;
5748 #else*/
5749    return _malloc(size);
5750 //#endif
5751 }
5752
5753 public dllexport void * eSystem_New0(unsigned int size)
5754 {
5755    return _calloc(1,size);
5756 }
5757
5758 public dllexport void eSystem_Delete(void * memory)
5759 {
5760    if(memory)
5761       _free(memory);
5762 }
5763
5764 // Properties
5765 public dllexport void eInstance_FireSelfWatchers(Instance instance, Property _property)
5766 {
5767    if(instance && _property && _property.selfWatchable)
5768    {
5769       Class _class;
5770       for(_class = instance._class; _class; _class = _class.base)
5771       {
5772          SelfWatcher selfWatcher, next;
5773          for(selfWatcher = _class.selfWatchers.first; selfWatcher; selfWatcher = next)
5774          {
5775             next = selfWatcher.next;
5776             if(selfWatcher._property == _property)
5777                selfWatcher.callback(instance);
5778          }
5779       }
5780    }
5781 }
5782
5783 public dllexport void eInstance_FireWatchers(Instance instance, Property _property)
5784 {
5785    if(instance && _property && _property.isWatchable)
5786    {
5787       Module module = instance._class ? instance._class.module : null;
5788       Application application = module ? module.application : null;
5789       int flags = application ? application.isGUIApp : 0;
5790       bool inCompiler = (flags & 8) ? true : false;
5791       bool force32Bits = (flags & 4) ? true : false;
5792       if(!force32Bits || !inCompiler)
5793       {
5794          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5795          Watcher watcher, next;
5796
5797          for(watcher = watchers->first; watcher; watcher = next)
5798          {
5799             next = watcher.next;
5800             watcher.callback(watcher.object, instance);
5801          }
5802       }
5803    }
5804 }
5805
5806 public dllexport void eProperty_Watchable(Property _property)
5807 {
5808    if(!_property.isWatchable)
5809    {
5810       Class _class = _property._class;
5811       if(!_class.computeSize)
5812       {
5813          _property.watcherOffset = _class.structSize;
5814          _class.structSize += sizeof(OldList);
5815
5816          // highly inefficient
5817          FixDerivativesBase(_class, _class);
5818       }
5819       _property.isWatchable = true;
5820    }
5821 }
5822
5823 public dllexport void eClass_DestructionWatchable(Class _class)
5824 {
5825    if(!_class.destructionWatchOffset)
5826    {
5827       _class.destructionWatchOffset = _class.structSize;
5828       _class.structSize += sizeof(OldList);
5829       // highly inefficient
5830       FixDerivativesBase(_class, _class);
5831    }
5832 }
5833
5834 public dllexport void eProperty_SelfWatch(Class _class, char * name, void (*callback)(void *))
5835 {
5836    if(_class)
5837    {
5838       Property _property = eClass_FindProperty(_class, name, _class.module);
5839       
5840       if(!_property)
5841          _property = eClass_AddProperty(_class, name, null, null, null, baseSystemAccess /*privateAccess*/);
5842       _class.selfWatchers.Add(SelfWatcher { _property = _property, callback = callback });
5843       _property.selfWatchable = true;
5844    }
5845 }
5846
5847 public dllexport void eInstance_Watch(void * instance, Property _property, void * object, void (*callback)(void *, void *))
5848 {
5849    if(_property.isWatchable)
5850    {
5851       OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5852       watchers->Add(Watcher { callback = callback, object = object });
5853    }
5854 }
5855
5856 public dllexport void eInstance_WatchDestruction(Instance instance, Instance object, void (*callback)(Instance, Instance))
5857 {
5858    OldList * watchers = (OldList *)((byte *)instance + instance._class.destructionWatchOffset);
5859    watchers->Add(Watcher { callback = callback, object = object });
5860 }
5861
5862 public dllexport void eInstance_StopWatching(Instance instance, Property _property, Instance object)
5863 {
5864    if(instance && (!_property || _property.isWatchable))
5865    {
5866       if(_property)
5867       {
5868          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5869          Watcher watcher;
5870          for(watcher = watchers->first; watcher; watcher = watcher.next)
5871             if(watcher.object == object)
5872             {
5873                watchers->Delete(watcher);
5874                break;
5875             }
5876       }
5877       else
5878       {
5879          // Stop watching all properties as well as destruction
5880          Class _class, base;
5881          for(_class = instance._class; _class; _class = base)
5882          {
5883             if(_class.destructionWatchOffset)
5884             {
5885                OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
5886                Watcher watcher;
5887
5888                for(watcher = watchers->first; watcher; watcher = watcher.next)
5889                {
5890                   watchers->Delete(watcher);
5891                   break;
5892                }
5893             }
5894             for(_property = (Property)_class.membersAndProperties.first; _property; _property = _property.next)
5895             {
5896                if(_property.isProperty && _property.isWatchable)
5897                {
5898                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5899                   Watcher watcher;
5900                   for(watcher = watchers->first; watcher; watcher = watcher.next)
5901                      if(watcher.object == object)
5902                      {
5903                         watchers->Delete(watcher);
5904                         break;
5905                      }
5906                }
5907             }
5908             base = _class.base;
5909             if(base && base.type == systemClass) base = null;
5910          }
5911       }
5912    }
5913 }
5914
5915 public dllexport subclass(ClassDesignerBase) eClass_GetDesigner(Class _class)
5916 {
5917    for(;_class;_class = _class.base)
5918    {
5919       if(_class.designerClass)
5920          return (subclass(ClassDesignerBase))eSystem_FindClass(_class.module, _class.designerClass);
5921    }
5922    return null;
5923 }
5924
5925
5926 public dllexport subclass(ClassDesignerBase) eInstance_GetDesigner(Instance instance)
5927 {
5928    if(instance)
5929       return eClass_GetDesigner(instance._class);
5930    return null;
5931 }
5932
5933 public bool LocateModule(char * name, char * fileName)
5934 {
5935    return Instance_LocateModule(name, fileName);
5936 }
5937
5938 static void LoadCOM(Module module)
5939 {
5940    bool force64Bits = (module.application.isGUIApp & 2) ? true : false;
5941    bool force32Bits = (module.application.isGUIApp & 4) ? true : false;
5942    bool inCompiler = (module.application.isGUIApp & 8) ? true : false;
5943    int pointerSize = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
5944    Class applicationClass;
5945    Class enumClass, structClass, boolClass;
5946    Class moduleClass;
5947
5948    // Create Base Class
5949    Class baseClass = eSystem_RegisterClass(normalClass, "class", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5950    baseClass.type = systemClass;
5951    baseClass.memberOffset = 0;
5952    baseClass.offset = 0;
5953    baseClass.structSize = 0;
5954    baseClass.typeSize = 0;
5955
5956    {
5957       Class instanceClass = eSystem_RegisterClass(normalClass, "ecere::com::Instance", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5958       // Instance should really be a Normal class, but inheritance checks for systemClass to see if something has a non system ancestor
5959       instanceClass.type = systemClass;
5960       instanceClass.fixed = true;
5961       instanceClass.memberOffset = 0;
5962       instanceClass.offset = 0;
5963
5964       instanceClass.memberID = -3;
5965       instanceClass.startMemberID = -3;
5966
5967       eClass_AddDataMember(instanceClass, "_vTbl", "int (**)()", pointerSize, pointerSize, publicAccess);
5968       eClass_AddDataMember(instanceClass, "_class", "ecere::com::Class", pointerSize, pointerSize, publicAccess);
5969       eClass_AddDataMember(instanceClass, "_refCount", "int", sizeof(int), sizeof(int), publicAccess);
5970    }
5971
5972    InitializeDataTypes1(module);
5973
5974    // Create Enum class
5975    enumClass = eSystem_RegisterClass(normalClass, "enum", null, 0, force64Bits ? 40 : sizeof(class EnumClassData), null, null, module, baseSystemAccess, publicAccess);
5976    eClass_AddClassProperty(enumClass, "enumSize", "int", null, GetEnumSize).constant = true;
5977    enumClass.type = systemClass;
5978    
5979    delete enumClass.dataTypeString;
5980    enumClass.dataTypeString = CopyString(/*"unsigned int"*/"int");
5981
5982    // Create Struct (simple) class
5983    //structClass = eSystem_RegisterClass(structClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5984    structClass = eSystem_RegisterClass(normalClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5985    structClass.type = systemClass;
5986    structClass.memberOffset = 0;
5987    structClass.offset = 0;
5988    structClass.structSize = 0;
5989    structClass.typeSize = 0;
5990
5991    //eClass_AddMethod(enumClass, "AddValue", "int()", eEnum_AddValue);
5992    //eClass_AddMethod(enumClass, "AddFixedValue", "void()", eEnum_AddFixedValue);
5993
5994    InitializeDataTypes(module);
5995
5996    // Create bool class
5997    boolClass = eSystem_RegisterClass(ClassType::enumClass, "bool", "uint", 0, 0, null, null, module, baseSystemAccess, publicAccess);
5998    eEnum_AddFixedValue(boolClass, "true",  bool::true);
5999    eEnum_AddFixedValue(boolClass, "false", bool::false);
6000
6001    // Create Module class
6002    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) :
6003                                                                                 sizeof(struct Module), 0, (void *)Module_Constructor, (void *)Module_Destructor, module, baseSystemAccess, publicAccess);
6004    eClass_AddVirtualMethod(moduleClass, "OnLoad", "bool()", null, publicAccess);
6005    eClass_AddVirtualMethod(moduleClass, "OnUnload", "void()", null, publicAccess);
6006    eClass_AddMethod(moduleClass, "Load", "Module(char * name, AccessMode importAccess)", eModule_Load, publicAccess);
6007    eClass_AddMethod(moduleClass, "Unload", "void(Module module)", eModule_Unload, publicAccess);
6008    eClass_AddDataMember(moduleClass, "application", "Application", pointerSize, pointerSize, publicAccess);
6009    eClass_AddDataMember(moduleClass, "classes", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6010    eClass_AddDataMember(moduleClass, "defines", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6011    eClass_AddDataMember(moduleClass, "functions", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6012    eClass_AddDataMember(moduleClass, "modules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6013    eClass_AddDataMember(moduleClass, "prev", "Module", pointerSize, pointerSize, publicAccess);
6014    eClass_AddDataMember(moduleClass, "next", "Module", pointerSize, pointerSize, publicAccess);
6015    eClass_AddDataMember(moduleClass, "name", "char *", pointerSize, pointerSize, publicAccess);
6016    eClass_AddDataMember(moduleClass, "library", "void *", pointerSize, pointerSize, publicAccess);
6017    eClass_AddDataMember(moduleClass, "Unload", "void *", pointerSize, pointerSize, publicAccess);
6018    eClass_AddDataMember(moduleClass, "importType", "ImportType", sizeof(ImportType), 4, publicAccess);
6019    eClass_AddDataMember(moduleClass, "origImportType", "ImportType", sizeof(ImportType), 4, publicAccess);
6020    eClass_AddDataMember(moduleClass, "privateNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6021    eClass_AddDataMember(moduleClass, "publicNameSpace", "NameSpace",  force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6022    moduleClass.fixed = true;
6023    moduleClass.count++;
6024    if(inCompiler && force32Bits)
6025       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);
6026    
6027    // Create Application class
6028    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);
6029    if(inCompiler && force32Bits)
6030    {
6031       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);
6032       applicationClass.structSize = applicationClass.offset + (4+4+4+4 + 20 + 4 + 88);
6033    }
6034    eClass_AddVirtualMethod(applicationClass, "Main", "void()", null, publicAccess);
6035    eClass_AddDataMember(applicationClass, "argc", "int", sizeof(int), 4, publicAccess);
6036    eClass_AddDataMember(applicationClass, "argv", "char **", pointerSize, pointerSize, publicAccess);
6037    eClass_AddDataMember(applicationClass, "exitCode", "int", sizeof(int), 4, publicAccess);
6038    eClass_AddDataMember(applicationClass, "isGUIApp", "bool", sizeof(bool), 4, publicAccess);
6039    eClass_AddDataMember(applicationClass, "allModules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6040    eClass_AddDataMember(applicationClass, "parsedCommand", "char *", pointerSize, pointerSize, publicAccess);
6041    eClass_AddDataMember(applicationClass, "systemNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6042    applicationClass.fixed = true;
6043    applicationClass.count++;
6044
6045    //AttachConsole(-1);
6046    //AllocConsole();
6047
6048    // --- Math ---
6049    eSystem_RegisterFunction("sin", "double sin(Angle number)", sin, module, baseSystemAccess);
6050    eSystem_RegisterFunction("sinh", "double sinh(Angle number)", sinh, module, baseSystemAccess);
6051    eSystem_RegisterFunction("cosh", "double cosh(Angle number)", cosh, module, baseSystemAccess);
6052    eSystem_RegisterFunction("tanh", "double tanh(Angle number)", tanh, module, baseSystemAccess);
6053    eSystem_RegisterFunction("sqrt", "double sqrt(double number)", sqrt, module, baseSystemAccess);
6054    eSystem_RegisterFunction("cos", "double cos(Angle number)", cos, module, baseSystemAccess);
6055    eSystem_RegisterFunction("tan", "double tan(Angle number)", tan, module, baseSystemAccess);
6056    eSystem_RegisterFunction("atan2", "Angle atan2(double y, double x)", atan2, module, baseSystemAccess);
6057    eSystem_RegisterFunction("asin", "Angle asin(double number)", asin, module, baseSystemAccess);
6058    eSystem_RegisterFunction("acos", "Angle acos(double number)", acos, module, baseSystemAccess);
6059    eSystem_RegisterFunction("atan", "Angle atan(double number)", atan, module, baseSystemAccess);
6060    eSystem_RegisterFunction("pow", "double pow(double number, double number2)", pow, module, baseSystemAccess);
6061    eSystem_RegisterFunction("fmod", "double fmod(double x, double y)", fmod, module, baseSystemAccess);
6062    eSystem_RegisterFunction("fabs", "double fabs(double number)", fabs, module, baseSystemAccess);
6063    eSystem_RegisterFunction("log", "double log(double number)", log, module, baseSystemAccess);
6064    eSystem_RegisterFunction("log10", "double log10(double number)", log10, module, baseSystemAccess);
6065    eSystem_RegisterFunction("ceil", "double ceil(double number)", ceil, module, baseSystemAccess);
6066    eSystem_RegisterFunction("floor", "double floor(double number)", floor, module, baseSystemAccess);
6067    eSystem_RegisterFunction("exp", "double exp(double number)", exp, module, baseSystemAccess);
6068
6069    // --- Stdlib ---
6070    eSystem_RegisterFunction("qsort", "void qsort(void *, uintsize, uintsize, int (*)(void *, void *))", qsort, module, baseSystemAccess);
6071    eSystem_RegisterFunction("strtod", "double strtod(char*, char**)", strtod, module, baseSystemAccess);
6072    eSystem_RegisterFunction("strtol", "int strtol(char*, char**, int base)", strtol, module, baseSystemAccess);
6073    eSystem_RegisterFunction("system", "int system(const char*)", system, module, baseSystemAccess);
6074    eSystem_RegisterFunction("atoi", "int atoi(const char*)", atoi, module, baseSystemAccess);
6075    eSystem_RegisterFunction("atof", "float atof(const char*)", atof, module, baseSystemAccess);
6076    eSystem_RegisterFunction("tolower", "int tolower(int)", tolower, module, baseSystemAccess);
6077    eSystem_RegisterFunction("toupper", "int toupper(int)", toupper, module, baseSystemAccess);
6078    eSystem_RegisterFunction("isdigit", "bool isdigit(int)", isdigit, module, baseSystemAccess);
6079    eSystem_RegisterFunction("memset", "void * memset(void * area, int value, uintsize count)", memset, module, baseSystemAccess);
6080    eSystem_RegisterFunction("getenv", "char * getenv(const char * name)", getenv, module, baseSystemAccess);
6081    eSystem_RegisterFunction("rename", "int rename(const char *oldpath, const char *newpath)", rename, module, baseSystemAccess);
6082
6083    // --- String --- (These might move to the string class)
6084    eSystem_RegisterFunction("strlen", "uintsize strlen(const char *)", strlen, module, baseSystemAccess);
6085    eSystem_RegisterFunction("strcat", "char * strcat(char *, const char *)", strcat, module, baseSystemAccess);
6086    eSystem_RegisterFunction("strncat", "char * strncat(char *, const char *, uintsize n)", strncat, module, baseSystemAccess);
6087    eSystem_RegisterFunction("strchr", "char * strchr(const char *, int)", strchr, module, baseSystemAccess);
6088    eSystem_RegisterFunction("strstr", "char * strstr(const char *, const char *)", strstr, module, baseSystemAccess);
6089
6090    eSystem_RegisterDefine("fstrcmp", "(GetRuntimePlatform() == win32) ? strcmpi : strcmp", module, baseSystemAccess);
6091
6092 //#if defined(__GNUC__)
6093    eSystem_RegisterDefine("strcmpi", "strcasecmp", module, baseSystemAccess);
6094    eSystem_RegisterDefine("strnicmp", "strncasecmp", module, baseSystemAccess);
6095    eSystem_RegisterFunction("strcasecmp", "int strcasecmp(const char *, const char *)", strcmpi, module, baseSystemAccess);
6096    eSystem_RegisterFunction("strncasecmp", "int strncasecmp(const char *, const char *, uintsize n)", strnicmp, module, baseSystemAccess);
6097 /*
6098 #else
6099    eSystem_RegisterDefine("strcasecmp", "strcmpi", module, baseSystemAccess);
6100    eSystem_RegisterDefine("strncasecmp", "strnicmp", module, baseSystemAccess);
6101    eSystem_RegisterFunction("strcmpi", "int strcmpi(const char *, const char *)", strcmpi, module, baseSystemAccess);
6102    eSystem_RegisterFunction("strnicmp", "int strnicmp(const char *, const char *, int n)", strnicmp, module, baseSystemAccess);
6103 #endif
6104 */
6105
6106    eSystem_RegisterFunction("strcmp", "int strcmp(const char *, const char *)", strcmp, module, baseSystemAccess);
6107    eSystem_RegisterFunction("strncmp", "int strncmp(const char *, const char *, uintsize n)", strncmp, module, baseSystemAccess);
6108    eSystem_RegisterFunction("strlwr", "char * strlwr(char *)", strlwr, module, baseSystemAccess);
6109    eSystem_RegisterFunction("strupr", "char * strupr(char *)", strupr, module, baseSystemAccess);
6110    eSystem_RegisterFunction("strcpy", "char * strcpy(char *, const char *)", strcpy, module, baseSystemAccess);
6111    eSystem_RegisterFunction("strncpy", "char * strncpy(char *, const char *, uintsize n)", strncpy, module, baseSystemAccess);
6112    eSystem_RegisterFunction("memcpy", "void * memcpy(void *, const void *, uintsize size)", memcpy, module, baseSystemAccess);
6113    eSystem_RegisterFunction("memmove", "void * memmove(void *, const void *, uintsize size)", memmove, module, baseSystemAccess);
6114
6115    // --- Stdio ---
6116    eSystem_RegisterFunction("sprintf", "int sprintf(char *, char *, ...)", sprintf, module, baseSystemAccess);
6117    eSystem_RegisterFunction("snprintf", "int sprintf(char *, uintsize, char *, ...)", snprintf, module, baseSystemAccess);
6118    eSystem_RegisterFunction("printf", "int printf(char *, ...)", printf, module, baseSystemAccess);
6119    eSystem_RegisterFunction("vsprintf", "int vsprintf(char*, const char*, __builtin_va_list)", vsprintf, module, baseSystemAccess);
6120    eSystem_RegisterFunction("vsnprintf", "int vsnprintf(char*, uintsize, const char*, __builtin_va_list)", vsnprintf, module, baseSystemAccess);
6121    eSystem_RegisterFunction("puts", "int puts(char *)", puts, module, baseSystemAccess);
6122    eSystem_RegisterFunction("fputs", "int fputs(char *, void * stream)", fputs, module, baseSystemAccess);
6123
6124    // --- Ctype ---
6125    eSystem_RegisterFunction("isalnum", "int isalnum(int c)", isalnum, module, baseSystemAccess);
6126    eSystem_RegisterFunction("isspace", "int isspace(int c)", isspace, module, baseSystemAccess);
6127    eSystem_RegisterFunction("isalpha", "int isalpha(int c)", isalpha, module, baseSystemAccess);
6128    eSystem_RegisterFunction("islower", "int islower(int c)", islower, module, baseSystemAccess);
6129    eSystem_RegisterFunction("isupper", "int isupper(int c)", isupper, module, baseSystemAccess);
6130    eSystem_RegisterFunction("isprint", "int isprint(int c)", isprint, module, baseSystemAccess);
6131    eSystem_RegisterFunction("strtoul", "unsigned long strtoul(const char * nptr, char ** endptr, int base)", strtoul, module, baseSystemAccess);
6132
6133 }
6134
6135 public dllexport Application __ecere_COM_Initialize(bool guiApp, int argc, char * argv[])
6136 {
6137    Application app;
6138
6139 #ifdef __ANDROID__
6140    // Clean up global variables
6141    memoryInitialized = false;
6142    pools = null;
6143 #ifdef MEMINFO
6144    memset(&memStacks, 0, sizeof(BinaryTree));
6145    memoryErrorsCount = 0;
6146    memset(&memBlocks, 0, sizeof(BinaryTree));
6147    recurse = false;
6148    blockID = 0;
6149    allocateClass = null;
6150    allocateInternal = false;
6151    TOTAL_MEM = 0;
6152    OUTSIDE_MEM = 0;
6153 #endif
6154 #endif
6155
6156 #ifdef _DEBUG
6157    // printf("Using debug ecere runtime library\n");
6158 #endif
6159    app = _calloc(1, sizeof(class Application));
6160
6161    Module_Constructor(app);
6162    app.systemNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
6163    app.systemNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
6164    app.systemNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
6165    app.systemNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
6166
6167    Instance_COM_Initialize(argc, argv, &app.parsedCommand, &app.argc, &app.argv);
6168
6169    app.application = app;
6170    app.allModules.offset = sizeof(class Instance) + (uint)&((struct Module *)0)->prev;
6171    app.isGUIApp = guiApp;
6172
6173    LoadCOM(app);
6174
6175    app._class = eSystem_FindClass(app, "Application");
6176
6177    return app;
6178 }
6179
6180 public dllexport ClassTemplateParameter eClass_AddTemplateParameter(Class _class, char * name, TemplateParameterType type, void * info, ClassTemplateArgument defaultArg)
6181 {
6182    if(_class && name)
6183    {
6184       ClassTemplateParameter param;
6185
6186       for(param = _class.templateParams.first; param; param = param.next)
6187       {
6188          if(!strcmp(param.name, name))
6189             return param;
6190       }
6191       param =
6192       {
6193          name = CopyString(name);
6194          type = type;
6195          (type == identifier) ? info : CopyString(info);
6196       };
6197       if(defaultArg != null) 
6198       {
6199          param.defaultArg = defaultArg;
6200          CopyTemplateArg(param, param.defaultArg);
6201       }
6202       _class.templateParams.Add(param);
6203       return param;
6204    }
6205    return null;
6206 }
6207
6208 public dllexport void eClass_DoneAddingTemplateParameters(Class base)
6209 {
6210    if(base)
6211    {
6212       OldLink derivative;
6213       ClassTemplateParameter param;
6214       {
6215          void * first = base.templateParams.first;
6216          int count = base.templateParams.count;
6217          base.templateParams.first = null;
6218          base.templateParams.count = 0;
6219
6220          FreeTemplateArgs(base);
6221          delete base.templateArgs;
6222          FreeTemplatesDerivatives(base);
6223
6224          base.templateParams.first = first;
6225          base.templateParams.count = count;
6226       }
6227
6228       for(param = base.templateParams.first; param; param = param.next)
6229       {
6230          if(param.type == identifier && param.defaultArg.memberString)
6231          {
6232             Class memberClass = base;
6233             char * colon = strstr(param.defaultArg.memberString, "::");
6234             char * memberName;
6235             if(colon)
6236             {
6237                char className[1024];
6238                Class sClass;
6239
6240                memcpy(className, param.defaultArg.memberString, colon - param.defaultArg.memberString);
6241                className[colon - param.defaultArg.memberString] = '\0';
6242                memberName = colon + 2;
6243
6244                for(sClass = base; sClass; sClass = sClass.base)
6245                {
6246                   ClassTemplateParameter cParam;
6247                   Class nextClass;
6248                   int id = 0;
6249                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) id += nextClass.templateParams.count;
6250                   // Safety! What could cause base.templateArgs to be null?
6251                   if(sClass == base || base.templateArgs)
6252                   {
6253                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
6254                      {
6255                         if(cParam.type == type && !strcmp(cParam.name, className))
6256                            strcpy(className, (sClass == base) ? cParam.defaultArg.dataTypeString : base.templateArgs[id].dataTypeString);
6257                         id++;
6258                      }
6259                   }
6260                }
6261                memberClass = eSystem_FindClass(base.module, className);
6262                if(!memberClass)
6263                   memberClass = eSystem_FindClass(base.module.application, className);
6264             }
6265             else
6266                memberName = param.defaultArg.memberString;
6267
6268             if(memberClass)
6269             {
6270                switch(param.memberType)
6271                {
6272                   case dataMember:
6273                      param.defaultArg.member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
6274                      break;
6275                   case method:
6276                      param.defaultArg.method = eClass_FindMethod(memberClass, memberName, memberClass.module);
6277                      break;
6278                   case prop:
6279                      param.defaultArg.prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
6280                      break;
6281                }
6282             }
6283          }
6284       }      
6285
6286       //ComputeClassParameters(base, null, null);
6287
6288       FixDerivativesBase(base, base);
6289    }
6290 }
6291
6292 static void FreeTemplatesDerivatives(Class base)
6293 {
6294    OldLink derivative, templateLink;
6295    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
6296    {
6297       Class _class = derivative.data;
6298       if(_class.templateArgs)
6299       {
6300          FreeTemplateArgs(_class);
6301          delete _class.templateArgs;
6302       }
6303       FreeTemplatesDerivatives(_class);
6304    }
6305
6306    for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
6307    {
6308       Class _class = templateLink.data;
6309       if(_class.templateArgs)
6310       {
6311          FreeTemplateArgs(_class);
6312          delete _class.templateArgs;
6313       }
6314       FreeTemplatesDerivatives(_class);
6315    }
6316 }
6317
6318 static const char * platformNames[Platform] = { "", "win32", "linux", "apple" }; // how to have this be accessible outside of dll/lib
6319 static const Platform firstPlatform = win32;
6320 static const Platform lastPlatform = apple;
6321
6322 public enum Platform
6323 {
6324    unknown, win32, tux, apple;
6325
6326    property char *
6327    {
6328       get { return OnGetString(null, null, null); }
6329       set
6330       {  
6331          if(value)
6332          {
6333             Platform c;
6334             for(c = firstPlatform; c <= lastPlatform; c++)
6335                if(!strcmpi(value, platformNames[c]))
6336                   return c;
6337          }
6338          return unknown;
6339       }
6340    };
6341
6342    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
6343    {
6344       if(this >= firstPlatform && this <= lastPlatform)
6345       {
6346          if(tempString)
6347             strcpy(tempString, platformNames[this]);
6348          return platformNames[this];
6349       }
6350       if(tempString && tempString[0])
6351          tempString[0] = '\0';
6352       return null;
6353    }
6354    
6355    bool OnGetDataFromString(char * string)
6356    {
6357       this = string;
6358       return (bool)this;
6359    }
6360 };
6361
6362 default extern Platform runtimePlatform;
6363
6364 public Platform GetRuntimePlatform()
6365 {
6366    return runtimePlatform;
6367 }
6368
6369 namespace gui;
6370
6371 class Window;
6372
6373 namespace com;
6374 // CLASS DESIGNER SUPPORT
6375
6376 public class ObjectInfo : struct
6377 {
6378 public:
6379    ObjectInfo prev, next;
6380    Instance instance;
6381    char * name;
6382    Instantiation instCode;
6383    bool deleted;
6384    ObjectInfo oClass;
6385    OldList instances;
6386    ClassDefinition classDefinition;
6387    bool modified;
6388 };
6389
6390 public class DesignerBase : Window
6391 {
6392 public:
6393    virtual bool FindObject(Instance * instance, char * string);
6394    virtual void RenameObject(ObjectInfo object, char * name);
6395    virtual void SelectObjectFromDesigner(ObjectInfo object);
6396    virtual void CodeAddObject(Instance instance, ObjectInfo * object);
6397    virtual void SheetAddObject(ObjectInfo object);
6398    virtual void AddToolBoxClass(Class _class);
6399    virtual void AddDefaultMethod(Instance instance, Instance classInstance);
6400    virtual void DeleteObject(ObjectInfo object);
6401    virtual bool ObjectContainsCode(ObjectInfo object);
6402    virtual void ModifyCode(void);
6403    virtual void UpdateProperties(void);
6404
6405    ClassDesignerBase classDesigner;
6406    char * objectClass;
6407    bool isDragging;
6408
6409    // FIX THIS WITH PUBLIC:
6410    property ClassDesignerBase classDesigner
6411    { 
6412       get { return classDesigner; }
6413       set { classDesigner = value; }
6414    };
6415    property char * objectClass
6416    { 
6417       get { return objectClass; }
6418       set { objectClass = value; }
6419    };
6420    property bool isDragging
6421    { 
6422       get { return isDragging; }
6423       set { isDragging = value; }
6424    };
6425 }
6426  
6427 public class ClassDesignerBase : Window
6428 {
6429 public:
6430    virtual void Reset(void);
6431    virtual void AddObject(void);
6432    virtual void SelectObject(ObjectInfo object, Instance control);
6433
6434    virtual void ListToolBoxClasses(DesignerBase designer);
6435
6436    virtual void ::PrepareTestObject(DesignerBase designer, Instance test);
6437    virtual void ::CreateObject(DesignerBase designer, Instance instance, ObjectInfo object, bool isClass, Instance _class);
6438    virtual void ::PostCreateObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6439    virtual void ::DroppedObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6440    virtual void ::DestroyObject(Instance object);
6441    virtual void ::FixProperty(Property prop, Instance object);
6442    virtual void ::CreateNew(EditBox editBox, Size clientSize, char * name, char * inherit);
6443 }
6444
6445 DesignerBase activeDesigner;
6446
6447 public void SetActiveDesigner(DesignerBase designer)
6448 {
6449    activeDesigner = designer;
6450 }
6451
6452 public DesignerBase GetActiveDesigner()
6453 {
6454    return activeDesigner;
6455 }
6456
6457 namespace sys;
6458
6459 // constants
6460 define LEAD_OFFSET      = 0xD800 - (0x10000 >> 10);
6461 define SURROGATE_OFFSET = 0x10000 - (0xD800 << 10) - 0xDC00;
6462
6463 public bool UTF8Validate(char * source)
6464 {
6465    if(source)
6466    {
6467       int c;
6468       for(c = 0; source[c];)
6469       {
6470          byte ch = source[c];
6471          unichar codePoint = 0;
6472          int numBytes = 1;
6473          int i;
6474          byte mask = 0x7F;
6475          if(ch & 0x80)
6476          {
6477             if(ch & 0x40)
6478             {
6479                mask >>= 2;
6480                numBytes++;
6481                if(ch & 0x20)
6482                {
6483                   numBytes++;
6484                   mask >>= 1;
6485                   if(ch & 0x10)
6486                   {
6487                      if(ch & 0x08)
6488                         return false;
6489                      numBytes++;
6490                      mask >>= 1;
6491                   }
6492                }
6493             }
6494             else
6495                return false;
6496          }
6497          for(i = 0; i<numBytes && (ch = source[c]); i++, c++)
6498          {
6499             codePoint <<= 6;
6500             codePoint |= ch & mask;
6501             mask = 0x3F;
6502             if(i > 1)
6503             {
6504                if(!(ch & 0x80) || (ch & 0x40))
6505                   return false;
6506             }
6507          }
6508          if(i < numBytes) return false;
6509
6510          if(codePoint > 0x10FFFF || (codePoint >= 0xD800 && codePoint <= 0xDFFF) || 
6511            (codePoint < 0x80 && numBytes > 1) || 
6512            (codePoint < 0x800 && numBytes > 2) || 
6513            (codePoint < 0x10000 && numBytes > 3))
6514             return false;
6515       }
6516    }
6517    return true;
6518 }
6519
6520 public int ISO8859_1toUTF8(char * source, char * dest, int max)
6521 {
6522    int c;
6523    int d = 0;
6524    for(c = 0; source[c]; c++)
6525    {
6526       unichar ch = ((byte *)source)[c];
6527       if(ch < 0x80)
6528       {
6529          if(d + 1 >= max) break;
6530          dest[d++] = (char)ch;
6531       }
6532       else if(ch < 0x800)
6533       {
6534          if(d + 2 >= max) break;
6535          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6536          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6537       }
6538       else if(ch < 0x10000)
6539       {
6540          if(d + 3 >= max) break;
6541          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6542          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6543          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6544       }
6545       else
6546       {
6547          if(d + 4 >= max) break;
6548          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6549          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6550          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6551          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6552       }
6553    }
6554    dest[d] = 0;
6555    return d;
6556 }
6557
6558 public char * UTF16toUTF8(uint16 * source)
6559 {
6560    int c;
6561    int d = 0;
6562    int len;
6563    char * dest;
6564    uint16 u16;
6565    bool invert = false;
6566
6567    for(len = 0; source[len]; len++);
6568    dest = new char[len * 3 + 1];
6569    for(c = 0; (u16 = source[c]); c++)
6570    {
6571       unichar ch;
6572       if(!c && (u16 == 0xFFFE || u16 == 0xFEFF))
6573       {
6574          if(u16 == 0xFFFE) invert = true;
6575          continue;
6576       }
6577       if(invert) { u16 = ((u16 & 0xFF00) >> 8) | ((u16 & 0x00FF) << 8); }
6578       
6579       if(u16 < 0xD800 || u16 > 0xDBFF)
6580          ch = (unichar)u16;         
6581       else
6582          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
6583                   
6584       if(ch < 0x80)
6585       {
6586          dest[d++] = (char)ch;
6587       }
6588       else if(ch < 0x800)
6589       {
6590          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6591          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6592       }
6593       else if(ch < 0x10000)
6594       {
6595          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6596          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6597          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6598       }
6599       else
6600       {
6601          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6602          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6603          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6604          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6605       }
6606    }
6607    dest[d] = 0;
6608    dest = renew dest char[d+1];
6609    return dest;
6610 }
6611
6612 public int UTF16toUTF8Buffer(uint16 * source, byte * dest, int max)
6613 {
6614    int c;
6615    int d = 0;
6616    uint16 u16;
6617    for(c = 0; (u16 = source[c]); c++)
6618    {
6619       unichar ch;
6620       if(u16 < 0xD800 || u16 > 0xDBFF)
6621          ch = (unichar)u16;         
6622       else
6623          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
6624
6625       if(ch < 0x80)
6626       {
6627          if(d + 1 >= max) break;
6628          dest[d++] = (char)ch;
6629       }
6630       else if(ch < 0x800)
6631       {
6632          if(d + 2 >= max) break;
6633          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6634          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6635       }
6636       else if(ch < 0x10000)
6637       {
6638          if(d + 3 >= max) break;
6639          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6640          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6641          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6642       }
6643       else
6644       {
6645          if(d + 4 >= max) break;
6646          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6647          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6648          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6649          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6650       }
6651    }
6652    dest[d] = 0;
6653    return d;
6654 }
6655
6656 // NOTE: UTF8GetChar now returns 0 into numBytes for the null-terminating character ('\0')
6657 public unichar UTF8GetChar(char * string, int * numBytes)
6658 {
6659    unichar ch;
6660    byte b = ((byte *)string)[0];
6661    int i;
6662    byte mask = 0x7F;
6663    int nb = b ? 1 : 0;
6664    ch = 0;
6665    if(b & 0x80)
6666    {
6667       if(b & 0x40)
6668       {
6669          mask >>= 2;
6670          nb++;
6671          if(b & 0x20)
6672          {
6673             nb++;
6674             mask >>= 1;
6675             if(b & 0x10)
6676             {
6677                if(b & 0x08) { nb = 0; }
6678                nb++;
6679                mask >>= 1;
6680             }
6681          }
6682       }
6683       else
6684          nb = 0;
6685    }
6686    for(i = 0; i<nb; i++)
6687    {
6688       ch <<= 6;
6689       ch |= (b = ((byte *)string)[i]) & mask;
6690       mask = 0x3F;
6691       if(i > 1 && (!(b & 0x80) || (b & 0x40)))
6692       {
6693          nb = 0;
6694          ch = 0;
6695       }
6696    }
6697
6698    if(i < nb || 
6699       ch > 0x10FFFF || (ch >= 0xD800 && ch <= 0xDFFF) || 
6700      (ch < 0x80 && nb > 1) || 
6701      (ch < 0x800 && nb > 2) || 
6702      (ch < 0x10000 && nb > 3))
6703    {
6704       ch = 0;
6705       nb = 0;
6706    }
6707    if(numBytes) *numBytes = nb;
6708    return ch;
6709 }
6710
6711 public int UTF8toUTF16Buffer(char * source, uint16 * dest, int max)
6712 {
6713    if(source)
6714    {
6715       int c;
6716       int d = 0;
6717       for(c = 0; source[c];)
6718       {
6719          byte ch = source[c];
6720          unichar codePoint = 0;
6721          int numBytes = 1;
6722          int i;
6723          byte mask = 0x7F;
6724          if(ch & 0x80 && ch & 0x40)
6725          {
6726             mask >>= 2;
6727             numBytes++;
6728             if(ch & 0x20)
6729             {
6730                numBytes++;
6731                mask >>= 1;
6732                if(ch & 0x10)
6733                {
6734                   numBytes++;
6735                   mask >>= 1;
6736                }
6737             }
6738          }
6739          for(i = 0; i<numBytes; i++)
6740          {
6741             codePoint <<= 6;
6742             codePoint |= source[c++] & mask;
6743             mask = 0x3F;
6744          }
6745
6746          if(codePoint > 0xFFFF)
6747          {
6748             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
6749             uint16 trail = 0xDC00 + (uint16)(codePoint & 0x3FF);
6750             if(d >= max - 1) break;
6751             dest[d++] = lead;
6752             dest[d++] = trail;
6753          }
6754          else
6755          {
6756             if(d >= max) break;
6757             dest[d++] = (uint16)codePoint;
6758          }
6759       }
6760       dest[d] = 0;
6761       return d;
6762    }
6763    return 0;   
6764 }
6765
6766 public int UTF32toUTF8Len(unichar * source, int count, byte * dest, int max)
6767 {
6768    int c;
6769    int d = 0;
6770    uint32 ch;
6771    for(c = 0; c<count && (ch = source[c]); c++)
6772    {
6773       if(ch < 0x80)
6774       {
6775          if(d + 1 >= max) break;
6776          dest[d++] = (char)ch;
6777       }
6778       else if(ch < 0x800)
6779       {
6780          if(d + 2 >= max) break;
6781          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6782          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6783       }
6784       else if(ch < 0x10000)
6785       {
6786          if(d + 3 >= max) break;
6787          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6788          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6789          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6790       }
6791       else
6792       {
6793          if(d + 4 >= max) break;
6794          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6795          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6796          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6797          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6798       }
6799    }
6800    dest[d] = 0;
6801    return d;
6802 }
6803
6804 public uint16 * UTF8toUTF16(char * source, int * wordCount)
6805 {
6806    if(source)
6807    {
6808       int len = strlen(source);
6809       uint16 * dest = new uint16[len + 1];
6810       int c;
6811       int d = 0;
6812       for(c = 0; source[c];)
6813       {
6814          byte ch = source[c];
6815          unichar codePoint = 0;
6816          int numBytes = 1;
6817          int i;
6818          byte mask = 0x7F;
6819          if(ch & 0x80 && ch & 0x40)
6820          {
6821             mask >>= 2;
6822             numBytes++;
6823             if(ch & 0x20)
6824             {
6825                numBytes++;
6826                mask >>= 1;
6827                if(ch & 0x10)
6828                {
6829                   numBytes++;
6830                   mask >>= 1;
6831                }
6832             }
6833          }
6834          for(i = 0; i<numBytes; i++)
6835          {
6836             codePoint <<= 6;
6837             codePoint |= source[c++] & mask;
6838             mask = 0x3F;
6839          }
6840
6841          if(codePoint > 0xFFFF)
6842          {
6843             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
6844             uint16 trail = 0xDC00 + (uint16)(codePoint & 0x3FF);
6845             dest[d++] = lead;
6846             dest[d++] = trail;
6847          }
6848          else
6849          {
6850             dest[d++] = (uint16)codePoint;
6851          }
6852       }
6853       dest[d] = 0;
6854       if(wordCount) *wordCount = d;
6855       return dest;
6856    }
6857    return null;
6858 }
6859
6860 namespace com;