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