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