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