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