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